## Automatically generated incremental diff
## From:   linux-2.5.4-pre2
## To:     linux-2.5.4-pre3
## Robot:  $Id: make-incremental-diff,v 1.9 2001/12/10 00:06:56 hpa Exp $

diff -urN linux-2.5.4-pre2/Documentation/networking/8139too.txt linux/Documentation/networking/8139too.txt
--- linux-2.5.4-pre2/Documentation/networking/8139too.txt	Fri Nov  9 13:45:35 2001
+++ linux/Documentation/networking/8139too.txt	Thu Feb  7 16:09:54 2002
@@ -96,7 +96,10 @@
 KTI KF-230TX
 KTI KF-230TX/2
 Lantech FastNet TX
+Ovislink Fast Ethernet
+Planet ENW-9504 (V.4) 10/100
 SMC EZNET 10/100
+UNEX NexNIC ND012C
 
 (please add your adapter model to this list)
 
@@ -181,11 +184,18 @@
 Change History
 --------------
 
+Version 0.9.23 - In progress
+
+* New, compile-time conditional for testing better RX reset
+* Only account specific RX errors if rx_status is !OK
+
+
 Version 0.9.22 - November 8, 2001
 
 * Additional retries before aborting Tx
 * Do not write other TxConfig bits when writing clear-abort bit.
 * Ack TxErr intr status after each Tx abort, too.
+* Fix oops in interface restart
 
 
 Version 0.9.21 - November 1, 2001
diff -urN linux-2.5.4-pre2/Documentation/networking/dl2k.txt linux/Documentation/networking/dl2k.txt
--- linux-2.5.4-pre2/Documentation/networking/dl2k.txt	Mon Nov 19 15:19:42 2001
+++ linux/Documentation/networking/dl2k.txt	Thu Feb  7 16:09:54 2002
@@ -1,7 +1,7 @@
 
     D-Link DL2000-based Gigabit Ethernet Adapter Installation
     for Linux
-    Nov 12, 2001
+    Jan 02, 2002
 
 Contents
 ========
@@ -182,7 +182,7 @@
 mtu=packet_size			- Specifies the maximum packet size. default
 				  is 1500.
 
-media=xxxxxxxxx			- Specifies the media type the NIC operates at.
+media=media_type		- Specifies the media type the NIC operates at.
 				  autosense	Autosensing active media.
 				  10mbps_hd	10Mbps half duplex.
 				  10mbps_fd	10Mbps full duplex.
@@ -195,28 +195,41 @@
 				  2		10Mbps full duplex.
 				  3		100Mbps half duplex.
 				  4		100Mbps full duplex.
-				  5          	1000Mbps full duplex.
-				  6          	1000Mbps half duplex.
+				  5          	1000Mbps half duplex.
+				  6          	1000Mbps full duplex.
 
 				  By default, the NIC operates at autosense.
 				  Note that only 1000mbps_fd and 1000mbps_hd
 				  types are available for fiber adapter.
 
-vlan=x				- Specifies the VLAN ID. If vlan=0, the
+vlan=[0|1]			- Specifies the VLAN ID. If vlan=0, the
 				  Virtual Local Area Network (VLAN) function is
 				  disable.
 
-jumbo=x				- Specifies the jumbo frame support. If jumbo=1,
+jumbo=[0|1]			- Specifies the jumbo frame support. If jumbo=1,
 				  the NIC accept jumbo frames. By default, this
 				  function is disabled.
 				  Jumbo frame usually improve the performance
 				  int gigabit.
 				  
-int_count			- Rx frame count each interrupt.
-int_timeout			- Rx DMA wait time for an interrupt. Proper 
-				  values of int_count and int_timeout bring 
-				  a conspicuous performance in the fast machine. 
-				  Ex. int_count=5 and int_timeout=750 
+rx_coalesce=n			- Rx frame count each interrupt.
+rx_timeout=n			- Rx DMA wait time for an interrupt. Proper 
+				  values of rx_coalesce and rx_timeout bring 
+				  a conspicuous performance in the fast machine.
+				  Ex. rx_coalesce=5 and rx_timeout=750 
+
+tx_coalesce=n			- Tx transmit count each TxComp interrupt.
+				  Setting value larger than 1 will improve 
+				  performance, but this is possible to lower 
+				  stability in slow UP machines. By default, 
+				  tx_coalesce=1. (dl2k)
+				  
+tx_flow=[1|0]			- Specifies the Tx flow control. If tx_flow=1, 
+				  the Tx flow control enable.
+				  
+rx_flow=[1|0]			- Specifies the Rx flow control. If rx_flow=1, 
+				  the Rx flow control enable.
+
 
 Configuration Script Sample
 ===========================
diff -urN linux-2.5.4-pre2/Makefile linux/Makefile
--- linux-2.5.4-pre2/Makefile	Thu Feb  7 16:09:51 2002
+++ linux/Makefile	Thu Feb  7 16:09:54 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 4
-EXTRAVERSION =-pre2
+EXTRAVERSION =-pre3
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.5.4-pre2/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- linux-2.5.4-pre2/arch/alpha/kernel/setup.c	Tue Dec 25 15:39:20 2001
+++ linux/arch/alpha/kernel/setup.c	Thu Feb  7 16:09:54 2002
@@ -436,8 +436,8 @@
 
 static kdev_t srm_console_device(struct console *c)
 {
-  /* Huh? */
-        return MKDEV(TTY_MAJOR, 64 + c->index);
+	/* Huh? */
+        return mk_kdev(TTY_MAJOR, 64 + c->index);
 }
 
 static int __init srm_console_setup(struct console *co, char *options)
diff -urN linux-2.5.4-pre2/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c
--- linux-2.5.4-pre2/arch/alpha/mm/fault.c	Mon Sep 17 16:15:02 2001
+++ linux/arch/alpha/mm/fault.c	Thu Feb  7 16:09:54 2002
@@ -196,8 +196,7 @@
  */
 out_of_memory:
 	if (current->pid == 1) {
-		current->policy |= SCHED_YIELD;
-		schedule();
+		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
 	}
diff -urN linux-2.5.4-pre2/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-2.5.4-pre2/arch/i386/kernel/entry.S	Thu Feb  7 16:09:51 2002
+++ linux/arch/i386/kernel/entry.S	Thu Feb  7 16:09:54 2002
@@ -43,6 +43,8 @@
 #include <linux/config.h>
 #include <linux/sys.h>
 #include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
 #include <asm/segment.h>
 #include <asm/smp.h>
 
@@ -67,24 +69,6 @@
 NT_MASK		= 0x00004000
 VM_MASK		= 0x00020000
 
-/*
- * these are offsets into the task-struct.
- */
-state		=  0
-flags		=  4
-work		=  8
-need_resched	= work+0
-syscall_trace	= work+1
-sigpending	= work+2
-notify_resume	= work+3
-addr_limit	= 12
-exec_domain	= 16
-tsk_ptrace	= 24
-cpu		= 32
-
-ENOSYS = 38
-
-
 #define SAVE_ALL \
 	cld; \
 	pushl %es; \
@@ -131,10 +115,6 @@
 	.long 3b,6b;	\
 .previous
 
-#define GET_CURRENT(reg) \
-	movl $-8192, reg; \
-	andl %esp, reg
-
 ENTRY(lcall7)
 	pushfl			# We get a different stack layout with call gates,
 	pushl %eax		# which has to be cleaned up later..
@@ -147,8 +127,8 @@
 	movl %ecx,CS(%esp)	#
 	movl %esp,%ebx
 	pushl %ebx
-	andl $-8192,%ebx	# GET_CURRENT
-	movl exec_domain(%ebx),%edx	# Get the execution domain
+	andl $-8192,%ebx	# GET_THREAD_INFO
+	movl TI_EXEC_DOMAIN(%ebx),%edx	# Get the execution domain
 	movl 4(%edx),%edx	# Get the lcall7 handler for the domain
 	pushl $0x7
 	call *%edx
@@ -168,8 +148,8 @@
 	movl %ecx,CS(%esp)	#
 	movl %esp,%ebx
 	pushl %ebx
-	andl $-8192,%ebx	# GET_CURRENT
-	movl exec_domain(%ebx),%edx	# Get the execution domain
+	andl $-8192,%ebx	# GET_THREAD_INFO
+	movl TI_EXEC_DOMAIN(%ebx),%edx	# Get the execution domain
 	movl 4(%edx),%edx	# Get the lcall7 handler for the domain
 	pushl $0x27
 	call *%edx
@@ -182,7 +162,7 @@
 	pushl %ebx
 	call SYMBOL_NAME(schedule_tail)
 	addl $4, %esp
-	GET_CURRENT(%ebx)
+	GET_THREAD_INFO(%ebx)
 	jmp syscall_exit
 
 /*
@@ -195,17 +175,17 @@
 	# userspace resumption stub bypassing syscall exit tracing
 	ALIGN
 ENTRY(ret_from_intr)
-	GET_CURRENT(%ebx)
+	GET_THREAD_INFO(%ebx)
 ret_from_exception:
 	movl EFLAGS(%esp),%eax		# mix EFLAGS and CS
 	movb CS(%esp),%al
 	testl $(VM_MASK | 3),%eax
 	jz restore_all			# returning to kernel-space or vm86-space
 ENTRY(resume_userspace)
-	cli				# make sure need_resched and sigpending don't change
-					# between sampling and the iret
-	movl work(%ebx),%ecx
-	andl $0xffff00ff,%ecx		# current->work (ignoring syscall_trace)
+ 	cli				# make sure we don't miss an interrupt setting need_resched
+ 					# or sigpending between sampling and the iret
+	movl TI_FLAGS(%ebx),%ecx
+	andl $_TIF_WORK_MASK,%ecx	# is there any work to be done on int/excp return?
 	jne work_pending
 	jmp restore_all
 
@@ -214,19 +194,19 @@
 ENTRY(system_call)
 	pushl %eax			# save orig_eax
 	SAVE_ALL
-	GET_CURRENT(%ebx)
+	GET_THREAD_INFO(%ebx)
 	cmpl $(NR_syscalls),%eax
 	jae syscall_badsys
-	testb $0xff,syscall_trace(%ebx)	# system call tracing in operation
+	testb $_TIF_SYSCALL_TRACE,TI_FLAGS(%ebx)	# system call tracing in operation
 	jnz syscall_trace_entry
-syscall_traced:
+syscall_call:
 	call *SYMBOL_NAME(sys_call_table)(,%eax,4)
 	movl %eax,EAX(%esp)		# store the return value
 syscall_exit:
-	cli				# make sure need_resched and sigpending don't change
-					# between sampling and the iret
-	movl work(%ebx),%ecx
-	testl %ecx,%ecx			# current->work
+ 	cli				# make sure we don't miss an interrupt setting need_resched
+ 					# or sigpending between sampling and the iret
+	movl TI_FLAGS(%ebx),%ecx
+	testw $_TIF_ALLWORK_MASK,%cx	# current->work
 	jne syscall_exit_work
 restore_all:
 	RESTORE_ALL
@@ -234,16 +214,16 @@
 	# perform work that needs to be done immediately before resumption
 	ALIGN
 work_pending:
-	testb %cl,%cl			# current->work.need_resched
+	testb $_TIF_NEED_RESCHED,%cl
 	jz work_notifysig
 work_resched:
 	call SYMBOL_NAME(schedule)
-	cli				# make sure need_resched and sigpending don't change
-					# between sampling and the iret
-	movl work(%ebx),%ecx
-	andl $0xffff00ff,%ecx		# ignore the syscall trace counter
+ 	cli				# make sure we don't miss an interrupt setting need_resched
+ 					# or sigpending between sampling and the iret
+	movl TI_FLAGS(%ebx),%ecx
+	andl $_TIF_WORK_MASK,%ecx	# is there any work to be done other than syscall tracing?
 	jz restore_all
-	testb %cl,%cl			# current->work.need_resched
+	testb $_TIF_NEED_RESCHED,%cl
 	jnz work_resched
 
 work_notifysig:				# deal with pending signals and notify-resume requests
@@ -273,13 +253,13 @@
 	call SYMBOL_NAME(do_syscall_trace)
 	movl ORIG_EAX(%esp),%eax
 	cmpl $(NR_syscalls),%eax
-	jnae syscall_traced
+	jnae syscall_call
 	jmp syscall_exit
 
 	# perform syscall exit tracing
 	ALIGN
 syscall_exit_work:
-	testb %ch,%ch			# current->work.syscall_trace
+	testb $_TIF_SYSCALL_TRACE,%cl
 	jz work_pending
 	sti				# could let do_syscall_trace() call schedule() instead
 	movl %esp,%eax
@@ -319,7 +299,7 @@
 	movl $(__KERNEL_DS),%edx
 	movl %edx,%ds
 	movl %edx,%es
-	GET_CURRENT(%ebx)
+	GET_THREAD_INFO(%ebx)
 	call *%edi
 	addl $8,%esp
 	jmp ret_from_exception
@@ -337,7 +317,7 @@
 ENTRY(device_not_available)
 	pushl $-1		# mark this as an int
 	SAVE_ALL
-	GET_CURRENT(%ebx)
+	GET_THREAD_INFO(%ebx)
 	movl %cr0,%eax
 	testl $0x4,%eax			# EM (math emulation bit)
 	jne device_not_available_emulate
diff -urN linux-2.5.4-pre2/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- linux-2.5.4-pre2/arch/i386/kernel/head.S	Tue Jan 29 18:24:01 2002
+++ linux/arch/i386/kernel/head.S	Thu Feb  7 16:09:54 2002
@@ -320,7 +320,7 @@
 	ret
 
 ENTRY(stack_start)
-	.long SYMBOL_NAME(init_task_union)+8192
+	.long SYMBOL_NAME(init_thread_union)+8192
 	.long __KERNEL_DS
 
 /* This is the default interrupt "handler" :-) */
diff -urN linux-2.5.4-pre2/arch/i386/kernel/i387.c linux/arch/i386/kernel/i387.c
--- linux-2.5.4-pre2/arch/i386/kernel/i387.c	Fri Feb 23 10:09:08 2001
+++ linux/arch/i386/kernel/i387.c	Thu Feb  7 16:09:54 2002
@@ -52,7 +52,7 @@
 		asm volatile( "fnsave %0 ; fwait"
 			      : "=m" (tsk->thread.i387.fsave) );
 	}
-	tsk->flags &= ~PF_USEDFPU;
+	clear_thread_flag(TIF_USEDFPU);
 }
 
 void save_init_fpu( struct task_struct *tsk )
@@ -65,7 +65,7 @@
 {
 	struct task_struct *tsk = current;
 
-	if (tsk->flags & PF_USEDFPU) {
+	if (test_thread_flag(TIF_USEDFPU)) {
 		__save_init_fpu(tsk);
 		return;
 	}
diff -urN linux-2.5.4-pre2/arch/i386/kernel/init_task.c linux/arch/i386/kernel/init_task.c
--- linux-2.5.4-pre2/arch/i386/kernel/init_task.c	Tue Jan 15 11:06:55 2002
+++ linux/arch/i386/kernel/init_task.c	Thu Feb  7 16:09:54 2002
@@ -13,15 +13,22 @@
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
- * Initial task structure.
+ * Initial thread structure.
  *
  * We need to make sure that this is 8192-byte aligned due to the
  * way process stacks are handled. This is done by having a special
  * "init_task" linker map entry..
  */
-union task_union init_task_union 
+union thread_union init_thread_union 
 	__attribute__((__section__(".data.init_task"))) =
-		{ INIT_TASK(init_task_union.task) };
+		{ INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
 
 /*
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
diff -urN linux-2.5.4-pre2/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- linux-2.5.4-pre2/arch/i386/kernel/irq.c	Wed Nov 28 13:22:25 2001
+++ linux/arch/i386/kernel/irq.c	Thu Feb  7 16:09:54 2002
@@ -220,7 +220,7 @@
 			continue;
 		}
 		esp &= ~(THREAD_SIZE-1);
-		esp += sizeof(struct task_struct);
+		esp += sizeof(struct thread_info);
 		show_stack((void*)esp);
  	}
 	printk("\nCPU %d:",cpu);
diff -urN linux-2.5.4-pre2/arch/i386/kernel/nmi.c linux/arch/i386/kernel/nmi.c
--- linux-2.5.4-pre2/arch/i386/kernel/nmi.c	Mon Jan  7 12:55:17 2002
+++ linux/arch/i386/kernel/nmi.c	Thu Feb  7 16:09:54 2002
@@ -263,8 +263,9 @@
 {
 
 	/*
-	 * Since current-> is always on the stack, and we always switch
-	 * the stack NMI-atomically, it's safe to use smp_processor_id().
+	 * Since current_thread_info()-> is always on the stack, and we
+	 * always switch the stack NMI-atomically, it's safe to use
+	 * smp_processor_id().
 	 */
 	int sum, cpu = smp_processor_id();
 
diff -urN linux-2.5.4-pre2/arch/i386/kernel/pci-dma.c linux/arch/i386/kernel/pci-dma.c
--- linux-2.5.4-pre2/arch/i386/kernel/pci-dma.c	Mon Feb 14 15:34:21 2000
+++ linux/arch/i386/kernel/pci-dma.c	Thu Feb  7 16:09:54 2002
@@ -25,7 +25,7 @@
 
 	if (ret != NULL) {
 		memset(ret, 0, size);
-		*dma_handle = virt_to_bus(ret);
+		*dma_handle = virt_to_phys(ret);
 	}
 	return ret;
 }
diff -urN linux-2.5.4-pre2/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- linux-2.5.4-pre2/arch/i386/kernel/process.c	Mon Jan 28 15:11:45 2002
+++ linux/arch/i386/kernel/process.c	Thu Feb  7 16:09:54 2002
@@ -102,15 +102,21 @@
 	 * Deal with another CPU just having chosen a thread to
 	 * run here:
 	 */
-	oldval = xchg(&current->work.need_resched, -1);
+	oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
 
-	if (!oldval)
+	if (!oldval) {
+		set_thread_flag(TIF_POLLING_NRFLAG);
 		asm volatile(
 			"2:"
-			"cmpb $-1, %0;"
+			"testl %0, %1;"
 			"rep; nop;"
 			"je 2b;"
-				: :"m" (current->work.need_resched));
+			: : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
+
+		clear_thread_flag(TIF_POLLING_NRFLAG);
+	} else {
+		set_need_resched();
+	}
 }
 
 /*
@@ -576,7 +582,7 @@
 {
 	struct pt_regs * childregs;
 
-	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1;
+	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
 	struct_cpy(childregs, regs);
 	childregs->eax = 0;
 	childregs->esp = esp;
@@ -673,6 +679,8 @@
 	struct thread_struct *prev = &prev_p->thread,
 				 *next = &next_p->thread;
 	struct tss_struct *tss = init_tss + smp_processor_id();
+
+	/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
 	unlazy_fpu(prev_p);
 
diff -urN linux-2.5.4-pre2/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- linux-2.5.4-pre2/arch/i386/kernel/ptrace.c	Mon Jan 28 15:11:45 2002
+++ linux/arch/i386/kernel/ptrace.c	Thu Feb  7 16:09:54 2002
@@ -278,16 +278,10 @@
 		if ((unsigned long) data > _NSIG)
 			break;
 		if (request == PTRACE_SYSCALL) {
-			if (!(child->ptrace & PT_SYSCALLTRACE)) {
-				child->ptrace |= PT_SYSCALLTRACE;
-				child->work.syscall_trace++;
-			}
+			set_thread_flag(TIF_SYSCALL_TRACE);
 		}
 		else {
-			if (child->ptrace & PT_SYSCALLTRACE) {
-				child->ptrace &= ~PT_SYSCALLTRACE;
-				child->work.syscall_trace--;
-			}
+			clear_thread_flag(TIF_SYSCALL_TRACE);
 		}
 		child->exit_code = data;
 	/* make sure the single step bit is not set. */
@@ -323,10 +317,7 @@
 		ret = -EIO;
 		if ((unsigned long) data > _NSIG)
 			break;
-		if (child->ptrace & PT_SYSCALLTRACE) {
-			child->ptrace &= ~PT_SYSCALLTRACE;
-			child->work.syscall_trace--;
-		}
+		clear_thread_flag(TIF_SYSCALL_TRACE);
 		if ((child->ptrace & PT_DTRACE) == 0) {
 			/* Spurious delayed TF traps may occur */
 			child->ptrace |= PT_DTRACE;
@@ -444,7 +435,7 @@
 		break;
 	}
 out_tsk:
-	free_task_struct(child);
+	put_task_struct(child);
 out:
 	unlock_kernel();
 	return ret;
@@ -456,8 +447,9 @@
 __attribute__((regparm(3)))
 void do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
-	if ((current->ptrace & (PT_PTRACED|PT_SYSCALLTRACE)) !=
-	    (PT_PTRACED|PT_SYSCALLTRACE))
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		return;
+	if (current->ptrace & PT_PTRACED)
 		return;
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
@@ -475,16 +467,4 @@
 		send_sig(current->exit_code, current, 1);
 		current->exit_code = 0;
 	}
-}
-
-/* notification of userspace execution resumption
- * - triggered by current->work.notify_resume
- */
-__attribute__((regparm(3)))
-void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
-		      struct task_work work_pending)
-{
-	/* deal with pending signal delivery */
-	if (work_pending.sigpending)
-		do_signal(regs,oldset);
 }
diff -urN linux-2.5.4-pre2/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- linux-2.5.4-pre2/arch/i386/kernel/setup.c	Sun Jan 27 11:21:34 2002
+++ linux/arch/i386/kernel/setup.c	Thu Feb  7 16:09:54 2002
@@ -232,7 +232,7 @@
 
 	/* Video ROM is standard at C000:0000 - C7FF:0000, check signature */
 	for (base = 0xC0000; base < 0xE0000; base += 2048) {
-		romstart = bus_to_virt(base);
+		romstart = isa_bus_to_virt(base);
 		if (!romsignature(romstart))
 			continue;
 		request_resource(&iomem_resource, rom_resources + roms);
@@ -244,7 +244,7 @@
 	for (base = 0xC8000; base < 0xE0000; base += 2048) {
 		unsigned long length;
 
-		romstart = bus_to_virt(base);
+		romstart = isa_bus_to_virt(base);
 		if (!romsignature(romstart))
 			continue;
 		length = romstart[2] * 512;
@@ -273,7 +273,7 @@
 
 	/* Final check for motherboard extension rom at E000:0000 */
 	base = 0xE0000;
-	romstart = bus_to_virt(base);
+	romstart = isa_bus_to_virt(base);
 
 	if (romsignature(romstart)) {
 		rom_resources[roms].start = base;
@@ -692,10 +692,10 @@
 	init_mm.end_data = (unsigned long) &_edata;
 	init_mm.brk = (unsigned long) &_end;
 
-	code_resource.start = virt_to_bus(&_text);
-	code_resource.end = virt_to_bus(&_etext)-1;
-	data_resource.start = virt_to_bus(&_etext);
-	data_resource.end = virt_to_bus(&_edata)-1;
+	code_resource.start = virt_to_phys(&_text);
+	code_resource.end = virt_to_phys(&_etext)-1;
+	data_resource.start = virt_to_phys(&_etext);
+	data_resource.end = virt_to_phys(&_edata)-1;
 
 	parse_mem_cmdline(cmdline_p);
 
@@ -2817,7 +2817,7 @@
 	/*
 	 * Force FPU initialization:
 	 */
-	current->flags &= ~PF_USEDFPU;
+	clear_thread_flag(TIF_USEDFPU);
 	current->used_math = 0;
 	stts();
 }
diff -urN linux-2.5.4-pre2/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- linux-2.5.4-pre2/arch/i386/kernel/signal.c	Thu Feb  7 16:09:51 2002
+++ linux/arch/i386/kernel/signal.c	Thu Feb  7 16:09:54 2002
@@ -394,10 +394,10 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user((current->exec_domain
-		           && current->exec_domain->signal_invmap
+	err |= __put_user((current_thread_info()->exec_domain
+		           && current_thread_info()->exec_domain->signal_invmap
 		           && sig < 32
-		           ? current->exec_domain->signal_invmap[sig]
+		           ? current_thread_info()->exec_domain->signal_invmap[sig]
 		           : sig),
 		          &frame->sig);
 	if (err)
@@ -464,10 +464,10 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user((current->exec_domain
-		    	   && current->exec_domain->signal_invmap
+	err |= __put_user((current_thread_info()->exec_domain
+		    	   && current_thread_info()->exec_domain->signal_invmap
 		    	   && sig < 32
-		    	   ? current->exec_domain->signal_invmap[sig]
+		    	   ? current_thread_info()->exec_domain->signal_invmap[sig]
 			   : sig),
 			  &frame->sig);
 	err |= __put_user(&frame->info, &frame->pinfo);
@@ -711,4 +711,17 @@
 		}
 	}
 	return 0;
+}
+
+/*
+ * notification of userspace execution resumption
+ * - triggered by current->work.notify_resume
+ */
+__attribute__((regparm(3)))
+void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
+		      __u32 thread_info_flags)
+{
+	/* deal with pending signal delivery */
+	if (thread_info_flags & _TIF_SIGPENDING)
+		do_signal(regs,oldset);
 }
diff -urN linux-2.5.4-pre2/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- linux-2.5.4-pre2/arch/i386/kernel/smpboot.c	Mon Jan 28 13:12:04 2002
+++ linux/arch/i386/kernel/smpboot.c	Thu Feb  7 16:09:54 2002
@@ -818,7 +818,7 @@
 
 	/* So we see what's up   */
 	printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
-	stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle);
+	stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle->thread_info);
 
 	/*
 	 * This grunge runs the startup process for
@@ -1024,7 +1024,7 @@
 	map_cpu_to_boot_apicid(0, boot_cpu_apicid);
 
 	global_irq_holder = NO_PROC_ID;
-	current->cpu = 0;
+	current_thread_info()->cpu = 0;
 	smp_tune_scheduling();
 
 	/*
diff -urN linux-2.5.4-pre2/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- linux-2.5.4-pre2/arch/i386/kernel/traps.c	Tue Jan 29 18:24:01 2002
+++ linux/arch/i386/kernel/traps.c	Thu Feb  7 16:09:54 2002
@@ -158,7 +158,7 @@
 	unsigned long esp = tsk->thread.esp;
 
 	/* User space on another CPU? */
-	if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1))
+	if ((esp ^ (unsigned long)tsk->thread_info) & (PAGE_MASK<<1))
 		return;
 	show_trace((unsigned long *)esp);
 }
@@ -208,8 +208,8 @@
 		regs->esi, regs->edi, regs->ebp, esp);
 	printk("ds: %04x   es: %04x   ss: %04x\n",
 		regs->xds & 0xffff, regs->xes & 0xffff, ss);
-	printk("Process %s (pid: %d, stackpage=%08lx)",
-		current->comm, current->pid, 4096+(unsigned long)current);
+	printk("Process %s (pid: %d, threadinfo=%p task=%p)",
+		current->comm, current->pid, current_thread_info(), current);
 	/*
 	 * When in-kernel, we also print out the stack and code at the
 	 * time of the fault..
@@ -720,7 +720,7 @@
 	} else {
 		init_fpu();
 	}
-	current->flags |= PF_USEDFPU;	/* So we fnsave on switch_to() */
+	set_thread_flag(TIF_USEDFPU);	/* So we fnsave on switch_to() */
 }
 
 #ifndef CONFIG_MATH_EMULATION
diff -urN linux-2.5.4-pre2/arch/i386/lib/getuser.S linux/arch/i386/lib/getuser.S
--- linux-2.5.4-pre2/arch/i386/lib/getuser.S	Mon Jan 12 13:42:52 1998
+++ linux/arch/i386/lib/getuser.S	Thu Feb  7 16:09:54 2002
@@ -8,6 +8,8 @@
  * return an error value in addition to the "real"
  * return value.
  */
+#include <asm/thread_info.h>
+
 
 /*
  * __get_user_X
@@ -21,15 +23,12 @@
  * as they get called from within inline assembly.
  */
 
-addr_limit = 12
-
 .text
 .align 4
 .globl __get_user_1
 __get_user_1:
-	movl %esp,%edx
-	andl $0xffffe000,%edx
-	cmpl addr_limit(%edx),%eax
+	GET_THREAD_INFO(%edx)
+	cmpl TI_ADDR_LIMIT(%edx),%eax
 	jae bad_get_user
 1:	movzbl (%eax),%edx
 	xorl %eax,%eax
@@ -39,10 +38,9 @@
 .globl __get_user_2
 __get_user_2:
 	addl $1,%eax
-	movl %esp,%edx
 	jc bad_get_user
-	andl $0xffffe000,%edx
-	cmpl addr_limit(%edx),%eax
+	GET_THREAD_INFO(%edx)
+	cmpl TI_ADDR_LIMIT(%edx),%eax
 	jae bad_get_user
 2:	movzwl -1(%eax),%edx
 	xorl %eax,%eax
@@ -52,10 +50,9 @@
 .globl __get_user_4
 __get_user_4:
 	addl $3,%eax
-	movl %esp,%edx
 	jc bad_get_user
-	andl $0xffffe000,%edx
-	cmpl addr_limit(%edx),%eax
+	GET_THREAD_INFO(%edx)
+	cmpl TI_ADDR_LIMIT(%edx),%eax
 	jae bad_get_user
 3:	movl -3(%eax),%edx
 	xorl %eax,%eax
diff -urN linux-2.5.4-pre2/arch/ia64/kernel/entry.S linux/arch/ia64/kernel/entry.S
--- linux-2.5.4-pre2/arch/ia64/kernel/entry.S	Thu Feb  7 16:09:51 2002
+++ linux/arch/ia64/kernel/entry.S	Thu Feb  7 16:09:54 2002
@@ -1133,7 +1133,6 @@
 	data8 sys_tkill
 	data8 ia64_ni_syscall
 	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
 	data8 ia64_ni_syscall			// 1220
 	data8 ia64_ni_syscall
 	data8 ia64_ni_syscall
diff -urN linux-2.5.4-pre2/drivers/block/DAC960.h linux/drivers/block/DAC960.h
--- linux-2.5.4-pre2/drivers/block/DAC960.h	Thu Jan  3 13:51:36 2002
+++ linux/drivers/block/DAC960.h	Thu Feb  7 16:09:55 2002
@@ -2573,39 +2573,7 @@
   spin_unlock_irqrestore(&Controller->RequestQueue->queue_lock, *ProcessorFlags);
 }
 
-
-/*
-  Virtual_to_Bus32 maps from Kernel Virtual Addresses to 32 Bit PCI Bus
-  Addresses.
-*/
-
-static inline DAC960_BusAddress32_T Virtual_to_Bus32(void *VirtualAddress)
-{
-  return (DAC960_BusAddress32_T) virt_to_bus(VirtualAddress);
-}
-
-
-/*
-  Bus32_to_Virtual maps from 32 Bit PCI Bus Addresses to Kernel Virtual
-  Addresses.
-*/
-
-static inline void *Bus32_to_Virtual(DAC960_BusAddress32_T BusAddress)
-{
-  return (void *) bus_to_virt(BusAddress);
-}
-
-
-/*
-  Virtual_to_Bus64 maps from Kernel Virtual Addresses to 64 Bit PCI Bus
-  Addresses.
-*/
-
-static inline DAC960_BusAddress64_T Virtual_to_Bus64(void *VirtualAddress)
-{
-  return (DAC960_BusAddress64_T) virt_to_bus(VirtualAddress);
-}
-
+#error I am a non-portable driver, please convert me to use the Documentation/DMA-mapping.txt interfaces
 
 /*
   Define the DAC960 BA Series Controller Interface Register Offsets.
diff -urN linux-2.5.4-pre2/drivers/block/blkpg.c linux/drivers/block/blkpg.c
--- linux-2.5.4-pre2/drivers/block/blkpg.c	Tue Jan  1 11:28:30 2002
+++ linux/drivers/block/blkpg.c	Thu Feb  7 16:09:55 2002
@@ -280,7 +280,8 @@
 
 			if (cmd == BLKGETSIZE)
 				return put_user((unsigned long)ullval, (unsigned long *)arg);
-			return put_user(ullval, (u64 *)arg);
+			else
+				return put_user((u64)ullval << 9 , (u64 *)arg);
 #if 0
 		case BLKRRPART: /* Re-read partition tables */
 			if (!capable(CAP_SYS_ADMIN)) 
diff -urN linux-2.5.4-pre2/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- linux-2.5.4-pre2/drivers/block/ps2esdi.c	Mon Jan 21 16:03:19 2002
+++ linux/drivers/block/ps2esdi.c	Thu Feb  7 16:09:55 2002
@@ -475,7 +475,7 @@
 	   list + sanity checks.                     */
 	INIT_REQUEST;
 
-	if (virt_to_bus(CURRENT->buffer + CURRENT->current_nr_sectors * 512) > 16 * MB) {
+	if (isa_virt_to_bus(CURRENT->buffer + CURRENT->current_nr_sectors * 512) > 16 * MB) {
 		printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
 		end_request(FAIL);
 	}			/* check for above 16Mb dmas */
@@ -663,7 +663,7 @@
 
 	mca_disable_dma(dma_arb_level);
 
-	mca_set_dma_addr(dma_arb_level, virt_to_bus(buffer));
+	mca_set_dma_addr(dma_arb_level, isa_virt_to_bus(buffer));
 
 	mca_set_dma_count(dma_arb_level, length * 512 / 2);
 
diff -urN linux-2.5.4-pre2/drivers/block/smart1,2.h linux/drivers/block/smart1,2.h
--- linux-2.5.4-pre2/drivers/block/smart1,2.h	Tue May  1 16:05:00 2001
+++ linux/drivers/block/smart1,2.h	Thu Feb  7 16:09:55 2002
@@ -252,6 +252,7 @@
 
 		outb(CHANNEL_CLEAR, h->ioaddr + SMART1_LOCAL_DOORBELL);
 
+#error Please convert me to Documentation/DMA-mapping.txt
 		if (cmd) ((cmdlist_t*)bus_to_virt(cmd))->req.hdr.rcode = status;
 	} else {
 		cmd = 0;
diff -urN linux-2.5.4-pre2/drivers/bluetooth/hci_vhci.c linux/drivers/bluetooth/hci_vhci.c
--- linux-2.5.4-pre2/drivers/bluetooth/hci_vhci.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/bluetooth/hci_vhci.c	Thu Feb  7 16:09:55 2002
@@ -291,7 +291,7 @@
 
 static struct file_operations hci_vhci_fops = {
 	owner:	THIS_MODULE,	
-	llseek:	no_lseek,
+	llseek:	no_llseek,
 	read:	hci_vhci_chr_read,
 	write:	hci_vhci_chr_write,
 	poll:	hci_vhci_chr_poll,
diff -urN linux-2.5.4-pre2/drivers/char/esp.c linux/drivers/char/esp.c
--- linux-2.5.4-pre2/drivers/char/esp.c	Fri Jan  4 21:19:50 2002
+++ linux/drivers/char/esp.c	Thu Feb  7 16:09:55 2002
@@ -392,7 +392,7 @@
         disable_dma(dma);
         clear_dma_ff(dma);
         set_dma_mode(dma, DMA_MODE_READ);
-        set_dma_addr(dma, virt_to_bus(dma_buffer));
+        set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
         set_dma_count(dma, dma_bytes);
         enable_dma(dma);
         release_dma_lock(flags);
@@ -569,7 +569,7 @@
         disable_dma(dma);
         clear_dma_ff(dma);
         set_dma_mode(dma, DMA_MODE_WRITE);
-        set_dma_addr(dma, virt_to_bus(dma_buffer));
+        set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
         set_dma_count(dma, dma_bytes);
         enable_dma(dma);
         release_dma_lock(flags);
@@ -599,7 +599,7 @@
         	disable_dma(dma);
         	clear_dma_ff(dma);
         	set_dma_mode(dma, DMA_MODE_WRITE);
-        	set_dma_addr(dma, virt_to_bus(dma_buffer));
+        	set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
         	set_dma_count(dma, dma_bytes);
         	enable_dma(dma);
         	release_dma_lock(flags);
diff -urN linux-2.5.4-pre2/drivers/char/synclink.c linux/drivers/char/synclink.c
--- linux-2.5.4-pre2/drivers/char/synclink.c	Fri Jan  4 21:19:54 2002
+++ linux/drivers/char/synclink.c	Thu Feb  7 16:09:55 2002
@@ -60,6 +60,8 @@
 #  define BREAKPOINT() { }
 #endif
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #define MAX_ISA_DEVICES 10
 #define MAX_PCI_DEVICES 10
 #define MAX_TOTAL_DEVICES 20
diff -urN linux-2.5.4-pre2/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- linux-2.5.4-pre2/drivers/char/tpqic02.c	Fri Jan  4 21:19:54 2002
+++ linux/drivers/char/tpqic02.c	Thu Feb  7 16:09:55 2002
@@ -1408,7 +1408,7 @@
 	clear_dma_ff(QIC02_TAPE_DMA);
 	set_dma_mode(QIC02_TAPE_DMA, dma_mode);
 	set_dma_addr(QIC02_TAPE_DMA,
-		     virt_to_bus(buffaddr) + dma_bytes_done);
+		     isa_virt_to_bus(buffaddr) + dma_bytes_done);
 	set_dma_count(QIC02_TAPE_DMA, TAPE_BLKSIZE);
 
 	/* start tape DMA controller */
diff -urN linux-2.5.4-pre2/drivers/hotplug/pci_hotplug_core.c linux/drivers/hotplug/pci_hotplug_core.c
--- linux-2.5.4-pre2/drivers/hotplug/pci_hotplug_core.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/hotplug/pci_hotplug_core.c	Thu Feb  7 16:09:55 2002
@@ -414,7 +414,7 @@
 	}
 
 	spin_unlock (&mount_lock);
-	mnt = kern_mount (&pcihpfs_fs_type);
+	mnt = kern_mount (&pcihpfs_type);
 	if (IS_ERR(mnt)) {
 		err ("could not mount the fs...erroring out!\n");
 		return -ENODEV;
@@ -1114,7 +1114,7 @@
 	spin_lock_init(&list_lock);
 
 	dbg("registering filesystem.\n");
-	result = register_filesystem(&pcihpfs_fs_type);
+	result = register_filesystem(&pcihpfs_type);
 	if (result) {
 		err("register_filesystem failed with %d\n", result);
 		goto exit;
@@ -1128,7 +1128,7 @@
 
 static void __exit pci_hotplug_exit (void)
 {
-	unregister_filesystem(&pcihpfs_fs_type);
+	unregister_filesystem(&pcihpfs_type);
 }
 
 module_init(pci_hotplug_init);
diff -urN linux-2.5.4-pre2/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- linux-2.5.4-pre2/drivers/ide/ide-disk.c	Thu Jan 17 13:58:35 2002
+++ linux/drivers/ide/ide-disk.c	Thu Feb  7 16:09:55 2002
@@ -192,11 +192,6 @@
 	sectors = rq->nr_sectors;
 	if (sectors == 256)
 		sectors = 0;
-	if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
-		sectors = drive->mult_count;
-		if (sectors > rq->current_nr_sectors)
-			sectors = rq->current_nr_sectors;
-	}
 
 	taskfile.sector_count	= sectors;
 	taskfile.sector_number	= sect;
@@ -241,11 +236,6 @@
 	sectors = rq->nr_sectors;
 	if (sectors == 256)
 		sectors = 0;
-	if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
-		sectors = drive->mult_count;
-		if (sectors > rq->current_nr_sectors)
-			sectors = rq->current_nr_sectors;
-	}
 
 	memset(&taskfile, 0, sizeof(task_struct_t));
 	memset(&hobfile, 0, sizeof(hob_struct_t));
@@ -300,13 +290,8 @@
 	memset(&hobfile, 0, sizeof(hob_struct_t));
 
 	sectors = rq->nr_sectors;
-	if (sectors == 256)
+	if (sectors == 65536)
 		sectors = 0;
-	if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
-		sectors = drive->mult_count;
-		if (sectors > rq->current_nr_sectors)
-			sectors = rq->current_nr_sectors;
-	}
 
 	taskfile.sector_count	= sectors;
 	hobfile.sector_count	= sectors >> 8;
diff -urN linux-2.5.4-pre2/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c
--- linux-2.5.4-pre2/drivers/ide/ide-taskfile.c	Thu Jan 17 13:58:35 2002
+++ linux/drivers/ide/ide-taskfile.c	Thu Feb  7 16:09:55 2002
@@ -255,6 +255,7 @@
 	return 1;		/* drive ready: *might* be interrupting */
 }
 
+ide_startstop_t bio_mulout_intr (ide_drive_t *drive);
 ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
 {
 	task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
@@ -263,7 +264,7 @@
 	byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
 
 	/* (ks/hs): Moved to start, do not use for multiple out commands */
-	if (task->handler != task_mulout_intr) {
+	if (task->handler != task_mulout_intr && task->handler != bio_mulout_intr) {
 		if (IDE_CONTROL_REG)
 			OUT_BYTE(drive->ctl, IDE_CONTROL_REG);	/* clear nIEN */
 		SELECT_MASK(HWIF(drive), drive, 0);
@@ -313,7 +314,7 @@
 	byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
 
 	/* (ks/hs): Moved to start, do not use for multiple out commands */
-	if (*handler != task_mulout_intr) {
+	if (*handler != task_mulout_intr && handler != bio_mulout_intr) {
 		if (IDE_CONTROL_REG)
 			OUT_BYTE(drive->ctl, IDE_CONTROL_REG);  /* clear nIEN */
 		SELECT_MASK(HWIF(drive), drive, 0);
@@ -936,15 +937,12 @@
 	char *pBuf		= NULL;
 	unsigned long flags;
 
-	if (!rq->current_nr_sectors) { 
-		printk("task_out_intr: should not trigger\n");
-		ide_end_request(1, HWGROUP(drive));
-		return ide_stopped;
-	}
-
-	if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) {
+	if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat))
 		return ide_error(drive, "task_out_intr", stat);
-	}
+
+	if (!rq->current_nr_sectors)
+		if (!ide_end_request(1, HWGROUP(drive)))
+			return ide_stopped;
 
 	if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) {
 		rq = HWGROUP(drive)->rq;
@@ -958,16 +956,8 @@
 		rq->current_nr_sectors--;
 	}
 
-	if (rq->current_nr_sectors <= 0) {
-		if (ide_end_request(1, HWGROUP(drive))) {
-			ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL);
-			return ide_started;
-		}
-	} else {
-		ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL);
-		return ide_started;
-	}
-	return ide_stopped;
+	ide_set_handler(drive, task_out_intr, WAIT_CMD, NULL);
+	return ide_started;
 }
 
 /*
@@ -1061,14 +1051,132 @@
 	return ide_started;
 }
 
+ide_startstop_t pre_bio_out_intr (ide_drive_t *drive, struct request *rq)
+{
+	ide_task_t *args = rq->special;
+	ide_startstop_t startstop;
+
+	/*
+	 * assign private copy for multi-write
+	 */
+	memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request));
+
+	if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ))
+		return startstop;
+
+	/*
+	 * (ks/hs): Stuff the first sector(s)
+	 * by implicitly calling the handler
+	 */
+	if (!(drive_is_ready(drive))) {
+		int i;
+		/*
+		 * (ks/hs): FIXME: Replace hard-coded
+		 *               100, error handling?
+		 */
+		for (i=0; i<100; i++) {
+			if (drive_is_ready(drive))
+				break;
+		}
+	}
+
+	return args->handler(drive);
+}
+
+
+ide_startstop_t bio_mulout_intr (ide_drive_t *drive)
+{
+#ifdef ALTSTAT_SCREW_UP
+	byte stat	= altstat_multi_busy(drive, GET_ALTSTAT(), "write");
+#else
+	byte stat		= GET_STAT();
+#endif /* ALTSTAT_SCREW_UP */
+
+	byte io_32bit		= drive->io_32bit;
+	struct request *rq	= &HWGROUP(drive)->wrq;
+	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
+	int mcount		= drive->mult_count;
+	ide_startstop_t startstop;
+
+	/*
+	 * (ks/hs): Handle last IRQ on multi-sector transfer,
+	 * occurs after all data was sent in this chunk
+	 */
+	if (!rq->nr_sectors) {
+		if (stat & (ERR_STAT|DRQ_STAT)) {
+			startstop = ide_error(drive, "bio_mulout_intr", stat);
+			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
+			return startstop;
+		}
+
+		__ide_end_request(HWGROUP(drive), 1, rq->hard_nr_sectors);
+		HWGROUP(drive)->wrq.bio = NULL;
+		return ide_stopped;
+	}
+
+	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
+		if (stat & (ERR_STAT | DRQ_STAT)) {
+			startstop = ide_error(drive, "bio_mulout_intr", stat);
+			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
+			return startstop;
+		}
+
+		/* no data yet, so wait for another interrupt */
+		if (hwgroup->handler == NULL)
+			ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
+
+		return ide_started;
+	}
+
+	do {
+  		char *buffer;
+  		int nsect = rq->current_nr_sectors;
+		unsigned long flags;
+
+		if (nsect > mcount)
+			nsect = mcount;
+		mcount -= nsect;
+
+		buffer = ide_map_buffer(rq, &flags);
+		rq->sector += nsect;
+		rq->nr_sectors -= nsect;
+		rq->current_nr_sectors -= nsect;
+
+		/* Do we move to the next bio after this? */
+		if (!rq->current_nr_sectors) {
+			/* remember to fix this up /jens */
+			struct bio *bio = rq->bio->bi_next;
+
+			/* end early early we ran out of requests */
+			if (!bio) {
+				mcount = 0;
+			} else {
+				rq->bio = bio;
+				rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
+			}
+		}
+
+		/*
+		 * Ok, we're all setup for the interrupt
+		 * re-entering us on the last transfer.
+		 */
+		taskfile_output_data(drive, buffer, nsect * SECTOR_WORDS);
+		ide_unmap_buffer(buffer, &flags);
+	} while (mcount);
+
+	drive->io_32bit = io_32bit;
+	rq->errors = 0;
+	if (hwgroup->handler == NULL)
+		ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
+
+	return ide_started;
+}
+
 /* Called by internal to feature out type of command being called */
 ide_pre_handler_t * ide_pre_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile)
 {
 	switch(taskfile->command) {
 				/* IDE_DRIVE_TASK_RAW_WRITE */
-		case CFA_WRITE_MULTI_WO_ERASE:
-		case WIN_MULTWRITE:
-		case WIN_MULTWRITE_EXT:
 				/* IDE_DRIVE_TASK_OUT */
 		case WIN_WRITE:
 		case WIN_WRITE_EXT:
@@ -1077,7 +1185,10 @@
 		case CFA_WRITE_SECT_WO_ERASE:
 		case WIN_DOWNLOAD_MICROCODE:
 			return &pre_task_out_intr;
-				/* IDE_DRIVE_TASK_OUT */
+		case CFA_WRITE_MULTI_WO_ERASE:
+		case WIN_MULTWRITE:
+		case WIN_MULTWRITE_EXT:
+			return &pre_bio_out_intr;
 		case WIN_SMART:
 			if (taskfile->feature == SMART_WRITE_LOG_SECTOR)
 				return &pre_task_out_intr;
@@ -1120,7 +1231,7 @@
 		case CFA_WRITE_MULTI_WO_ERASE:
 		case WIN_MULTWRITE:
 		case WIN_MULTWRITE_EXT:
-			return &task_mulout_intr;
+			return &bio_mulout_intr;
 		case WIN_SMART:
 			switch(taskfile->feature) {
 				case SMART_READ_VALUES:
diff -urN linux-2.5.4-pre2/drivers/input/evdev.c linux/drivers/input/evdev.c
--- linux-2.5.4-pre2/drivers/input/evdev.c	Wed Jan 23 15:28:39 2002
+++ linux/drivers/input/evdev.c	Thu Feb  7 16:09:55 2002
@@ -1,11 +1,9 @@
 /*
- * $Id: evdev.c,v 1.27 2001/05/28 09:06:44 vojtech Exp $
+ * $Id: evdev.c,v 1.42 2002/01/02 11:59:56 vojtech Exp $
  *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Event char devices, giving access to raw input device events.
- *
- *  Sponsored by SuSE
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #define EVDEV_MINOR_BASE	64
@@ -42,7 +40,9 @@
 struct evdev {
 	int exist;
 	int open;
+	int open_for_write;
 	int minor;
+	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
 	devfs_handle_t devfs;
@@ -89,6 +89,11 @@
 	return retval < 0 ? retval : 0;
 }
 
+static int evdev_flush(struct file * file)
+{
+	return input_flush_device(&((struct evdev_list*)file->private_data)->evdev->handle, file);
+}
+
 static int evdev_release(struct inode * inode, struct file * file)
 {
 	struct evdev_list *list = file->private_data;
@@ -120,10 +125,16 @@
 {
 	struct evdev_list *list;
 	int i = minor(inode->i_rdev) - EVDEV_MINOR_BASE;
+	int accept_err;
 
 	if (i >= EVDEV_MINORS || !evdev_table[i])
 		return -ENODEV;
 
+	/* Ask the driver if he wishes to accept the open() */
+	if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file))) {
+		return accept_err;
+	}
+
 	if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
 		return -ENOMEM;
 	memset(list, 0, sizeof(struct evdev_list));
@@ -167,7 +178,7 @@
 	if (list->head == list->tail) {
 
 		add_wait_queue(&list->evdev->wait, &wait);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 
 		while (list->head == list->tail) {
 
@@ -187,7 +198,7 @@
 			schedule();
 		}
 
-		current->state = TASK_RUNNING;
+		set_current_state(TASK_RUNNING);
 		remove_wait_queue(&list->evdev->wait, &wait);
 	}
 
@@ -219,7 +230,7 @@
 	struct evdev_list *list = file->private_data;
 	struct evdev *evdev = list->evdev;
 	struct input_dev *dev = evdev->handle.dev;
-	int retval;
+	int retval, t, u;
 
 	switch (cmd) {
 
@@ -232,6 +243,40 @@
 			if ((retval = put_user(dev->idproduct, ((short *) arg) + 2))) return retval;
 			if ((retval = put_user(dev->idversion, ((short *) arg) + 3))) return retval;
 			return 0;
+		
+		case EVIOCGREP:
+			if ((retval = put_user(dev->rep[0], ((int *) arg) + 0))) return retval;
+			if ((retval = put_user(dev->rep[1], ((int *) arg) + 1))) return retval;
+			return 0;
+
+		case EVIOCSREP:
+			if ((retval = get_user(dev->rep[0], ((int *) arg) + 0))) return retval;
+			if ((retval = get_user(dev->rep[1], ((int *) arg) + 1))) return retval;
+			return 0;
+
+		case EVIOCGKEYCODE:
+			if ((retval = get_user(t, ((int *) arg) + 0))) return retval;
+			if (t < 0 || t > dev->keycodemax) return -EINVAL;
+			switch (dev->keycodesize) {
+				case 1: u = *(u8*)(dev->keycode + t); break;
+				case 2: u = *(u16*)(dev->keycode + t * 2); break;
+				case 4: u = *(u32*)(dev->keycode + t * 4); break;
+				default: return -EINVAL;
+			}
+			if ((retval = put_user(u, ((int *) arg) + 1))) return retval;
+			return 0;
+
+		case EVIOCSKEYCODE:
+			if ((retval = get_user(t, ((int *) arg) + 0))) return retval;
+			if (t < 0 || t > dev->keycodemax) return -EINVAL;
+			if ((retval = get_user(u, ((int *) arg) + 1))) return retval;
+			switch (dev->keycodesize) {
+				case 1: *(u8*)(dev->keycode + t) = u; break;
+				case 2: *(u16*)(dev->keycode + t * 2) = u; break;
+				case 4: *(u32*)(dev->keycode + t * 4) = u; break;
+				default: return -EINVAL;
+			}
+			return 0;
 
 		case EVIOCSFF:
 			if (dev->upload_effect) {
@@ -280,22 +325,55 @@
 					default: return -EINVAL;
 				}
 				len = NBITS(len) * sizeof(long);
-				if (len > _IOC_SIZE(cmd)) {
-					printk(KERN_WARNING "evdev.c: Truncating bitfield length from %d to %d\n",
-						len, _IOC_SIZE(cmd));
-					len = _IOC_SIZE(cmd);
-				}
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
 				return copy_to_user((char *) arg, bits, len) ? -EFAULT : len;
 			}
 
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
+				int len;
+				len = NBITS(KEY_MAX) * sizeof(long);
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+				return copy_to_user((char *) arg, dev->key, len) ? -EFAULT : len;
+			}
+
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
+				int len;
+				len = NBITS(LED_MAX) * sizeof(long);
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+				return copy_to_user((char *) arg, dev->led, len) ? -EFAULT : len;
+			}
+
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
+				int len;
+				len = NBITS(SND_MAX) * sizeof(long);
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+				return copy_to_user((char *) arg, dev->snd, len) ? -EFAULT : len;
+			}
+
 			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
 				int len;
-				if (!dev->name) return 0;
+				if (!dev->name) return -ENOENT;
 				len = strlen(dev->name) + 1;
 				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
 				return copy_to_user((char *) arg, dev->name, len) ? -EFAULT : len;
 			}
 
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
+				int len;
+				if (!dev->phys) return -ENOENT;
+				len = strlen(dev->phys) + 1;
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+				return copy_to_user((char *) arg, dev->phys, len) ? -EFAULT : len;
+			}
+
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
+				int len;
+				if (!dev->uniq) return -ENOENT;
+				len = strlen(dev->uniq) + 1;
+				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+				return copy_to_user((char *) arg, dev->uniq, len) ? -EFAULT : len;
+			}
+
 			if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
 
 				int t = _IOC_NR(cmd) & ABS_MAX;
@@ -321,9 +399,10 @@
 	release:	evdev_release,
 	ioctl:		evdev_ioctl,
 	fasync:		evdev_fasync,
+	flush:		evdev_flush
 };
 
-static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct evdev *evdev;
 	int minor;
@@ -342,16 +421,17 @@
 
 	evdev->minor = minor;
 	evdev_table[minor] = evdev;
+	
+	sprintf(evdev->name, "event%d", minor);
 
 	evdev->handle.dev = dev;
+	evdev->handle.name = evdev->name;
 	evdev->handle.handler = handler;
 	evdev->handle.private = evdev;
 
-	evdev->exist = 1;
-
 	evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
 
-//	printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev->number);
+	evdev->exist = 1;
 
 	return &evdev->handle;
 }
@@ -372,12 +452,21 @@
 	}
 }
 
+static struct input_device_id evdev_ids[] = {
+	{ driver_info: 1 },	/* Matches all devices */
+	{ },			/* Terminating zero entry */
+};
+
+MODULE_DEVICE_TABLE(input, evdev_ids);
+
 static struct input_handler evdev_handler = {
 	event:		evdev_event,
 	connect:	evdev_connect,
 	disconnect:	evdev_disconnect,
 	fops:		&evdev_fops,
 	minor:		EVDEV_MINOR_BASE,
+	name:		"evdev",
+	id_table:	evdev_ids,
 };
 
 static int __init evdev_init(void)
@@ -394,7 +483,6 @@
 module_init(evdev_init);
 module_exit(evdev_exit);
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Event character device driver");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input driver event char devices");
 MODULE_LICENSE("GPL");
-
diff -urN linux-2.5.4-pre2/drivers/input/input.c linux/drivers/input/input.c
--- linux-2.5.4-pre2/drivers/input/input.c	Thu Jan  3 12:20:10 2002
+++ linux/drivers/input/input.c	Thu Feb  7 16:09:55 2002
@@ -1,11 +1,9 @@
 /*
- * $Id: input.c,v 1.20 2001/05/17 15:50:27 vojtech Exp $
+ * $Id: input.c,v 1.48 2001/12/26 21:08:33 jsimmons Exp $
  *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
- *  The input layer module itself
- *
- *  Sponsored by SuSE
+ *  The input core
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  * 
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #include <linux/init.h>
@@ -34,12 +32,16 @@
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/random.h>
+#include <linux/pm.h>
+#include <linux/proc_fs.h>
+#include <linux/kmod.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Input layer module");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input core");
 MODULE_LICENSE("GPL");
 
-
 EXPORT_SYMBOL(input_register_device);
 EXPORT_SYMBOL(input_unregister_device);
 EXPORT_SYMBOL(input_register_handler);
@@ -48,6 +50,8 @@
 EXPORT_SYMBOL(input_unregister_minor);
 EXPORT_SYMBOL(input_open_device);
 EXPORT_SYMBOL(input_close_device);
+EXPORT_SYMBOL(input_accept_process);
+EXPORT_SYMBOL(input_flush_device);
 EXPORT_SYMBOL(input_event);
 
 #define INPUT_MAJOR	13
@@ -60,17 +64,31 @@
 static int input_number;
 static long input_devices[NBITS(INPUT_DEVICES)];
 
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_bus_input_dir;
+DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
+static int input_devices_state;
+#endif
+
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
 	struct input_handle *handle = dev->handle;
 
 /*
+ * Wake up the device if it is sleeping.
+ */
+	if (dev->pm_dev)
+		pm_access(dev->pm_dev);
+
+/*
  * Filter non-events, and bad input values out.
  */
 
 	if (type > EV_MAX || !test_bit(type, dev->evbit))
 		return;
 
+	add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value);
+
 	switch (type) {
 
 		case EV_KEY:
@@ -130,6 +148,8 @@
 
 			if (code > MSC_MAX || !test_bit(code, dev->mscbit))
 				return;
+
+			if (dev->event) dev->event(dev, type, code, value);	
 	
 			break;
 
@@ -185,16 +205,36 @@
 	mod_timer(&dev->timer, jiffies + dev->rep[REP_PERIOD]);
 }
 
+int input_accept_process(struct input_handle *handle, struct file *file)
+{
+	if (handle->dev->accept)
+		return handle->dev->accept(handle->dev, file);
+
+	return 0;
+}
+
 int input_open_device(struct input_handle *handle)
 {
+	if (handle->dev->pm_dev)
+		pm_access(handle->dev->pm_dev);
 	handle->open++;
 	if (handle->dev->open)
 		return handle->dev->open(handle->dev);
 	return 0;
 }
 
+int input_flush_device(struct input_handle* handle, struct file* file)
+{
+	if (handle->dev->flush)
+		return handle->dev->flush(handle->dev, file);
+
+	return 0;
+}
+
 void input_close_device(struct input_handle *handle)
 {
+	if (handle->dev->pm_dev)
+		pm_dev_idle(handle->dev->pm_dev);
 	if (handle->dev->close)
 		handle->dev->close(handle->dev);
 	handle->open--;
@@ -208,25 +248,197 @@
 	handle->handler->handle = handle;
 }
 
+/**
+ *     input_find_and_remove - Find and remove node
+ *
+ *     @type:          data type
+ *     @initval:       initial value
+ *     @targ:          node to find
+ *     @next:          next node in the list
+ *
+ *     Searches the linked list for the target node @targ. If the node
+ *     is found, it is removed from the list.
+ *
+ *     If the node is not found, the end of the list will be hit,
+ *     indicating that it wasn't in the list to begin with.
+ *
+ *     Returns nothing.
+ */
+#define input_find_and_remove(type, initval, targ, next)		\
+	do {								\
+		type **ptr;						\
+		for (ptr = &initval; *ptr; ptr = &((*ptr)->next))	\
+			if (*ptr == targ) break;			\
+		if (*ptr) *ptr = (*ptr)->next;				\
+	} while (0)
+
 static void input_unlink_handle(struct input_handle *handle)
 {
-	struct input_handle **handleptr;
+	input_find_and_remove(struct input_handle, handle->dev->handle, handle, dnext);
+        input_find_and_remove(struct input_handle, handle->handler->handle, handle, hnext);
+}
+
+#define MATCH_BIT(bit, max) \
+		for (i = 0; i < NBITS(max); i++) \
+			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
+				break; \
+		if (i != NBITS(max)) \
+			continue;
+
+static struct input_device_id *input_match_device(struct input_device_id *id, struct input_dev *dev)
+{
+	int i;
+
+	for (; id->flags || id->driver_info; id++) {
+
+		if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
+			if (id->idbus != dev->idbus)
+				continue;
 
-	handleptr = &handle->dev->handle;
-	while (*handleptr && (*handleptr != handle))
-		handleptr = &((*handleptr)->dnext);
-	*handleptr = (*handleptr)->dnext;
-
-	handleptr = &handle->handler->handle;
-	while (*handleptr && (*handleptr != handle))
-		handleptr = &((*handleptr)->hnext);
-	*handleptr = (*handleptr)->hnext;
+		if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
+			if (id->idvendor != dev->idvendor)
+				continue;
+	
+		if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
+			if (id->idproduct != dev->idproduct)
+				continue;
+		
+		if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
+			if (id->idversion != dev->idversion)
+				continue;
+
+		MATCH_BIT(evbit,  EV_MAX);
+		MATCH_BIT(keybit, KEY_MAX);
+		MATCH_BIT(relbit, REL_MAX);
+		MATCH_BIT(absbit, ABS_MAX);
+		MATCH_BIT(mscbit, MSC_MAX);
+		MATCH_BIT(ledbit, LED_MAX);
+		MATCH_BIT(sndbit, SND_MAX);
+		MATCH_BIT(ffbit,  FF_MAX);
+
+		return id;
+	}
+
+	return NULL;
 }
 
+/*
+ * Input hotplugging interface - loading event handlers based on
+ * device bitfields.
+ */
+
+#ifdef CONFIG_HOTPLUG
+
+/*
+ * Input hotplugging invokes what /proc/sys/kernel/hotplug says
+ * (normally /sbin/hotplug) when input devices get added or removed.
+ *
+ * This invokes a user mode policy agent, typically helping to load driver
+ * or other modules, configure the device, and more.  Drivers can provide
+ * a MODULE_DEVICE_TABLE to help with module loading subtasks.
+ *
+ */
+
+#define SPRINTF_BIT_A(bit, name, max) \
+	do { \
+		envp[i++] = scratch; \
+		scratch += sprintf(scratch, name); \
+		for (j = NBITS(max) - 1; j >= 0; j--) \
+			if (dev->bit[j]) break; \
+		for (; j >= 0; j--) \
+			scratch += sprintf(scratch, "%lx ", dev->bit[j]); \
+		scratch++; \
+	} while (0)
+
+#define SPRINTF_BIT_A2(bit, name, max, ev) \
+	do { \
+		if (test_bit(ev, dev->evbit)) \
+			SPRINTF_BIT_A(bit, name, max); \
+	} while (0)
+
+static void input_call_hotplug(char *verb, struct input_dev *dev)
+{
+	char *argv[3], **envp, *buf, *scratch;
+	int i = 0, j, value;
+
+	if (!hotplug_path[0]) {
+		printk(KERN_ERR "input.c: calling hotplug a hotplug agent defined\n");
+		return;
+	}
+	if (in_interrupt()) {
+		printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
+		return; 
+	}
+	if (!current->fs->root) {
+		printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
+		return; 
+	}
+	if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
+		printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
+		return;
+	}
+	if (!(buf = kmalloc(1024, GFP_KERNEL))) {
+		kfree (envp);
+		printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
+		return;
+	}
+
+	argv[0] = hotplug_path;
+	argv[1] = "input";
+	argv[2] = 0;
+
+	envp[i++] = "HOME=/";
+	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+
+	scratch = buf;
+
+	envp[i++] = scratch;
+	scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
+
+	envp[i++] = scratch;
+	scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
+		dev->idbus, dev->idvendor, dev->idproduct, dev->idversion) + 1; 
+	
+	if (dev->name) {
+		envp[i++] = scratch;
+		scratch += sprintf(scratch, "NAME=%s", dev->name) + 1; 
+	}
+
+	if (dev->phys) {
+		envp[i++] = scratch;
+		scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1; 
+	}	
+
+	SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
+	SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
+	SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL);
+	SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS);
+	SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC);
+	SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
+	SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
+	SPRINTF_BIT_A2(ffbit,  "FF=",  FF_MAX, EV_FF);
+
+	envp[i++] = 0;
+
+	printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
+		argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
+
+	value = call_usermodehelper(argv [0], argv, envp);
+
+	kfree(buf);
+	kfree(envp);
+
+	if (value != 0)
+		printk(KERN_WARNING "input.c: hotplug returned %d\n", value);
+}
+
+#endif
+
 void input_register_device(struct input_dev *dev)
 {
 	struct input_handler *handler = input_handler;
 	struct input_handle *handle;
+	struct input_device_id *id;
 
 /*
  * Initialize repeat timer to default values.
@@ -259,18 +471,45 @@
  */
 
 	while (handler) {
-		if ((handle = handler->connect(handler, dev)))
-			input_link_handle(handle);
+		if ((id = input_match_device(handler->id_table, dev)))
+			if ((handle = handler->connect(handler, dev)))
+				input_link_handle(handle);
 		handler = handler->next;
 	}
+
+/*
+ * Notify the hotplug agent.
+ */
+
+#ifdef CONFIG_HOTPLUG
+	input_call_hotplug("add", dev);
+#endif
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+	input_devices_state++;
+	wake_up(&input_devices_poll_wait);
+#endif
+
 }
 
 void input_unregister_device(struct input_dev *dev)
 {
 	struct input_handle *handle = dev->handle;
-	struct input_dev **devptr = &input_dev;
 	struct input_handle *dnext;
 
+	if (!dev) return;
+
+/*
+ * Turn off power management for the device.
+ */
+	if (dev->pm_dev)
+		pm_unregister(dev->pm_dev);
+
+
 /*
  * Kill any pending repeat timers.
  */
@@ -289,23 +528,36 @@
 	}
 
 /*
- * Remove the device.
+ * Notify the hotplug agent.
  */
 
-	while (*devptr && (*devptr != dev))
-		devptr = &((*devptr)->next);
-	*devptr = (*devptr)->next;
+#ifdef CONFIG_HOTPLUG
+	input_call_hotplug("remove", dev);
+#endif
+
+/*
+ * Remove the device.
+ */
+	input_find_and_remove(struct input_dev, input_dev, dev, next);
 
 	input_number--;
+/*
+ * Notify /proc.
+ */
 
-	if (dev->number < INPUT_DEVICES)
-		clear_bit(dev->number, input_devices);
+#ifdef CONFIG_PROC_FS
+	input_devices_state++;
+	wake_up(&input_devices_poll_wait);
+#endif
 }
 
 void input_register_handler(struct input_handler *handler)
 {
 	struct input_dev *dev = input_dev;
 	struct input_handle *handle;
+	struct input_device_id *id;
+
+	if (!handler) return;
 
 /*
  * Add minors if needed.
@@ -326,15 +578,24 @@
  */
 
 	while (dev) {
-		if ((handle = handler->connect(handler, dev)))
-			input_link_handle(handle);
+		if ((id = input_match_device(handler->id_table, dev)))
+			if ((handle = handler->connect(handler, dev, id)))
+				input_link_handle(handle);
 		dev = dev->next;
 	}
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+	input_devices_state++;
+	wake_up(&input_devices_poll_wait);
+#endif
 }
 
 void input_unregister_handler(struct input_handler *handler)
 {
-	struct input_handler **handlerptr = &input_handler;
 	struct input_handle *handle = handler->handle;
 	struct input_handle *hnext;
 
@@ -352,18 +613,23 @@
 /*
  * Remove it.
  */
-
-	while (*handlerptr && (*handlerptr != handler))
-		handlerptr = &((*handlerptr)->next);
-
-	*handlerptr = (*handlerptr)->next;
+	input_find_and_remove(struct input_handler, input_handler, handler,
+				next);
 
 /*
  * Remove minors.
  */
-
 	if (handler->fops != NULL)
 		input_table[handler->minor >> 5] = NULL;
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+	input_devices_state++;
+	wake_up(&input_devices_poll_wait);
+#endif
 }
 
 static int input_open_file(struct inode *inode, struct file *file)
@@ -415,18 +681,164 @@
 	devfs_unregister(handle);
 }
 
+/*
+ * ProcFS interface for the input drivers.
+ */
+
+#ifdef CONFIG_PROC_FS
+
+#define SPRINTF_BIT_B(bit, name, max) \
+	do { \
+		len += sprintf(buf + len, "B: %s", name); \
+		for (i = NBITS(max) - 1; i >= 0; i--) \
+			if (dev->bit[i]) break; \
+		for (; i >= 0; i--) \
+			len += sprintf(buf + len, "%lx ", dev->bit[i]); \
+		len += sprintf(buf + len, "\n"); \
+	} while (0)
+
+#define SPRINTF_BIT_B2(bit, name, max, ev) \
+	do { \
+		if (test_bit(ev, dev->evbit)) \
+			SPRINTF_BIT_B(bit, name, max); \
+	} while (0)
+
+
+static unsigned int input_devices_poll(struct file *file, poll_table *wait)
+{
+	int state = input_devices_state;
+	poll_wait(file, &input_devices_poll_wait, wait);
+	if (state != input_devices_state)
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+{
+	struct input_dev *dev = input_dev;
+	struct input_handle *handle;
+
+	off_t at = 0;
+	int i, len, cnt = 0;
+
+	while (dev) {
+
+		len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
+			dev->idbus, dev->idvendor, dev->idproduct, dev->idversion);
+
+		len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
+		len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+		len += sprintf(buf + len, "D: Drivers=");
+
+		handle = dev->handle;
+
+		while (handle) {
+			len += sprintf(buf + len, "%s ", handle->name);
+			handle = handle->dnext;
+		}
+
+		len += sprintf(buf + len, "\n");
+
+		SPRINTF_BIT_B(evbit, "EV=", EV_MAX);
+		SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY);
+		SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL);
+		SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS);
+		SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC);
+		SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
+		SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
+		SPRINTF_BIT_B2(ffbit,  "FF=",  FF_MAX, EV_FF);
+
+		len += sprintf(buf + len, "\n");
+
+		at += len;
+
+		if (at >= pos) {
+			if (!*start) {
+				*start = buf + (pos - (at - len));
+				cnt = at - pos;
+			} else  cnt += len;
+			buf += len;
+			if (cnt >= count)
+				break;
+		}
+
+		dev = dev->next;
+	}
+
+	if (!dev) *eof = 1;
+
+	return (count > cnt) ? cnt : count;
+}
+
+static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+{
+	struct input_handler *handler = input_handler;
+
+	off_t at = 0;
+	int len = 0, cnt = 0;
+	int i = 0;
+
+	while (handler) {
+
+		if (handler->fops)
+			len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",
+				i++, handler->name, handler->minor);
+		else
+			len = sprintf(buf, "N: Number=%d Name=%s\n",
+				i++, handler->name);
+
+		at += len;
+
+		if (at >= pos) {
+			if (!*start) {
+				*start = buf + (pos - (at - len));
+				cnt = at - pos;
+			} else  cnt += len;
+			buf += len;
+			if (cnt >= count)
+				break;
+		}
+
+		handler = handler->next;
+	}
+
+	if (!handler) *eof = 1;
+
+	return (count > cnt) ? cnt : count;
+}
+
+#endif
+
 static int __init input_init(void)
 {
+	struct proc_dir_entry *entry;
+
+#ifdef CONFIG_PROC_FS
+	proc_bus_input_dir = proc_mkdir("input", proc_bus);
+	proc_bus_input_dir->owner = THIS_MODULE;
+	entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);
+	entry->owner = THIS_MODULE;
+	entry->proc_fops->poll = input_devices_poll;
+	entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
+	entry->owner = THIS_MODULE;
+#endif
 	if (devfs_register_chrdev(INPUT_MAJOR, "input", &input_fops)) {
 		printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
 		return -EBUSY;
 	}
+
 	input_devfs_handle = devfs_mk_dir(NULL, "input", NULL);
+
 	return 0;
 }
 
 static void __exit input_exit(void)
 {
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("devices", proc_bus_input_dir);
+	remove_proc_entry("handlers", proc_bus_input_dir);
+	remove_proc_entry("input", proc_bus);
+#endif
 	devfs_unregister(input_devfs_handle);
         if (devfs_unregister_chrdev(INPUT_MAJOR, "input"))
                 printk(KERN_ERR "input: can't unregister char major %d", INPUT_MAJOR);
diff -urN linux-2.5.4-pre2/drivers/input/joydev.c linux/drivers/input/joydev.c
--- linux-2.5.4-pre2/drivers/input/joydev.c	Thu Jan  3 12:20:10 2002
+++ linux/drivers/input/joydev.c	Thu Feb  7 16:09:55 2002
@@ -1,12 +1,10 @@
 /*
- * $Id: joydev.c,v 1.19 2001/01/10 19:49:40 vojtech Exp $
+ * $Id: joydev.c,v 1.38 2001/12/27 10:37:41 vojtech Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik 
+ *  Copyright (c) 1999-2001 Vojtech Pavlik 
  *  Copyright (c) 1999 Colin Van Dyke 
  *
  *  Joystick device driver for the input driver suite.
- *
- *  Sponsored by SuSE and Intel
  */
 
 /*
@@ -25,8 +23,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  * 
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #include <asm/io.h>
@@ -45,14 +43,22 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Joystick device interfaces");
+MODULE_SUPPORTED_DEVICE("input/js");
+MODULE_LICENSE("GPL");
+
 #define JOYDEV_MINOR_BASE	0
 #define JOYDEV_MINORS		32
 #define JOYDEV_BUFFER_SIZE	64
 
+#define MSECS(t)	(1000 * ((t) / HZ) + 1000 * ((t) % HZ) / HZ)
+
 struct joydev {
 	int exist;
 	int open;
 	int minor;
+	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
 	devfs_handle_t devfs;
@@ -81,11 +87,6 @@
 
 static struct joydev *joydev_table[JOYDEV_MINORS];
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Joystick device driver");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("input/js");
-
 static int joydev_correct(int value, struct js_corr *corr)
 {
 	switch (corr->type) {
@@ -133,7 +134,7 @@
 			return;
 	}  
 
-	event.time = jiffies * (1000 / HZ);
+	event.time = MSECS(jiffies);
 
 	while (list) {
 
@@ -163,7 +164,7 @@
 {
 	struct joydev_list *list = file->private_data;
 	struct joydev_list **listptr;
-	
+
 	listptr = &list->joydev->list;
 	joydev_fasync(-1, file, 0);
 
@@ -249,7 +250,7 @@
 	if (list->head == list->tail && list->startup == joydev->nabs + joydev->nkey) {
 
 		add_wait_queue(&list->joydev->wait, &wait);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 
 		while (list->head == list->tail) {
 
@@ -265,7 +266,7 @@
 			schedule();
 		}
 
-		current->state = TASK_RUNNING;
+		set_current_state(TASK_RUNNING);
 		remove_wait_queue(&list->joydev->wait, &wait);
 	}
 
@@ -276,7 +277,7 @@
 
 		struct js_event event;
 
-		event.time = jiffies * (1000/HZ);
+		event.time = MSECS(jiffies);
 
 		if (list->startup < joydev->nkey) {
 			event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
@@ -360,9 +361,9 @@
 			return copy_to_user((struct js_corr *) arg, joydev->corr,
 						sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
 		case JSIOCSAXMAP:
-			if (copy_from_user((__u8 *) arg, joydev->abspam, sizeof(__u8) * ABS_MAX))
+			if (copy_from_user(joydev->abspam, (__u8 *) arg, sizeof(__u8) * ABS_MAX))
 				return -EFAULT;
-			for (i = 0; i < ABS_MAX; i++) {
+			for (i = 0; i < joydev->nabs; i++) {
 				if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
 				joydev->absmap[joydev->abspam[i]] = i;
 			}
@@ -371,11 +372,11 @@
 			return copy_to_user((__u8 *) arg, joydev->abspam,
 						sizeof(__u8) * ABS_MAX) ? -EFAULT : 0;
 		case JSIOCSBTNMAP:
-			if (copy_from_user((__u16 *) arg, joydev->absmap, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
+			if (copy_from_user(joydev->keypam, (__u16 *) arg, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
 				return -EFAULT;
-			for (i = 0; i < KEY_MAX - BTN_MISC; i++); {
+			for (i = 0; i < joydev->nkey; i++); {
 				if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
-				joydev->keymap[joydev->abspam[i - BTN_MISC]] = i;
+				joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
 			}
 			return 0;
 		case JSIOCGBTNMAP:
@@ -405,15 +406,13 @@
 	fasync:		joydev_fasync,
 };
 
-static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct joydev *joydev;
-	int i, j, minor;
+	int i, j, t, minor;
 
-	if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) &&
-	     (test_bit(ABS_X, dev->absbit) || test_bit(ABS_Y, dev->absbit)) &&
-	     (test_bit(BTN_TRIGGER, dev->keybit) || test_bit(BTN_A, dev->keybit)
-		|| test_bit(BTN_1, dev->keybit)))) return NULL; 
+        if (test_bit(BTN_TOUCH, dev->keybit))
+		return NULL;
 
 	for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
 	if (minor == JOYDEV_MINORS) {
@@ -430,12 +429,13 @@
 	joydev->minor = minor;
 	joydev_table[minor] = joydev;
 
+	sprintf(joydev->name, "js%d", minor);
+
 	joydev->handle.dev = dev;
+	joydev->handle.name = joydev->name;
 	joydev->handle.handler = handler;
 	joydev->handle.private = joydev;
 
-	joydev->exist = 1;
-
 	for (i = 0; i < ABS_MAX; i++)
 		if (test_bit(i, dev->absbit)) {
 			joydev->absmap[i] = joydev->nabs;
@@ -467,15 +467,17 @@
 		joydev->corr[i].prec = dev->absfuzz[j];
 		joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
 		joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
-		joydev->corr[i].coef[2] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
-		joydev->corr[i].coef[3] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
+		if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j])))
+			continue;
+		joydev->corr[i].coef[2] = (1 << 29) / t;
+		joydev->corr[i].coef[3] = (1 << 29) / t;
 
 		joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
 	}
 
 	joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
 
-//	printk(KERN_INFO "js%d: Joystick device for input%d\n", minor, dev->number);
+	joydev->exist = 1;
 
 	return &joydev->handle;
 }
@@ -495,12 +497,35 @@
 	}
 }
 
+static struct input_device_id joydev_ids[] = {
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+		evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+		absbit: { BIT(ABS_X) },
+	},
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+		evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+		absbit: { BIT(ABS_WHEEL) },
+	},
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+		evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+		absbit: { BIT(ABS_THROTTLE) },
+	},
+	{ }, 	/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, joydev_ids);
+
 static struct input_handler joydev_handler = {
 	event:		joydev_event,
 	connect:	joydev_connect,
 	disconnect:	joydev_disconnect,
 	fops:		&joydev_fops,
 	minor:		JOYDEV_MINOR_BASE,
+	name:		"joydev",
+	id_table:	joydev_ids,
 };
 
 static int __init joydev_init(void)
diff -urN linux-2.5.4-pre2/drivers/input/joystick/iforce.c linux/drivers/input/joystick/iforce.c
--- linux-2.5.4-pre2/drivers/input/joystick/iforce.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/input/joystick/iforce.c	Thu Feb  7 16:09:56 2002
@@ -641,7 +641,7 @@
 		effect->replay.delay,
 		effect->trigger.button,
 		effect->trigger.interval,
-		effect->u.periodic.direction);
+		effect->direction);
 
 	return err;
 }
@@ -680,7 +680,7 @@
 		effect->replay.delay,
 		effect->trigger.button,
 		effect->trigger.interval,
-		effect->u.constant.direction);
+		effect->direction);
 
 	return err;
 }
@@ -722,7 +722,7 @@
 		case 0: /* Only one axis, choose orientation */
 			mod1 = mod_chunk->start;
 			mod2 = 0xffff;
-			direction = effect->u.interactive.direction;
+			direction = effect->direction;
 			axes = 0x20;
 			break;
 
diff -urN linux-2.5.4-pre2/drivers/input/keybdev.c linux/drivers/input/keybdev.c
--- linux-2.5.4-pre2/drivers/input/keybdev.c	Thu Oct 11 09:14:32 2001
+++ linux/drivers/input/keybdev.c	Thu Feb  7 16:09:56 2002
@@ -1,11 +1,9 @@
 /*
- * $Id: keybdev.c,v 1.3 2000/05/28 17:31:36 vojtech Exp $
+ * $Id: keybdev.c,v 1.16 2002/01/09 04:21:41 lethal Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
- *  Input driver to keyboard driver binding.
- *
- *  Sponsored by SuSE
+ *  Input core to console keyboard binding.
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #include <linux/config.h>
@@ -37,10 +35,16 @@
 #include <linux/module.h>
 #include <linux/kbd_kern.h>
 
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input core to console keyboard binding");
+MODULE_LICENSE("GPL");
+
+char keybdev_name[] = "keyboard";
+
 #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || \
     defined(__mips__) || defined(CONFIG_SPARC64) || defined(CONFIG_SUPERH) || \
     defined(CONFIG_PPC) || defined(__mc68000__) || defined(__hppa__) || \
-    defined(__arm__)
+    defined(__arm__) || defined(__x86_64__)
 
 static int x86_sysrq_alt = 0;
 #ifdef CONFIG_SPARC64
@@ -48,8 +52,6 @@
 extern void batten_down_hatches(void);
 #endif
 
-static int jp_kbd_109 = 1;	/* Yes, .jp is the default. See 51142. */
-
 static unsigned short x86_keycodes[256] =
 	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
@@ -62,7 +64,7 @@
 	360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355,
 	103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361,
 	291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114,
-	118,117,125,374,379,259,260,261,262,263,264,265,266,267,268,269,
+	118,117,125,374,379,115,112,125,121,123,264,265,266,267,268,269,
 	271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307,
 	308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330,
 	332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 };
@@ -167,26 +169,38 @@
 	}
 }
 
+/* Tell the user who may be running in X and not see the console that we have 
+   panic'ed. This is to distingush panics from "real" lockups. 
+   Could in theory send the panic message as morse, but that is left as an
+   exercise for the reader.  */ 
+
+void panic_blink(void)
+{ 
+	static unsigned long last_jiffie;
+	static char led;
+	/* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is different. */
+	if (jiffies - last_jiffie > HZ/2) {
+		led ^= 0x01 | 0x04;
+		keybdev_ledfunc(led);
+		last_jiffie = jiffies;
+	}
+}  
+
 void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int down)
 {
 	if (type != EV_KEY) return;
-
-	if (emulate_raw(code, down))
-		printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", code);
-
+	emulate_raw(code, down);
 	tasklet_schedule(&keyboard_tasklet);
 }
 
-static struct input_handle *keybdev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *keybdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct input_handle *handle;
 	int i;
 
-	if (!test_bit(EV_KEY, dev->evbit))
-		return NULL;
-
-	for (i = KEY_RESERVED; i < BTN_MISC; i++)
-		if (test_bit(i, dev->keybit)) break;
+	for (i = KEY_ESC; i < BTN_MISC; i++)
+		if (test_bit(i, dev->keybit))
+			break;
 
 	if (i == BTN_MISC)
  		return NULL;
@@ -196,41 +210,42 @@
 	memset(handle, 0, sizeof(struct input_handle));
 
 	handle->dev = dev;
+	handle->name = keybdev_name;
 	handle->handler = handler;
 
 	input_open_device(handle);
 
-//	printk(KERN_INFO "keybdev.c: Adding keyboard: input%d\n", dev->number);
-
 	return handle;
 }
 
 static void keybdev_disconnect(struct input_handle *handle)
 {
-//	printk(KERN_INFO "keybdev.c: Removing keyboard: input%d\n", handle->dev->number);
 	input_close_device(handle);
 	kfree(handle);
 }
+
+static struct input_device_id keybdev_ids[] = {
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+		evbit: { BIT(EV_KEY) },
+	},	
+	{ }, 	/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, keybdev_ids);
 	
 static struct input_handler keybdev_handler = {
 	event:		keybdev_event,
 	connect:	keybdev_connect,
 	disconnect:	keybdev_disconnect,
+	name:		"keybdev",
+	id_table:	keybdev_ids,
 };
 
 static int __init keybdev_init(void)
 {
 	input_register_handler(&keybdev_handler);
 	kbd_ledfunc = keybdev_ledfunc;
-
-	if (jp_kbd_109) {
-		x86_keycodes[0xb5] = 0x73;	/* backslash, underscore */
-		x86_keycodes[0xb6] = 0x70;
-		x86_keycodes[0xb7] = 0x7d;	/* Yen, pipe */
-		x86_keycodes[0xb8] = 0x79;
-		x86_keycodes[0xb9] = 0x7b;
-	}
-
 	return 0;
 }
 
@@ -243,7 +258,3 @@
 module_init(keybdev_init);
 module_exit(keybdev_exit);
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Input driver to keyboard driver binding");
-MODULE_PARM(jp_kbd_109, "i");
-MODULE_LICENSE("GPL");
diff -urN linux-2.5.4-pre2/drivers/input/mousedev.c linux/drivers/input/mousedev.c
--- linux-2.5.4-pre2/drivers/input/mousedev.c	Thu Jan  3 12:20:10 2002
+++ linux/drivers/input/mousedev.c	Thu Feb  7 16:09:56 2002
@@ -1,11 +1,9 @@
 /*
- * $Id: mousedev.c,v 1.24 2000/11/15 10:57:45 vojtech Exp $
+ * $Id: mousedev.c,v 1.38 2001/12/26 21:08:33 jsimmons Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
- *  Input driver to ImExPS/2 device driver module.
- *
- *  Sponsored by SuSE
+ *  Input driver to ExplorerPS/2 device driver module.
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  * 
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #define MOUSEDEV_MINOR_BASE 	32
@@ -41,6 +39,10 @@
 #include <linux/smp_lock.h>
 #include <linux/random.h>
 
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces");
+MODULE_LICENSE("GPL");
+
 #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X
 #define CONFIG_INPUT_MOUSEDEV_SCREEN_X	1024
 #endif
@@ -52,6 +54,7 @@
 	int exist;
 	int open;
 	int minor;
+	char name[16];
 	wait_queue_head_t wait;
 	struct mousedev_list *list;
 	struct input_handle handle;
@@ -89,8 +92,6 @@
 	struct mousedev_list *list;
 	int index, size;
 
-	add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value);
-
 	while (*mousedev) {
 		list = (*mousedev)->list;
 		while (list) {
@@ -101,13 +102,23 @@
 					switch (code) {
 						case ABS_X:	
 							size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
-							list->dx += (value * xres - list->oldx) / size;
-							list->oldx += list->dx * size;
+							if (size != 0) {
+								list->dx += (value * xres - list->oldx) / size;
+								list->oldx += list->dx * size;
+							} else {
+								list->dx += value - list->oldx;
+								list->oldx += list->dx;
+							}
 							break;
 						case ABS_Y:
 							size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
-							list->dy -= (value * yres - list->oldy) / size;
-							list->oldy -= list->dy * size;
+							if (size != 0) {
+								list->dy -= (value * yres - list->oldy) / size;
+								list->oldy -= list->dy * size;
+							} else {
+								list->dy -= value - list->oldy;
+								list->oldy -= list->dy;
+							}
 							break;
 					}
 					break;
@@ -169,7 +180,7 @@
 {
 	struct mousedev_list *list = file->private_data;
 	struct mousedev_list **listptr;
-	
+
 	listptr = &list->mousedev->list;
 	mousedev_fasync(-1, file, 0);
 
@@ -344,7 +355,7 @@
 	if (!list->ready && !list->buffer) {
 
 		add_wait_queue(&list->mousedev->wait, &wait);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 
 		while (!list->ready) {
 
@@ -360,7 +371,7 @@
 			schedule();
 		}
 
-		current->state = TASK_RUNNING;
+		set_current_state(TASK_RUNNING);
 		remove_wait_queue(&list->mousedev->wait, &wait);
 	}
 
@@ -401,19 +412,11 @@
 	fasync:		mousedev_fasync,
 };
 
-static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct mousedev *mousedev;
 	int minor = 0;
 
-	if (!test_bit(EV_KEY, dev->evbit) ||
-	   (!test_bit(BTN_LEFT, dev->keybit) && !test_bit(BTN_TOUCH, dev->keybit)))
-		return NULL;
-
-	if ((!test_bit(EV_REL, dev->evbit) || !test_bit(REL_X, dev->relbit)) &&
-	    (!test_bit(EV_ABS, dev->evbit) || !test_bit(ABS_X, dev->absbit)))
-		return NULL;
-
 	for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
 	if (minor == MOUSEDEV_MINORS) {
 		printk(KERN_ERR "mousedev: no more free mousedev devices\n");
@@ -425,11 +428,12 @@
 	memset(mousedev, 0, sizeof(struct mousedev));
 	init_waitqueue_head(&mousedev->wait);
 
-	mousedev->exist = 1;
 	mousedev->minor = minor;
 	mousedev_table[minor] = mousedev;
+	sprintf(mousedev->name, "mouse%d", minor);
 
 	mousedev->handle.dev = dev;
+	mousedev->handle.name = mousedev->name;
 	mousedev->handle.handler = handler;
 	mousedev->handle.private = mousedev;
 
@@ -438,7 +442,7 @@
 	if (mousedev_mix.open)
 		input_open_device(&mousedev->handle);
 
-//	printk(KERN_INFO "mouse%d: PS/2 mouse device for input%d\n", minor, dev->number);
+	mousedev->exist = 1;
 
 	return &mousedev->handle;
 }
@@ -459,6 +463,26 @@
 		kfree(mousedev);
 	}
 }
+
+static struct input_device_id mousedev_ids[] = {
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
+		evbit: { BIT(EV_KEY) | BIT(EV_REL) },
+		keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
+		relbit: { BIT(REL_X) | BIT(REL_Y) },
+	},	/* A mouse like device, at least one button, two relative axes */
+
+	{
+		flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
+		evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+		keybit: { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
+		absbit: { BIT(ABS_X) | BIT(ABS_Y) },
+	},	/* A tablet like device, at least touch detection, two absolute axes */
+
+	{ }, 	/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, mousedev_ids);
 	
 static struct input_handler mousedev_handler = {
 	event:		mousedev_event,
@@ -466,6 +490,8 @@
 	disconnect:	mousedev_disconnect,
 	fops:		&mousedev_fops,
 	minor:		MOUSEDEV_MINOR_BASE,
+	name:		"mousedev",
+	id_table:	mousedev_ids,
 };
 
 static int __init mousedev_init(void)
@@ -492,10 +518,6 @@
 
 module_init(mousedev_init);
 module_exit(mousedev_exit);
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Input driver to PS/2 or ImPS/2 device driver");
-MODULE_LICENSE("GPL");
 
 MODULE_PARM(xres, "i");
 MODULE_PARM_DESC(xres, "Horizontal screen resolution");
diff -urN linux-2.5.4-pre2/drivers/message/i2o/i2o_block.c linux/drivers/message/i2o/i2o_block.c
--- linux-2.5.4-pre2/drivers/message/i2o/i2o_block.c	Thu Jan 10 10:15:38 2002
+++ linux/drivers/message/i2o/i2o_block.c	Thu Feb  7 16:09:56 2002
@@ -40,6 +40,8 @@
  *		Serial number scanning to find duplicates for FC multipathing
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/major.h>
 
 #include <linux/module.h>
diff -urN linux-2.5.4-pre2/drivers/message/i2o/i2o_config.c linux/drivers/message/i2o/i2o_config.c
--- linux-2.5.4-pre2/drivers/message/i2o/i2o_config.c	Fri Nov 30 08:26:04 2001
+++ linux/drivers/message/i2o/i2o_config.c	Thu Feb  7 16:09:56 2002
@@ -25,6 +25,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
diff -urN linux-2.5.4-pre2/drivers/message/i2o/i2o_core.c linux/drivers/message/i2o/i2o_core.c
--- linux-2.5.4-pre2/drivers/message/i2o/i2o_core.c	Tue Nov 27 09:23:27 2001
+++ linux/drivers/message/i2o/i2o_core.c	Thu Feb  7 16:09:56 2002
@@ -22,6 +22,8 @@
  * 
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
diff -urN linux-2.5.4-pre2/drivers/message/i2o/i2o_lan.c linux/drivers/message/i2o/i2o_lan.c
--- linux-2.5.4-pre2/drivers/message/i2o/i2o_lan.c	Mon Oct 22 08:39:56 2001
+++ linux/drivers/message/i2o/i2o_lan.c	Thu Feb  7 16:09:56 2002
@@ -25,6 +25,8 @@
  *	TODO:		tests for other LAN classes (Token Ring, Fibre Channel)
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/config.h>
 #include <linux/module.h>
 
diff -urN linux-2.5.4-pre2/drivers/message/i2o/i2o_scsi.c linux/drivers/message/i2o/i2o_scsi.c
--- linux-2.5.4-pre2/drivers/message/i2o/i2o_scsi.c	Wed Nov 28 08:49:22 2001
+++ linux/drivers/message/i2o/i2o_scsi.c	Thu Feb  7 16:09:56 2002
@@ -31,6 +31,8 @@
  *		Fix the resource management problems.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
diff -urN linux-2.5.4-pre2/drivers/net/3c501.c linux/drivers/net/3c501.c
--- linux-2.5.4-pre2/drivers/net/3c501.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/3c501.c	Thu Feb  7 16:09:56 2002
@@ -87,8 +87,12 @@
  *
  */
 
+#define DRV_NAME	"3c501"
+#define DRV_VERSION	"2001/11/17"
+
+
 static const char version[] =
-    "3c501.c: 2000/02/08 Alan Cox (alan@redhat.com).\n";
+	DRV_NAME ".c: " DRV_VERSION " Alan Cox (alan@redhat.com).\n";
 
 /*
  *	Braindamage remaining:
@@ -108,7 +112,9 @@
 #include <linux/errno.h>
 #include <linux/config.h>	/* for CONFIG_IP_MULTICAST */
 #include <linux/spinlock.h>
+#include <linux/ethtool.h>
 
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 
@@ -139,12 +145,14 @@
 static int  el1_close(struct net_device *dev);
 static struct net_device_stats *el1_get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 #define EL1_IO_EXTENT	16
 
 #ifndef EL_DEBUG
 #define EL_DEBUG  0	/* use 0 for production, 1 for devel., >2 for debug */
 #endif			/* Anything above 5 is wordy death! */
+#define debug el_debug
 static int el_debug = EL_DEBUG;
 
 /*
@@ -377,6 +385,7 @@
 	dev->stop = &el1_close;
 	dev->get_stats = &el1_get_stats;
 	dev->set_multicast_list = &set_multicast_list;
+	dev->do_ioctl = netdev_ioctl;
 
 	/*
 	 *	Setup the generic properties
@@ -915,6 +924,86 @@
 	}
 }
 
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
 #ifdef MODULE
 
 static struct net_device dev_3c501 = {
diff -urN linux-2.5.4-pre2/drivers/net/3c503.c linux/drivers/net/3c503.c
--- linux-2.5.4-pre2/drivers/net/3c503.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/3c503.c	Thu Feb  7 16:09:56 2002
@@ -29,11 +29,17 @@
     Paul Gortmaker	: add support for the 2nd 8kB of RAM on 16 bit cards.
     Paul Gortmaker	: multiple card support for module users.
     rjohnson@analogic.com : Fix up PIO interface for efficient operation.
+    Jeff Garzik		: ethtool support
 
 */
 
+#define DRV_NAME	"3c503"
+#define DRV_VERSION	"1.10a"
+#define DRV_RELDATE	"11/17/2001"
+
+
 static const char version[] =
-    "3c503.c:v1.10 9/23/93  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+    DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Donald Becker (becker@scyld.com)\n";
 
 #include <linux/module.h>
 
@@ -45,7 +51,9 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/ethtool.h>
 
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/byteorder.h>
@@ -74,6 +82,7 @@
 			   int ring_offset);
 static void el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 			 int ring_page);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 
 /* This routine probes for a memory-mapped 3c503 board by looking for
@@ -301,6 +310,7 @@
 
     dev->open = &el2_open;
     dev->stop = &el2_close;
+    dev->do_ioctl = &netdev_ioctl;
 
     if (dev->mem_start)
 	printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
@@ -607,6 +617,71 @@
     outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
     return;
 }
+
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
+
 #ifdef MODULE
 #define MAX_EL2_CARDS	4	/* Max number of EL2 cards per module */
 
diff -urN linux-2.5.4-pre2/drivers/net/3c505.c linux/drivers/net/3c505.c
--- linux-2.5.4-pre2/drivers/net/3c505.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/3c505.c	Thu Feb  7 16:09:56 2002
@@ -35,8 +35,13 @@
  *                      Philip Blundell <Philip.Blundell@pobox.com>
  *              Multicard/soft configurable dma channel/rev 2 hardware support
  *                      by Christopher Collins <ccollins@pcug.org.au>
+ *		Ethtool support (jgarzik), 11/17/2001
  */
 
+#define DRV_NAME	"3c505"
+#define DRV_VERSION	"1.10a"
+
+
 /* Theory of operation:
  *
  * The 3c505 is quite an intelligent board.  All communication with it is done
@@ -103,6 +108,9 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -148,10 +156,11 @@
  *********************************************************/
 
 #ifdef ELP_DEBUG
-static const int elp_debug = ELP_DEBUG;
+static int elp_debug = ELP_DEBUG;
 #else
-static const int elp_debug;
+static int elp_debug;
 #endif
+#define debug elp_debug
 
 /*
  *  0 = no messages (well, some)
@@ -630,7 +639,7 @@
 	disable_dma(dev->dma);
 	clear_dma_ff(dev->dma);
 	set_dma_mode(dev->dma, 0x04);	/* dma read */
-	set_dma_addr(dev->dma, virt_to_bus(target));
+	set_dma_addr(dev->dma, isa_virt_to_bus(target));
 	set_dma_count(dev->dma, rlen);
 	enable_dma(dev->dma);
 	release_dma_lock(flags);
@@ -1029,10 +1038,10 @@
 
 	if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS) {
 		memcpy(adapter->dma_buffer, skb->data, nlen);
-		target = virt_to_bus(adapter->dma_buffer);
+		target = isa_virt_to_bus(adapter->dma_buffer);
 	}
 	else {
-		target = virt_to_bus(skb->data);
+		target = isa_virt_to_bus(skb->data);
 	}
 	adapter->current_dma.skb = skb;
 
@@ -1260,6 +1269,87 @@
 	}
 }
 
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
+
 /******************************************************
  *
  * initialise Etherlink Plus board
@@ -1280,6 +1370,7 @@
 	dev->tx_timeout = elp_timeout;			/* local */
 	dev->watchdog_timeo = 10*HZ;
 	dev->set_multicast_list = elp_set_mc_list;	/* local */
+	dev->do_ioctl = netdev_ioctl;			/* local */
 
 	/* Setup the generic properties */
 	ether_setup(dev);
diff -urN linux-2.5.4-pre2/drivers/net/3c507.c linux/drivers/net/3c507.c
--- linux-2.5.4-pre2/drivers/net/3c507.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/net/3c507.c	Thu Feb  7 16:09:56 2002
@@ -25,8 +25,12 @@
 	The statistics need to be updated correctly.
 */
 
+#define DRV_NAME		"3c507"
+#define DRV_VERSION		"1.10a"
+#define DRV_RELDATE		"11/17/2001"
+
 static const char version[] =
-	"3c507.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+	DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Donald Becker (becker@scyld.com)\n";
 
 
 #include <linux/module.h>
@@ -52,6 +56,9 @@
 #include <linux/in.h>
 #include <linux/string.h>
 #include <linux/spinlock.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -70,6 +77,8 @@
 #define NET_DEBUG 1
 #endif
 static unsigned int net_debug = NET_DEBUG;
+#define debug net_debug
+
 
 /* A zero-terminated list of common I/O addresses to be probed. */
 static unsigned int netcard_portlist[] __initdata =
@@ -296,6 +305,7 @@
 
 static void hardware_send_packet(struct net_device *dev, void *buf, short length);
 static void init_82586_mem(struct net_device *dev);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 
 /* Check for a network adaptor of this type, and return '0' iff one exists.
@@ -427,6 +437,7 @@
 	dev->get_stats	= el16_get_stats;
 	dev->tx_timeout = el16_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->do_ioctl = netdev_ioctl;
 
 	ether_setup(dev);	/* Generic ethernet behaviour */
 
@@ -864,6 +875,88 @@
 	lp->rx_head = rx_head;
 	lp->rx_tail = rx_tail;
 }
+
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
+
 #ifdef MODULE
 static struct net_device dev_3c507;
 static int io = 0x300;
diff -urN linux-2.5.4-pre2/drivers/net/3c509.c linux/drivers/net/3c509.c
--- linux-2.5.4-pre2/drivers/net/3c509.c	Sun Nov 25 09:43:42 2001
+++ linux/drivers/net/3c509.c	Thu Feb  7 16:09:56 2002
@@ -43,8 +43,14 @@
 		v1.18 12Mar2001 Andrew Morton <andrewm@uow.edu.au>
 			- Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
 			- Reviewed against 1.18 from scyld.com
+		v1.18 17Nov2001 Jeff Garzik <jgarzik@mandrakesoft.com>
+			- ethtool support
 */
 
+#define DRV_NAME	"3c509"
+#define DRV_VERSION	"1.18a"
+#define DRV_RELDATE	"17Nov2001"
+
 /* A few values that may be tweaked. */
 
 /* Time in jiffies before concluding the transmitter is hung. */
@@ -70,12 +76,14 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>	/* for udelay() */
 #include <linux/spinlock.h>
+#include <linux/ethtool.h>
 
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
-static char versionA[] __initdata = "3c509.c:1.18 12Mar2001 becker@scyld.com\n";
+static char versionA[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE "becker@scyld.com\n";
 static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n";
 
 #ifdef EL3_DEBUG
@@ -84,6 +92,7 @@
 static int el3_debug = 2;
 #endif
 
+
 /* To minimize the size of the driver source I only define operating
    constants if they are used several times.  You'll need the manual
    anyway if you want to understand driver details. */
@@ -158,6 +167,7 @@
 static int el3_close(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static void el3_tx_timeout (struct net_device *dev);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 #ifdef CONFIG_MCA
 struct el3_mca_adapters_struct {
@@ -513,6 +523,7 @@
 	dev->set_multicast_list = &set_multicast_list;
 	dev->tx_timeout = el3_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->do_ioctl = netdev_ioctl;
 
 	/* Fill in the generic fields of the device structure. */
 	ether_setup(dev);
@@ -1003,6 +1014,85 @@
 	return 0;
 }
 
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = el3_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		el3_debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
 #ifdef MODULE
 /* Parameters that may be passed into the module. */
 static int debug = -1;
diff -urN linux-2.5.4-pre2/drivers/net/3c515.c linux/drivers/net/3c515.c
--- linux-2.5.4-pre2/drivers/net/3c515.c	Sun Nov 25 09:43:42 2001
+++ linux/drivers/net/3c515.c	Thu Feb  7 16:09:56 2002
@@ -16,9 +16,17 @@
 	2/2/00- Added support for kernel-level ISAPnP 
 		by Stephen Frost <sfrost@snowman.net> and Alessandro Zummo
 	Cleaned up for 2.3.x/softnet by Jeff Garzik and Alan Cox.
+	
+	11/17/2001 - Added ethtool support (jgarzik)
+
 */
 
-static char *version = "3c515.c:v0.99-sn 2000/02/12 becker@cesdis.gsfc.nasa.gov and others\n";
+#define DRV_NAME		"3c515"
+#define DRV_VERSION		"0.99t"
+#define DRV_RELDATE		"17-Nov-2001"
+
+static char *version =
+DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " becker@scyld.com and others\n";
 
 #define CORKSCREW 1
 
@@ -63,6 +71,9 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -393,6 +404,7 @@
 static void update_stats(int addr, struct net_device *dev);
 static struct net_device_stats *corkscrew_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 
 /* 
@@ -721,6 +733,7 @@
 	dev->stop = &corkscrew_close;
 	dev->get_stats = &corkscrew_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
+	dev->do_ioctl = netdev_ioctl;
 
 	return 0;
 }
@@ -844,7 +857,7 @@
 			struct sk_buff *skb;
 			if (i < (RX_RING_SIZE - 1))
 				vp->rx_ring[i].next =
-				    virt_to_bus(&vp->rx_ring[i + 1]);
+				    isa_virt_to_bus(&vp->rx_ring[i + 1]);
 			else
 				vp->rx_ring[i].next = 0;
 			vp->rx_ring[i].status = 0;	/* Clear complete bit. */
@@ -855,10 +868,10 @@
 				break;	/* Bad news!  */
 			skb->dev = dev;	/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[i].addr = virt_to_bus(skb->tail);
+			vp->rx_ring[i].addr = isa_virt_to_bus(skb->tail);
 		}
-		vp->rx_ring[i - 1].next = virt_to_bus(&vp->rx_ring[0]);	/* Wrap the ring. */
-		outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
+		vp->rx_ring[i - 1].next = isa_virt_to_bus(&vp->rx_ring[0]);	/* Wrap the ring. */
+		outl(isa_virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
 	}
 	if (vp->full_bus_master_tx) {	/* Boomerang bus master Tx. */
 		vp->cur_tx = vp->dirty_tx = 0;
@@ -1053,7 +1066,7 @@
 		/* vp->tx_full = 1; */
 		vp->tx_skbuff[entry] = skb;
 		vp->tx_ring[entry].next = 0;
-		vp->tx_ring[entry].addr = virt_to_bus(skb->data);
+		vp->tx_ring[entry].addr = isa_virt_to_bus(skb->data);
 		vp->tx_ring[entry].length = skb->len | 0x80000000;
 		vp->tx_ring[entry].status = skb->len | 0x80000000;
 
@@ -1066,9 +1079,9 @@
 			    0) break;
 		if (prev_entry)
 			prev_entry->next =
-			    virt_to_bus(&vp->tx_ring[entry]);
+			    isa_virt_to_bus(&vp->tx_ring[entry]);
 		if (inl(ioaddr + DownListPtr) == 0) {
-			outl(virt_to_bus(&vp->tx_ring[entry]),
+			outl(isa_virt_to_bus(&vp->tx_ring[entry]),
 			     ioaddr + DownListPtr);
 			queued_packet++;
 		}
@@ -1205,7 +1218,7 @@
 			while (lp->cur_tx - dirty_tx > 0) {
 				int entry = dirty_tx % TX_RING_SIZE;
 				if (inl(ioaddr + DownListPtr) ==
-				    virt_to_bus(&lp->tx_ring[entry]))
+				    isa_virt_to_bus(&lp->tx_ring[entry]))
 					break;	/* It still hasn't been processed. */
 				if (lp->tx_skbuff[entry]) {
 					dev_kfree_skb_irq(lp->
@@ -1414,7 +1427,7 @@
 				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
 				/* 'skb_put()' points to the start of sk_buff data area. */
 				memcpy(skb_put(skb, pkt_len),
-				       bus_to_virt(vp->rx_ring[entry].
+				       isa_bus_to_virt(vp->rx_ring[entry].
 						   addr), pkt_len);
 				rx_copy++;
 			} else {
@@ -1424,11 +1437,11 @@
 				vp->rx_skbuff[entry] = NULL;
 				temp = skb_put(skb, pkt_len);
 				/* Remove this checking code for final release. */
-				if (bus_to_virt(vp->rx_ring[entry].addr) != temp)
+				if (isa_bus_to_virt(vp->rx_ring[entry].addr) != temp)
 					    printk("%s: Warning -- the skbuff addresses do not match"
 					     " in boomerang_rx: %p vs. %p / %p.\n",
 					     dev->name,
-					     bus_to_virt(vp->
+					     isa_bus_to_virt(vp->
 							 rx_ring[entry].
 							 addr), skb->head,
 					     temp);
@@ -1451,7 +1464,7 @@
 				break;	/* Bad news!  */
 			skb->dev = dev;	/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[entry].addr = virt_to_bus(skb->tail);
+			vp->rx_ring[entry].addr = isa_virt_to_bus(skb->tail);
 			vp->rx_skbuff[entry] = skb;
 		}
 		vp->rx_ring[entry].status = 0;	/* Clear complete bit. */
@@ -1591,6 +1604,87 @@
 
 	outw(new_mode, ioaddr + EL3_CMD);
 }
+
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = corkscrew_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		corkscrew_debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
 
 #ifdef MODULE
 void cleanup_module(void)
diff -urN linux-2.5.4-pre2/drivers/net/3c523.c linux/drivers/net/3c523.c
--- linux-2.5.4-pre2/drivers/net/3c523.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/3c523.c	Thu Feb  7 16:09:56 2002
@@ -81,10 +81,15 @@
    added option to disable multicast as is causes problems
        Ganesh Sittampalam <ganesh.sittampalam@magdalen.oxford.ac.uk>
        Stuart Adamson <stuart.adamson@compsoc.net>
+   Nov 2001
+   added support for ethtool (jgarzik)
 	
    $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $
  */
 
+#define DRV_NAME		"3c523"
+#define DRV_VERSION		"17-Nov-2001"
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -95,6 +100,9 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/mca.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/processor.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -182,6 +190,7 @@
 #ifdef ELMC_MULTICAST
 static void set_multicast_list(struct net_device *dev);
 #endif
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 /* helper-functions */
 static int init586(struct net_device *dev);
@@ -304,13 +313,13 @@
 	char *iscp_addrs[2];
 	int i = 0;
 
-	p->base = (unsigned long) bus_to_virt((unsigned long)where) + size - 0x01000000;
-	p->memtop = bus_to_virt((unsigned long)where) + size;
+	p->base = (unsigned long) isa_bus_to_virt((unsigned long)where) + size - 0x01000000;
+	p->memtop = isa_bus_to_virt((unsigned long)where) + size;
 	p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
 	memset((char *) p->scp, 0, sizeof(struct scp_struct));
 	p->scp->sysbus = SYSBUSVAL;	/* 1 = 8Bit-Bus, 0 = 16 Bit */
 
-	iscp_addrs[0] = bus_to_virt((unsigned long)where);
+	iscp_addrs[0] = isa_bus_to_virt((unsigned long)where);
 	iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);
 
 	for (i = 0; i < 2; i++) {
@@ -347,7 +356,7 @@
 	DELAY(2);
 
 	p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
-	p->scb = (struct scb_struct *) bus_to_virt(dev->mem_start);
+	p->scb = (struct scb_struct *) isa_bus_to_virt(dev->mem_start);
 	p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct));
 
 	memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
@@ -529,8 +538,8 @@
 	}
 	dev->mem_end = dev->mem_start + size;	/* set mem_end showed by 'ifconfig' */
 
-	pr->memtop = bus_to_virt(dev->mem_start) + size;
-	pr->base = (unsigned long) bus_to_virt(dev->mem_start) + size - 0x01000000;
+	pr->memtop = isa_bus_to_virt(dev->mem_start) + size;
+	pr->base = (unsigned long) isa_bus_to_virt(dev->mem_start) + size - 0x01000000;
 	alloc586(dev);
 
 	elmc_id_reset586();	/* make sure it doesn't generate spurious ints */
@@ -563,7 +572,8 @@
 #else
 	dev->set_multicast_list = NULL;
 #endif
-
+	dev->do_ioctl = netdev_ioctl;
+	
 	ether_setup(dev);
 
 	/* note that we haven't actually requested the IRQ from the kernel.
@@ -1214,6 +1224,69 @@
 }
 #endif
 
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "MCA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
 /*************************************************************************/
 
 #ifdef MODULE
diff -urN linux-2.5.4-pre2/drivers/net/3c527.c linux/drivers/net/3c527.c
--- linux-2.5.4-pre2/drivers/net/3c527.c	Thu Apr 12 12:15:25 2001
+++ linux/drivers/net/3c527.c	Thu Feb  7 16:09:56 2002
@@ -16,8 +16,12 @@
  *
  */
 
+#define DRV_NAME		"3c527"
+#define DRV_VERSION		"0.6a"
+#define DRV_RELDATE		"2001/11/17"
+
 static const char *version =
-	"3c527.c:v0.6 2001/03/03 Richard Proctor (rnp@netlink.co.nz)\n";
+DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Proctor (rnp@netlink.co.nz)\n";
 
 /**
  * DOC: Traps for the unwary
@@ -90,6 +94,9 @@
 #include <linux/in.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -108,7 +115,7 @@
  * The name of the card. Is used for messages and in the requests for
  * io regions, irqs and dma channels
  */
-static const char* cardname = "3c527";
+static const char* cardname = DRV_NAME;
 
 /* use 0 for production, 1 for verification, >2 for debug */
 #ifndef NET_DEBUG
@@ -213,6 +220,7 @@
 static struct	net_device_stats *mc32_get_stats(struct net_device *dev);
 static void	mc32_set_multicast_list(struct net_device *dev);
 static void	mc32_reset_multicast_list(struct net_device *dev);
+static int	netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 /**
  * mc32_probe 	-	Search for supported boards
@@ -470,16 +478,16 @@
 		base|=(inb(dev->base_addr)<<(8*i));
 	}
 	
-	lp->exec_box=bus_to_virt(dev->mem_start+base);
+	lp->exec_box=isa_bus_to_virt(dev->mem_start+base);
 	
 	base=lp->exec_box->data[1]<<16|lp->exec_box->data[0];  
 	
 	lp->base = dev->mem_start+base;
 	
-	lp->rx_box=bus_to_virt(lp->base + lp->exec_box->data[2]); 
-	lp->tx_box=bus_to_virt(lp->base + lp->exec_box->data[3]);
+	lp->rx_box=isa_bus_to_virt(lp->base + lp->exec_box->data[2]); 
+	lp->tx_box=isa_bus_to_virt(lp->base + lp->exec_box->data[3]);
 	
-	lp->stats = bus_to_virt(lp->base + lp->exec_box->data[5]);
+	lp->stats = isa_bus_to_virt(lp->base + lp->exec_box->data[5]);
 
 	/*
 	 *	Descriptor chains (card relative)
@@ -502,7 +510,7 @@
 	dev->set_multicast_list = mc32_set_multicast_list;
 	dev->tx_timeout		= mc32_timeout;
 	dev->watchdog_timeo	= HZ*5;	/* Board does all the work */
-
+	dev->do_ioctl		= netdev_ioctl;
 	
 	lp->xceiver_state = HALTED; 
 	
@@ -781,10 +789,10 @@
 			return -ENOBUFS;
 		}
 		
-		p=bus_to_virt(lp->base+rx_base);
+		p=isa_bus_to_virt(lp->base+rx_base);
 				
 		p->control=0;
-		p->data=virt_to_bus(lp->rx_ring[i].skb->data);
+		p->data=isa_virt_to_bus(lp->rx_ring[i].skb->data);
 		p->status=0;
 		p->length=1532;
 	
@@ -854,7 +862,7 @@
 
 	for(i=0;i<lp->tx_len;i++) 
 	{
-		p=bus_to_virt(lp->base+tx_base);
+		p=isa_bus_to_virt(lp->base+tx_base);
 		lp->tx_ring[i].p=p; 
 		lp->tx_ring[i].skb=NULL;
 
@@ -1080,7 +1088,7 @@
    	   
 	np->length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; 
 			
-	np->data	= virt_to_bus(skb->data);
+	np->data	= isa_virt_to_bus(skb->data);
 	np->status	= 0;
 	np->control     = CONTROL_EOP | CONTROL_EOL;     
 	wmb();
@@ -1197,7 +1205,7 @@
 				
 				skb_reserve(newskb,18); 
 				lp->rx_ring[rx_ring_tail].skb=newskb;  
-				p->data=virt_to_bus(newskb->data);  
+				p->data=isa_virt_to_bus(newskb->data);  
 			} 
 			else 
 			{
@@ -1644,6 +1652,86 @@
 	do_mc32_set_multicast_list(dev,1);
 }
 
+/**
+ * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @useraddr: userspace address to which data is to be read and returned
+ *
+ * Process the various commands of the SIOCETHTOOL interface.
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "MCA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = mc32_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		mc32_debug = edata.data;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * netdev_ioctl: Handle network interface ioctls
+ * @dev: network interface on which out-of-band action is to be performed
+ * @rq: user request data
+ * @cmd: command issued by user
+ *
+ * Process the various out-of-band ioctls passed to this driver.
+ */
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc = 0;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+ 
 #ifdef MODULE
 
 static struct net_device this_device;
diff -urN linux-2.5.4-pre2/drivers/net/8139cp.c linux/drivers/net/8139cp.c
--- linux-2.5.4-pre2/drivers/net/8139cp.c	Thu Jan 24 11:51:11 2002
+++ linux/drivers/net/8139cp.c	Thu Feb  7 16:09:56 2002
@@ -20,7 +20,6 @@
 	TODO, in rough priority order:
 	* dev->tx_timeout
 	* LinkChg interrupt
-	* ETHTOOL_[GS]SET
 	* Support forcing media type with a module parameter,
 	  like dl2k.c/sundance.c
 	* Implement PCI suspend/resume
@@ -33,18 +32,19 @@
 	* Rx checksumming
 	* Tx checksumming
 	* ETHTOOL_GREGS, ETHTOOL_[GS]WOL,
-	  ETHTOOL_[GS]MSGLVL, ETHTOOL_NWAY_RST
 	* Jumbo frames / dev->change_mtu
 	* Investigate using skb->priority with h/w VLAN priority
 	* Investigate using High Priority Tx Queue with skb->priority
 	* Adjust Rx FIFO threshold and Max Rx DMA burst on Rx FIFO error
 	* Adjust Tx FIFO threshold and Max Tx DMA burst on Tx FIFO error
+        * Implement Tx software interrupt mitigation via
+	          Tx descriptor bit
 
  */
 
 #define DRV_NAME		"8139cp"
-#define DRV_VERSION		"0.0.5"
-#define DRV_RELDATE		"Oct 19, 2001"
+#define DRV_VERSION		"0.0.6cvs"
+#define DRV_RELDATE		"Nov 19, 2001"
 
 
 #include <linux/module.h>
@@ -56,6 +56,7 @@
 #include <linux/delay.h>
 #include <linux/ethtool.h>
 #include <linux/crc32.h>
+#include <linux/mii.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -94,10 +95,10 @@
 	(((CP)->tx_tail <= (CP)->tx_head) ?			\
 	  (CP)->tx_tail + (CP_TX_RING_SIZE - 1) - (CP)->tx_head :	\
 	  (CP)->tx_tail - (CP)->tx_head - 1)
-#define CP_CHIP_VERSION		0x76
 
 #define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer.*/
 #define RX_OFFSET		2
+#define CP_INTERNAL_PHY		32
 
 /* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024, 7==end of packet. */
 #define RX_FIFO_THRESH		5	/* Rx buffer level before first PCI xfer.  */
@@ -126,6 +127,11 @@
 	Config3		= 0x59, /* Config3 */
 	Config4		= 0x5A, /* Config4 */
 	MultiIntr	= 0x5C, /* Multiple interrupt select */
+	BasicModeCtrl	= 0x62,	/* MII BMCR */
+	BasicModeStatus	= 0x64, /* MII BMSR */
+	NWayAdvert	= 0x66, /* MII ADVERTISE */
+	NWayLPAR	= 0x68, /* MII LPA */
+	NWayExpansion	= 0x6A, /* MII Expansion */
 	Config5		= 0xD8,	/* Config5 */
 	TxPoll		= 0xD9,	/* Tell chip to check Tx descriptors for work */
 	CpCmd		= 0xE0, /* C+ Command register (C+ mode only) */
@@ -279,6 +285,8 @@
 
 	struct sk_buff		*frag_skb;
 	unsigned		dropping_frag : 1;
+
+	struct mii_if_info	mii_if;
 };
 
 #define cpr8(reg)	readb(cp->regs + (reg))
@@ -985,6 +993,39 @@
 	return 0;
 }
 
+static char mii_2_8139_map[8] = {
+	BasicModeCtrl,
+	BasicModeStatus,
+	0,
+	0,
+	NWayAdvert,
+	NWayLPAR,
+	NWayExpansion,
+	0
+};
+
+static int mdio_read(struct net_device *dev, int phy_id, int location)
+{
+	struct cp_private *cp = dev->priv;
+
+	return location < 8 && mii_2_8139_map[location] ?
+	       readw(cp->regs + mii_2_8139_map[location]) : 0;
+}
+
+
+static void mdio_write(struct net_device *dev, int phy_id, int location,
+		       int value)
+{
+	struct cp_private *cp = dev->priv;
+
+	if (location == 0) {
+		cpw8(Cfg9346, Cfg9346_Unlock);
+		cpw16(BasicModeCtrl, value);
+		cpw8(Cfg9346, Cfg9346_Lock);
+	} else if (location < 8 && mii_2_8139_map[location])
+		cpw16(mii_2_8139_map[location], value);
+}
+
 static int cp_ethtool_ioctl (struct cp_private *cp, void *useraddr)
 {
 	u32 ethcmd;
@@ -992,21 +1033,71 @@
 	/* dev_ioctl() in ../../net/core/dev.c has already checked
 	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
 
-	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+	if (get_user(ethcmd, (u32 *)useraddr))
 		return -EFAULT;
 
 	switch (ethcmd) {
 
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy (info.driver, DRV_NAME);
-			strcpy (info.version, DRV_VERSION);
-			strcpy (info.bus_info, cp->pdev->slot_name);
-			if (copy_to_user (useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, cp->pdev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&cp->lock);
+		mii_ethtool_gset(&cp->mii_if, &ecmd);
+		spin_unlock_irq(&cp->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&cp->lock);
+		r = mii_ethtool_sset(&cp->mii_if, &ecmd);
+		spin_unlock_irq(&cp->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&cp->mii_if);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&cp->mii_if);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = cp->msg_enable;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		cp->msg_enable = edata.data;
+		return 0;
+	}
 
 	default:
 		break;
@@ -1136,6 +1227,10 @@
 	cp->dev = dev;
 	cp->msg_enable = (debug < 0 ? CP_DEF_MSG_ENABLE : debug);
 	spin_lock_init (&cp->lock);
+	cp->mii_if.dev = dev;
+	cp->mii_if.mdio_read = mdio_read;
+	cp->mii_if.mdio_write = mdio_write;
+	cp->mii_if.phy_id = CP_INTERNAL_PHY;
 
 	rc = pci_enable_device(pdev);
 	if (rc)
diff -urN linux-2.5.4-pre2/drivers/net/8139too.c linux/drivers/net/8139too.c
--- linux-2.5.4-pre2/drivers/net/8139too.c	Thu Jan 24 11:51:11 2002
+++ linux/drivers/net/8139too.c	Thu Feb  7 16:09:56 2002
@@ -92,7 +92,7 @@
 */
 
 #define DRV_NAME	"8139too"
-#define DRV_VERSION	"0.9.22"
+#define DRV_VERSION	"0.9.24"
 
 
 #include <linux/config.h>
@@ -160,6 +160,9 @@
    The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
 static int multicast_filter_limit = 32;
 
+/* bitmapped message enable number */
+static int debug = -1;
+
 /* Size of the in-memory receive ring. */
 #define RX_BUF_LEN_IDX	2	/* 0==8K, 1==16K, 2==32K, 3==64K */
 #define RX_BUF_LEN	(8192 << RX_BUF_LEN_IDX)
@@ -213,6 +216,7 @@
 	ADDTRON8139,
 	DFE538TX,
 	DFE690TXD,
+	FE2000VX,
 	RTL8129,
 } board_t;
 
@@ -230,6 +234,7 @@
 	{ "Addtron Technolgy 8139 10/100BaseTX", RTL8139_CAPS },
 	{ "D-Link DFE-538TX (RealTek RTL8139)", RTL8139_CAPS },
 	{ "D-Link DFE-690TXD (RealTek RTL8139)", RTL8139_CAPS },
+	{ "AboCom FE2000VX (RealTek RTL8139)", RTL8139_CAPS },
 	{ "RealTek RTL8129", RTL8129_CAPS },
 };
 
@@ -243,6 +248,7 @@
 	{0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 },
 	{0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE538TX },
 	{0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE690TXD },
+	{0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FE2000VX },
 
 #ifdef CONFIG_8139TOO_8129
 	{0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 },
@@ -254,6 +260,7 @@
 	 */
 	{PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 },
 	{PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, DFE538TX },
+	{PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, FE2000VX },
 
 	{0,}
 };
@@ -526,6 +533,7 @@
 	unsigned long early_rx;
 	unsigned long tx_buf_mapped;
 	unsigned long tx_timeouts;
+	unsigned long rx_lost_in_ring;
 };
 
 struct rtl8139_private {
@@ -544,12 +552,8 @@
 	dma_addr_t tx_bufs_dma;
 	signed char phys[4];		/* MII device addresses. */
 	char twistie, twist_row, twist_col;	/* Twister tune state. */
-	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
-	unsigned int duplex_lock:1;
 	unsigned int default_port:4;	/* Last dev->if_port value. */
-	unsigned int media2:4;	/* Secondary monitored media port. */
 	unsigned int medialock:1;	/* Don't sense media type. */
-	unsigned int mediasense:1;	/* Media sensing in progress. */
 	spinlock_t lock;
 	chip_t chipset;
 	pid_t thr_pid;
@@ -558,6 +562,7 @@
 	u32 rx_config;
 	struct rtl_extra_stats xstats;
 	int time_to_die;
+	struct mii_if_info mii;
 };
 
 MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
@@ -568,6 +573,8 @@
 MODULE_PARM (max_interrupt_work, "i");
 MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM (debug, "i");
+MODULE_PARM_DESC (debug, "8139too bitmapped message enable number");
 MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses");
 MODULE_PARM_DESC (max_interrupt_work, "8139too maximum events handled per interrupt");
 MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
@@ -948,6 +955,9 @@
 	spin_lock_init (&tp->lock);
 	init_waitqueue_head (&tp->thr_wait);
 	init_completion (&tp->thr_exited);
+	tp->mii.dev = dev;
+	tp->mii.mdio_read = mdio_read;
+	tp->mii.mdio_write = mdio_write;
 
 	/* dev is fully set up and ready to use now */
 	DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);
@@ -999,18 +1009,18 @@
 	/* The lower four bits are the media type. */
 	option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];
 	if (option > 0) {
-		tp->full_duplex = (option & 0x210) ? 1 : 0;
+		tp->mii.full_duplex = (option & 0x210) ? 1 : 0;
 		tp->default_port = option & 0xFF;
 		if (tp->default_port)
 			tp->medialock = 1;
 	}
 	if (board_idx < MAX_UNITS  &&  full_duplex[board_idx] > 0)
-		tp->full_duplex = full_duplex[board_idx];
-	if (tp->full_duplex) {
+		tp->mii.full_duplex = full_duplex[board_idx];
+	if (tp->mii.full_duplex) {
 		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
 		/* Changing the MII-advertised media because might prevent
 		   re-connection. */
-		tp->duplex_lock = 1;
+		tp->mii.duplex_lock = 1;
 	}
 	if (tp->default_port) {
 		printk(KERN_INFO "  Forcing %dMbps %s-duplex operation.\n",
@@ -1267,7 +1277,7 @@
 
 	}
 
-	tp->full_duplex = tp->duplex_lock;
+	tp->mii.full_duplex = tp->mii.duplex_lock;
 	tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
 	tp->twistie = 1;
 	tp->time_to_die = 0;
@@ -1279,7 +1289,7 @@
 			" GP Pins %2.2x %s-duplex.\n",
 			dev->name, pci_resource_start (tp->pci_dev, 1),
 			dev->irq, RTL_R8 (MediaStatus),
-			tp->full_duplex ? "full" : "half");
+			tp->mii.full_duplex ? "full" : "half");
 
 	tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES);
 	if (tp->thr_pid < 0)
@@ -1295,18 +1305,18 @@
 	struct rtl8139_private *tp = dev->priv;
 
 	if (tp->phys[0] >= 0) {
-		u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);
-		if (mii_reg5 == 0xffff)
+		u16 mii_lpa = mdio_read(dev, tp->phys[0], MII_LPA);
+		if (mii_lpa == 0xffff)
 			;					/* Not there */
-		else if ((mii_reg5 & 0x0100) == 0x0100
-				 || (mii_reg5 & 0x00C0) == 0x0040)
-			tp->full_duplex = 1;
+		else if ((mii_lpa & LPA_100FULL) == LPA_100FULL
+				 || (mii_lpa & 0x00C0) == LPA_10FULL)
+			tp->mii.full_duplex = 1;
 
 		printk (KERN_INFO"%s: Setting %s%s-duplex based on"
 				" auto-negotiated partner ability %4.4x.\n",
-		        dev->name, mii_reg5 == 0 ? "" :
-				(mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
-			tp->full_duplex ? "full" : "half", mii_reg5);
+		        dev->name, mii_lpa == 0 ? "" :
+				(mii_lpa & 0x0180) ? "100mbps " : "10mbps ",
+			tp->mii.full_duplex ? "full" : "half", mii_lpa);
 	}
 }
 
@@ -1494,30 +1504,30 @@
 				 struct rtl8139_private *tp,
 				 void *ioaddr)
 {
-	int mii_reg5;
+	int mii_lpa;
 
-	mii_reg5 = mdio_read (dev, tp->phys[0], 5);
+	mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
 
-	if (!tp->duplex_lock && mii_reg5 != 0xffff) {
-		int duplex = (mii_reg5 & 0x0100)
-		    || (mii_reg5 & 0x01C0) == 0x0040;
-		if (tp->full_duplex != duplex) {
-			tp->full_duplex = duplex;
+	if (!tp->mii.duplex_lock && mii_lpa != 0xffff) {
+		int duplex = (mii_lpa & LPA_100FULL)
+		    || (mii_lpa & 0x01C0) == 0x0040;
+		if (tp->mii.full_duplex != duplex) {
+			tp->mii.full_duplex = duplex;
 
-			if (mii_reg5) {
+			if (mii_lpa) {
 				printk (KERN_INFO
 					"%s: Setting %s-duplex based on MII #%d link"
 					" partner ability of %4.4x.\n",
 					dev->name,
-					tp->full_duplex ? "full" : "half",
-					tp->phys[0], mii_reg5);
+					tp->mii.full_duplex ? "full" : "half",
+					tp->phys[0], mii_lpa);
 			} else {
 				printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n",
 				       dev->name);
 			}
 #if 0
 			RTL_W8 (Cfg9346, Cfg9346_Unlock);
-			RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+			RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20);
 			RTL_W8 (Cfg9346, Cfg9346_Lock);
 #endif
 		}
@@ -1750,23 +1760,36 @@
 			    struct rtl8139_private *tp, void *ioaddr)
 {
 	u8 tmp8;
+#ifndef CONFIG_8139_NEW_RX_RESET
 	int tmp_work;
+#endif
 
 	DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n",
 	         dev->name, rx_status);
-	if (rx_status & RxTooLong) {
-		DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
-			 dev->name, rx_status);
-		/* A.C.: The chip hangs here. */
-	}
 	tp->stats.rx_errors++;
-	if (rx_status & (RxBadSymbol | RxBadAlign))
-		tp->stats.rx_frame_errors++;
-	if (rx_status & (RxRunt | RxTooLong))
-		tp->stats.rx_length_errors++;
-	if (rx_status & RxCRCErr)
-		tp->stats.rx_crc_errors++;
+	if (!(rx_status & RxStatusOK)) {
+		if (rx_status & RxTooLong) {
+			DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
+			 	dev->name, rx_status);
+			/* A.C.: The chip hangs here. */
+		}
+		if (rx_status & (RxBadSymbol | RxBadAlign))
+			tp->stats.rx_frame_errors++;
+		if (rx_status & (RxRunt | RxTooLong))
+			tp->stats.rx_length_errors++;
+		if (rx_status & RxCRCErr)
+			tp->stats.rx_crc_errors++;
+	} else {
+		tp->xstats.rx_lost_in_ring++;
+	}
 
+#ifdef CONFIG_8139_NEW_RX_RESET
+	tmp8 = RTL_R8 (ChipCmd);
+	RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb);
+	RTL_W8 (ChipCmd, tmp8);
+	RTL_W32 (RxConfig, tp->rx_config);
+	tp->cur_rx = 0;
+#else
 	/* Reset the receiver, based on RealTek recommendation. (Bug?) */
 
 	/* disable receive */
@@ -1811,6 +1834,7 @@
 
 	/* A.C.: Reset the multicast list. */
 	__set_rx_mode (dev);
+#endif
 }
 
 static void rtl8139_rx_interrupt (struct net_device *dev,
@@ -1945,13 +1969,13 @@
 	    (tp->drv_flags & HAS_LNK_CHNG)) {
 		/* Really link-change on new chips. */
 		int lpar = RTL_R16 (NWayLPAR);
-		int duplex = (lpar & 0x0100) || (lpar & 0x01C0) == 0x0040
-				|| tp->duplex_lock;
-		if (tp->full_duplex != duplex) {
-			tp->full_duplex = duplex;
+		int duplex = (lpar & LPA_100FULL) || (lpar & 0x01C0) == 0x0040
+				|| tp->mii.duplex_lock;
+		if (tp->mii.full_duplex != duplex) {
+			tp->mii.full_duplex = duplex;
 #if 0
 			RTL_W8 (Cfg9346, Cfg9346_Unlock);
-			RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+			RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20);
 			RTL_W8 (Cfg9346, Cfg9346_Lock);
 #endif
 		}
@@ -2110,48 +2134,6 @@
 }
 
 
-/* Get the ethtool settings.  Assumes that eset points to kernel
-   memory, *eset has been initialized as {ETHTOOL_GSET}, and other
-   threads or interrupts aren't messing with the 8139.  */
-static void netdev_get_eset (struct net_device *dev, struct ethtool_cmd *eset)
-{
-	struct rtl8139_private *np = dev->priv;
-	void *ioaddr = np->mmio_addr;
-	u16 advert;
-
-	eset->supported = SUPPORTED_10baseT_Half
-		      	| SUPPORTED_10baseT_Full
-		      	| SUPPORTED_100baseT_Half
-		      	| SUPPORTED_100baseT_Full
-		      	| SUPPORTED_Autoneg
-		      	| SUPPORTED_TP;
-
-	eset->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
-	advert = mdio_read (dev, np->phys[0], 4);
-	if (advert & 0x0020)
-		eset->advertising |= ADVERTISED_10baseT_Half;
-	if (advert & 0x0040)
-		eset->advertising |= ADVERTISED_10baseT_Full;
-	if (advert & 0x0080)
-		eset->advertising |= ADVERTISED_100baseT_Half;
-	if (advert & 0x0100)
-		eset->advertising |= ADVERTISED_100baseT_Full;
-
-	eset->speed = (RTL_R8 (MediaStatus) & 0x08) ? 10 : 100;
-	/* (KON)FIXME: np->full_duplex is set or reset by the thread,
-	   which means this always shows half duplex if the interface
-	   isn't up yet, even if it has already autonegotiated.  */
-	eset->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-	eset->port = PORT_TP;
-	/* (KON)FIXME: Is np->phys[0] correct?  starfire.c uses that.  */
-	eset->phy_address = np->phys[0];
-	eset->transceiver = XCVR_INTERNAL;
-	eset->autoneg = (mdio_read (dev, np->phys[0], 0) & 0x1000) != 0;
-	eset->maxtxpkt = 1;
-	eset->maxrxpkt = 1;
-}
-
-
 /* Get the ethtool Wake-on-LAN settings.  Assumes that wol points to
    kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and
    other threads or interrupts aren't messing with the 8139.  */
@@ -2226,7 +2208,6 @@
 	return 0;
 }
 
-
 static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
 {
 	struct rtl8139_private *np = dev->priv;
@@ -2235,33 +2216,71 @@
 	/* dev_ioctl() in ../../net/core/dev.c has already checked
 	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
 
-	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+	if (get_user(ethcmd, (u32 *)useraddr))
 		return -EFAULT;
 
 	switch (ethcmd) {
-	case ETHTOOL_GSET:
-		{
-			struct ethtool_cmd eset = { ETHTOOL_GSET };
-			spin_lock_irq (&np->lock);
-			netdev_get_eset (dev, &eset);
-			spin_unlock_irq (&np->lock);
-			if (copy_to_user (useraddr, &eset, sizeof (eset)))
-				return -EFAULT;
-			return 0;
-		}
 
-	/* TODO: ETHTOOL_SSET */
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
 
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy (info.driver, DRV_NAME);
-			strcpy (info.version, DRV_VERSION);
-			strcpy (info.bus_info, np->pci_dev->slot_name);
-			if (copy_to_user (useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
 
 	case ETHTOOL_GWOL:
 		{
@@ -2315,17 +2334,14 @@
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 
 	case SIOCGMIIPHY:	/* Get the address of the PHY in use. */
-	case SIOCDEVPRIVATE:	/* binary compat, remove in 2.5 */
 		data->phy_id = phy;
 		/* Fall Through */
 
 	case SIOCGMIIREG:	/* Read the specified MII register. */
-	case SIOCDEVPRIVATE+1:	/* binary compat, remove in 2.5 */
 		data->val_out = mdio_read (dev, data->phy_id, data->reg_num);
 		break;
 
 	case SIOCSMIIREG:	/* Write the specified MII register */
-	case SIOCDEVPRIVATE+2:	/* binary compat, remove in 2.5 */
 		if (!capable (CAP_NET_ADMIN)) {
 			rc = -EPERM;
 			break;
@@ -2338,9 +2354,9 @@
 				/* Check for autonegotiation on or reset. */
 				tp->medialock = (value & 0x9000) ? 0 : 1;
 				if (tp->medialock)
-					tp->full_duplex = (value & 0x0100) ? 1 : 0;
+					tp->mii.full_duplex = (value & 0x0100) ? 1 : 0;
 				break;
-			case 4: /* tp->advertising = value; */ break;
+			case 4: tp->mii.advertising = value; break;
 			}
 		}
 		mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
diff -urN linux-2.5.4-pre2/drivers/net/Config.in linux/drivers/net/Config.in
--- linux-2.5.4-pre2/drivers/net/Config.in	Thu Feb  7 16:09:52 2002
+++ linux/drivers/net/Config.in	Thu Feb  7 16:09:56 2002
@@ -179,6 +179,7 @@
       dep_mbool '      Use PIO instead of MMIO' CONFIG_8139TOO_PIO $CONFIG_8139TOO
       dep_mbool '      Support for automatic channel equalization (EXPERIMENTAL)' CONFIG_8139TOO_TUNE_TWISTER $CONFIG_8139TOO $CONFIG_EXPERIMENTAL
       dep_mbool '      Support for older RTL-8129/8130 boards' CONFIG_8139TOO_8129 $CONFIG_8139TOO
+      dep_mbool '      Experiment for better RX reset (EXPERIMENTAL)' CONFIG_8139_NEW_RX_RESET $CONFIG_8139TOO $CONFIG_EXPERIMENTAL
       dep_tristate '    SiS 900/7016 PCI Fast Ethernet Adapter support' CONFIG_SIS900 $CONFIG_PCI
       dep_tristate '    SMC EtherPower II' CONFIG_EPIC100 $CONFIG_PCI
       dep_tristate '    Sundance Alta support' CONFIG_SUNDANCE $CONFIG_PCI
diff -urN linux-2.5.4-pre2/drivers/net/Makefile linux/drivers/net/Makefile
--- linux-2.5.4-pre2/drivers/net/Makefile	Thu Jan 24 11:51:10 2002
+++ linux/drivers/net/Makefile	Thu Feb  7 16:09:56 2002
@@ -68,7 +68,7 @@
 obj-$(CONFIG_PCNET32) += pcnet32.o
 obj-$(CONFIG_EEPRO100) += eepro100.o
 obj-$(CONFIG_TLAN) += tlan.o
-obj-$(CONFIG_EPIC100) += epic100.o
+obj-$(CONFIG_EPIC100) += epic100.o mii.o
 obj-$(CONFIG_SIS900) += sis900.o
 obj-$(CONFIG_DM9102) += dmfe.o
 obj-$(CONFIG_YELLOWFIN) += yellowfin.o
@@ -77,7 +77,7 @@
 obj-$(CONFIG_NATSEMI) += natsemi.o
 obj-$(CONFIG_NS83820) += ns83820.o
 obj-$(CONFIG_STNIC) += stnic.o 8390.o
-obj-$(CONFIG_FEALNX) += fealnx.o
+obj-$(CONFIG_FEALNX) += fealnx.o mii.o
 
 ifeq ($(CONFIG_SK98LIN),y)
 obj-y += sk98lin/sk98lin.o
@@ -87,7 +87,7 @@
   obj-y += skfp/skfp.o
 endif
 
-obj-$(CONFIG_VIA_RHINE) += via-rhine.o
+obj-$(CONFIG_VIA_RHINE) += via-rhine.o mii.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
 
 #
@@ -100,7 +100,7 @@
 obj-$(CONFIG_AIRONET4500_PROC)	+= aironet4500_proc.o
 obj-$(CONFIG_AIRONET4500_CS)	+= aironet4500_proc.o
 
-obj-$(CONFIG_WINBOND_840) += winbond-840.o
+obj-$(CONFIG_WINBOND_840) += winbond-840.o mii.o
 obj-$(CONFIG_SUNDANCE) += sundance.o
 obj-$(CONFIG_HAMACHI) += hamachi.o
 obj-$(CONFIG_NET) += Space.o setup.o net_init.o loopback.o
@@ -164,8 +164,8 @@
 obj-$(CONFIG_3C515) += 3c515.o
 obj-$(CONFIG_EEXPRESS) += eexpress.o
 obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
-obj-$(CONFIG_8139CP) += 8139cp.o
-obj-$(CONFIG_8139TOO) += 8139too.o
+obj-$(CONFIG_8139CP) += 8139cp.o mii.o
+obj-$(CONFIG_8139TOO) += 8139too.o mii.o
 obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o
 obj-$(CONFIG_ZNET) += znet.o
 obj-$(CONFIG_LAN_SAA9730) += saa9730.o
diff -urN linux-2.5.4-pre2/drivers/net/ac3200.c linux/drivers/net/ac3200.c
--- linux-2.5.4-pre2/drivers/net/ac3200.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/ac3200.c	Thu Feb  7 16:09:56 2002
@@ -205,10 +205,10 @@
 	 *  the card mem within the region covered by `normal' RAM  !!!
 	 */
 	if (dev->mem_start > 1024*1024) {	/* phys addr > 1MB */
-		if (dev->mem_start < virt_to_bus(high_memory)) {
+		if (dev->mem_start < virt_to_phys(high_memory)) {
 			printk(KERN_CRIT "ac3200.c: Card RAM overlaps with normal memory!!!\n");
 			printk(KERN_CRIT "ac3200.c: Use EISA SCU to set card memory below 1MB,\n");
-			printk(KERN_CRIT "ac3200.c: or to an address above 0x%lx.\n", virt_to_bus(high_memory));
+			printk(KERN_CRIT "ac3200.c: or to an address above 0x%lx.\n", virt_to_phys(high_memory));
 			printk(KERN_CRIT "ac3200.c: Driver NOT installed.\n");
 			retval = -EINVAL;
 			goto out2;
diff -urN linux-2.5.4-pre2/drivers/net/au1000_eth.c linux/drivers/net/au1000_eth.c
--- linux-2.5.4-pre2/drivers/net/au1000_eth.c	Mon Jan 21 16:17:16 2002
+++ linux/drivers/net/au1000_eth.c	Thu Feb  7 16:09:56 2002
@@ -1135,12 +1135,14 @@
 
 	/* fixme */
 	switch(cmd) { 
-		case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
+		case SIOCGMIIPHY:		/* Get the address of the PHY in use. */
 		data[0] = PHY_ADDRESS;
-		case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+
+		case SIOCGMIIREG:		/* Read the specified MII register. */
 		//data[3] = mdio_read(ioaddr, data[0], data[1]); 
 		return 0;
-		case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+		case SIOCSMIIREG:		/* Write the specified MII register */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		//mdio_write(ioaddr, data[0], data[1], data[2]);
diff -urN linux-2.5.4-pre2/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c
--- linux-2.5.4-pre2/drivers/net/cs89x0.c	Thu Jan 24 11:51:10 2002
+++ linux/drivers/net/cs89x0.c	Thu Feb  7 16:09:56 2002
@@ -1109,7 +1109,7 @@
 				printk(	"%s: dma %lx %lx\n",
 					dev->name,
 					(unsigned long)lp->dma_buff,
-					(unsigned long)virt_to_bus(lp->dma_buff));
+					(unsigned long)isa_virt_to_bus(lp->dma_buff));
 			}
 			if ((unsigned long) lp->dma_buff >= MAX_DMA_ADDRESS ||
 			    !dma_page_eq(lp->dma_buff, lp->dma_buff+lp->dmasize*1024-1)) {
@@ -1128,7 +1128,7 @@
 			disable_dma(dev->dma);
 			clear_dma_ff(dev->dma);
 			set_dma_mode(dev->dma, 0x14); /* auto_init as well */
-			set_dma_addr(dev->dma, virt_to_bus(lp->dma_buff));
+			set_dma_addr(dev->dma, isa_virt_to_bus(lp->dma_buff));
 			set_dma_count(dev->dma, lp->dmasize*1024);
 			enable_dma(dev->dma);
 			spin_unlock_irqrestore(&lp->lock, flags);
diff -urN linux-2.5.4-pre2/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- linux-2.5.4-pre2/drivers/net/de4x5.c	Thu Jan 10 16:23:45 2002
+++ linux/drivers/net/de4x5.c	Thu Feb  7 16:09:56 2002
@@ -3645,7 +3645,7 @@
     tmp = virt_to_bus(p->data);
     i = ((tmp + ALIGN) & ~ALIGN) - tmp;
     skb_reserve(p, i);
-    lp->rx_ring[index].buf = tmp + i;
+    lp->rx_ring[index].buf = cpu_to_le32(tmp + i);
 
     ret = lp->rx_skb[index];
     lp->rx_skb[index] = p;
@@ -5616,7 +5616,7 @@
 	if (!capable(CAP_NET_ADMIN)) return -EPERM;
 	omr = inl(DE4X5_OMR);
 	omr &= ~OMR_PR;
-	outb(omr, DE4X5_OMR);
+	outl(omr, DE4X5_OMR);
 	dev->flags &= ~IFF_PROMISC;
 	break;
 
diff -urN linux-2.5.4-pre2/drivers/net/defxx.c linux/drivers/net/defxx.c
--- linux-2.5.4-pre2/drivers/net/defxx.c	Thu Jan  3 12:20:12 2002
+++ linux/drivers/net/defxx.c	Thu Feb  7 16:09:56 2002
@@ -199,6 +199,8 @@
  *		Feb 2001	davej		PCI enable cleanups.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 /* Include files */
 
 #include <linux/module.h>
diff -urN linux-2.5.4-pre2/drivers/net/dl2k.c linux/drivers/net/dl2k.c
--- linux-2.5.4-pre2/drivers/net/dl2k.c	Mon Jan 21 16:17:16 2002
+++ linux/drivers/net/dl2k.c	Thu Feb  7 16:09:56 2002
@@ -15,18 +15,24 @@
     0.01	2001/05/03	Created DL2000-based linux driver
     0.02	2001/05/21	Added VLAN and hardware checksum support.
     1.00	2001/06/26	Added jumbo frame support.
-    1.01	2001/08/21	Added two parameters, int_count and int_timeout.
+    1.01	2001/08/21	Added two parameters, rx_coalesce and rx_timeout.
     1.02	2001/10/08	Supported fiber media.
     				Added flow control parameters.
-    1.03	2001/10/12	Changed the default media to 1000mbps_fd for the 
-    				fiber devices.
-    1.04	2001/11/08	Fixed a bug which Tx stop when a very busy case.
-*/
+    1.03	2001/10/12	Changed the default media to 1000mbps_fd for 
+    				the fiber devices.
+    1.04	2001/11/08	Fixed Tx stopped when tx very busy.
+    1.05	2001/11/22	Fixed Tx stopped when unidirectional tx busy.
+    1.06	2001/12/13	Fixed disconnect bug at 10Mbps mode.
+    				Fixed tx_full flag incorrect.
+				Added tx_coalesce paramter.
+    1.07	2002/01/03	Fixed miscount of RX frame error.
+    1.08	2002/01/17	Fixed the multicast bug.
+ */
 
 #include "dl2k.h"
 
 static char version[] __devinitdata =
-    KERN_INFO "D-Link DL2000-based linux driver v1.04 2001/11/08\n";
+    KERN_INFO "D-Link DL2000-based linux driver v1.08 2002/01/17\n";
 
 #define MAX_UNITS 8
 static int mtu[MAX_UNITS];
@@ -36,11 +42,13 @@
 static int tx_flow[MAX_UNITS];
 static int rx_flow[MAX_UNITS];
 static int copy_thresh;
-static int int_count;		/* Rx frame count each interrupt */
-static int int_timeout;		/* Rx DMA wait time in 64ns increments */
+static int rx_coalesce = DEFAULT_RXC;
+static int rx_timeout = DEFAULT_RXT;	
+static int tx_coalesce = DEFAULT_TXC;	
 
 MODULE_AUTHOR ("Edward Peng");
 MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter");
+MODULE_LICENSE("GPL");
 MODULE_PARM (mtu, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (media, "1-" __MODULE_STRING (MAX_UNITS) "s");
 MODULE_PARM (vlan, "1-" __MODULE_STRING (MAX_UNITS) "i");
@@ -48,13 +56,16 @@
 MODULE_PARM (tx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (rx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (copy_thresh, "i");
-MODULE_PARM (int_count, "i");
-MODULE_PARM (int_timeout, "i");
+MODULE_PARM (rx_coalesce, "i");	/* Rx frame count each interrupt */
+MODULE_PARM (rx_timeout, "i");	/* Rx DMA wait time in 64ns increments */
+MODULE_PARM (tx_coalesce, "i"); /* HW xmit count each TxComplete [1-8] */
+
 
 /* Enable the default interrupts */
+#define DEFAULT_INTR (RxDMAComplete | HostError | IntRequested | TxComplete| \
+       UpdateStats | LinkEvent)
 #define EnableInt() \
-writew(RxDMAComplete | HostError | IntRequested | TxComplete| \
-       UpdateStats | LinkEvent, ioaddr + IntEnable)
+writew(DEFAULT_INTR, ioaddr + IntEnable)
 
 static int max_intrloop = 50;
 static int multicast_filter_limit = 0x40;
@@ -162,11 +173,11 @@
 				np->speed = 10;
 				np->full_duplex = 0;
 			} else if (strcmp (media[card_idx], "1000mbps_fd") == 0 ||
-				 strcmp (media[card_idx], "5") == 0) {
+				 strcmp (media[card_idx], "6") == 0) {
 				np->speed=1000;
 				np->full_duplex=1;
 			} else if (strcmp (media[card_idx], "1000mbps_hd") == 0 ||
-				 strcmp (media[card_idx], "6") == 0) {
+				 strcmp (media[card_idx], "5") == 0) {
 				np->speed = 1000;
 				np->full_duplex = 0;
 			} else {
@@ -175,7 +186,7 @@
 		}
 		if (jumbo[card_idx] != 0) {
 			np->jumbo = 1;
-			dev->mtu = 9000;
+			dev->mtu = MAX_JUMBO;
 		} else {
 			np->jumbo = 0;
 			if (mtu[card_idx] > 0 && mtu[card_idx] < PACKET_SIZE)
@@ -183,14 +194,17 @@
 		}
 		np->vlan = (vlan[card_idx] > 0 && vlan[card_idx] < 4096) ?
 		    vlan[card_idx] : 0;
-		if (int_count != 0 && int_timeout != 0) {
-			np->int_count = int_count;
-			np->int_timeout = int_timeout;
+		if (rx_coalesce != 0 && rx_timeout != 0) {
+			np->rx_coalesce = rx_coalesce;
+			np->rx_timeout = rx_timeout;
 			np->coalesce = 1;
 		}
 		np->tx_flow = (tx_flow[card_idx]) ? 1 : 0;
 		np->rx_flow = (rx_flow[card_idx]) ? 1 : 0;
-		
+		if (tx_coalesce < 1)
+			tx_coalesce = 1;
+		if (tx_coalesce > 8)
+			tx_coalesce = 8;
 	}
 	dev->open = &rio_open;
 	dev->hard_start_xmit = &start_xmit;
@@ -201,8 +215,8 @@
 	dev->tx_timeout = &tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->change_mtu = &change_mtu;
-#ifdef TX_HW_CHECKSUM
-	dev->features = NETIF_F_SG | NETIF_F_HW_CSUM;
+#if 0
+	dev->features = NETIF_F_IP_CSUM;
 #endif
 	pci_set_drvdata (pdev, dev);
 
@@ -326,7 +340,7 @@
 	}
 
 	/* Check CRC */
- 	crc = ~ether_crc_le(256-4, sromdata);
+	crc = ~ether_crc_le(256 - 4, sromdata);
 	if (psrom->crc != crc) {
 		printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name);
 		return -1;
@@ -388,13 +402,12 @@
 	i = request_irq (dev->irq, &rio_interrupt, SA_SHIRQ, dev->name, dev);
 	if (i)
 		return i;
-
 	/* DebugCtrl bit 4, 5, 9 must set */
 	writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);
 
 	/* Jumbo frame */
 	if (np->jumbo != 0)
-		writew (9014, ioaddr + MaxFrameSize);
+		writew (MAX_JUMBO+14, ioaddr + MaxFrameSize);
 
 	alloc_list (dev);
 
@@ -404,7 +417,7 @@
 
 	set_multicast (dev);
 	if (np->coalesce) {
-		writel (np->int_count | np->int_timeout << 16,
+		writel (np->rx_coalesce | np->rx_timeout << 16,
 			ioaddr + RxDMAIntCtrl);
 	}
 	/* Set RIO to poll every N*320nsec. */
@@ -441,13 +454,31 @@
 	struct netdev_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
 
-	printk (KERN_WARNING "%s: Transmit timed out, TxStatus %4.4x.\n",
+	printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n",
 		dev->name, readl (ioaddr + TxStatus));
+	/* Free used tx skbuffs */
+	for (; np->cur_tx - np->old_tx > 0; np->old_tx++) {
+		int entry = np->old_tx % TX_RING_SIZE;
+		struct sk_buff *skb;
+
+		if (!(np->tx_ring[entry].status & TFDDone))
+			break;
+		skb = np->tx_skbuff[entry];
+		pci_unmap_single (np->pdev,
+				  np->tx_ring[entry].fraginfo,
+				  skb->len, PCI_DMA_TODEVICE);
+		dev_kfree_skb_irq (skb);
+		np->tx_skbuff[entry] = 0;
+	}
 	dev->if_port = 0;
 	dev->trans_start = jiffies;
 	np->stats.tx_errors++;
-	if (!np->tx_full)
+	/* If the ring is no longer full, clear tx_full and 
+	   call netif_wake_queue() */
+	if (np->tx_full && np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1) {
+		np->tx_full = 0;
 		netif_wake_queue (dev);
+	}
 }
 
  /* allocate and initialize Tx and Rx descriptors */
@@ -465,16 +496,19 @@
 	/* Initialize Tx descriptors, TFDListPtr leaves in start_xmit(). */
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		np->tx_skbuff[i] = 0;
-		np->tx_ring[i].status = 0;
+		np->tx_ring[i].status = cpu_to_le64 (TFDDone);
+		np->tx_ring[i].next_desc = cpu_to_le64 (np->tx_ring_dma +
+					      ((i+1)%TX_RING_SIZE) *
+					      sizeof (struct
+					      netdev_desc));
 	}
 
 	/* Initialize Rx descriptors */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		np->rx_ring[i].next_desc = cpu_to_le64 (np->rx_ring_dma +
-							((i +
-							  1) % RX_RING_SIZE) *
-							sizeof (struct
-								netdev_desc));
+						((i + 1) % RX_RING_SIZE) *
+						sizeof (struct
+						netdev_desc));
 		np->rx_ring[i].status = 0;
 		np->rx_ring[i].fraginfo = 0;
 		np->rx_skbuff[i] = 0;
@@ -522,13 +556,12 @@
 	entry = np->cur_tx % TX_RING_SIZE;
 	np->tx_skbuff[entry] = skb;
 	txdesc = &np->tx_ring[entry];
-	txdesc->next_desc = 0;
 
 	/* Set TFDDone to avoid TxDMA gather this descriptor */
 	txdesc->status = cpu_to_le64 (TFDDone);
 	txdesc->status |=
 	    cpu_to_le64 (entry | WordAlignDisable | (1 << FragCountShift));
-#ifdef TX_HW_CHECKSUM
+#if 0
 	if (skb->ip_summed == CHECKSUM_HW) {
 		txdesc->status |=
 		    cpu_to_le64 (TCPChecksumEnable | UDPChecksumEnable |
@@ -544,21 +577,13 @@
 
 	/* Send one packet each time at 10Mbps mode */
 	/* Tx coalescing loop do not exceed 8 */
-	if (entry % 0x08 == 0 || np->speed == 10)
+	if (entry % tx_coalesce == 0 || np->speed == 10)
 		txdesc->status |= cpu_to_le64 (TxIndicate);
 	txdesc->fraginfo = cpu_to_le64 (pci_map_single (np->pdev, skb->data,
 							skb->len,
 							PCI_DMA_TODEVICE));
 	txdesc->fraginfo |= cpu_to_le64 (skb->len) << 48;
 
-	/* Chain the last descriptor's pointer to this one */
-	if (np->last_tx)
-		np->last_tx->next_desc = cpu_to_le64 (np->tx_ring_dma +
-						      entry *
-						      sizeof (struct
-							      netdev_desc));
-	np->last_tx = txdesc;
-
 	/* Clear TFDDone, then TxDMA start to send this descriptor */
 	txdesc->status &= ~cpu_to_le64 (TFDDone);
 
@@ -570,8 +595,10 @@
 	if (np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1 && np->speed != 10) {
 		/* do nothing */
 	} else {
+		spin_lock_irqsave(&np->lock, flags);
 		np->tx_full = 1;
 		netif_stop_queue (dev);
+		spin_unlock_irqrestore (&np->lock, flags);
 	}
 
 	/* The first TFDListPtr */
@@ -580,15 +607,15 @@
 			dev->base_addr + TFDListPtr0);
 		writel (0, dev->base_addr + TFDListPtr1);
 	}
-
-	spin_lock_irqsave (&np->lock, flags);
+	
 	if (np->old_tx > TX_RING_SIZE) {
+		spin_lock_irqsave (&np->lock, flags);
 		tx_shift = TX_RING_SIZE;
 		np->old_tx -= tx_shift;
 		np->cur_tx -= tx_shift;
+		spin_unlock_irqrestore (&np->lock, flags);
 	}
-	spin_unlock_irqrestore (&np->lock, flags);
-
+	
 	/* NETDEV WATCHDOG timer */
 	dev->trans_start = jiffies;
 	return 0;
@@ -605,33 +632,24 @@
 
 	ioaddr = dev->base_addr;
 	np = dev->priv;
-	spin_lock (&np->lock);
+	spin_lock(&np->lock);
 	while (1) {
-		int_status = readw (ioaddr + IntStatus) &
-		    (HostError | TxComplete | IntRequested |
-		     UpdateStats | LinkEvent | RxDMAComplete);
-		writew (int_status & (HostError | TxComplete | RxComplete |
-				      IntRequested | UpdateStats | LinkEvent |
-				      TxDMAComplete | RxDMAComplete | RFDListEnd
-				      | RxDMAPriority), ioaddr + IntStatus);
+		int_status = readw (ioaddr + IntStatus); 
+		writew (int_status, ioaddr + IntStatus);
+		int_status &= DEFAULT_INTR;
 		if (int_status == 0)
 			break;
 		/* Processing received packets */
 		if (int_status & RxDMAComplete)
 			receive_packet (dev);
 		/* TxComplete interrupt */
-		if (int_status & TxComplete || np->tx_full) {
-			int tx_status = readl (ioaddr + TxStatus);
+		if ((int_status & TxComplete) || np->tx_full) {
+			int tx_status;
+			tx_status = readl (ioaddr + TxStatus);
 			if (tx_status & 0x01)
 				tx_error (dev, tx_status);
-			/* Send one packet each time at 10Mbps mode */
-			if (np->speed == 10) {
-				np->tx_full = 0;
-				netif_wake_queue (dev);
-			}
-
 			/* Free used tx skbuffs */
-			for (; np->cur_tx - np->old_tx > 0; np->old_tx++) {
+			for (;np->cur_tx - np->old_tx > 0; np->old_tx++) {
 				int entry = np->old_tx % TX_RING_SIZE;
 				struct sk_buff *skb;
 
@@ -648,9 +666,12 @@
 		/* If the ring is no longer full, clear tx_full and 
 		   call netif_wake_queue() */
 		if (np->tx_full && np->cur_tx - np->old_tx < TX_QUEUE_LEN - 1) {
-			np->tx_full = 0;
-			netif_wake_queue (dev);
+			if (np->speed != 10 || int_status & TxComplete) {
+				np->tx_full = 0;
+				netif_wake_queue (dev);
+			}
 		}
+
 		/* Handle uncommon events */
 		if (int_status &
 		    (IntRequested | HostError | LinkEvent | UpdateStats))
@@ -665,7 +686,7 @@
 			break;
 		}
 	}
-	spin_unlock (&np->lock);
+	spin_unlock(&np->lock);
 }
 
 static void
@@ -741,7 +762,7 @@
 		np->stats.collisions++;
 #endif
 
-	/* Restart the Tx. */
+	/* Restart the Tx */
 	writel (readw (dev->base_addr + MACCtrl) | TxEnable, ioaddr + MACCtrl);
 }
 
@@ -782,7 +803,7 @@
 			if (frame_status & 0x00300000)
 				np->stats.rx_length_errors++;
 			if (frame_status & 0x00010000)
-				np->stats.rx_fifo_errors++;
+	 			np->stats.rx_fifo_errors++;
 			if (frame_status & 0x00060000)
 				np->stats.rx_frame_errors++;
 			if (frame_status & 0x00080000)
@@ -807,7 +828,7 @@
 				skb_put (skb, pkt_len);
 			}
 			skb->protocol = eth_type_trans (skb, dev);
-#ifdef RX_HW_CHECKSUM
+#if 0
 			/* Checksum done by hw, but csum value unavailable. */
 			if (!(frame_status & (TCPError | UDPError | IPError))) {
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -898,7 +919,7 @@
 	/* PCI Error, a catastronphic error related to the bus interface 
 	   occurs, set GlobalReset and HostReset to reset. */
 	if (int_status & HostError) {
-		printk (KERN_ERR "%s: PCI Error! IntStatus %4.4x.\n",
+		printk (KERN_ERR "%s: HostError! IntStatus %4.4x.\n",
 			dev->name, int_status);
 		writew (GlobalReset | HostReset, ioaddr + ASICCtrl + 2);
 		mdelay (500);
@@ -913,8 +934,8 @@
 	u16 temp1;
 	u16 temp2;
 	int i;
-	/* All statistics registers need to acknowledge,
-	   else overflow could cause some problem */
+	/* All statistics registers need to be acknowledged,
+	   else statistic overflow could cause problems */
 	np->stats.rx_packets += readl (ioaddr + FramesRcvOk);
 	np->stats.tx_packets += readl (ioaddr + FramesXmtOk);
 	np->stats.rx_bytes += readl (ioaddr + OctetRcvOk);
@@ -931,11 +952,11 @@
 	    readl (ioaddr + FramesWDeferredXmt) + temp2;
 
 	/* detailed rx_error */
-	np->stats.rx_length_errors += readw (ioaddr + InRangeLengthErrors) +
-	    readw (ioaddr + FrameTooLongErrors);
+	np->stats.rx_length_errors += readw (ioaddr + FrameTooLongErrors);
 	np->stats.rx_crc_errors += readw (ioaddr + FrameCheckSeqError);
 
 	/* Clear all other statistic register. */
+	readw (ioaddr + InRangeLengthErrors);
 	readw (ioaddr + MacControlFramesXmtd);
 	readw (ioaddr + BcstFramesXmtdOk);
 	readl (ioaddr + McstFramesXmtdOk);
@@ -960,7 +981,7 @@
 change_mtu (struct net_device *dev, int new_mtu)
 {
 	struct netdev_private *np = dev->priv;
-	int max = (np->jumbo) ? 9000 : 1536;
+	int max = (np->jumbo) ? MAX_JUMBO : 1536;
 
 	if ((new_mtu < 68) || (new_mtu > max)) {
 		return -EINVAL;
@@ -978,36 +999,42 @@
 	u32 hash_table[2];
 	u16 rx_mode = 0;
 	int i;
+	int bit;
+	int index, crc;
 	struct dev_mc_list *mclist;
 	struct netdev_private *np = dev->priv;
-
-	/* Default: receive broadcast and unicast */
-	rx_mode = ReceiveBroadcast | ReceiveUnicast;
+	
+	hash_table[0] = hash_table[1] = 0;
+	/* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */
+	hash_table[1] |= 0x02000000;
 	if (dev->flags & IFF_PROMISC) {
 		/* Receive all frames promiscuously. */
-		rx_mode |= ReceiveAllFrames;
-	} else if (((dev->flags & IFF_MULTICAST)
-		    && (dev->mc_count > multicast_filter_limit))
-		   || (dev->flags & IFF_ALLMULTI)) {
+		rx_mode = ReceiveAllFrames;
+	} else if ((dev->flags & IFF_ALLMULTI) || 
+			(dev->mc_count > multicast_filter_limit)) {
 		/* Receive broadcast and multicast frames */
-		rx_mode |= ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;
-	} else if ((dev->flags & IFF_MULTICAST) & (dev->mc_count > 0)) {
-		/* Receive broadcast frames and multicast frames filtering by Hashtable */
-		rx_mode |=
+		rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;
+	} else if (dev->mc_count > 0) {
+		/* Receive broadcast frames and multicast frames filtering 
+		   by Hashtable */
+		rx_mode =
 		    ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast;
+		for (i=0, mclist = dev->mc_list; mclist && i < dev->mc_count; 
+				i++, mclist=mclist->next) {
+			crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr);
+			for (index=0, bit=0; bit<6; bit++, crc<<=1) {
+				if (crc & 0x80000000) index |= 1 << bit;
+			}
+			hash_table[index / 32] |= (1 << (index % 32));
+		}
+	} else {
+		rx_mode = ReceiveBroadcast | ReceiveUnicast;
 	}
 	if (np->vlan) {
 		/* ReceiveVLANMatch field in ReceiveMode */
 		rx_mode |= ReceiveVLANMatch;
 	}
-	hash_table[0] = 0x00000000;
-	hash_table[1] = 0x00000000;
 
-	for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
-	     i++, mclist = mclist->next) {
-		set_bit (ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f,
-			 hash_table);
-	}
 	writel (hash_table[0], ioaddr + HashTable0);
 	writel (hash_table[1], ioaddr + HashTable1);
 	writew (rx_mode, ioaddr + ReceiveMode);
@@ -1677,8 +1704,9 @@
  
 Compile command: 
  
-gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2x.c
+gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2k.c
 
 Read Documentation/networking/dl2k.txt for details.
 
 */
+
diff -urN linux-2.5.4-pre2/drivers/net/dl2k.h linux/drivers/net/dl2k.h
--- linux-2.5.4-pre2/drivers/net/dl2k.h	Thu Jan 10 16:23:45 2002
+++ linux/drivers/net/dl2k.h	Thu Feb  7 16:09:56 2002
@@ -34,7 +34,7 @@
 #include <linux/spinlock.h>
 #include <linux/time.h>
 #define TX_RING_SIZE	128
-#define TX_QUEUE_LEN	96	/* Limit ring entries actually used.  */
+#define TX_QUEUE_LEN	120	/* Limit ring entries actually used.  */
 #define RX_RING_SIZE 	128
 #define TX_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct netdev_desc)
 #define RX_TOTAL_SIZE	RX_RING_SIZE*sizeof(struct netdev_desc)
@@ -183,12 +183,12 @@
 
 /* Bits in the ReceiveMode register. */
 enum ReceiveMode_bits {
-	ReceiveIPMulticast = 0x0020,
-	ReceiveMulticastHash = 0x0010,
-	ReceiveAllFrames = 0x0008,
-	ReceiveBroadcast = 0x0004,
-	ReceiveMulticast = 0x0002,
 	ReceiveUnicast = 0x0001,
+	ReceiveMulticast = 0x0002,
+	ReceiveBroadcast = 0x0004,
+	ReceiveAllFrames = 0x0008,
+	ReceiveMulticastHash = 0x0010,
+	ReceiveIPMulticast = 0x0020,
 	ReceiveVLANMatch = 0x0100,
 	ReceiveVLANHash = 0x0200,
 };
@@ -650,20 +650,20 @@
 	struct pci_dev *pdev;
 	spinlock_t lock;
 	struct net_device_stats stats;
-	unsigned int rx_buf_sz;	/* Based on MTU+slack. */
-	unsigned int speed;	/* Operating speed */
-	unsigned int vlan;	/* VLAN Id */
-	unsigned int chip_id;	/* PCI table chip id */
-	unsigned int int_count; /* Maximum frames each RxDMAComplete intr */
-	unsigned int int_timeout; /* Wait time between RxDMAComplete intr */
-	unsigned int tx_full:1;	/* The Tx queue is full. */
+	unsigned int rx_buf_sz;		/* Based on MTU+slack. */
+	unsigned int speed;		/* Operating speed */
+	unsigned int vlan;		/* VLAN Id */
+	unsigned int chip_id;		/* PCI table chip id */
+	unsigned int rx_coalesce; 	/* Maximum frames each RxDMAComplete intr */
+	unsigned int rx_timeout; 	/* Wait time between RxDMAComplete intr */
+	unsigned int tx_full:1;		/* The Tx queue is full. */
 	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
 	unsigned int an_enable:2;	/* Auto-Negotiated Enable */
 	unsigned int jumbo:1;		/* Jumbo frame enable */
 	unsigned int coalesce:1;	/* Rx coalescing enable */
 	unsigned int tx_flow:1;		/* Tx flow control enable */
 	unsigned int rx_flow:1;		/* Rx flow control enable */
-	unsigned int phy_media:1;	/* 1: fiber, 0: copper */ 
+	unsigned int phy_media:1;	/* 1: fiber, 0: copper */
 	struct netdev_desc *last_tx;	/* Last Tx descriptor used. */
 	unsigned long cur_rx, old_rx;	/* Producer/consumer ring indices */
 	unsigned long cur_tx, old_tx;
@@ -698,7 +698,12 @@
 MODULE_DEVICE_TABLE (pci, rio_pci_tbl);
 #define TX_TIMEOUT  (4*HZ)
 #define PACKET_SIZE		1536
+#define MAX_JUMBO		8000
 #define RIO_IO_SIZE             340
+#define DEFAULT_RXC		5
+#define DEFAULT_RXT		750
+#define DEFAULT_TXC		1
+#define MAX_TXC			8
 #ifdef RIO_DEBUG
 #define DEBUG_TFD_DUMP(x) debug_tfd_dump(x)
 #define DEBUG_RFD_DUMP(x,flag) debug_rfd_dump(x,flag)
@@ -792,6 +797,7 @@
 	}
 	if (np->rx_debug == 7) {
 
+#error Please convert me to Documentation/DMA-mapping.txt
 		phead =
 		    bus_to_virt (le64_to_cpu (desc->fraginfo & 0xffffffffff));
 		for (pchar = phead, i = 0; i < pkt_len; i++, pchar++) {
diff -urN linux-2.5.4-pre2/drivers/net/epic100.c linux/drivers/net/epic100.c
--- linux-2.5.4-pre2/drivers/net/epic100.c	Thu Jan 10 16:23:45 2002
+++ linux/drivers/net/epic100.c	Thu Feb  7 16:09:56 2002
@@ -53,11 +53,18 @@
 	LK1.1.10:
 	* revert MII transceiver init change (jgarzik)
 
+	LK1.1.11:
+	* implement ETHTOOL_[GS]SET, _NWAY_RST, _[GS]MSGLVL, _GLINK (jgarzik)
+	* replace some MII-related magic numbers with constants
+
+	LK1.1.12:
+	* fix power-up sequence
+
 */
 
 #define DRV_NAME	"epic100"
-#define DRV_VERSION	"1.11+LK1.1.10"
-#define DRV_RELDATE	"July 6, 2001"
+#define DRV_VERSION	"1.11+LK1.1.12"
+#define DRV_RELDATE	"Jan 18, 2002"
 
 
 /* The user-configurable values.
@@ -318,12 +325,9 @@
 	/* Ring pointers. */
 	spinlock_t lock;				/* Group with Tx control cache line. */
 	unsigned int cur_tx, dirty_tx;
-	struct descriptor  *last_tx_desc;
 
 	unsigned int cur_rx, dirty_rx;
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
-	struct descriptor  *last_rx_desc;
-	long last_rx_time;					/* Last Rx, in jiffies. */
 
 	struct pci_dev *pci_dev;			/* PCI bus location. */
 	int chip_id, chip_flags;
@@ -335,13 +339,9 @@
 	signed char phys[4];				/* MII device addresses. */
 	u16 advertising;					/* NWay media advertisement */
 	int mii_phy_cnt;
+	struct mii_if_info mii;
 	unsigned int tx_full:1;				/* The Tx queue is full. */
-	unsigned int full_duplex:1;			/* Current duplex setting. */
-	unsigned int duplex_lock:1;			/* Duplex forced by the user. */
 	unsigned int default_port:4;		/* Last dev->if_port value. */
-	unsigned int media2:4;				/* Secondary monitored media port. */
-	unsigned int medialock:1;			/* Don't sense media type. */
-	unsigned int mediasense:1;			/* Media sensing in progress. */
 };
 
 static int epic_open(struct net_device *dev);
@@ -420,6 +420,9 @@
 
 	pci_set_drvdata(pdev, dev);
 	ep = dev->priv;
+	ep->mii.dev = dev;
+	ep->mii.mdio_read = mdio_read;
+	ep->mii.mdio_write = mdio_write;
 
 	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
@@ -481,7 +484,7 @@
 	{
 		int phy, phy_idx = 0;
 		for (phy = 1; phy < 32 && phy_idx < sizeof(ep->phys); phy++) {
-			int mii_status = mdio_read(dev, phy, 1);
+			int mii_status = mdio_read(dev, phy, MII_BMSR);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				ep->phys[phy_idx++] = phy;
 				printk(KERN_INFO DRV_NAME "(%s): MII transceiver #%d control "
@@ -492,16 +495,17 @@
 		ep->mii_phy_cnt = phy_idx;
 		if (phy_idx != 0) {
 			phy = ep->phys[0];
-			ep->advertising = mdio_read(dev, phy, 4);
+			ep->mii.advertising = mdio_read(dev, phy, MII_ADVERTISE);
 			printk(KERN_INFO DRV_NAME "(%s): Autonegotiation advertising %4.4x link "
 				   "partner %4.4x.\n",
-				   pdev->slot_name, ep->advertising, mdio_read(dev, phy, 5));
+				   pdev->slot_name, ep->mii.advertising, mdio_read(dev, phy, 5));
 		} else if ( ! (ep->chip_flags & NO_MII)) {
 			printk(KERN_WARNING DRV_NAME "(%s): ***WARNING***: No MII transceiver found!\n",
 			       pdev->slot_name);
 			/* Use the known PHY address of the EPII. */
 			ep->phys[0] = 3;
 		}
+		ep->mii.phy_id = ep->phys[0];
 	}
 
 	/* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
@@ -511,13 +515,11 @@
 
 	/* The lower four bits are the media type. */
 	if (duplex) {
-		ep->duplex_lock = ep->full_duplex = 1;
+		ep->mii.duplex_lock = ep->mii.full_duplex = 1;
 		printk(KERN_INFO DRV_NAME "(%s):  Forced full duplex operation requested.\n",
 		       pdev->slot_name);
 	}
 	dev->if_port = ep->default_port = option;
-	if (ep->default_port)
-		ep->medialock = 1;
 
 	/* The Epic-specific entries in the device structure. */
 	dev->open = &epic_open;
@@ -676,9 +678,8 @@
 	   required by the details of which bits are reset and the transceiver
 	   wiring on the Ositech CardBus card.
 	*/
-#if 0
-	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
-#endif
+
+	outl(0x12, ioaddr + MIICfg);
 	if (ep->chip_flags & MII_PWRDWN)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
@@ -700,29 +701,29 @@
 
 	if (media2miictl[dev->if_port & 15]) {
 		if (ep->mii_phy_cnt)
-			mdio_write(dev, ep->phys[0], 0, media2miictl[dev->if_port&15]);
+			mdio_write(dev, ep->phys[0], MII_BMCR, media2miictl[dev->if_port&15]);
 		if (dev->if_port == 1) {
 			if (debug > 1)
 				printk(KERN_INFO "%s: Using the 10base2 transceiver, MII "
 					   "status %4.4x.\n",
-					   dev->name, mdio_read(dev, ep->phys[0], 1));
+					   dev->name, mdio_read(dev, ep->phys[0], MII_BMSR));
 		}
 	} else {
-		int mii_reg5 = mdio_read(dev, ep->phys[0], 5);
-		if (mii_reg5 != 0xffff) {
-			if ((mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040)
-				ep->full_duplex = 1;
-			else if (! (mii_reg5 & 0x4000))
-				mdio_write(dev, ep->phys[0], 0, 0x1200);
+		int mii_lpa = mdio_read(dev, ep->phys[0], MII_LPA);
+		if (mii_lpa != 0xffff) {
+			if ((mii_lpa & LPA_100FULL) || (mii_lpa & 0x01C0) == LPA_10FULL)
+				ep->mii.full_duplex = 1;
+			else if (! (mii_lpa & LPA_LPACK))
+				mdio_write(dev, ep->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART);
 			if (debug > 1)
 				printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d"
 					   " register read of %4.4x.\n", dev->name,
-					   ep->full_duplex ? "full" : "half",
-					   ep->phys[0], mii_reg5);
+					   ep->mii.full_duplex ? "full" : "half",
+					   ep->phys[0], mii_lpa);
 		}
 	}
 
-	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+	outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	outl(ep->rx_ring_dma, ioaddr + PRxCDAR);
 	outl(ep->tx_ring_dma, ioaddr + PTxCDAR);
 
@@ -742,7 +743,7 @@
 		printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
 			   "%s-duplex.\n",
 			   dev->name, ioaddr, dev->irq, (int)inl(ioaddr + GENCTL),
-			   ep->full_duplex ? "full" : "half");
+			   ep->mii.full_duplex ? "full" : "half");
 
 	/* Set the timer to switch to check for link beat and perhaps switch
 	   to an alternate media type. */
@@ -811,7 +812,7 @@
 
 	ep->tx_threshold = TX_FIFO_THRESH;
 	outl(ep->tx_threshold, ioaddr + TxThresh);
-	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+	outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	outl(ep->rx_ring_dma + (ep->cur_rx%RX_RING_SIZE)*
 		sizeof(struct epic_rx_desc), ioaddr + PRxCDAR);
 	outl(ep->tx_ring_dma + (ep->dirty_tx%TX_RING_SIZE)*
@@ -837,20 +838,20 @@
 {
 	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
-	int mii_reg5 = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], 5) : 0;
-	int negotiated = mii_reg5 & ep->advertising;
+	int mii_lpa = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], MII_LPA) : 0;
+	int negotiated = mii_lpa & ep->mii.advertising;
 	int duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
 
-	if (ep->duplex_lock)
+	if (ep->mii.duplex_lock)
 		return;
-	if (mii_reg5 == 0xffff)		/* Bogus read */
+	if (mii_lpa == 0xffff)		/* Bogus read */
 		return;
-	if (ep->full_duplex != duplex) {
-		ep->full_duplex = duplex;
+	if (ep->mii.full_duplex != duplex) {
+		ep->mii.full_duplex = duplex;
 		printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
 			   " partner capability of %4.4x.\n", dev->name,
-			   ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
-		outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+			   ep->mii.full_duplex ? "full" : "half", ep->phys[0], mii_lpa);
+		outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	}
 }
 
@@ -914,7 +915,6 @@
 	ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
 	ep->dirty_tx = ep->cur_tx = 0;
 	ep->cur_rx = ep->dirty_rx = 0;
-	ep->last_rx_time = jiffies;
 	ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
 
 	/* Initialize all Rx descriptors. */
@@ -1351,17 +1351,66 @@
 		return -EFAULT;
 
 	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy (info.driver, DRV_NAME);
-			strcpy (info.version, DRV_VERSION);
-			strcpy (info.bus_info, np->pci_dev->slot_name);
-			if (copy_to_user (useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
 
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
 	default:
 		break;
 	}
@@ -1380,12 +1429,10 @@
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = ep->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		if (! netif_running(dev)) {
 			outl(0x0200, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
@@ -1400,7 +1447,6 @@
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		if (! netif_running(dev)) {
@@ -1412,11 +1458,11 @@
 			switch (data->reg_num) {
 			case 0:
 				/* Check for autonegotiation on or reset. */
-				ep->duplex_lock = (value & 0x9000) ? 0 : 1;
-				if (ep->duplex_lock)
-					ep->full_duplex = (value & 0x0100) ? 1 : 0;
+				ep->mii.duplex_lock = (value & 0x9000) ? 0 : 1;
+				if (ep->mii.duplex_lock)
+					ep->mii.full_duplex = (value & 0x0100) ? 1 : 0;
 				break;
-			case 4: ep->advertising = value; break;
+			case 4: ep->mii.advertising = value; break;
 			}
 			/* Perhaps check_duplex(dev), depending on chip semantics. */
 		}
diff -urN linux-2.5.4-pre2/drivers/net/fealnx.c linux/drivers/net/fealnx.c
--- linux-2.5.4-pre2/drivers/net/fealnx.c	Thu Jan 24 11:51:10 2002
+++ linux/drivers/net/fealnx.c	Thu Feb  7 16:09:56 2002
@@ -15,8 +15,19 @@
 
 	Support information and updates available at
 	http://www.scyld.com/network/pci-skeleton.html
+
+	Linux kernel updates:
+
+	Version 2.51, Nov 17, 2001 (jgarzik):
+	- Add ethtool support
+	- Replace some MII-related magic numbers with constants
+
 */
 
+#define DRV_NAME	"fealnx"
+#define DRV_VERSION	"2.51"
+#define DRV_RELDATE	"Nov-17-2001"
+
 static int debug;		/* 1-> print debug message */
 static int max_interrupt_work = 20;
 
@@ -72,14 +83,16 @@
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/mii.h>
+#include <linux/ethtool.h>
 #include <linux/crc32.h>
 #include <asm/processor.h>	/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/uaccess.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
-KERN_INFO "fealnx.c:v2.50 1/17/2001\n";
+KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n";
 
 
 /* This driver was written to use PCI memory space, however some x86 systems
@@ -380,6 +393,8 @@
 	dma_addr_t rx_ring_dma;
 	dma_addr_t tx_ring_dma;
 
+	spinlock_t lock;
+
 	struct net_device_stats stats;
 
 	/* Media monitoring timer. */
@@ -404,19 +419,17 @@
 	unsigned int linkok;
 	unsigned int line_speed;
 	unsigned int duplexmode;
-	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
-	unsigned int duplex_lock:1;
-	unsigned int medialock:1;	/* Do not sense media. */
 	unsigned int default_port:4;	/* Last dev->if_port value. */
 	unsigned int PHYType;
 
 	/* MII transceiver section. */
 	int mii_cnt;		/* MII device addresses. */
 	unsigned char phys[2];	/* MII device addresses. */
+	struct mii_if_info mii;
 };
 
 
-static unsigned int mdio_read(struct net_device *dev, int phy_id, int location);
+static int mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int netdev_open(struct net_device *dev);
 static void getlinktype(struct net_device *dev);
@@ -539,9 +552,13 @@
 
 	/* Make certain the descriptor lists are aligned. */
 	np = dev->priv;
+	spin_lock_init(&np->lock);
 	np->pci_dev = pdev;
 	np->flags = skel_netdrv_tbl[chip_id].flags;
 	pci_set_drvdata(pdev, dev);
+	np->mii.dev = dev;
+	np->mii.mdio_read = mdio_read;
+	np->mii.mdio_write = mdio_write;
 
 	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space) {
@@ -606,6 +623,7 @@
 		else
 			np->PHYType = OtherPHY;
 	}
+	np->mii.phy_id = np->phys[0];
 
 	if (dev->mem_start)
 		option = dev->mem_start;
@@ -613,17 +631,14 @@
 	/* The lower four bits are the media type. */
 	if (option > 0) {
 		if (option & 0x200)
-			np->full_duplex = 1;
+			np->mii.full_duplex = 1;
 		np->default_port = option & 15;
-
-		if (np->default_port)
-			np->medialock = 1;
 	}
 
 	if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
-		np->full_duplex = full_duplex[card_idx];
+		np->mii.full_duplex = full_duplex[card_idx];
 
-	if (np->full_duplex) {
+	if (np->mii.full_duplex) {
 		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
 /* 89/6/13 add, (begin) */
 //      if (np->PHYType==MarvellPHY)
@@ -636,10 +651,10 @@
 		}
 /* 89/6/13 add, (end) */
 		if (np->flags == HAS_MII_XCVR)
-			mdio_write(dev, np->phys[0], 4, 0x141);
+			mdio_write(dev, np->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
 		else
-			writel(0x141, dev->base_addr + ANARANLPAR);
-		np->duplex_lock = 1;
+			writel(ADVERTISE_FULL, dev->base_addr + ANARANLPAR);
+		np->mii.duplex_lock = 1;
 	}
 
 	/* The chip-specific entries in the device structure. */
@@ -787,7 +802,7 @@
 }
 
 
-static unsigned int mdio_read(struct net_device *dev, int phyad, int regad)
+static int mdio_read(struct net_device *dev, int phyad, int regad)
 {
 	long miiport = dev->base_addr + MANAGEMENT;
 	ulong miir;
@@ -821,7 +836,7 @@
 	miir &= ~MASK_MIIR_MII_MDC;
 	writel(miir, miiport);
 
-	return data;
+	return data & 0xffff;
 }
 
 
@@ -941,7 +956,7 @@
 // 89/9/1 modify,
 //   np->crvalue = 0x00e40001;    /* tx store and forward, tx/rx enable */
 	np->crvalue |= 0x00e40001;	/* tx store and forward, tx/rx enable */
-	np->full_duplex = np->duplex_lock;
+	np->mii.full_duplex = np->mii.duplex_lock;
 	getlinkstatus(dev);
 	if (np->linkok)
 		getlinktype(dev);
@@ -990,7 +1005,7 @@
 		}
 	} else {
 		for (i = 0; i < DelayTime; ++i) {
-			if (mdio_read(dev, np->phys[0], 1) & 0x4) {
+			if (mdio_read(dev, np->phys[0], MII_BMSR) & BMSR_LSTATUS) {
 				np->linkok = 1;
 				return;
 			}
@@ -1475,7 +1490,7 @@
 						np->stats.tx_window_errors++;
 					if (tx_status & UDF)
 						np->stats.tx_fifo_errors++;
-					if ((tx_status & HF) && np->full_duplex == 0)
+					if ((tx_status & HF) && np->mii.full_duplex == 0)
 						np->stats.tx_heartbeat_errors++;
 
 #ifdef ETHER_STATS
@@ -1751,24 +1766,100 @@
 	writel(np->crvalue, ioaddr + TCRRCR);
 }
 
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	struct netdev_private *np = dev->priv;
+	u32 ethcmd;
+
+	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+		return -EFAULT;
+
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
 
 static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
 
 	switch (cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = ((struct netdev_private *) dev->priv)->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
diff -urN linux-2.5.4-pre2/drivers/net/hamachi.c linux/drivers/net/hamachi.c
--- linux-2.5.4-pre2/drivers/net/hamachi.c	Tue Oct  9 15:13:03 2001
+++ linux/drivers/net/hamachi.c	Thu Feb  7 16:09:56 2002
@@ -1941,17 +1941,14 @@
 	case SIOCETHTOOL:
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = ((struct hamachi_private *)dev->priv)->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		/* TODO: Check the sequencing of this.  Might need to stop and
 		 * restart Rx and Tx engines. -KDU
 		 */
diff -urN linux-2.5.4-pre2/drivers/net/hp100.c linux/drivers/net/hp100.c
--- linux-2.5.4-pre2/drivers/net/hp100.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/net/hp100.c	Thu Feb  7 16:09:56 2002
@@ -83,6 +83,8 @@
 **
 */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #define HP100_DEFAULT_PRIORITY_TX 0
 
 #undef HP100_DEBUG
diff -urN linux-2.5.4-pre2/drivers/net/lance.c linux/drivers/net/lance.c
--- linux-2.5.4-pre2/drivers/net/lance.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/lance.c	Thu Feb  7 16:09:56 2002
@@ -495,15 +495,15 @@
 		lp->init_block.phys_addr[i] = dev->dev_addr[i];
 	lp->init_block.filter[0] = 0x00000000;
 	lp->init_block.filter[1] = 0x00000000;
-	lp->init_block.rx_ring = ((u32)virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
-	lp->init_block.tx_ring = ((u32)virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
+	lp->init_block.rx_ring = ((u32)isa_virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
+	lp->init_block.tx_ring = ((u32)isa_virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
 
 	outw(0x0001, ioaddr+LANCE_ADDR);
 	inw(ioaddr+LANCE_ADDR);
-	outw((short) (u32) virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
+	outw((short) (u32) isa_virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
 	outw(0x0002, ioaddr+LANCE_ADDR);
 	inw(ioaddr+LANCE_ADDR);
-	outw(((u32)virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA);
+	outw(((u32)isa_virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA);
 	outw(0x0000, ioaddr+LANCE_ADDR);
 	inw(ioaddr+LANCE_ADDR);
 
@@ -704,16 +704,16 @@
 	if (lance_debug > 1)
 		printk("%s: lance_open() irq %d dma %d tx/rx rings %#x/%#x init %#x.\n",
 			   dev->name, dev->irq, dev->dma,
-		           (u32) virt_to_bus(lp->tx_ring),
-		           (u32) virt_to_bus(lp->rx_ring),
-			   (u32) virt_to_bus(&lp->init_block));
+		           (u32) isa_virt_to_bus(lp->tx_ring),
+		           (u32) isa_virt_to_bus(lp->rx_ring),
+			   (u32) isa_virt_to_bus(&lp->init_block));
 
 	lance_init_ring(dev, GFP_KERNEL);
 	/* Re-initialize the LANCE, and start it when done. */
 	outw(0x0001, ioaddr+LANCE_ADDR);
-	outw((short) (u32) virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
+	outw((short) (u32) isa_virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
 	outw(0x0002, ioaddr+LANCE_ADDR);
-	outw(((u32)virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA);
+	outw(((u32)isa_virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA);
 
 	outw(0x0004, ioaddr+LANCE_ADDR);
 	outw(0x0915, ioaddr+LANCE_DATA);
@@ -735,7 +735,7 @@
 
 	if (lance_debug > 2)
 		printk("%s: LANCE open after %d ticks, init block %#x csr0 %4.4x.\n",
-			   dev->name, i, (u32) virt_to_bus(&lp->init_block), inw(ioaddr+LANCE_DATA));
+			   dev->name, i, (u32) isa_virt_to_bus(&lp->init_block), inw(ioaddr+LANCE_DATA));
 
 	return 0;					/* Always succeed */
 }
@@ -799,7 +799,7 @@
 		if (rx_buff == NULL)
 			lp->rx_ring[i].base = 0;
 		else
-			lp->rx_ring[i].base = (u32)virt_to_bus(rx_buff) | 0x80000000;
+			lp->rx_ring[i].base = (u32)isa_virt_to_bus(rx_buff) | 0x80000000;
 		lp->rx_ring[i].buf_length = -PKT_BUF_SZ;
 	}
 	/* The Tx buffer address is filled in as needed, but we do need to clear
@@ -814,8 +814,8 @@
 		lp->init_block.phys_addr[i] = dev->dev_addr[i];
 	lp->init_block.filter[0] = 0x00000000;
 	lp->init_block.filter[1] = 0x00000000;
-	lp->init_block.rx_ring = ((u32)virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
-	lp->init_block.tx_ring = ((u32)virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
+	lp->init_block.rx_ring = ((u32)isa_virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
+	lp->init_block.tx_ring = ((u32)isa_virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
 }
 
 static void
@@ -904,17 +904,17 @@
 
 	/* If any part of this buffer is >16M we must copy it to a low-memory
 	   buffer. */
-	if ((u32)virt_to_bus(skb->data) + skb->len > 0x01000000) {
+	if ((u32)isa_virt_to_bus(skb->data) + skb->len > 0x01000000) {
 		if (lance_debug > 5)
 			printk("%s: bouncing a high-memory packet (%#x).\n",
-				   dev->name, (u32)virt_to_bus(skb->data));
+				   dev->name, (u32)isa_virt_to_bus(skb->data));
 		memcpy(&lp->tx_bounce_buffs[entry], skb->data, skb->len);
 		lp->tx_ring[entry].base =
-			((u32)virt_to_bus((lp->tx_bounce_buffs + entry)) & 0xffffff) | 0x83000000;
+			((u32)isa_virt_to_bus((lp->tx_bounce_buffs + entry)) & 0xffffff) | 0x83000000;
 		dev_kfree_skb(skb);
 	} else {
 		lp->tx_skbuff[entry] = skb;
-		lp->tx_ring[entry].base = ((u32)virt_to_bus(skb->data) & 0xffffff) | 0x83000000;
+		lp->tx_ring[entry].base = ((u32)isa_virt_to_bus(skb->data) & 0xffffff) | 0x83000000;
 	}
 	lp->cur_tx++;
 
@@ -1112,7 +1112,7 @@
 				skb_reserve(skb,2);	/* 16 byte align */
 				skb_put(skb,pkt_len);	/* Make room */
 				eth_copy_and_sum(skb,
-					(unsigned char *)bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)),
+					(unsigned char *)isa_bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)),
 					pkt_len,0);
 				skb->protocol=eth_type_trans(skb,dev);
 				netif_rx(skb);
diff -urN linux-2.5.4-pre2/drivers/net/lasi_82596.c linux/drivers/net/lasi_82596.c
--- linux-2.5.4-pre2/drivers/net/lasi_82596.c	Tue Oct 16 21:56:29 2001
+++ linux/drivers/net/lasi_82596.c	Thu Feb  7 16:09:56 2002
@@ -1184,7 +1184,7 @@
 			printk("%s: Couldn't get shared memory\n", dev->name);
 			return -ENOMEM;
 		}
-		dma_addr = virt_to_bus(dev->mem_start);
+		dma_addr = virt_to_phys(dev->mem_start);
 	}
 
 	ether_setup(dev);
diff -urN linux-2.5.4-pre2/drivers/net/lne390.c linux/drivers/net/lne390.c
--- linux-2.5.4-pre2/drivers/net/lne390.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/lne390.c	Thu Feb  7 16:09:56 2002
@@ -226,10 +226,10 @@
 	   the card mem within the region covered by `normal' RAM  !!!
 	*/
 	if (dev->mem_start > 1024*1024) {	/* phys addr > 1MB */
-		if (dev->mem_start < virt_to_bus(high_memory)) {
+		if (dev->mem_start < virt_to_phys(high_memory)) {
 			printk(KERN_CRIT "lne390.c: Card RAM overlaps with normal memory!!!\n");
 			printk(KERN_CRIT "lne390.c: Use EISA SCU to set card memory below 1MB,\n");
-			printk(KERN_CRIT "lne390.c: or to an address above 0x%lx.\n", virt_to_bus(high_memory));
+			printk(KERN_CRIT "lne390.c: or to an address above 0x%lx.\n", virt_to_phys(high_memory));
 			printk(KERN_CRIT "lne390.c: Driver NOT installed.\n");
 			ret = -EINVAL;
 			goto cleanup;
diff -urN linux-2.5.4-pre2/drivers/net/mii.c linux/drivers/net/mii.c
--- linux-2.5.4-pre2/drivers/net/mii.c	Thu Jan 24 11:51:10 2002
+++ linux/drivers/net/mii.c	Thu Feb  7 16:09:56 2002
@@ -168,6 +168,10 @@
 	return r;
 }
 
+MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
+MODULE_DESCRIPTION ("MII hardware support library");
+MODULE_LICENSE("GPL");
+
 EXPORT_SYMBOL(mii_link_ok);
 EXPORT_SYMBOL(mii_nway_restart);
 EXPORT_SYMBOL(mii_ethtool_gset);
diff -urN linux-2.5.4-pre2/drivers/net/ne3210.c linux/drivers/net/ne3210.c
--- linux-2.5.4-pre2/drivers/net/ne3210.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/net/ne3210.c	Thu Feb  7 16:09:56 2002
@@ -213,10 +213,10 @@
 	   the card mem within the region covered by `normal' RAM  !!!
 	*/
 	if (dev->mem_start > 1024*1024) {	/* phys addr > 1MB */
-		if (dev->mem_start < virt_to_bus(high_memory)) {
+		if (dev->mem_start < virt_to_phys(high_memory)) {
 			printk(KERN_CRIT "ne3210.c: Card RAM overlaps with normal memory!!!\n");
 			printk(KERN_CRIT "ne3210.c: Use EISA SCU to set card memory below 1MB,\n");
-			printk(KERN_CRIT "ne3210.c: or to an address above 0x%lx.\n", virt_to_bus(high_memory));
+			printk(KERN_CRIT "ne3210.c: or to an address above 0x%lx.\n", virt_to_phys(high_memory));
 			printk(KERN_CRIT "ne3210.c: Driver NOT installed.\n");
 			retval = -EINVAL;
 			goto out2;
diff -urN linux-2.5.4-pre2/drivers/net/ni52.c linux/drivers/net/ni52.c
--- linux-2.5.4-pre2/drivers/net/ni52.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/net/ni52.c	Thu Feb  7 16:09:56 2002
@@ -286,8 +286,8 @@
 	char *iscp_addrs[2];
 	int i;
 
-	p->base = (unsigned long) bus_to_virt((unsigned long)where) + size - 0x01000000;
-	p->memtop = bus_to_virt((unsigned long)where) + size;
+	p->base = (unsigned long) isa_bus_to_virt((unsigned long)where) + size - 0x01000000;
+	p->memtop = isa_bus_to_virt((unsigned long)where) + size;
 	p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
 	memset((char *)p->scp,0, sizeof(struct scp_struct));
 	for(i=0;i<sizeof(struct scp_struct);i++) /* memory was writeable? */
@@ -297,7 +297,7 @@
 	if(p->scp->sysbus != SYSBUSVAL)
 		return 0;
 
-	iscp_addrs[0] = bus_to_virt((unsigned long)where);
+	iscp_addrs[0] = isa_bus_to_virt((unsigned long)where);
 	iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct);
 
 	for(i=0;i<2;i++)
@@ -329,7 +329,7 @@
 	DELAY(1);
 
 	p->scp	= (struct scp_struct *)	(p->base + SCP_DEFAULT_ADDRESS);
-	p->scb	= (struct scb_struct *)	bus_to_virt(dev->mem_start);
+	p->scb	= (struct scb_struct *)	isa_bus_to_virt(dev->mem_start);
 	p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct));
 
 	memset((char *) p->iscp,0,sizeof(struct iscp_struct));
@@ -477,8 +477,8 @@
 																	/* warning: we don't free it on errors */
 	memset((char *) dev->priv,0,sizeof(struct priv));
 
-	((struct priv *) (dev->priv))->memtop = bus_to_virt(dev->mem_start) + size;
-	((struct priv *) (dev->priv))->base =	(unsigned long) bus_to_virt(dev->mem_start) + size - 0x01000000;
+	((struct priv *) (dev->priv))->memtop = isa_bus_to_virt(dev->mem_start) + size;
+	((struct priv *) (dev->priv))->base =	(unsigned long) isa_bus_to_virt(dev->mem_start) + size - 0x01000000;
 	alloc586(dev);
 
 	/* set number of receive-buffs according to memsize */
diff -urN linux-2.5.4-pre2/drivers/net/ni65.c linux/drivers/net/ni65.c
--- linux-2.5.4-pre2/drivers/net/ni65.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/net/ni65.c	Thu Feb  7 16:09:56 2002
@@ -507,10 +507,10 @@
 		p->ib.filter[i] = filter;
 	p->ib.mode = mode;
 
-	p->ib.trp = (u32) virt_to_bus(p->tmdhead) | TMDNUMMASK;
-	p->ib.rrp = (u32) virt_to_bus(p->rmdhead) | RMDNUMMASK;
+	p->ib.trp = (u32) isa_virt_to_bus(p->tmdhead) | TMDNUMMASK;
+	p->ib.rrp = (u32) isa_virt_to_bus(p->rmdhead) | RMDNUMMASK;
 	writereg(0,CSR3);	/* busmaster/no word-swap */
-	pib = (u32) virt_to_bus(&p->ib);
+	pib = (u32) isa_virt_to_bus(&p->ib);
 	writereg(pib & 0xffff,CSR1);
 	writereg(pib >> 16,CSR2);
 
@@ -551,7 +551,7 @@
 			return NULL;
 		}
 	}
-	if( (u32) virt_to_bus(ptr+size) > 0x1000000) {
+	if( (u32) virt_to_phys(ptr+size) > 0x1000000) {
 		printk("%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what);
 		if(type)
 			kfree_skb(skb);
@@ -683,7 +683,7 @@
 #ifdef XMT_VIA_SKB
 			skb_save[i] = p->tmd_skb[i];
 #endif
-			buffer[i] = (u32) bus_to_virt(tmdp->u.buffer);
+			buffer[i] = (u32) isa_bus_to_virt(tmdp->u.buffer);
 			blen[i] = tmdp->blen;
 			tmdp->u.s.status = 0x0;
 		}
@@ -697,7 +697,7 @@
 
 		for(i=0;i<TMDNUM;i++) {
 			int num = (i + p->tmdlast) & (TMDNUM-1);
-			p->tmdhead[i].u.buffer = (u32) virt_to_bus((char *)buffer[num]); /* status is part of buffer field */
+			p->tmdhead[i].u.buffer = (u32) isa_virt_to_bus((char *)buffer[num]); /* status is part of buffer field */
 			p->tmdhead[i].blen = blen[num];
 			if(p->tmdhead[i].u.s.status & XMIT_OWN) {
 				 p->tmdnum = (p->tmdnum + 1) & (TMDNUM-1);
@@ -766,9 +766,9 @@
 	 {
 		 struct rmd *rmdp = p->rmdhead + i;
 #ifdef RCV_VIA_SKB
-		 rmdp->u.buffer = (u32) virt_to_bus(p->recv_skb[i]->data);
+		 rmdp->u.buffer = (u32) isa_virt_to_bus(p->recv_skb[i]->data);
 #else
-		 rmdp->u.buffer = (u32) virt_to_bus(p->recvbounce[i]);
+		 rmdp->u.buffer = (u32) isa_virt_to_bus(p->recvbounce[i]);
 #endif
 		 rmdp->blen = -(R_BUF_SIZE-8);
 		 rmdp->mlen = 0;
@@ -1033,7 +1033,7 @@
 					struct sk_buff *skb1 = p->recv_skb[p->rmdnum];
 					skb_put(skb,R_BUF_SIZE);
 					p->recv_skb[p->rmdnum] = skb;
-					rmdp->u.buffer = (u32) virt_to_bus(skb->data);
+					rmdp->u.buffer = (u32) isa_virt_to_bus(skb->data);
 					skb = skb1;
 					skb_trim(skb,len);
 				}
@@ -1115,7 +1115,7 @@
 			cli();
 
 			tmdp = p->tmdhead + p->tmdnum;
-			tmdp->u.buffer = (u32) virt_to_bus(p->tmdbounce[p->tmdbouncenum]);
+			tmdp->u.buffer = (u32) isa_virt_to_bus(p->tmdbounce[p->tmdbouncenum]);
 			p->tmdbouncenum = (p->tmdbouncenum + 1) & (TMDNUM - 1);
 
 #ifdef XMT_VIA_SKB
@@ -1125,7 +1125,7 @@
 			cli();
 
 			tmdp = p->tmdhead + p->tmdnum;
-			tmdp->u.buffer = (u32) virt_to_bus(skb->data);
+			tmdp->u.buffer = (u32) isa_virt_to_bus(skb->data);
 			p->tmd_skb[p->tmdnum] = skb;
 		}
 #endif
diff -urN linux-2.5.4-pre2/drivers/net/ns83820.c linux/drivers/net/ns83820.c
--- linux-2.5.4-pre2/drivers/net/ns83820.c	Fri Nov  9 13:45:35 2001
+++ linux/drivers/net/ns83820.c	Thu Feb  7 16:09:56 2002
@@ -1,4 +1,4 @@
-#define VERSION "0.13"
+#define VERSION "0.14"
 /* ns83820.c by Benjamin LaHaise <bcrl@redhat.com>
  *
  * $Revision: 1.34.2.8 $
@@ -45,6 +45,7 @@
  *			0.12 - add statistics counters
  *			     - add allmulti/promisc support
  *	20011009	0.13 - hotplug support, other smaller pci api cleanups
+ *	20011117	0.14 - ethtool GDRVINFO, GLINK support
  *
  * Driver Overview
  * ===============
@@ -86,9 +87,11 @@
 #include <linux/in.h>	/* for IPPROTO_... */
 #include <linux/eeprom.h>
 #include <linux/compiler.h>
+#include <linux/ethtool.h>
 //#include <linux/skbrefill.h>
 
 #include <asm/io.h>
+#include <asm/uaccess.h>
 
 /* Dprintk is used for more interesting debug events */
 #undef Dprintk
@@ -1007,6 +1010,59 @@
 	return &dev->stats;
 }
 
+static int ns83820_ethtool_ioctl (struct ns83820 *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+		return -EFAULT;
+
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO:
+		{
+			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+			strcpy (info.driver, "ns83820");
+			strcpy (info.version, VERSION);
+			strcpy (info.bus_info, dev->pci_dev->slot_name);
+			if (copy_to_user (useraddr, &info, sizeof (info)))
+				return -EFAULT;
+			return 0;
+		}
+
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		u32 cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY;
+
+		if (cfg & CFG_LNKSTS)
+			edata.data = 1;
+		else
+			edata.data = 0;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int ns83820_ioctl(struct net_device *_dev, struct ifreq *rq, int cmd)
+{
+	struct ns83820 *dev = _dev->priv;
+
+	switch(cmd) {
+	case SIOCETHTOOL:
+		return ns83820_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static void ns83820_irq(int foo, void *data, struct pt_regs *regs)
 {
 	struct ns83820 *dev = data;
@@ -1294,6 +1350,7 @@
 	dev->net_dev.get_stats = ns83820_get_stats;
 	dev->net_dev.change_mtu = ns83820_change_mtu;
 	dev->net_dev.set_multicast_list = ns83820_set_multicast;
+	dev->net_dev.do_ioctl = ns83820_ioctl;
 	//FIXME: dev->net_dev.tx_timeout = ns83820_tx_timeout;
 
 	pci_set_drvdata(pci_dev, dev);
diff -urN linux-2.5.4-pre2/drivers/net/pci-skeleton.c linux/drivers/net/pci-skeleton.c
--- linux-2.5.4-pre2/drivers/net/pci-skeleton.c	Thu Jan 10 16:23:45 2002
+++ linux/drivers/net/pci-skeleton.c	Thu Feb  7 16:09:56 2002
@@ -834,7 +834,7 @@
 		printk (KERN_INFO
 			"%s: Media type forced to Full Duplex.\n",
 			dev->name);
-		mdio_write (dev, tp->phys[0], 4, 0x141);
+		mdio_write (dev, tp->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
 		tp->duplex_lock = 1;
 	}
 
@@ -1235,20 +1235,20 @@
 	struct netdrv_private *tp = dev->priv;
 	void *ioaddr = tp->mmio_addr;
 	int next_tick = 60 * HZ;
-	int mii_reg5;
+	int mii_lpa;
 
-	mii_reg5 = mdio_read (dev, tp->phys[0], 5);
+	mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
 
-	if (!tp->duplex_lock && mii_reg5 != 0xffff) {
-		int duplex = (mii_reg5 & 0x0100)
-		    || (mii_reg5 & 0x01C0) == 0x0040;
+	if (!tp->duplex_lock && mii_lpa != 0xffff) {
+		int duplex = (mii_lpa & LPA_100FULL)
+		    || (mii_lpa & 0x01C0) == 0x0040;
 		if (tp->full_duplex != duplex) {
 			tp->full_duplex = duplex;
 			printk (KERN_INFO
 				"%s: Setting %s-duplex based on MII #%d link"
 				" partner ability of %4.4x.\n", dev->name,
 				tp->full_duplex ? "full" : "half",
-				tp->phys[0], mii_reg5);
+				tp->phys[0], mii_lpa);
 			NETDRV_W8 (Cfg9346, Cfg9346_Unlock);
 			NETDRV_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
 			NETDRV_W8 (Cfg9346, Cfg9346_Lock);
@@ -1793,19 +1793,16 @@
 
 	switch (cmd) {
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = tp->phys[0] & 0x3f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		spin_lock_irqsave (&tp->lock, flags);
 		data->val_out = mdio_read (dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		spin_unlock_irqrestore (&tp->lock, flags);
 		break;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable (CAP_NET_ADMIN)) {
 			rc = -EPERM;
 			break;
diff -urN linux-2.5.4-pre2/drivers/net/pcmcia/3c589_cs.c linux/drivers/net/pcmcia/3c589_cs.c
--- linux-2.5.4-pre2/drivers/net/pcmcia/3c589_cs.c	Tue Nov 13 09:02:30 2001
+++ linux/drivers/net/pcmcia/3c589_cs.c	Thu Feb  7 16:09:56 2002
@@ -17,6 +17,9 @@
 
 ======================================================================*/
 
+#define DRV_NAME	"3c589_cs"
+#define DRV_VERSION	"1.162"
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -28,6 +31,9 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/delay.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -134,7 +140,7 @@
 INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"3c589_cs.c 1.162 2001/10/13 00:08:50 (David Hinds)";
+DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -159,6 +165,7 @@
 static int el3_close(struct net_device *dev);
 static void el3_tx_timeout(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 
 static dev_info_t dev_info = "3c589_cs";
 
@@ -249,7 +256,8 @@
     dev->tx_timeout = el3_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
-    
+    dev->do_ioctl = netdev_ioctl;
+
     /* Register with Card Services */
     link->next = dev_list;
     dev_list = link;
@@ -638,6 +646,71 @@
 	 ioaddr + EL3_CMD);
     outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
 	 | AdapterFailure, ioaddr + EL3_CMD);
+}
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+#ifdef PCMCIA_DEBUG
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = pc_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		pc_debug = edata.data;
+		return 0;
+	}
+#endif
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	int rc;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
 }
 
 static int el3_config(struct net_device *dev, struct ifmap *map)
diff -urN linux-2.5.4-pre2/drivers/net/pcmcia/aironet4500_cs.c linux/drivers/net/pcmcia/aironet4500_cs.c
--- linux-2.5.4-pre2/drivers/net/pcmcia/aironet4500_cs.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/net/pcmcia/aironet4500_cs.c	Thu Feb  7 16:09:56 2002
@@ -10,8 +10,11 @@
  *
  */
 
+#define DRV_NAME	"aironet4500_cs"
+#define DRV_VERSION	"0.1"
+
 static const char *awc_version =
-"aironet4500_cs.c v0.1 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
+DRV_NAME ".c v" DRV_VERSION " 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
 
 
 #include <linux/module.h>
@@ -24,6 +27,9 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -159,6 +165,66 @@
 	return ret;
 }
 
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+#ifdef PCMCIA_DEBUG
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = pc_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		pc_debug = edata.data;
+		return 0;
+	}
+#endif
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int awc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
 /*
 	awc_attach() creates an "instance" of the driver, allocating
 	local data structures for one device.  The device is registered
@@ -230,7 +296,8 @@
 //	dev->set_config = 		&awc_config_misiganes,aga mitte awc_config;
 	dev->get_stats = 		&awc_get_stats;
 //	dev->set_multicast_list = 	&awc_set_multicast_list;
-
+	dev->do_ioctl =			&awc_ioctl;
+	
 	strcpy(dev->name, ((struct awc_private *)dev->priv)->node.dev_name);
 
 	ether_setup(dev);
diff -urN linux-2.5.4-pre2/drivers/net/pcmcia/fmvj18x_cs.c linux/drivers/net/pcmcia/fmvj18x_cs.c
--- linux-2.5.4-pre2/drivers/net/pcmcia/fmvj18x_cs.c	Thu Jan 10 16:23:45 2002
+++ linux/drivers/net/pcmcia/fmvj18x_cs.c	Thu Feb  7 16:09:56 2002
@@ -28,6 +28,9 @@
    
 ======================================================================*/
 
+#define DRV_NAME	"fmvj18x_cs"
+#define DRV_VERSION	"2.6"
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -39,6 +42,9 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/delay.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -74,7 +80,7 @@
 #ifdef PCMCIA_DEBUG
 INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version = "fmvj18x_cs.c 2.6 2001/09/17";
+static char *version = DRV_NAME ".c " DRV_VERSION " 2001/09/17";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -104,6 +110,7 @@
 static struct net_device_stats *fjn_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
 static void fjn_tx_timeout(struct net_device *dev);
+static int fjn_ioctl(struct net_device *, struct ifreq *, int);
 
 static dev_info_t dev_info = "fmvj18x_cs";
 static dev_link_t *dev_list;
@@ -316,6 +323,7 @@
     dev->tx_timeout = fjn_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
+    dev->do_ioctl = fjn_ioctl;
     
     /* Register with Card Services */
     link->next = dev_list;
@@ -1102,6 +1110,65 @@
 } /* fjn_rx */
 
 /*====================================================================*/
+
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+#ifdef PCMCIA_DEBUG
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = pc_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		pc_debug = edata.data;
+		return 0;
+	}
+#endif
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int fjn_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
 
 static int fjn_config(struct net_device *dev, struct ifmap *map){
     return 0;
diff -urN linux-2.5.4-pre2/drivers/net/pcmcia/xircom_tulip_cb.c linux/drivers/net/pcmcia/xircom_tulip_cb.c
--- linux-2.5.4-pre2/drivers/net/pcmcia/xircom_tulip_cb.c	Thu Jan 10 16:23:45 2002
+++ linux/drivers/net/pcmcia/xircom_tulip_cb.c	Thu Feb  7 16:09:56 2002
@@ -1472,21 +1472,18 @@
 
 	/* Legacy mii-diag interface */
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		if (tp->mii_cnt)
 			data[0] = phy;
 		else
 			return -ENODEV;
 		return 0;
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		save_flags(flags);
 		cli();
 		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
 		restore_flags(flags);
 		return 0;
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		save_flags(flags);
diff -urN linux-2.5.4-pre2/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c
--- linux-2.5.4-pre2/drivers/net/rcpci45.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/net/rcpci45.c	Thu Feb  7 16:09:56 2002
@@ -44,6 +44,8 @@
 **
 ***************************************************************************/
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -urN linux-2.5.4-pre2/drivers/net/rrunner.c linux/drivers/net/rrunner.c
--- linux-2.5.4-pre2/drivers/net/rrunner.c	Fri Nov  9 13:45:35 2001
+++ linux/drivers/net/rrunner.c	Thu Feb  7 16:09:56 2002
@@ -21,6 +21,8 @@
  * ODS/Essential.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #define DEBUG 1
 #define RX_DMA_SKBUFF 1
 #define PKT_COPY_THRESHOLD 512
diff -urN linux-2.5.4-pre2/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c
--- linux-2.5.4-pre2/drivers/net/sk_g16.c	Tue Oct 16 21:56:29 2001
+++ linux/drivers/net/sk_g16.c	Thu Feb  7 16:09:56 2002
@@ -810,7 +810,7 @@
     SK_print_pos(dev, "POS registers after ROM, RAM config");
 #endif
 
-    board = (SK_RAM *) bus_to_virt(rom_addr);
+    board = (SK_RAM *) isa_bus_to_virt(rom_addr);
 
     /* Read in station address */
     for (i = 0, j = 0; i < ETH_ALEN; i++, j+=2)
diff -urN linux-2.5.4-pre2/drivers/net/slip.c linux/drivers/net/slip.c
--- linux-2.5.4-pre2/drivers/net/slip.c	Mon Jan  7 12:55:17 2002
+++ linux/drivers/net/slip.c	Thu Feb  7 16:09:56 2002
@@ -483,7 +483,7 @@
 		 *      14 Oct 1994 Dmitry Gorodchanin.
 		 */
 #ifdef SL_CHECK_TRANSMIT
-		if (jiffies - dev->trans_start  < 20 * HZ)  {
+		if (time_before(jiffies, dev->trans_start + 20 * HZ))  {
 			/* 20 sec timeout not reached */
 			goto out;
 		}
@@ -1387,7 +1387,7 @@
 	int i;
 
 	if (slip_ctrls != NULL) {
-		unsigned long start = jiffies;
+		unsigned long timeout = jiffies + HZ;
 		int busy = 0;
 
 		/* First of all: check for active disciplines and hangup them.
@@ -1410,7 +1410,7 @@
 				spin_unlock(&slc->ctrl.lock);
 			}
 			local_bh_enable();
-		} while (busy && jiffies - start < 1*HZ);
+		} while (busy && time_before(jiffies, timeout));
 
 		busy = 0;
 		for (i = 0; i < slip_maxdev; i++) {
diff -urN linux-2.5.4-pre2/drivers/net/starfire.c linux/drivers/net/starfire.c
--- linux-2.5.4-pre2/drivers/net/starfire.c	Thu Jan 10 16:23:45 2002
+++ linux/drivers/net/starfire.c	Thu Feb  7 16:09:56 2002
@@ -93,13 +93,16 @@
 	- Fixed initialization timing problems
 	- Fixed interrupt mask definitions
 
+	LK1.3.5 (jgarzik)
+	- ethtool NWAY_RST, GLINK, [GS]MSGLVL support
+
 TODO:
 	- implement tx_timeout() properly
 */
 
 #define DRV_NAME	"starfire"
-#define DRV_VERSION	"1.03+LK1.3.4"
-#define DRV_RELDATE	"August 14, 2001"
+#define DRV_VERSION	"1.03+LK1.3.5"
+#define DRV_RELDATE	"November 17, 2001"
 
 #include <linux/version.h>
 #include <linux/module.h>
@@ -1767,6 +1770,47 @@
 		return 0;
 	}
 
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		int tmp;
+		int r = -EINVAL;
+		/* if autoneg is off, it's an error */
+		tmp = mdio_read(dev, np->phys[0], MII_BMCR);
+		if (tmp & BMCR_ANENABLE) {
+			tmp |= (BMCR_ANRESTART);
+			mdio_write(dev, np->phys[0], MII_BMCR, tmp);
+			r = 0;
+		}
+		return r;
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		if (mdio_read(dev, np->phys[0], MII_BMSR) & BMSR_LSTATUS)
+			edata.data = 1;
+		else
+			edata.data = 0;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -1784,17 +1828,14 @@
 
 	/* Legacy mii-diag interface */
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = np->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		if (data->phy_id == np->phys[0]) {
diff -urN linux-2.5.4-pre2/drivers/net/sundance.c linux/drivers/net/sundance.c
--- linux-2.5.4-pre2/drivers/net/sundance.c	Thu Jan 24 11:51:10 2002
+++ linux/drivers/net/sundance.c	Thu Feb  7 16:09:56 2002
@@ -21,11 +21,15 @@
 	Version 1.01a (jgarzik):
 	- Replace some MII-related magic numbers with constants
 
+	Version 1.02 (D-Link):
+	- Add new board to PCI ID list
+	- Fix multicast bug
+
 */
 
 #define DRV_NAME	"sundance"
-#define DRV_VERSION	"1.01a"
-#define DRV_RELDATE	"11-Nov-2001"
+#define DRV_VERSION	"1.02"
+#define DRV_RELDATE	"17-Jan-2002"
 
 
 /* The user-configurable values.
@@ -223,8 +227,9 @@
 	{0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0},
 	{0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1},
 	{0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2},
-	{0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
-	{0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+	{0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3},
+	{0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+	{0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
 	{0,}
 };
 MODULE_DEVICE_TABLE(pci, sundance_pci_tbl);
@@ -247,6 +252,8 @@
 	 PCI_IOTYPE, 128, CanHaveMII},
 	{"D-Link DFE-580TX 4 port Server Adapter", {0x10121186, 0xffffffff,},
 	 PCI_IOTYPE, 128, CanHaveMII},
+	{"D-Link DFE-530TXS FAST Ethernet Adapter", {0x10021186, 0xffffffff,},
+	 PCI_IOTYPE, 128, CanHaveMII},
 	{"D-Link DL10050-based FAST Ethernet Adapter",
 	 {0x10021186, 0xffffffff,},
 	 PCI_IOTYPE, 128, CanHaveMII},
@@ -1287,11 +1294,16 @@
 		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
 	} else if (dev->mc_count) {
 		struct dev_mc_list *mclist;
-		memset(mc_filter, 0, sizeof(mc_filter));
+		int bit;
+		int index;
+		int crc;
+		memset (mc_filter, 0, sizeof (mc_filter));
 		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
-			 i++, mclist = mclist->next) {
-			set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f,
-					mc_filter);
+		     i++, mclist = mclist->next) {
+			crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr);
+			for (index=0, bit=0; bit < 6; bit++, crc <<= 1)
+				if (crc & 0x80000000) index |= 1 << bit;
+			mc_filter[index/16] |= (1 << (index % 16));
 		}
 		rx_mode = AcceptBroadcast | AcceptMultiHash | AcceptMyPhys;
 	} else {
@@ -1335,17 +1347,14 @@
 	case SIOCETHTOOL:
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
diff -urN linux-2.5.4-pre2/drivers/net/tlan.c linux/drivers/net/tlan.c
--- linux-2.5.4-pre2/drivers/net/tlan.c	Tue Nov 27 09:23:27 2001
+++ linux/drivers/net/tlan.c	Thu Feb  7 16:09:56 2002
@@ -160,6 +160,7 @@
  *
  *******************************************************************************/
 
+#error Please convert me to Documentation/DMA-mapping.txt
                                                                                 
 #include <linux/module.h>
 
@@ -922,18 +923,15 @@
 
 	switch(cmd) {
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 			data->phy_id = phy;
 
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 			TLan_MiiReadReg(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, &data->val_out);
 			return 0;
 		
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 			if (!capable(CAP_NET_ADMIN))
 				return -EPERM;
 			TLan_MiiWriteReg(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
diff -urN linux-2.5.4-pre2/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- linux-2.5.4-pre2/drivers/net/via-rhine.c	Thu Jan 10 16:23:45 2002
+++ linux/drivers/net/via-rhine.c	Thu Feb  7 16:09:56 2002
@@ -76,8 +76,17 @@
 
 	LK1.1.12:
 	- Martin Eriksson: Allow Memory-Mapped IO to be enabled.
+
+	LK1.1.13 (jgarzik):
+	- Add ethtool support
+	- Replace some MII-related magic numbers with constants
+	
 */
 
+#define DRV_NAME	"via-rhine"
+#define DRV_VERSION	"1.1.13"
+#define DRV_RELDATE	"Nov-17-2001"
+
 
 /* A few user-configurable values.
    These may be modified when a driver module is loaded. */
@@ -151,18 +160,20 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/mii.h>
+#include <linux/ethtool.h>
 #include <linux/crc32.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/uaccess.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
-KERN_INFO "via-rhine.c:v1.10-LK1.1.12  03/11/2001  Written by Donald Becker\n"
+KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION "  " DRV_RELDATE "  Written by Donald Becker\n"
 KERN_INFO "  http://www.scyld.com/network/via-rhine.html\n";
 
-static char shortname[] __devinitdata = "via-rhine";
+static char shortname[] __devinitdata = DRV_NAME;
 
 
 /* This driver was written to use PCI memory space, however most versions
@@ -471,6 +482,7 @@
 	unsigned char phys[MAX_MII_CNT];			/* MII device addresses. */
 	unsigned int mii_cnt;			/* number of MIIs found, but only the first one is used */
 	u16 mii_status;						/* last read MII status */
+	struct mii_if_info mii_if;
 };
 
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
@@ -486,7 +498,7 @@
 static void via_rhine_error(struct net_device *dev, int intr_status);
 static void via_rhine_set_rx_mode(struct net_device *dev);
 static struct net_device_stats *via_rhine_get_stats(struct net_device *dev);
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int  via_rhine_close(struct net_device *dev);
 static inline void clear_tally_counters(long ioaddr);
 
@@ -684,6 +696,9 @@
 	np->chip_id = chip_id;
 	np->drv_flags = via_rhine_chip_info[chip_id].drv_flags;
 	np->pdev = pdev;
+	np->mii_if.dev = dev;
+	np->mii_if.mdio_read = mdio_read;
+	np->mii_if.mdio_write = mdio_write;
 
 	if (dev->mem_start)
 		option = dev->mem_start;
@@ -691,16 +706,16 @@
 	/* The lower four bits are the media type. */
 	if (option > 0) {
 		if (option & 0x200)
-			np->full_duplex = 1;
+			np->mii_if.full_duplex = 1;
 		np->default_port = option & 15;
 	}
 	if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)
-		np->full_duplex = 1;
+		np->mii_if.full_duplex = 1;
 
-	if (np->full_duplex) {
+	if (np->mii_if.full_duplex) {
 		printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation"
 			   " disabled.\n", dev->name);
-		np->duplex_lock = 1;
+		np->mii_if.duplex_lock = 1;
 	}
 
 	/* The chip-specific entries in the device structure. */
@@ -709,7 +724,7 @@
 	dev->stop = via_rhine_close;
 	dev->get_stats = via_rhine_get_stats;
 	dev->set_multicast_list = via_rhine_set_rx_mode;
-	dev->do_ioctl = mii_ioctl;
+	dev->do_ioctl = via_rhine_ioctl;
 	dev->tx_timeout = via_rhine_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	if (np->drv_flags & ReqTxAlign)
@@ -736,10 +751,10 @@
 			int mii_status = mdio_read(dev, phy, 1);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				np->phys[phy_idx++] = phy;
-				np->advertising = mdio_read(dev, phy, 4);
+				np->mii_if.advertising = mdio_read(dev, phy, 4);
 				printk(KERN_INFO "%s: MII PHY found at address %d, status "
 					   "0x%4.4x advertising %4.4x Link %4.4x.\n",
-					   dev->name, phy, mii_status, np->advertising,
+					   dev->name, phy, mii_status, np->mii_if.advertising,
 					   mdio_read(dev, phy, 5));
 
 				/* set IFF_RUNNING */
@@ -750,12 +765,13 @@
 			}
 		}
 		np->mii_cnt = phy_idx;
+		np->mii_if.phy_id = np->phys[0];
 	}
 
 	/* Allow forcing the media type. */
 	if (option > 0) {
 		if (option & 0x220)
-			np->full_duplex = 1;
+			np->mii_if.full_duplex = 1;
 		np->default_port = option & 0x3ff;
 		if (np->default_port & 0x330) {
 			/* FIXME: shouldn't someone check this variable? */
@@ -969,7 +985,7 @@
 		   ioaddr + IntrEnable);
 
 	np->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll;
-	if (np->duplex_lock)
+	if (np->mii_if.duplex_lock)
 		np->chip_cmd |= CmdFDuplex;
 	writew(np->chip_cmd, ioaddr + ChipCmd);
 
@@ -1011,12 +1027,12 @@
 		switch (regnum) {
 		case 0:							/* Is user forcing speed/duplex? */
 			if (value & 0x9000)			/* Autonegotiation. */
-				np->duplex_lock = 0;
+				np->mii_if.duplex_lock = 0;
 			else
-				np->full_duplex = (value & 0x0100) ? 1 : 0;
+				np->mii_if.full_duplex = (value & 0x0100) ? 1 : 0;
 			break;
 		case 4:
-			np->advertising = value;
+			np->mii_if.advertising = value;
 			break;
 		}
 	}
@@ -1060,7 +1076,7 @@
 		printk(KERN_DEBUG "%s: Done via_rhine_open(), status %4.4x "
 			   "MII status: %4.4x.\n",
 			   dev->name, readw(ioaddr + ChipCmd),
-			   mdio_read(dev, np->phys[0], 1));
+			   mdio_read(dev, np->phys[0], MII_BMSR));
 
 	netif_start_queue(dev);
 
@@ -1078,19 +1094,19 @@
 {
 	struct netdev_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
-	int mii_reg5 = mdio_read(dev, np->phys[0], 5);
-	int negotiated = mii_reg5 & np->advertising;
+	int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
+	int negotiated = mii_lpa & np->mii_if.advertising;
 	int duplex;
 
-	if (np->duplex_lock  ||  mii_reg5 == 0xffff)
+	if (np->mii_if.duplex_lock  ||  mii_lpa == 0xffff)
 		return;
 	duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
-	if (np->full_duplex != duplex) {
-		np->full_duplex = duplex;
+	if (np->mii_if.full_duplex != duplex) {
+		np->mii_if.full_duplex = duplex;
 		if (debug)
 			printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
 				   " partner capability of %4.4x.\n", dev->name,
-				   duplex ? "full" : "half", np->phys[0], mii_reg5);
+				   duplex ? "full" : "half", np->phys[0], mii_lpa);
 		if (duplex)
 			np->chip_cmd |= CmdFDuplex;
 		else
@@ -1118,7 +1134,7 @@
 	via_rhine_check_duplex(dev);
 
 	/* make IFF_RUNNING follow the MII status bit "Link established" */
-	mii_status = mdio_read(dev, np->phys[0], 1);
+	mii_status = mdio_read(dev, np->phys[0], MII_BMSR);
 	if ( (mii_status & MIILink) != (np->mii_status & MIILink) ) {
 		if (mii_status & MIILink)
 			netif_carrier_on(dev);
@@ -1142,7 +1158,7 @@
 	printk (KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
 		"%4.4x, resetting...\n",
 		dev->name, readw (ioaddr + IntrStatus),
-		mdio_read (dev, np->phys[0], 1));
+		mdio_read (dev, np->phys[0], MII_BMSR));
 
 	dev->if_port = 0;
 
@@ -1457,14 +1473,14 @@
 		if (readb(ioaddr + MIIStatus) & 0x02) {
 			/* Link failed, restart autonegotiation. */
 			if (np->drv_flags & HasDavicomPhy)
-				mdio_write(dev, np->phys[0], 0, 0x3300);
+				mdio_write(dev, np->phys[0], MII_BMCR, 0x3300);
 		} else
 			via_rhine_check_duplex(dev);
 		if (debug)
 			printk(KERN_ERR "%s: MII status changed: Autonegotiation "
 				   "advertising %4.4x  partner %4.4x.\n", dev->name,
-			   mdio_read(dev, np->phys[0], 4),
-			   mdio_read(dev, np->phys[0], 5));
+			   mdio_read(dev, np->phys[0], MII_ADVERTISE),
+			   mdio_read(dev, np->phys[0], MII_LPA));
 	}
 	if (intr_status & IntrStatsMax) {
 		np->stats.rx_crc_errors	+= readw(ioaddr + RxCRCErrs);
@@ -1554,29 +1570,112 @@
 	writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);
 }
 
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int via_rhine_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	struct netdev_private *np = dev->priv;
+	u32 ethcmd;
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pdev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		return mii_nway_restart(&np->mii_if);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		edata.data = mii_link_ok(&np->mii_if);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct netdev_private *np = dev->priv;
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 	unsigned long flags;
 	int retval;
 
+	if (cmd == SIOCETHTOOL)
+		return via_rhine_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
 	spin_lock_irqsave(&np->lock, flags);
 	retval = 0;
 
 	switch(cmd) {
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = np->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		break;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN)) {
 			retval = -EPERM;
 			break;
diff -urN linux-2.5.4-pre2/drivers/net/wan/lmc/lmc_main.c linux/drivers/net/wan/lmc/lmc_main.c
--- linux-2.5.4-pre2/drivers/net/wan/lmc/lmc_main.c	Sun Dec 30 10:31:51 2001
+++ linux/drivers/net/wan/lmc/lmc_main.c	Thu Feb  7 16:09:56 2002
@@ -175,7 +175,7 @@
 
     case LMCIOCSINFO: /*fold01*/
         sp = &((struct ppp_device *) dev)->sppp;
-        if (!suser ()) {
+        if (!capable(CAP_NET_ADMIN)) {
             ret = -EPERM;
             break;
         }
@@ -210,7 +210,7 @@
             u_int16_t	old_type = sc->if_type;
             u_int16_t	new_type;
 
-	    if (!suser ()) {
+	    if (!capable(CAP_NET_ADMIN)) {
 		ret = -EPERM;
 		break;
 	    }
@@ -290,7 +290,7 @@
         break;
 
     case LMCIOCCLEARLMCSTATS: /*fold01*/
-        if (!suser ()){
+        if (!capable(CAP_NET_ADMIN)){
             ret = -EPERM;
             break;
         }
@@ -304,7 +304,7 @@
         break;
 
     case LMCIOCSETCIRCUIT: /*fold01*/
-        if (!suser ()){
+        if (!capable(CAP_NET_ADMIN)){
             ret = -EPERM;
             break;
         }
@@ -322,7 +322,7 @@
         break;
 
     case LMCIOCRESET: /*fold01*/
-        if (!suser ()){
+        if (!capable(CAP_NET_ADMIN)){
             ret = -EPERM;
             break;
         }
@@ -355,7 +355,7 @@
         {
             struct lmc_xilinx_control xc; /*fold02*/
 
-            if (!suser ()){
+            if (!capable(CAP_NET_ADMIN)){
                 ret = -EPERM;
                 break;
             }
diff -urN linux-2.5.4-pre2/drivers/net/winbond-840.c linux/drivers/net/winbond-840.c
--- linux-2.5.4-pre2/drivers/net/winbond-840.c	Thu Jan 10 16:23:45 2002
+++ linux/drivers/net/winbond-840.c	Thu Feb  7 16:09:56 2002
@@ -36,6 +36,8 @@
 		power management.
 		support for big endian descriptors
 			Copyright (C) 2001 Manfred Spraul
+  	* ethtool support (jgarzik)
+	* Replace some MII-related magic numbers with constants (jgarzik)
   
 	TODO:
 	* enable pci_power_off
@@ -43,8 +45,8 @@
 */
   
 #define DRV_NAME	"winbond-840"
-#define DRV_VERSION	"1.01-c"
-#define DRV_RELDATE	"6/30/2000"
+#define DRV_VERSION	"1.01-d"
+#define DRV_RELDATE	"Nov-17-2001"
 
 
 /* Automatically extracted configuration info:
@@ -364,14 +366,11 @@
 	unsigned int cur_tx, dirty_tx;
 	unsigned int tx_q_bytes;
 	unsigned int tx_full;				/* The Tx queue is full. */
-	/* These values are keep track of the transceiver/media in use. */
-	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
-	unsigned int duplex_lock:1;
 	/* MII transceiver section. */
 	int mii_cnt;						/* MII device addresses. */
-	u16 advertising;					/* NWay media advertisement */
 	unsigned char phys[MII_CNT];		/* MII device addresses, but only the first is used */
 	u32 mii;
+	struct mii_if_info mii_if;
 };
 
 static int  eeprom_read(long ioaddr, int location);
@@ -453,6 +452,9 @@
 	np->chip_id = chip_idx;
 	np->drv_flags = pci_id_tbl[chip_idx].drv_flags;
 	spin_lock_init(&np->lock);
+	np->mii_if.dev = dev;
+	np->mii_if.mdio_read = mdio_read;
+	np->mii_if.mdio_write = mdio_write;
 	
 	pci_set_drvdata(pdev, dev);
 
@@ -462,16 +464,16 @@
 	/* The lower four bits are the media type. */
 	if (option > 0) {
 		if (option & 0x200)
-			np->full_duplex = 1;
+			np->mii_if.full_duplex = 1;
 		if (option & 15)
 			printk(KERN_INFO "%s: ignoring user supplied media type %d",
 				dev->name, option & 15);
 	}
 	if (find_cnt < MAX_UNITS  &&  full_duplex[find_cnt] > 0)
-		np->full_duplex = 1;
+		np->mii_if.full_duplex = 1;
 
-	if (np->full_duplex)
-		np->duplex_lock = 1;
+	if (np->mii_if.full_duplex)
+		np->mii_if.duplex_lock = 1;
 
 	/* The chip-specific entries in the device structure. */
 	dev->open = &netdev_open;
@@ -496,18 +498,19 @@
 	if (np->drv_flags & CanHaveMII) {
 		int phy, phy_idx = 0;
 		for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
-			int mii_status = mdio_read(dev, phy, 1);
+			int mii_status = mdio_read(dev, phy, MII_BMSR);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				np->phys[phy_idx++] = phy;
-				np->advertising = mdio_read(dev, phy, 4);
-				np->mii = (mdio_read(dev, phy, 2) << 16)+
-						mdio_read(dev, phy, 3);
+				np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
+				np->mii = (mdio_read(dev, phy, MII_PHYSID1) << 16)+
+						mdio_read(dev, phy, MII_PHYSID2);
 				printk(KERN_INFO "%s: MII PHY %8.8xh found at address %d, status "
 					   "0x%4.4x advertising %4.4x.\n",
-					   dev->name, np->mii, phy, mii_status, np->advertising);
+					   dev->name, np->mii, phy, mii_status, np->mii_if.advertising);
 			}
 		}
 		np->mii_cnt = phy_idx;
+		np->mii_if.phy_id = np->phys[0];
 		if (phy_idx == 0) {
 				printk(KERN_WARNING "%s: MII PHY not found -- this device may "
 					   "not operate correctly.\n", dev->name);
@@ -654,7 +657,7 @@
 	int i;
 
 	if (location == 4  &&  phy_id == np->phys[0])
-		np->advertising = value;
+		np->mii_if.advertising = value;
 
 	if (mii_preamble_required)
 		mdio_sync(mdio_addr);
@@ -728,12 +731,12 @@
 	int duplex, fasteth, result, mii_reg;
 
 	/* BSMR */
-	mii_reg = mdio_read(dev, np->phys[0], 1);
+	mii_reg = mdio_read(dev, np->phys[0], MII_BMSR);
 
 	if (mii_reg == 0xffff)
 		return np->csr6;
 	/* reread: the link status bit is sticky */
-	mii_reg = mdio_read(dev, np->phys[0], 1);
+	mii_reg = mdio_read(dev, np->phys[0], MII_BMSR);
 	if (!(mii_reg & 0x4)) {
 		if (netif_carrier_ok(dev)) {
 			if (debug)
@@ -759,18 +762,18 @@
 		 * Instead bit 9 and 13 of the BMCR are updated to the result
 		 * of the negotiation..
 		 */
-		mii_reg = mdio_read(dev, np->phys[0], 0);
-		duplex = mii_reg & 0x100;
-		fasteth = mii_reg & 0x2000;
+		mii_reg = mdio_read(dev, np->phys[0], MII_BMCR);
+		duplex = mii_reg & BMCR_FULLDPLX;
+		fasteth = mii_reg & BMCR_SPEED100;
 	} else {
 		int negotiated;
-		mii_reg	= mdio_read(dev, np->phys[0], 5);
-		negotiated = mii_reg & np->advertising;
+		mii_reg	= mdio_read(dev, np->phys[0], MII_LPA);
+		negotiated = mii_reg & np->mii_if.advertising;
 
-		duplex = (negotiated & 0x0100) || ((negotiated & 0x02C0) == 0x0040);
+		duplex = (negotiated & LPA_100FULL) || ((negotiated & 0x02C0) == LPA_10FULL);
 		fasteth = negotiated & 0x380;
 	}
-	duplex |= np->duplex_lock;
+	duplex |= np->mii_if.duplex_lock;
 	/* remove fastether and fullduplex */
 	result = np->csr6 & ~0x20000200;
 	if (duplex)
@@ -822,7 +825,7 @@
 	/* and restart them with the new configuration */
 	writel(np->csr6, ioaddr + NetworkConfig);
 	if (new & 0x200)
-		np->full_duplex = 1;
+		np->mii_if.full_duplex = 1;
 }
 
 static void netdev_timer(unsigned long data)
@@ -1131,7 +1134,7 @@
 			if (tx_status & 0x0C80) np->stats.tx_carrier_errors++;
 			if (tx_status & 0x0200) np->stats.tx_window_errors++;
 			if (tx_status & 0x0002) np->stats.tx_fifo_errors++;
-			if ((tx_status & 0x0080) && np->full_duplex == 0)
+			if ((tx_status & 0x0080) && np->mii_if.full_duplex == 0)
 				np->stats.tx_heartbeat_errors++;
 #ifdef ETHER_STATS
 			if (tx_status & 0x0100) np->stats.collisions16++;
@@ -1469,6 +1472,56 @@
 		return 0;
 	}
 
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii_if);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii_if);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
         }
 	
 	return -EOPNOTSUPP;
@@ -1483,19 +1536,16 @@
 	case SIOCETHTOOL:
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		spin_lock_irq(&np->lock);
 		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		spin_unlock_irq(&np->lock);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		spin_lock_irq(&np->lock);
diff -urN linux-2.5.4-pre2/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- linux-2.5.4-pre2/drivers/net/yellowfin.c	Thu Jan 10 16:23:46 2002
+++ linux/drivers/net/yellowfin.c	Thu Feb  7 16:09:56 2002
@@ -1420,17 +1420,14 @@
 	case SIOCETHTOOL:
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = np->phys[0] & 0x1f;
 		/* Fall Through */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		if (data->phy_id == np->phys[0]) {
diff -urN linux-2.5.4-pre2/drivers/scsi/3w-xxxx.c linux/drivers/scsi/3w-xxxx.c
--- linux-2.5.4-pre2/drivers/scsi/3w-xxxx.c	Mon Jan 28 14:36:58 2002
+++ linux/drivers/scsi/3w-xxxx.c	Thu Feb  7 16:09:56 2002
@@ -108,6 +108,8 @@
                  Fix get_param for specific units.
 */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 
 MODULE_AUTHOR ("3ware Inc.");
diff -urN linux-2.5.4-pre2/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c
--- linux-2.5.4-pre2/drivers/scsi/53c7,8xx.c	Mon Jan 28 14:36:58 2002
+++ linux/drivers/scsi/53c7,8xx.c	Thu Feb  7 16:09:56 2002
@@ -62,6 +62,8 @@
  *  the fourth byte from 50 to 25.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/config.h>
 
 #ifdef CONFIG_SCSI_NCR53C7xx_sync
diff -urN linux-2.5.4-pre2/drivers/scsi/AM53C974.c linux/drivers/scsi/AM53C974.c
--- linux-2.5.4-pre2/drivers/scsi/AM53C974.c	Mon Jan 28 14:36:58 2002
+++ linux/drivers/scsi/AM53C974.c	Thu Feb  7 16:09:56 2002
@@ -1,3 +1,5 @@
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/signal.h>
diff -urN linux-2.5.4-pre2/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c
--- linux-2.5.4-pre2/drivers/scsi/BusLogic.c	Thu Dec 27 08:17:43 2001
+++ linux/drivers/scsi/BusLogic.c	Thu Feb  7 16:09:56 2002
@@ -29,6 +29,7 @@
 #define BusLogic_DriverVersion		"2.1.15"
 #define BusLogic_DriverDate		"17 August 1998"
 
+#error Please convert me to Documentation/DMA-mapping.txt
 
 #include <linux/version.h>
 #include <linux/module.h>
diff -urN linux-2.5.4-pre2/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
--- linux-2.5.4-pre2/drivers/scsi/advansys.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/advansys.c	Thu Feb  7 16:09:56 2002
@@ -752,6 +752,7 @@
 
 */
 
+#error Please convert me to Documentation/DMA-mapping.txt
 
 /*
  * --- Linux Version
diff -urN linux-2.5.4-pre2/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c
--- linux-2.5.4-pre2/drivers/scsi/aha1542.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/aha1542.c	Thu Feb  7 16:09:56 2002
@@ -51,13 +51,14 @@
 
 #include "aha1542.h"
 
-#define SCSI_PA(address) virt_to_bus(address)
+#define SCSI_BUF_PA(address)	isa_virt_to_bus(address)
+#define SCSI_SG_PA(sgent)	(isa_page_to_bus((sgent)->page) + (sgent)->offset)
 
 static void BAD_DMA(void *address, unsigned int length)
 {
 	printk(KERN_CRIT "buf vaddress %p paddress 0x%lx length %d\n",
 	       address,
-	       SCSI_PA(address),
+	       SCSI_BUS_PA(address),
 	       length);
 	panic("Buffer at physical address > 16Mb used for aha1542");
 }
@@ -70,7 +71,7 @@
 	printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%lx length %d\n",
 	       badseg, nseg,
 	       page_address(sgpnt[badseg].page) + sgpnt[badseg].offset,
-	       (unsigned long)page_to_bus(sgpnt[badseg].page) + sgpnt[badseg].offset,
+	       SCSI_SG_PA(&sgpnt[badseg]),
 	       sgpnt[badseg].length);
 
 	/*
@@ -511,7 +512,7 @@
 			return;
 		};
 
-		mbo = (scsi2int(mb[mbi].ccbptr) - (SCSI_PA(&ccb[0]))) / sizeof(struct ccb);
+		mbo = (scsi2int(mb[mbi].ccbptr) - (SCSI_BUF_PA(&ccb[0]))) / sizeof(struct ccb);
 		mbistatus = mb[mbi].status;
 		mb[mbi].status = 0;
 		HOSTDATA(shost)->aha1542_last_mbi_used = mbi;
@@ -681,7 +682,7 @@
 	printk(KERN_DEBUG "Sending command (%d %x)...", mbo, done);
 #endif
 
-	any2scsi(mb[mbo].ccbptr, SCSI_PA(&ccb[mbo]));	/* This gets trashed for some reason */
+	any2scsi(mb[mbo].ccbptr, SCSI_BUF_PA(&ccb[mbo]));	/* This gets trashed for some reason */
 
 	memset(&ccb[mbo], 0, sizeof(struct ccb));
 
@@ -715,7 +716,8 @@
 				printk(KERN_CRIT "Bad segment list supplied to aha1542.c (%d, %d)\n", SCpnt->use_sg, i);
 				for (i = 0; i < SCpnt->use_sg; i++) {
 					printk(KERN_CRIT "%d: %p %d\n", i,
-					       page_address(sgpnt[i].page) + sgpnt[i].offset,
+					       (page_address(sgpnt[i].page) +
+						sgpnt[i].offset),
 					       sgpnt[i].length);
 				};
 				printk(KERN_CRIT "cptr %x: ", (unsigned int) cptr);
@@ -724,13 +726,13 @@
 					printk("%02x ", ptr[i]);
 				panic("Foooooooood fight!");
 			};
-			any2scsi(cptr[i].dataptr, page_to_bus(sgpnt[i].page) + sgpnt[i].offset);
-			if (page_to_bus(sgpnt[i].page) + sgpnt[i].offset + sgpnt[i].length - 1 > ISA_DMA_THRESHOLD)
+			any2scsi(cptr[i].dataptr, SCSI_SG_PA(&sgpnt[i]));
+			if (SCSI_SG_PA(&sgpnt[i].page) + sgpnt[i].length - 1 > ISA_DMA_THRESHOLD)
 				BAD_SG_DMA(SCpnt, sgpnt, SCpnt->use_sg, i);
 			any2scsi(cptr[i].datalen, sgpnt[i].length);
 		};
 		any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
-		any2scsi(ccb[mbo].dataptr, SCSI_PA(cptr));
+		any2scsi(ccb[mbo].dataptr, SCSI_BUF_PA(cptr));
 #ifdef DEBUG
 		printk("cptr %x: ", cptr);
 		ptr = (unsigned char *) cptr;
@@ -741,9 +743,9 @@
 		ccb[mbo].op = 0;	/* SCSI Initiator Command */
 		SCpnt->host_scribble = NULL;
 		any2scsi(ccb[mbo].datalen, bufflen);
-		if (buff && SCSI_PA(buff + bufflen - 1) > ISA_DMA_THRESHOLD)
+		if (buff && SCSI_BUF_PA(buff + bufflen - 1) > ISA_DMA_THRESHOLD)
 			BAD_DMA(buff, bufflen);
-		any2scsi(ccb[mbo].dataptr, SCSI_PA(buff));
+		any2scsi(ccb[mbo].dataptr, SCSI_BUF_PA(buff));
 	};
 	ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7);	/*SCSI Target Id */
 	ccb[mbo].rsalen = 16;
@@ -803,10 +805,10 @@
 
 	for (i = 0; i < AHA1542_MAILBOXES; i++) {
 		mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0;
-		any2scsi(mb[i].ccbptr, SCSI_PA(&ccb[i]));
+		any2scsi(mb[i].ccbptr, SCSI_BUF_PA(&ccb[i]));
 	};
 	aha1542_intr_reset(bse);	/* reset interrupts, so they don't block */
-	any2scsi((cmd + 2), SCSI_PA(mb));
+	any2scsi((cmd + 2), SCSI_BUF_PA(mb));
 	aha1542_out(bse, cmd, 5);
 	WAIT(INTRFLAGS(bse), INTRMASK, HACC, 0);
 	while (0) {
@@ -1186,7 +1188,7 @@
 				continue;
 			/* For now we do this - until kmalloc is more intelligent
 			   we are resigned to stupid hacks like this */
-			if (SCSI_PA(shpnt) >= ISA_DMA_THRESHOLD) {
+			if (SCSI_BUF_PA(shpnt) >= ISA_DMA_THRESHOLD) {
 				printk(KERN_ERR "Invalid address for shpnt with 1542.\n");
 				goto unregister;
 			}
@@ -1399,7 +1401,7 @@
 	HOSTDATA(SCpnt->host)->aha1542_last_mbo_used = mbo;
 	restore_flags(flags);
 
-	any2scsi(mb[mbo].ccbptr, SCSI_PA(&ccb[mbo]));	/* This gets trashed for some reason */
+	any2scsi(mb[mbo].ccbptr, SCSI_BUF_PA(&ccb[mbo]));	/* This gets trashed for some reason */
 
 	memset(&ccb[mbo], 0, sizeof(struct ccb));
 
diff -urN linux-2.5.4-pre2/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c
--- linux-2.5.4-pre2/drivers/scsi/aha1740.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/aha1740.c	Thu Feb  7 16:09:56 2002
@@ -232,7 +232,7 @@
     {
 	DEB(printk("aha1740_intr top of loop.\n"));
 	adapstat = inb(G2INTST(base));
-	ecbptr = (struct ecb *) bus_to_virt(inl(MBOXIN0(base)));
+	ecbptr = (struct ecb *) isa_bus_to_virt(inl(MBOXIN0(base)));
 	outb(G2CNTRL_IRST,G2CNTRL(base)); /* interrupt reset */
       
 	switch ( adapstat & G2INTST_MASK )
@@ -397,10 +397,10 @@
 	for(i=0; i<SCpnt->use_sg; i++)
 	{
 	    cptr[i].datalen = sgpnt[i].length;
-	    cptr[i].dataptr = virt_to_bus(sgpnt[i].address);
+	    cptr[i].dataptr = isa_virt_to_bus(sgpnt[i].address);
 	}
 	host->ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain);
-	host->ecb[ecbno].dataptr = virt_to_bus(cptr);
+	host->ecb[ecbno].dataptr = isa_virt_to_bus(cptr);
 #ifdef DEBUG
 	printk("cptr %x: ",cptr);
 	ptr = (unsigned char *) cptr;
@@ -411,15 +411,15 @@
     {
 	SCpnt->host_scribble = NULL;
 	host->ecb[ecbno].datalen = bufflen;
-	host->ecb[ecbno].dataptr = virt_to_bus(buff);
+	host->ecb[ecbno].dataptr = isa_virt_to_bus(buff);
     }
     host->ecb[ecbno].lun = SCpnt->lun;
     host->ecb[ecbno].ses = 1;	/* Suppress underrun errors */
     host->ecb[ecbno].dir = direction;
     host->ecb[ecbno].ars = 1;  /* Yes, get the sense on an error */
     host->ecb[ecbno].senselen = 12;
-    host->ecb[ecbno].senseptr = virt_to_bus(host->ecb[ecbno].sense);
-    host->ecb[ecbno].statusptr = virt_to_bus(host->ecb[ecbno].status);
+    host->ecb[ecbno].senseptr = isa_virt_to_bus(host->ecb[ecbno].sense);
+    host->ecb[ecbno].statusptr = isa_virt_to_bus(host->ecb[ecbno].status);
     host->ecb[ecbno].done = done;
     host->ecb[ecbno].SCpnt = SCpnt;
 #ifdef DEBUG
@@ -459,7 +459,7 @@
 	    if (loopcnt == LOOPCNT_MAX)
 		panic("aha1740.c: mbxout busy!\n");
 	}
-	outl(virt_to_bus(host->ecb + ecbno), MBOXOUT0(base));
+	outl(isa_virt_to_bus(host->ecb + ecbno), MBOXOUT0(base));
 	for (loopcnt = 0; ; loopcnt++) {
 	    if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;
 	    if (loopcnt == LOOPCNT_WARN) {
diff -urN linux-2.5.4-pre2/drivers/scsi/aic7xxx_old.c linux/drivers/scsi/aic7xxx_old.c
--- linux-2.5.4-pre2/drivers/scsi/aic7xxx_old.c	Tue Jan 15 10:52:11 2002
+++ linux/drivers/scsi/aic7xxx_old.c	Thu Feb  7 16:09:56 2002
@@ -254,12 +254,6 @@
 
 #include <linux/config.h>        /* for CONFIG_PCI */
 
-/*
- * To generate the correct addresses for the controller to issue
- * on the bus.  Originally added for DEC Alpha support.
- */
-#define VIRT_TO_BUS(a) (unsigned int)virt_to_bus((void *)(a))
-
 #define AIC7XXX_C_VERSION  "5.2.4"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
@@ -2841,17 +2835,9 @@
         char *buffer;
 
         if(cmd->use_sg)
-        {
-          struct scatterlist *sg;
-
-          sg = (struct scatterlist *)cmd->request_buffer;
-          buffer = (char *)sg[0].address;
-        }
-        else
-        {
-          buffer = (char *)cmd->request_buffer;
-        }
+          BUG();
 
+        buffer = (char *)cmd->request_buffer;
 
         if ( (buffer[7] & WIDE_INQUIRY_BITS) &&
              (p->features & AHC_WIDE) )
diff -urN linux-2.5.4-pre2/drivers/scsi/atp870u.c linux/drivers/scsi/atp870u.c
--- linux-2.5.4-pre2/drivers/scsi/atp870u.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/atp870u.c	Thu Feb  7 16:09:56 2002
@@ -14,6 +14,8 @@
  *		   support atp880 chip lvd u160 2001/05/15 (7.1)
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 
 #include <linux/kernel.h>
diff -urN linux-2.5.4-pre2/drivers/scsi/dpt_i2o.c linux/drivers/scsi/dpt_i2o.c
--- linux-2.5.4-pre2/drivers/scsi/dpt_i2o.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/dpt_i2o.c	Thu Feb  7 16:09:56 2002
@@ -28,6 +28,8 @@
 
 #define ADDR32 (0)
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/version.h>
 #include <linux/module.h>
 
diff -urN linux-2.5.4-pre2/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- linux-2.5.4-pre2/drivers/scsi/eata.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/eata.c	Thu Feb  7 16:09:56 2002
@@ -401,6 +401,8 @@
  *  the driver sets host->wish_block = TRUE for all ISA boards.
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/version.h>
 
 #ifndef LinuxVersionCode
diff -urN linux-2.5.4-pre2/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
--- linux-2.5.4-pre2/drivers/scsi/eata_dma.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/eata_dma.c	Thu Feb  7 16:09:56 2002
@@ -63,6 +63,8 @@
 
 /* Look in eata_dma.h for configuration and revision information */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -urN linux-2.5.4-pre2/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c
--- linux-2.5.4-pre2/drivers/scsi/gdth.c	Mon Jan 28 18:48:08 2002
+++ linux/drivers/scsi/gdth.c	Thu Feb  7 16:09:56 2002
@@ -295,6 +295,8 @@
  * phase:                       Service/parameter/return code special command
  */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 
 #include <linux/version.h>
diff -urN linux-2.5.4-pre2/drivers/scsi/ibmmca.c linux/drivers/scsi/ibmmca.c
--- linux-2.5.4-pre2/drivers/scsi/ibmmca.c	Mon Jan 28 18:48:08 2002
+++ linux/drivers/scsi/ibmmca.c	Thu Feb  7 16:09:56 2002
@@ -766,12 +766,12 @@
       scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
       last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD;
       last_scsi_type(host_index)[ldn] = IM_SCB;
-      scb->sys_buf_adr = virt_to_bus(buf);
+      scb->sys_buf_adr = isa_virt_to_bus(buf);
       scb->sys_buf_length = 255; /* maximum bufferlength gives max info */
-      scb->tsb_adr = virt_to_bus(tsb);
+      scb->tsb_adr = isa_virt_to_bus(tsb);
       /* issue scb to passed ldn, and busy wait for interrupt */
       got_interrupt(host_index) = 0;
-      issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+      issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
       while (!got_interrupt(host_index))
 	barrier ();
 
@@ -804,12 +804,12 @@
       scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
       last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD;
       last_scsi_type(host_index)[ldn] = IM_SCB;
-      scb->sys_buf_adr = virt_to_bus(buf);
+      scb->sys_buf_adr = isa_virt_to_bus(buf);
       scb->sys_buf_length = 8;
-      scb->tsb_adr = virt_to_bus(tsb);
+      scb->tsb_adr = isa_virt_to_bus(tsb);
       /*issue scb to passed ldn, and busy wait for interrupt */
       got_interrupt(host_index) = 0;
-      issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+      issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
       while (!got_interrupt(host_index))
 	barrier ();
 
@@ -842,15 +842,15 @@
       scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
       last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
       last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB;
-      scb->sys_buf_adr = virt_to_bus(buf);
+      scb->sys_buf_adr = isa_virt_to_bus(buf);
       if (special(host_index)==IBM_SCSI2_FW)
 	scb->sys_buf_length = 256; /* get all info from F/W adapter */
       else
 	scb->sys_buf_length = 18; /* get exactly 18 bytes for other SCSI */
-      scb->tsb_adr = virt_to_bus(tsb);
+      scb->tsb_adr = isa_virt_to_bus(tsb);
       /*issue scb to ldn=15, and busy wait for interrupt */
       got_interrupt(host_index) = 0;
-      issue_cmd (host_index, virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
+      issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
       while (!got_interrupt(host_index))
 	barrier ();
 
@@ -1992,7 +1992,7 @@
    scb = &(ld(host_index)[ldn].scb);
    ld(host_index)[ldn].tsb.dev_status = 0;
    scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE;
-   scb->tsb_adr = virt_to_bus(&(ld(host_index)[ldn].tsb));
+   scb->tsb_adr = isa_virt_to_bus(&(ld(host_index)[ldn].tsb));
    scsi_cmd = cmd->cmnd[0];
 
    if (cmd->use_sg) {
@@ -2001,14 +2001,14 @@
       if (i > 16)
 	panic ("IBM MCA SCSI: scatter-gather list too long.\n");
       while (--i >= 0) {
-	 ld(host_index)[ldn].sge[i].address = (void *)(virt_to_bus(sl[i].address));
+	 ld(host_index)[ldn].sge[i].address = (void *)(isa_page_to_bus(sl[i].page) + sl[i].offset);
 	 ld(host_index)[ldn].sge[i].byte_length = sl[i].length;
       }
       scb->enable |= IM_POINTER_TO_LIST;
-      scb->sys_buf_adr = virt_to_bus(&(ld(host_index)[ldn].sge[0]));
+      scb->sys_buf_adr = isa_virt_to_bus(&(ld(host_index)[ldn].sge[0]));
       scb->sys_buf_length = cmd->use_sg * sizeof (struct im_sge);
    } else {
-      scb->sys_buf_adr = virt_to_bus(cmd->request_buffer);
+      scb->sys_buf_adr = isa_virt_to_bus(cmd->request_buffer);
       /* recent Linux midlevel SCSI places 1024 byte for inquiry
        * command. Far too much for old PS/2 hardware. */
       switch (scsi_cmd) {
@@ -2165,10 +2165,10 @@
      PS2_DISK_LED_ON (shpnt->host_no, target);
 
    if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB) {
-      issue_cmd (host_index, virt_to_bus(scb), IM_LONG_SCB | ldn);
+      issue_cmd (host_index, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);
       IBM_DS(host_index).long_scbs++;
    } else {
-      issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+      issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | ldn);
       IBM_DS(host_index).scbs++;
    }
    return 0;
diff -urN linux-2.5.4-pre2/drivers/scsi/ini9100u.c linux/drivers/scsi/ini9100u.c
--- linux-2.5.4-pre2/drivers/scsi/ini9100u.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/ini9100u.c	Thu Feb  7 16:09:56 2002
@@ -108,6 +108,8 @@
 
 #define CVT_LINUX_VERSION(V,P,S)        (V * 65536 + P * 256 + S)
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #ifndef LINUX_VERSION_CODE
 #include <linux/version.h>
 #endif
diff -urN linux-2.5.4-pre2/drivers/scsi/inia100.c linux/drivers/scsi/inia100.c
--- linux-2.5.4-pre2/drivers/scsi/inia100.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/inia100.c	Thu Feb  7 16:09:56 2002
@@ -67,6 +67,8 @@
 #include <linux/version.h>
 #endif
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <linux/module.h>
 
 #include <stdarg.h>
diff -urN linux-2.5.4-pre2/drivers/scsi/ips.c linux/drivers/scsi/ips.c
--- linux-2.5.4-pre2/drivers/scsi/ips.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/ips.c	Thu Feb  7 16:09:56 2002
@@ -140,6 +140,8 @@
  * ioctlsize            - Initial size of the IOCTL buffer
  */
  
+#error Please convert me to Documentation/DMA-mapping.txt
+
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/page.h>
diff -urN linux-2.5.4-pre2/drivers/scsi/mca_53c9x.c linux/drivers/scsi/mca_53c9x.c
--- linux-2.5.4-pre2/drivers/scsi/mca_53c9x.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/mca_53c9x.c	Thu Feb  7 16:09:56 2002
@@ -227,7 +227,7 @@
 
 			esp->esp_command = (volatile unsigned char*)
 			  cmd_buffer;
-	 		esp->esp_command_dvma = virt_to_bus(cmd_buffer);
+	 		esp->esp_command_dvma = isa_virt_to_bus(cmd_buffer);
 
 			/* SCSI chip speed */
 
diff -urN linux-2.5.4-pre2/drivers/scsi/osst.c linux/drivers/scsi/osst.c
--- linux-2.5.4-pre2/drivers/scsi/osst.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/scsi/osst.c	Thu Feb  7 16:09:56 2002
@@ -479,7 +479,8 @@
 	if (STp->raw) {
 		if (STp->buffer->syscall_result) {
 			for (i=0; i < STp->buffer->sg_segs; i++)
-				memset(STp->buffer->sg[i].address, 0, STp->buffer->sg[i].length);
+				memset(page_address(STp->buffer->sg[i].page),
+				       0, STp->buffer->sg[i].length);
 			strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
 		}
 		return 1;
@@ -4375,12 +4376,12 @@
 		for (i = 0, b_size = 0; 
 		     i < STp->buffer->sg_segs && (b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE; 
 		     b_size += STp->buffer->sg[i++].length);
-		STp->buffer->aux = (os_aux_t *) (STp->buffer->sg[i].address + OS_DATA_SIZE - b_size);
+		STp->buffer->aux = (os_aux_t *) (page_address(STp->buffer->sg[i].page) + OS_DATA_SIZE - b_size);
 #if DEBUG
 		printk(OSST_DEB_MSG "osst%d:D: b_data points to %p in segment 0 at %p\n", dev,
-			STp->buffer->b_data, STp->buffer->sg[0].address);
+			STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
 		printk(OSST_DEB_MSG "osst%d:D: AUX points to %p in segment %d at %p\n", dev,
-			 STp->buffer->aux, i, STp->buffer->sg[i].address);
+			 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
 #endif
 	} else
 		STp->buffer->aux = NULL; /* this had better never happen! */
@@ -4933,15 +4934,14 @@
 		     b_size *= 2,                 order++ );
 
 		for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
-			tb->sg[0].address =
-			    (unsigned char *)__get_free_pages(priority, order);
-			if (tb->sg[0].address != NULL) {
-			    tb->sg[0].page = NULL;
+			tb->sg[0].page = alloc_pages(priority, order);
+			tb->sg[0].offset = 0;
+			if (tb->sg[0].page != NULL) {
 			    tb->sg[0].length = b_size;
 			    break;
 			}
 		}
-		if (tb->sg[segs].address == NULL) {
+		if (tb->sg[segs].page == NULL) {
 			kfree(tb);
 			tb = NULL;
 		}
@@ -4953,9 +4953,9 @@
 
 			for (segs=1, got=tb->sg[0].length;
 			     got < osst_buffer_size && segs < OSST_FIRST_SG; ) {
-			    tb->sg[segs].address =
-				(unsigned char *)__get_free_pages(priority, order);
-			    if (tb->sg[segs].address == NULL) {
+			    tb->sg[segs].page = alloc_pages(priority, order);
+			    tb->sg[segs].offset = 0;
+			    if (tb->sg[segs].page == NULL) {
 				if (osst_buffer_size - got <=
 				    (OSST_FIRST_SG - segs) * b_size / 2) {
 				    b_size /= 2; /* Large enough for the rest of the buffers */
@@ -4985,7 +4985,7 @@
 		return NULL;
 	}
 	tb->sg_segs = tb->orig_sg_segs = segs;
-	tb->b_data = tb->sg[0].address;
+	tb->b_data = page_address(tb->sg[0].page);
 
 #if DEBUG
 	if (debugging) {
@@ -5030,9 +5030,9 @@
 
 	for (segs=STbuffer->sg_segs, got=STbuffer->buffer_size;
 	     segs < max_segs && got < new_size; ) {
-		STbuffer->sg[segs].address =
-			  (unsigned char *)__get_free_pages(priority, order);
-		if (STbuffer->sg[segs].address == NULL) {
+		STbuffer->sg[segs].page = alloc_pages(priority, order);
+		STbuffer->sg[segs].offset = 0;
+		if (STbuffer->sg[segs].page == NULL) {
 			if (new_size - got <= (max_segs - segs) * b_size / 2) {
 				b_size /= 2;  /* Large enough for the rest of the buffers */
 				order--;
@@ -5080,7 +5080,7 @@
 		     b_size < STbuffer->sg[i].length;
 		     b_size *= 2, order++);
 
-		free_pages((unsigned long)STbuffer->sg[i].address, order);
+		__free_pages(STbuffer->sg[i].page, order);
 		STbuffer->buffer_size -= STbuffer->sg[i].length;
 	}
 #if DEBUG
@@ -5108,7 +5108,7 @@
 	for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length - offset < do_count ?
 		      st_bp->sg[i].length - offset : do_count;
-		res = copy_from_user(st_bp->sg[i].address + offset, ubp, cnt);
+		res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt);
 		if (res)
 			return (-EFAULT);
 		do_count -= cnt;
@@ -5141,7 +5141,7 @@
 	for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length - offset < do_count ?
 		      st_bp->sg[i].length - offset : do_count;
-		res = copy_to_user(ubp, st_bp->sg[i].address + offset, cnt);
+		res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt);
 		if (res)
 			return (-EFAULT);
 		do_count -= cnt;
@@ -5174,7 +5174,7 @@
 	     i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length - offset < do_count ?
 		      st_bp->sg[i].length - offset : do_count ;
-		memset(st_bp->sg[i].address + offset, 0, cnt);
+		memset(page_address(st_bp->sg[i].page) + offset, 0, cnt);
 		do_count -= cnt;
 		offset = 0;
 	}
@@ -5194,7 +5194,7 @@
 	for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length < do_count ?
 		      st_bp->sg[i].length : do_count ;
-		memcpy(st_bp->sg[i].address, ptr, cnt);
+		memcpy(page_address(st_bp->sg[i].page), ptr, cnt);
 		do_count -= cnt;
 		ptr      += cnt;
 	}
@@ -5215,7 +5215,7 @@
 	for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length < do_count ?
 		      st_bp->sg[i].length : do_count ;
-		memcpy(ptr, st_bp->sg[i].address, cnt);
+		memcpy(ptr, page_address(st_bp->sg[i].page), cnt);
 		do_count -= cnt;
 		ptr      += cnt;
 	}
diff -urN linux-2.5.4-pre2/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c
--- linux-2.5.4-pre2/drivers/scsi/pci2220i.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/pci2220i.c	Thu Feb  7 16:09:56 2002
@@ -34,6 +34,8 @@
  *
  ****************************************************************************/
 
+#error Convert me to understand page+offset based scatterlists
+
 //#define DEBUG 1
 
 #include <linux/module.h>
diff -urN linux-2.5.4-pre2/drivers/scsi/qla1280.c linux/drivers/scsi/qla1280.c
--- linux-2.5.4-pre2/drivers/scsi/qla1280.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/qla1280.c	Thu Feb  7 16:09:56 2002
@@ -182,6 +182,7 @@
     -   Initial Beta Release.  
 *****************************************************************************/
 
+#error Please convert me to Documentation/DMA-mapping.txt
 
 #ifdef MODULE
 #include <linux/module.h>
diff -urN linux-2.5.4-pre2/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- linux-2.5.4-pre2/drivers/scsi/scsi.h	Tue Jan 29 21:44:26 2002
+++ linux/drivers/scsi/scsi.h	Thu Feb  7 16:09:56 2002
@@ -734,7 +734,6 @@
 
 	struct timer_list eh_timeout;	/* Used to time out the command. */
 	void *request_buffer;		/* Actual requested buffer */
-        void **bounce_buffers;		/* Array of bounce buffers when using scatter-gather */
 
 	/* These elements define the operation we ultimately want to perform */
 	unsigned char data_cmnd[MAX_COMMAND_SIZE];
diff -urN linux-2.5.4-pre2/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
--- linux-2.5.4-pre2/drivers/scsi/scsi_lib.c	Mon Jan 14 11:25:29 2002
+++ linux/drivers/scsi/scsi_lib.c	Thu Feb  7 16:09:56 2002
@@ -450,18 +450,8 @@
 	 */
 	if (SCpnt->use_sg) {
 		struct scatterlist *sgpnt;
-		void **bbpnt;
-		int i;
 
 		sgpnt = (struct scatterlist *) SCpnt->request_buffer;
-		bbpnt = SCpnt->bounce_buffers;
-
-		if (bbpnt) {
-			for (i = 0; i < SCpnt->use_sg; i++) {
-				if (bbpnt[i])
-					kfree(sgpnt[i].address);
-			}
-		}
 		scsi_free_sgtable(SCpnt->request_buffer, SCpnt->sglist_len);
 	} else {
 		if (SCpnt->request_buffer != req->buffer)
@@ -525,24 +515,8 @@
 	 */
 	if (SCpnt->use_sg) {
 		struct scatterlist *sgpnt;
-		void **bbpnt;
-		int i;
 
 		sgpnt = (struct scatterlist *) SCpnt->buffer;
-		bbpnt = SCpnt->bounce_buffers;
-
-		if (bbpnt) {
-			for (i = 0; i < SCpnt->use_sg; i++) {
-				if (bbpnt[i]) {
-					if (rq_data_dir(req) == READ) {
-						memcpy(bbpnt[i],
-						       sgpnt[i].address,
-						       sgpnt[i].length);
-					}
-					kfree(sgpnt[i].address);
-				}
-			}
-		}
 		scsi_free_sgtable(SCpnt->buffer, SCpnt->sglist_len);
 	} else {
 		if (SCpnt->buffer != req->buffer) {
diff -urN linux-2.5.4-pre2/drivers/scsi/scsiiom.c linux/drivers/scsi/scsiiom.c
--- linux-2.5.4-pre2/drivers/scsi/scsiiom.c	Sun Dec 31 11:06:00 2000
+++ linux/drivers/scsi/scsiiom.c	Thu Feb  7 16:09:56 2002
@@ -6,6 +6,8 @@
  ***********************************************************************/
 /* $Id: scsiiom.c,v 2.55.2.17 2000/12/20 00:39:37 garloff Exp $ */
 
+#error Please convert me to Documentation/DMA-mapping.txt
+
 static void __inline__
 dc390_freetag (PDCB pDCB, PSRB pSRB)
 {
diff -urN linux-2.5.4-pre2/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c
--- linux-2.5.4-pre2/drivers/scsi/seagate.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/seagate.c	Thu Feb  7 16:09:56 2002
@@ -1061,8 +1061,9 @@
 				     hostno, nobuffs);
 				for (i = 0; i < nobuffs; ++i)
 					printk
-					    ("scsi%d : buffer %d address = %08x length = %d\n",
-					     hostno, i, buffer[i].address,
+					    ("scsi%d : buffer %d address = %p length = %d\n",
+					     hostno, i,
+					     page_address(buffer[i].page) + buffer[i].offset,
 					     buffer[i].length);
 			}
 #endif
diff -urN linux-2.5.4-pre2/drivers/scsi/sgiwd93.c linux/drivers/scsi/sgiwd93.c
--- linux-2.5.4-pre2/drivers/scsi/sgiwd93.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/sgiwd93.c	Thu Feb  7 16:09:56 2002
@@ -120,9 +120,13 @@
 #endif
 		for(i = 0; i <= cmd->SCp.buffers_residual; i++) {
 #ifdef DEBUG_DMA
-			printk("[%p,%d]", slp[i].address, slp[i].length);
-#endif
-			fill_hpc_entries (&hcp, slp[i].address, slp[i].length);
+			printk("[%p,%d]",
+			       page_address(slp[i].page) + slp[i].offset,
+			       slp[i].length);
+#endif
+			fill_hpc_entries (&hcp,
+					  page_address(slp[i].page) + slp[i].offset,
+					  slp[i].length);
 			totlen += slp[i].length;
 		}
 #ifdef DEBUG_DMA
@@ -227,7 +231,7 @@
 		}
 		SCpnt->SCp.buffer = &slp[i];
 		SCpnt->SCp.buffers_residual = SCpnt->SCp.buffers_residual - i;
-		SCpnt->SCp.ptr = (char *) slp[i].address;
+		SCpnt->SCp.ptr = (char *) page_address(slp[i].page) + slp[i].offset;
 		SCpnt->SCp.this_residual = slp[i].length;
 	}
 #ifdef DEBUG_DMA
diff -urN linux-2.5.4-pre2/drivers/scsi/sim710.c linux/drivers/scsi/sim710.c
--- linux-2.5.4-pre2/drivers/scsi/sim710.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/sim710.c	Thu Feb  7 16:09:56 2002
@@ -572,11 +572,11 @@
     hostdata->running = NULL;
     memcpy (hostdata->script, SCRIPT, sizeof(SCRIPT));
     for (i = 0; i < PATCHES; i++)
-	hostdata->script[LABELPATCHES[i]] += virt_to_bus(hostdata->script);
+	hostdata->script[LABELPATCHES[i]] += isa_virt_to_bus(hostdata->script);
     patch_abs_32 (hostdata->script, 0, reselected_identify, 
-    	virt_to_bus((void *)&(hostdata->reselected_identify)));
+    	isa_virt_to_bus((void *)&(hostdata->reselected_identify)));
     patch_abs_32 (hostdata->script, 0, msgin_buf, 
-    	virt_to_bus((void *)&(hostdata->msgin_buf[0])));
+    	isa_virt_to_bus((void *)&(hostdata->msgin_buf[0])));
     hostdata->state = STATE_INITIALISED;
     hostdata->negotiate = 0xff;
 }
@@ -670,7 +670,7 @@
     struct sim710_target *targdata = hostdata->target + cmd->target;
     u32 resume_offset = 0, index;
 
-    index = (u32)((u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
+    index = (u32)((u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
 
     switch (index) {
     case Ent_wait_disc_complete/4 + 2:
@@ -717,7 +717,7 @@
     unsigned char sbcl;
 
     sbcl = NCR_read8(SBCL_REG) & SBCL_PHASE_MASK;
-    index = (u32)((u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
+    index = (u32)((u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
 
     DEB(DEB_PMM, printk("scsi%d: Phase mismatch, phase %s (%x) at script[0x%x]\n",
 	host->host_no, sbcl_to_phase(sbcl), sbcl, index));
@@ -754,7 +754,7 @@
 
 	sg_id = (index - Ent_patch_input_data/4 - 4) / 2;
 	targdata->data_in_jump = hostdata->script[Ent_patch_input_data/4+1] =
-		virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_id * 2 + 2);
+		isa_virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_id * 2 + 2);
 	olen  = targdata->dsa[DSA_DATAIN + sg_id * 2];
 	oaddr = targdata->dsa[DSA_DATAIN + sg_id * 2 + 1];
 	residual = datapath_residual (host);
@@ -783,7 +783,7 @@
 
 	sg_id = (index - Ent_patch_output_data/4 - 4) / 2;
 	targdata->data_out_jump = hostdata->script[Ent_patch_output_data/4+1] =
-		virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_id * 2 + 2);
+		isa_virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_id * 2 + 2);
 	olen  = targdata->dsa[DSA_DATAOUT + sg_id * 2];
 	oaddr = targdata->dsa[DSA_DATAOUT + sg_id * 2 + 1];
 	residual = datapath_residual (host);
@@ -860,7 +860,7 @@
     case A_int_reselected:
 	hostdata->script[Ent_patch_output_data/4+1] = targdata->data_out_jump;
 	hostdata->script[Ent_patch_input_data/4+1] = targdata->data_in_jump;
-	NCR_write32(DSA_REG, virt_to_bus(targdata->dsa));
+	NCR_write32(DSA_REG, isa_virt_to_bus(targdata->dsa));
 	resume_offset = targdata->resume_offset;
 	break;
     case A_int_data_bad_phase:
@@ -944,7 +944,7 @@
 	DEB(DEB_INTS, printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
 		"dstat %02x, dsp [%04x], scratch %02x\n",
 	    host->host_no, sim710_intrs, istat, sstat0, dstat,
-	    (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
+	    (u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
 	    NCR_read32(SCRATCH_REG)));
 	if ((dstat & DSTAT_SIR) && dsps == A_int_reselected) {
 	    /* Reselected.  Identify the target from LCRC_REG, and
@@ -991,7 +991,7 @@
 	    printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
 		"dstat %02x, dsp [%04x], scratch %02x, dsps %08x\n",
 		host->host_no, sim710_intrs, istat, sstat0, dstat,
-		(u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
+		(u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
 		NCR_read32(SCRATCH_REG), dsps);
 	    /* resume_offset is zero, which will cause a host reset */
 	}
@@ -1044,7 +1044,7 @@
 #ifdef DEBUG_LIMIT_INTS
 	if (sim710_intrs < DEBUG_LIMIT_INTS)
 #endif
-	NCR_write32(DSP_REG, virt_to_bus(hostdata->script+resume_offset/4));
+	NCR_write32(DSP_REG, isa_virt_to_bus(hostdata->script+resume_offset/4));
 	if (resume_offset == Ent_reselect)
 	    run_process_issue_queue(hostdata);
     }
@@ -1122,48 +1122,47 @@
     targdata->dsa_status[0] = 0xff;
 
     targdata->dsa[DSA_SELECT]		= (1 << cmd->target) << 16;
-    targdata->dsa[DSA_MSGOUT+1]		= virt_to_bus(targdata->dsa_msgout);
+    targdata->dsa[DSA_MSGOUT+1]		= isa_virt_to_bus(targdata->dsa_msgout);
     targdata->dsa[DSA_CMND]		= cmd->cmd_len;
-    targdata->dsa[DSA_CMND+1]		= virt_to_bus(targdata->dsa_cdb);
+    targdata->dsa[DSA_CMND+1]		= isa_virt_to_bus(targdata->dsa_cdb);
     targdata->dsa[DSA_STATUS]		= 1;
-    targdata->dsa[DSA_STATUS+1]		= virt_to_bus(targdata->dsa_status);
+    targdata->dsa[DSA_STATUS+1]		= isa_virt_to_bus(targdata->dsa_status);
     targdata->dsa[DSA_MSGIN]		= 1;
-    targdata->dsa[DSA_MSGIN+1]		= virt_to_bus(targdata->dsa_msgin);
+    targdata->dsa[DSA_MSGIN+1]		= isa_virt_to_bus(targdata->dsa_msgin);
 
     sg_start = (MAX_SG - (cmd->use_sg ? cmd->use_sg : 1)) * 2;
     dip = targdata->dsa + DSA_DATAIN + sg_start;
     dop = targdata->dsa + DSA_DATAOUT + sg_start;
 
     for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; i++) {
-	u32 vbuf = cmd->use_sg ?
-		(u32)(((struct scatterlist *)cmd->buffer)[i].address) :
-		(u32)(cmd->request_buffer);
-	u32 bbuf = virt_to_bus((void *)vbuf);
-	u32 cnt = cmd->use_sg ?
-		((struct scatterlist *)cmd->buffer)[i].length :
-		cmd->request_bufflen;
+	struct scatterlist *sgl = &((struct scatterlist *)cmd->buffer)[i];
+	void *vbuf = cmd->use_sg ?
+		(page_address(sgl->page) + sgl->offset) :
+		(cmd->request_buffer);
+	u32 bbuf = isa_virt_to_bus(vbuf);
+	u32 cnt = cmd->use_sg ? sgl->length : cmd->request_bufflen;
 
 	if (datain) {
 #ifdef CONFIG_TP34V_SCSI
-	    cache_clear(virt_to_phys((void *)vbuf), cnt);
+	    cache_clear(virt_to_phys(vbuf, cnt);
 #endif
 	    *dip++	= cnt;
 	    *dip++	= bbuf;
 	}
 	if (dataout) {
 #ifdef CONFIG_TP34V_SCSI
-	    cache_push(virt_to_phys((void *)vbuf), cnt);
+	    cache_push(virt_to_phys(vbuf, cnt);
 #endif
 	    *dop++	= cnt;
 	    *dop++	= bbuf;
 	}
     }
     targdata->data_out_jump = hostdata->script[Ent_patch_output_data/4+1] =
-	virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_start + 2);
+	isa_virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_start + 2);
     targdata->data_in_jump = hostdata->script[Ent_patch_input_data/4+1] =
-	virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_start + 2);
+	isa_virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_start + 2);
 
-    for (i = 0, dsa = virt_to_bus(targdata->dsa); i < 4; i++) {
+    for (i = 0, dsa = isa_virt_to_bus(targdata->dsa); i < 4; i++) {
 	u32 v = hostdata->script[Ent_patch_new_dsa/4 + i * 2];
 
 	v &= ~0x0000ff00;
@@ -1508,7 +1507,7 @@
 #endif
 	    chips++;
 	}
-	NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_reselect/4));
+	NCR_write32(DSP_REG, isa_virt_to_bus(hostdata->script+Ent_reselect/4));
 	hostdata->state = STATE_IDLE;
     }
     return chips;
@@ -1562,7 +1561,7 @@
     ncr_halt(host);
     printk("scsi%d: dsp = %08x (script[0x%04x]), scratch = %08x\n",
 	host->host_no, NCR_read32(DSP_REG),
-	((u32)bus_to_virt(NCR_read32(DSP_REG)) - (u32)hostdata->script)/4,
+	((u32)isa_bus_to_virt(NCR_read32(DSP_REG)) - (u32)hostdata->script)/4,
 	NCR_read32(SCRATCH_REG));
 
     for (target = 0; target < 7; target++) {
@@ -1578,7 +1577,7 @@
     sim710_soft_reset(host);
     sim710_driver_init(host);
 
-    NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_reselect/4));
+    NCR_write32(DSP_REG, isa_virt_to_bus(hostdata->script+Ent_reselect/4));
     hostdata->state = STATE_IDLE;
 
     run_process_issue_queue(hostdata);
diff -urN linux-2.5.4-pre2/drivers/scsi/st.c linux/drivers/scsi/st.c
--- linux-2.5.4-pre2/drivers/scsi/st.c	Wed Jan 23 15:30:47 2002
+++ linux/drivers/scsi/st.c	Thu Feb  7 16:09:56 2002
@@ -3404,15 +3404,14 @@
 		     order++, b_size *= 2)
 			;
 		for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
-			tb->sg[0].address =
-			    (unsigned char *) __get_free_pages(priority, order);
-			if (tb->sg[0].address != NULL) {
+			tb->sg[0].page = alloc_pages(priority, order);
+			tb->sg[0].offset = 0;
+			if (tb->sg[0].page != NULL) {
 				tb->sg[0].length = b_size;
 				break;
 			}
 		}
-		tb->sg[0].page = NULL;
-		if (tb->sg[segs].address == NULL) {
+		if (tb->sg[segs].page == NULL) {
 			kfree(tb);
 			tb = NULL;
 		} else {	/* Got something, continue */
@@ -3424,10 +3423,9 @@
 				;
 			for (segs = 1, got = tb->sg[0].length;
 			     got < st_buffer_size && segs < ST_FIRST_SG;) {
-				tb->sg[segs].address =
-					(unsigned char *) __get_free_pages(priority,
-									   order);
-				if (tb->sg[segs].address == NULL) {
+				tb->sg[segs].page = alloc_pages(priority, order);
+				tb->sg[segs].offset = 0;
+				if (tb->sg[segs].page == NULL) {
 					if (st_buffer_size - got <=
 					    (ST_FIRST_SG - segs) * b_size / 2) {
 						b_size /= 2; /* Large enough for the
@@ -3443,7 +3441,6 @@
 					tb = NULL;
 					break;
 				}
-				tb->sg[segs].page = NULL;
 				tb->sg[segs].length = b_size;
 				got += b_size;
 				segs++;
@@ -3457,7 +3454,7 @@
 		return NULL;
 	}
 	tb->sg_segs = tb->orig_sg_segs = segs;
-	tb->b_data = tb->sg[0].address;
+	tb->b_data = page_address(tb->sg[0].page);
 
         DEBC(printk(ST_DEB_MSG
                     "st: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n",
@@ -3503,9 +3500,9 @@
 
 	for (segs = STbuffer->sg_segs, got = STbuffer->buffer_size;
 	     segs < max_segs && got < new_size;) {
-		STbuffer->sg[segs].address =
-			(unsigned char *) __get_free_pages(priority, order);
-		if (STbuffer->sg[segs].address == NULL) {
+		STbuffer->sg[segs].page = alloc_pages(priority, order);
+		STbuffer->sg[segs].offset = 0;
+		if (STbuffer->sg[segs].page == NULL) {
 			if (new_size - got <= (max_segs - segs) * b_size / 2) {
 				b_size /= 2; /* Large enough for the rest of the buffers */
 				order--;
@@ -3517,7 +3514,6 @@
 			normalize_buffer(STbuffer);
 			return FALSE;
 		}
-		STbuffer->sg[segs].page = NULL;
 		STbuffer->sg[segs].length = b_size;
 		STbuffer->sg_segs += 1;
 		got += b_size;
@@ -3541,13 +3537,13 @@
 		for (b_size=PAGE_SIZE, order=0; b_size < STbuffer->sg[i].length;
 		     order++, b_size *= 2)
 			; /* empty */
-		free_pages((unsigned long)(STbuffer->sg[i].address), order);
+		__free_pages(STbuffer->sg[i].page, order);
 		STbuffer->buffer_size -= STbuffer->sg[i].length;
 	}
         DEB(
 	if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
 		printk(ST_DEB_MSG "st: Buffer at %p normalized to %d bytes (segs %d).\n",
-		       STbuffer->sg[0].address, STbuffer->buffer_size,
+		       page_address(STbuffer->sg[0].page), STbuffer->buffer_size,
 		       STbuffer->sg_segs);
         ) /* end DEB */
 	STbuffer->sg_segs = STbuffer->orig_sg_segs;
@@ -3570,7 +3566,7 @@
 	for (; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length - offset < do_count ?
 		    st_bp->sg[i].length - offset : do_count;
-		res = copy_from_user(st_bp->sg[i].address + offset, ubp, cnt);
+		res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt);
 		if (res)
 			return (-EFAULT);
 		do_count -= cnt;
@@ -3603,7 +3599,7 @@
 	for (; i < st_bp->sg_segs && do_count > 0; i++) {
 		cnt = st_bp->sg[i].length - offset < do_count ?
 		    st_bp->sg[i].length - offset : do_count;
-		res = copy_to_user(ubp, st_bp->sg[i].address + offset, cnt);
+		res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt);
 		if (res)
 			return (-EFAULT);
 		do_count -= cnt;
diff -urN linux-2.5.4-pre2/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c
--- linux-2.5.4-pre2/drivers/scsi/ultrastor.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/ultrastor.c	Thu Feb  7 16:09:56 2002
@@ -667,12 +667,12 @@
 	sl = (struct scatterlist *) SCpnt->request_buffer;
 	max = SCpnt->use_sg;
 	for (i = 0; i < max; i++) {
-		mscp->sglist[i].address = virt_to_bus(sl[i].address);
+		mscp->sglist[i].address = isa_page_to_bus(sl[i].page) + sl[i].offset;
 		mscp->sglist[i].num_bytes = sl[i].length;
 		transfer_length += sl[i].length;
 	}
 	mscp->number_of_sg_list = max;
-	mscp->transfer_data = virt_to_bus(mscp->sglist);
+	mscp->transfer_data = isa_virt_to_bus(mscp->sglist);
 	/* ??? May not be necessary.  Docs are unclear as to whether transfer
 	   length field is ignored or whether it should be set to the total
 	   number of bytes of the transfer.  */
@@ -728,7 +728,7 @@
     } else {
 	/* Unset scatter/gather flag in SCSI command packet */
 	my_mscp->sg = FALSE;
-	my_mscp->transfer_data = virt_to_bus(SCpnt->request_buffer);
+	my_mscp->transfer_data = isa_virt_to_bus(SCpnt->request_buffer);
 	my_mscp->transfer_data_length = SCpnt->request_bufflen;
     }
     my_mscp->command_link = 0;		/*???*/
@@ -738,7 +738,7 @@
     memcpy(my_mscp->scsi_cdbs, SCpnt->cmnd, my_mscp->length_of_scsi_cdbs);
     my_mscp->adapter_status = 0;
     my_mscp->target_status = 0;
-    my_mscp->sense_data = virt_to_bus(&SCpnt->sense_buffer);
+    my_mscp->sense_data = isa_virt_to_bus(&SCpnt->sense_buffer);
     my_mscp->done = done;
     my_mscp->SCint = SCpnt;
     SCpnt->host_scribble = (unsigned char *)my_mscp;
@@ -796,7 +796,7 @@
     }
 
     /* Store pointer in OGM address bytes */
-    outl(virt_to_bus(my_mscp), config.ogm_address);
+    outl(isa_virt_to_bus(my_mscp), config.ogm_address);
 
     /* Issue OGM interrupt */
     if (config.slot) {
@@ -872,9 +872,9 @@
 	out[28 + i * 3] = '\n';
 	out[29 + i * 3] = 0;
 	ogm_status = inb(port0 + 22);
-	ogm_addr = (unsigned int)bus_to_virt(inl(port0 + 23));
+	ogm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 23));
 	icm_status = inb(port0 + 27);
-	icm_addr = (unsigned int)bus_to_virt(inl(port0 + 28));
+	icm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 28));
 	restore_flags(flags);
       }
 
@@ -910,7 +910,7 @@
 
 	save_flags(flags);
 	cli();
-	outl(virt_to_bus(&config.mscp[mscp_index]), config.ogm_address);
+	outl(isa_virt_to_bus(&config.mscp[mscp_index]), config.ogm_address);
 	inb(0xc80);	/* delay */
 	outb(0x80, config.ogm_address - 1);
 	outb(0x2, LCL_DOORBELL_INTR(config.doorbell_address));
@@ -1043,7 +1043,7 @@
 #if ULTRASTOR_MAX_CMDS == 1
     mscp = &config.mscp[0];
 #else
-    mscp = (struct mscp *)bus_to_virt(inl(config.icm_address));
+    mscp = (struct mscp *)isa_bus_to_virt(inl(config.icm_address));
     mscp_index = mscp - config.mscp;
     if (mscp_index >= ULTRASTOR_MAX_CMDS) {
 	printk("Ux4F interrupt: bad MSCP address %x\n", (unsigned int) mscp);
diff -urN linux-2.5.4-pre2/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c
--- linux-2.5.4-pre2/drivers/scsi/wd7000.c	Mon Jan 28 14:36:59 2002
+++ linux/drivers/scsi/wd7000.c	Thu Feb  7 16:09:56 2002
@@ -1111,7 +1111,7 @@
 		return;
 	    }
 	    /* Aaaargh! (Zaga) */
-	    scb = bus_to_virt(scsi2int ((unchar *) icmbs[icmb].scbptr));
+	    scb = isa_bus_to_virt(scsi2int ((unchar *) icmbs[icmb].scbptr));
 	    icmbs[icmb].status = 0;
 	    if (!(scb->op & ICB_OP_MASK)) {	/* an SCB is done */
 		SCpnt = scb->SCpnt;
@@ -1187,13 +1187,14 @@
 	any2scsi (scb->maxlen, SCpnt->use_sg * sizeof (Sgb));
 
 	for (i = 0; i < SCpnt->use_sg; i++) {
-	    any2scsi (sgb[i].ptr, (int) sg[i].address);
+	    any2scsi (sgb[i].ptr,
+		      isa_page_to_bus(sg[i].page) + sg[i].offset);
 	    any2scsi (sgb[i].len, sg[i].length);
 	}
     }
     else {
 	scb->op = 0;
-	any2scsi (scb->dataptr, (int) SCpnt->request_buffer);
+	any2scsi (scb->dataptr, isa_virt_to_bus(SCpnt->request_buffer));
 	any2scsi (scb->maxlen, SCpnt->request_bufflen);
     }
 
diff -urN linux-2.5.4-pre2/drivers/usb/hcd/ehci-hcd.c linux/drivers/usb/hcd/ehci-hcd.c
--- linux-2.5.4-pre2/drivers/usb/hcd/ehci-hcd.c	Fri Jan 25 16:17:51 2002
+++ linux/drivers/usb/hcd/ehci-hcd.c	Thu Feb  7 16:09:57 2002
@@ -277,7 +277,7 @@
 	 */
 	usb_connect (udev);
 	udev->speed = USB_SPEED_HIGH;
-	if (usb_new_device (udev) != 0) {
+	if (usb_register_root_hub (udev, &ehci->hcd.pdev->dev) != 0) {
 		if (hcd->state == USB_STATE_RUNNING)
 			ehci_ready (ehci);
 		while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
diff -urN linux-2.5.4-pre2/drivers/usb/hcd/ohci-hcd.c linux/drivers/usb/hcd/ohci-hcd.c
--- linux-2.5.4-pre2/drivers/usb/hcd/ohci-hcd.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/hcd/ohci-hcd.c	Thu Feb  7 16:09:57 2002
@@ -469,7 +469,7 @@
 
 	usb_connect (udev);
 	udev->speed = USB_SPEED_FULL;
-	if (usb_new_device (udev) != 0) {
+	if (usb_register_root_hub (udev, &ohci->hcd.pdev->dev) != 0) {
 		usb_free_dev (udev); 
 		ohci->disabled = 1;
 // FIXME cleanup
diff -urN linux-2.5.4-pre2/drivers/usb/hpusbscsi.c linux/drivers/usb/hpusbscsi.c
--- linux-2.5.4-pre2/drivers/usb/hpusbscsi.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/hpusbscsi.c	Thu Feb  7 16:09:57 2002
@@ -454,7 +454,8 @@
                 u,
                 hpusbscsi->dev,
                 hpusbscsi->current_data_pipe,
-                sg[hpusbscsi->fragment].address,
+                page_address(sg[hpusbscsi->fragment].page) +
+		sg[hpusbscsi->fragment].offset,
                 sg[hpusbscsi->fragment++].length,
                 callback,
                 hpusbscsi
diff -urN linux-2.5.4-pre2/drivers/usb/hub.c linux/drivers/usb/hub.c
--- linux-2.5.4-pre2/drivers/usb/hub.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/hub.c	Thu Feb  7 16:09:57 2002
@@ -721,6 +721,20 @@
 		info("new USB device on bus %d path %s, assigned address %d",
 			dev->bus->busnum, dev->devpath, dev->devnum);
 
+		/* put the device in the global device tree */
+		dev->dev.parent = &dev->parent->dev;
+		sprintf (&dev->dev.name[0], "USB device %04x:%04x",
+			 dev->descriptor.idVendor,
+			 dev->descriptor.idProduct);
+		/* find the number of the port this device is connected to */
+		sprintf (&dev->dev.bus_id[0], "unknown_port_%03d", dev->devnum);
+		for (i = 0; i < USB_MAXCHILDREN; ++i) {
+			if (dev->parent->children[i] == dev) {
+				sprintf (&dev->dev.bus_id[0], "%02d", i);
+				break;
+			}
+		}
+
 		/* Run it through the hoops (find a driver, etc) */
 		if (!usb_new_device(dev))
 			goto done;
diff -urN linux-2.5.4-pre2/drivers/usb/inode.c linux/drivers/usb/inode.c
--- linux-2.5.4-pre2/drivers/usb/inode.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/inode.c	Thu Feb  7 16:09:57 2002
@@ -525,7 +525,7 @@
 static struct super_block *usb_get_sb(struct file_system_type *fs_type,
 	int flags, char *dev_name, void *data)
 {
-	return get_sb_single(fs_type, flags, data, usb_fill_super);
+	return get_sb_single(fs_type, flags, data, usbfs_fill_super);
 }
 
 static struct file_system_type usbdevice_fs_type = {
diff -urN linux-2.5.4-pre2/drivers/usb/microtek.c linux/drivers/usb/microtek.c
--- linux-2.5.4-pre2/drivers/usb/microtek.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/microtek.c	Thu Feb  7 16:09:57 2002
@@ -609,10 +609,11 @@
 	sg = context->srb->buffer;
 	context->fragment++;
 	mts_int_submit_urb(transfer,
-			context->data_pipe,
-			sg[context->fragment].address,
-			sg[context->fragment].length,
-			context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);
+			   context->data_pipe,
+			   page_address(sg[context->fragment].page) +
+			   sg[context->fragment].offset,
+			   sg[context->fragment].length,
+			   context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);
 	return;
 }
 
@@ -654,7 +655,7 @@
 	} else {
 		MTS_DEBUG("Using scatter/gather\n");
 		sg = srb->buffer;
-		desc->context.data = sg[0].address;
+		desc->context.data = page_address(sg[0].page) + sg[0].offset;
 		desc->context.data_length = sg[0].length;
 	}
 
diff -urN linux-2.5.4-pre2/drivers/usb/storage/freecom.c linux/drivers/usb/storage/freecom.c
--- linux-2.5.4-pre2/drivers/usb/storage/freecom.c	Thu Jan  3 18:52:28 2002
+++ linux/drivers/usb/storage/freecom.c	Thu Feb  7 16:09:57 2002
@@ -144,11 +144,11 @@
 			if (transfer_amount - total_transferred >= 
 					sg[i].length) {
 				result = usb_stor_transfer_partial(us,
-						sg[i].address, sg[i].length);
+						page_address(sg[i].page) + sg[i].offset, sg[i].length);
 				total_transferred += sg[i].length;
 			} else {
 				result = usb_stor_transfer_partial(us,
-						sg[i].address,
+						page_address(sg[i].page) + sg[i].offset,
 						transfer_amount - total_transferred);
 				total_transferred += transfer_amount - total_transferred;
 			}
diff -urN linux-2.5.4-pre2/drivers/usb/storage/isd200.c linux/drivers/usb/storage/isd200.c
--- linux-2.5.4-pre2/drivers/usb/storage/isd200.c	Tue Nov 13 09:19:41 2001
+++ linux/drivers/usb/storage/isd200.c	Thu Feb  7 16:09:57 2002
@@ -518,13 +518,13 @@
                             sg[i].length) {
                                 result = isd200_transfer_partial(us, 
                                                                  srb->sc_data_direction,
-                                                                 sg[i].address, 
+                                                                 page_address(sg[i].page) + sg[i].offset, 
                                                                  sg[i].length);
                                 total_transferred += sg[i].length;
                         } else
                                 result = isd200_transfer_partial(us, 
                                                                  srb->sc_data_direction,                            
-                                                                 sg[i].address,
+                                                                 page_address(sg[i].page) + sg[i].offset,
                                                                  transfer_amount - total_transferred);
 
                         /* if we get an error, end the loop here */
@@ -1415,10 +1415,10 @@
 				/* transfer the lesser of the next buffer or the
 				 * remaining data */
 				if (len - total >= sg[i].length) {
-					memcpy(sg[i].address, src + total, sg[i].length);
+					memcpy(page_address(sg[i].page) + sg[i].offset, src + total, sg[i].length);
 					total += sg[i].length;
 				} else {
-					memcpy(sg[i].address, src + total, len - total);
+					memcpy(page_address(sg[i].page) + sg[i].offset, src + total, len - total);
 					total = len;
 				}
 			} 
diff -urN linux-2.5.4-pre2/drivers/usb/storage/protocol.c linux/drivers/usb/storage/protocol.c
--- linux-2.5.4-pre2/drivers/usb/storage/protocol.c	Thu Jan 17 14:06:53 2002
+++ linux/drivers/usb/storage/protocol.c	Thu Feb  7 16:09:57 2002
@@ -67,13 +67,10 @@
 	US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n");
 
 	/* find the location of the data */
-	if (srb->use_sg) {
-		struct scatterlist *sg;
+	if (srb->use_sg)
+		BUG();
 
-		sg = (struct scatterlist *) srb->request_buffer;
-		data_ptr = (unsigned char *) sg[0].address;
-	} else
-		data_ptr = (unsigned char *)srb->request_buffer;
+	data_ptr = (unsigned char *) srb->request_buffer;
 
 	/* Change the SCSI revision number */
 	data_ptr[2] = (data_ptr[2] & ~7) | 2;
diff -urN linux-2.5.4-pre2/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c
--- linux-2.5.4-pre2/drivers/usb/storage/scsiglue.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/storage/scsiglue.c	Thu Feb  7 16:09:57 2002
@@ -564,7 +564,12 @@
 	    }
 
 	  /* copy one byte */
-	  sg[db].address[di] = sg[sb].address[si];
+	  {
+		  char *src = page_address(sg[sb].page) + sg[sb].offset + si;
+		  char *dst = page_address(sg[db].page) + sg[db].offset + di;
+
+		  *dst = *src;
+	  }
 
 	  /* get next destination */
 	  if ( sg[db].length-1 == di )
@@ -602,7 +607,7 @@
 	      break;
 	    }
 
-	  sg[db].address[di] = 0;
+	  *(char *)(page_address(sg[db].page) + sg[db].offset) = 0;
 
 	  /* get next destination */
 	  if ( sg[db].length-1 == di )
@@ -752,7 +757,12 @@
 	    }
 
 	  /* copy one byte */
-	  sg[db].address[di] = sg[sb].address[si];
+	  {
+		  char *src = page_address(sg[sb].page) + sg[sb].offset + si;
+		  char *dst = page_address(sg[db].page) + sg[db].offset + di;
+
+		  *dst = *src;
+	  }
 
 	  /* get next destination */
 	  if ( di == 0 )
@@ -789,7 +799,11 @@
 	      break;
 	    }
 
-	  sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
+	  {
+		  char *dst = page_address(sg[db].page) + sg[db].offset + di;
+
+		  *dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
+	  }
 
 	  /* get next destination */
 	  if ( di == 0 )
@@ -839,13 +853,19 @@
 		  if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
 		    {
 		      /* fill in the pointers for both header types */
-		      the6->array[element] = &(sg[i].address[j]);
-		      the10->array[element] = &(sg[i].address[j]);
+		      the6->array[element] =
+			      page_address(sg[i].page) +
+			      sg[i].offset + j;
+		      the10->array[element] =
+			      page_address(sg[i].page) +
+			      sg[i].offset + j;
 		    }
 		  else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
 		    {
 		      /* only the longer headers still cares now */
-		      the10->array[element] = &(sg[i].address[j]);
+		      the10->array[element] =
+			      page_address(sg[i].page) +
+			      sg[i].offset + j;
 		    }
 		  /* increase element counter */
 		  element++;
diff -urN linux-2.5.4-pre2/drivers/usb/storage/sddr09.c linux/drivers/usb/storage/sddr09.c
--- linux-2.5.4-pre2/drivers/usb/storage/sddr09.c	Thu Jan  3 18:52:28 2002
+++ linux/drivers/usb/storage/sddr09.c	Thu Feb  7 16:09:57 2002
@@ -239,7 +239,7 @@
 		sg = (struct scatterlist *)data;
 		for (i=0; i<use_sg && transferred<len; i++) {
 			result = sddr09_raw_bulk(us, direction,
-				sg[i].address, 
+				page_address(sg[i].page) + sg[i].offset, 
 				len-transferred > sg[i].length ?
 					sg[i].length : len-transferred);
 			if (result!=US_BULK_TRANSFER_GOOD)
@@ -384,7 +384,7 @@
 	if (use_sg) {
 		transferred = 0;
 		for (i=0; i<use_sg && transferred<len; i++) {
-			memcpy(sg[i].address, buffer+transferred,
+			memcpy(page_address(sg[i].page) + sg[i].offset, buffer+transferred,
 				len-transferred > sg[i].length ?
 					sg[i].length : len-transferred);
 			transferred += sg[i].length;
@@ -636,21 +636,24 @@
 
 	for (i=0; i<alloc_blocks; i++) {
 		if (i<alloc_blocks-1) {
-			sg[i].address = kmalloc( (1<<17), GFP_NOIO );
-			sg[i].page = NULL;
+			char *vaddr = kmalloc(1 << 17, GFP_NOIO);
+			sg[i].page = virt_to_page(vaddr);
+			sg[i].offset = ((unsigned long)vaddr & ~PAGE_MASK);
 			sg[i].length = (1<<17);
 		} else {
-			sg[i].address = kmalloc(alloc_len, GFP_NOIO);
-			sg[i].page = NULL;
+			char *vaddr = kmalloc(alloc_len, GFP_NOIO);
+			sg[i].page = virt_to_page(vaddr);
+			sg[i].offset = ((unsigned long)vaddr & ~PAGE_MASK);
 			sg[i].length = alloc_len;
 		}
 		alloc_len -= sg[i].length;
 	}
+
 	for (i=0; i<alloc_blocks; i++)
-		if (sg[i].address == NULL) {
+		if (sg[i].page == NULL) {
 			for (i=0; i<alloc_blocks; i++)
-				if (sg[i].address != NULL)
-					kfree(sg[i].address);
+				if (sg[i].page != NULL)
+					kfree(page_address(sg[i].page) + sg[i].offset);
 			kfree(sg);
 			return 0;
 		}
@@ -661,7 +664,7 @@
 			(unsigned char *)sg, alloc_blocks)) !=
 			USB_STOR_TRANSPORT_GOOD) {
 		for (i=0; i<alloc_blocks; i++)
-			kfree(sg[i].address);
+			kfree(page_address(sg[i].page) + sg[i].offset);
 		kfree(sg);
 		return -1;
 	}
@@ -683,7 +686,7 @@
 		info->lba_to_pba = NULL;
 		info->pba_to_lba = NULL;
 		for (i=0; i<alloc_blocks; i++)
-			kfree(sg[i].address);
+			kfree(page_address(sg[i].page) + sg[i].offset);
 		kfree(sg);
 		return 0;
 	}
@@ -695,7 +698,7 @@
 	// scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11)
 
 	for (i=0; i<numblocks; i++) {
-		ptr = sg[i>>11].address+((i&0x7ff)<<6);
+		ptr = page_address(sg[i>>11].page)+sg[i>>11].offset+((i&0x7ff)<<6);
 		if (ptr[0]!=0xFF || ptr[1]!=0xFF || ptr[2]!=0xFF ||
 		    ptr[3]!=0xFF || ptr[4]!=0xFF || ptr[5]!=0xFF) {
 			US_DEBUGP("PBA %04X has no logical mapping: reserved area = "
@@ -748,7 +751,7 @@
 	}
 
 	for (i=0; i<alloc_blocks; i++)
-		kfree(sg[i].address);
+		kfree(page_address(sg[i].page)+sg[i].offset);
 	kfree(sg);
 	return 0;
 }
diff -urN linux-2.5.4-pre2/drivers/usb/storage/shuttle_usbat.c linux/drivers/usb/storage/shuttle_usbat.c
--- linux-2.5.4-pre2/drivers/usb/storage/shuttle_usbat.c	Thu Jan  3 18:52:28 2002
+++ linux/drivers/usb/storage/shuttle_usbat.c	Thu Feb  7 16:09:57 2002
@@ -214,7 +214,7 @@
 		sg = (struct scatterlist *)data;
 		for (i=0; i<use_sg && transferred<len; i++) {
 			result = usbat_raw_bulk(us, direction,
-				sg[i].address, 
+				page_address(sg[i].page) + sg[i].offset,
 				len-transferred > sg[i].length ?
 					sg[i].length : len-transferred);
 			if (result!=US_BULK_TRANSFER_GOOD)
@@ -733,17 +733,19 @@
 			while (amount<len) {
 				if (len - amount >= 
 					  sg[sg_segment].length-sg_offset) {
-				  memcpy(sg[sg_segment].address + sg_offset,
-					buffer + amount,
-					sg[sg_segment].length - sg_offset);
+				  memcpy(page_address(sg[sg_segment].page) +
+					 sg[sg_segment].offset + sg_offset,
+					 buffer + amount,
+					 sg[sg_segment].length - sg_offset);
 				  amount += 
 					  sg[sg_segment].length-sg_offset;
 				  sg_segment++;
 				  sg_offset=0;
 				} else {
-				  memcpy(sg[sg_segment].address + sg_offset,
-					buffer + amount,
-					len - amount);
+				  memcpy(page_address(sg[sg_segment].page) +
+					 sg[sg_segment].offset + sg_offset,
+					 buffer + amount,
+					 len - amount);
 				  sg_offset += (len - amount);
 				  amount = len;
 				}
diff -urN linux-2.5.4-pre2/drivers/usb/storage/transport.c linux/drivers/usb/storage/transport.c
--- linux-2.5.4-pre2/drivers/usb/storage/transport.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/storage/transport.c	Thu Feb  7 16:09:57 2002
@@ -584,11 +584,11 @@
 			if (transfer_amount - total_transferred >= 
 					sg[i].length) {
 				result = usb_stor_transfer_partial(us,
-						sg[i].address, sg[i].length);
+						page_address(sg[i].page) + sg[i].offset, sg[i].length);
 				total_transferred += sg[i].length;
 			} else
 				result = usb_stor_transfer_partial(us,
-						sg[i].address,
+						page_address(sg[i].page) + sg[i].offset,
 						transfer_amount - total_transferred);
 
 			/* if we get an error, end the loop here */
diff -urN linux-2.5.4-pre2/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c
--- linux-2.5.4-pre2/drivers/usb/storage/usb.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/storage/usb.c	Thu Feb  7 16:09:57 2002
@@ -288,13 +288,13 @@
 	if (us->srb->use_sg) {
 		sg = (struct scatterlist *)us->srb->request_buffer;
 		for (i=0; i<us->srb->use_sg; i++)
-			memset(sg[i].address, 0, sg[i].length);
+			memset(page_address(sg[i].page) + sg[i].offset, 0, sg[i].length);
 		for (i=0, transferred=0; 
 				i<us->srb->use_sg && transferred < len;
 				i++) {
 			amt = sg[i].length > len-transferred ? 
 					len-transferred : sg[i].length;
-			memcpy(sg[i].address, data+transferred, amt);
+			memcpy(page_address(sg[i].page) + sg[i].offset, data+transferred, amt);
 			transferred -= amt;
 		}
 	} else {
diff -urN linux-2.5.4-pre2/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- linux-2.5.4-pre2/drivers/usb/uhci.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/uhci.c	Thu Feb  7 16:09:57 2002
@@ -2842,7 +2842,7 @@
 
 	usb_connect(uhci->rh.dev);
 
-	if (usb_new_device(uhci->rh.dev) != 0) {
+	if (usb_register_root_hub(uhci->rh.dev, &dev->dev) != 0) {
 		err("unable to start root hub");
 		retval = -ENOMEM;
 		goto err_start_root_hub;
diff -urN linux-2.5.4-pre2/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
--- linux-2.5.4-pre2/drivers/usb/usb-ohci.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/usb-ohci.c	Thu Feb  7 16:09:57 2002
@@ -2231,7 +2231,7 @@
 	dev = usb_to_ohci (usb_dev);
 	ohci->bus->root_hub = usb_dev;
 	usb_connect (usb_dev);
-	if (usb_new_device (usb_dev) != 0) {
+	if (usb_register_root_hub (usb_dev, &ohci->ohci_dev->dev) != 0) {
 		usb_free_dev (usb_dev); 
 		ohci->disabled = 1;
 		return -ENODEV;
diff -urN linux-2.5.4-pre2/drivers/usb/usb-uhci-debug.h linux/drivers/usb/usb-uhci-debug.h
--- linux-2.5.4-pre2/drivers/usb/usb-uhci-debug.h	Tue Oct 30 15:08:12 2001
+++ linux/drivers/usb/usb-uhci-debug.h	Thu Feb  7 16:09:57 2002
@@ -78,60 +78,6 @@
 #endif
 
 #ifdef DEBUG
-static void __attribute__((__unused__)) uhci_show_td_queue (puhci_desc_t td)
-{
-	//dbg("uhci_show_td_queue %p (%08lX):", td, td->dma_addr);
-#if 1
-	return;
-#else
-	while (1) {
-		uhci_show_td (td);
-		if (td->hw.td.link & UHCI_PTR_TERM)
-			break;
-		if (td != bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS))
-			td = bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS);
-		else {
-			dbg("td points to itself!");
-			break;
-		}
-	}
-#endif
-}
-
-static void __attribute__((__unused__)) uhci_show_queue (puhci_desc_t qh)
-{
-#if 0
-	uhci_desc_t *start_qh=qh;
-#endif
-
-	dbg("uhci_show_queue %p:", qh);
-#if 1
-	return;
-#else
-	while (1) {
-		uhci_show_qh (qh);
-
-		if (!(qh->hw.qh.element & UHCI_PTR_TERM))
-			uhci_show_td_queue (bus_to_virt (qh->hw.qh.element & ~UHCI_PTR_BITS));
-
-		if (qh->hw.qh.head & UHCI_PTR_TERM)
-			break;
-
-		if (qh != bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS))
-			qh = bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS);
-		else {
-			dbg("qh points to itself!");
-			break;
-		}
-		
-		if (qh==start_qh) { // avoid loop
-			dbg("Loop detect");
-			break;
-		}
-	}		
-#endif
-}
-
 static void __attribute__((__unused__)) uhci_show_sc (int port, unsigned short status)
 {
 	dbg("  stat%d     =     %04x   %s%s%s%s%s%s%s%s",
diff -urN linux-2.5.4-pre2/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
--- linux-2.5.4-pre2/drivers/usb/usb-uhci.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/usb-uhci.c	Thu Feb  7 16:09:57 2002
@@ -684,7 +684,6 @@
 	insert_td_horizontal (s, s->int_chain[5], td);
 
 	mb();
-	//uhci_show_queue(s->control_chain);   
 	dbg("init_skel exit");
 	return 0;
 
@@ -799,7 +798,6 @@
 
 	qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM);
 
-	//uhci_show_queue(qh);
 	/* Start it up... put low speed first */
 	if (urb->dev->speed == USB_SPEED_LOW)
 		insert_qh (s, s->control_chain, qh, 0);
@@ -948,7 +946,6 @@
 			insert_qh (s, s->chain_end, qh, 0);
 	}
 	
-	//uhci_show_queue(s->bulk_chain);
 	//dbg("uhci_submit_bulk_urb: exit\n");
 	return 0;
 }
@@ -2907,7 +2904,7 @@
 	s->bus->root_hub = usb_dev;
 	usb_connect (usb_dev);
 
-	if (usb_new_device (usb_dev) != 0) {
+	if (usb_register_root_hub (usb_dev, &s->uhci_pci->dev) != 0) {
 		usb_free_dev (usb_dev);
 		return -1;
 	}
diff -urN linux-2.5.4-pre2/drivers/usb/usb-uhci.h linux/drivers/usb/usb-uhci.h
--- linux-2.5.4-pre2/drivers/usb/usb-uhci.h	Mon Jan 21 15:44:21 2002
+++ linux/drivers/usb/usb-uhci.h	Thu Feb  7 16:09:57 2002
@@ -100,7 +100,6 @@
 
 #define uhci_status_bits(ctrl_sts)	(ctrl_sts & 0xFE0000)
 #define uhci_actual_length(ctrl_sts)	((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK)	/* 1-based */
-#define uhci_ptr_to_virt(x)	bus_to_virt(x & ~UHCI_PTR_BITS)
 
 /*
  * for TD <flags>:
diff -urN linux-2.5.4-pre2/drivers/usb/usb.c linux/drivers/usb/usb.c
--- linux-2.5.4-pre2/drivers/usb/usb.c	Thu Feb  7 16:09:52 2002
+++ linux/drivers/usb/usb.c	Thu Feb  7 16:09:57 2002
@@ -980,8 +980,16 @@
 	unsigned claimed = 0;
 
 	for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++) {
+		struct usb_interface *interface = &dev->actconfig->interface[ifnum];
+		
+		/* register this interface with driverfs */
+		interface->dev.parent = &dev->dev;
+		sprintf (&interface->dev.bus_id[0], "%03d", ifnum);
+		sprintf (&interface->dev.name[0], "figure out some name...");
+		device_register (&interface->dev);
+
 		/* if this interface hasn't already been claimed */
-		if (!usb_interface_claimed(dev->actconfig->interface + ifnum)) {
+		if (!usb_interface_claimed(interface)) {
 			if (usb_find_interface_driver(dev, ifnum))
 				rejected++;
 			else
@@ -1969,8 +1977,10 @@
 				if (driver->owner)
 					__MOD_DEC_USE_COUNT(driver->owner);
 				/* if driver->disconnect didn't release the interface */
-				if (interface->driver)
+				if (interface->driver) {
+					put_device (&interface->dev);
 					usb_driver_release_interface(driver, interface);
+				}
 			}
 		}
 	}
@@ -1989,6 +1999,7 @@
 	if (dev->devnum > 0) {
 		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
 		usbfs_remove_device(dev);
+		put_device(&dev->dev);
 	}
 
 	/* Free up the device itself */
@@ -2715,6 +2726,11 @@
 		usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
 #endif
 
+	/* register this device in the driverfs tree */
+	err = device_register (&dev->dev);
+	if (err)
+		return err;
+
 	/* now that the basic setup is over, add a /proc/bus/usb entry */
 	usbfs_add_device(dev);
 
@@ -2727,6 +2743,29 @@
 	return 0;
 }
 
+/**
+ * usb_register_root_hub - called by a usb host controller to register the root hub device in the system
+ * @usb_dev: the usb root hub device to be registered.
+ * @parent_dev: the parent device of this root hub.
+ *
+ * The USB host controller calls this function to register the root hub
+ * properly with the USB subsystem.  It sets up the device properly in
+ * the driverfs tree, and then calls usb_new_device() to register the
+ * usb device.
+ */
+int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev)
+{
+	int retval;
+
+	usb_dev->dev.parent = parent_dev;
+	strcpy (&usb_dev->dev.name[0], "usb_name");
+	strcpy (&usb_dev->dev.bus_id[0], "usb_bus");
+	retval = usb_new_device (usb_dev);
+	if (retval)
+		put_device (&usb_dev->dev);
+	return retval;
+}
+
 static int usb_open(struct inode * inode, struct file * file)
 {
 	int minor = minor(inode->i_rdev);
@@ -2832,6 +2871,7 @@
 EXPORT_SYMBOL(usb_free_bus);
 EXPORT_SYMBOL(usb_register_bus);
 EXPORT_SYMBOL(usb_deregister_bus);
+EXPORT_SYMBOL(usb_register_root_hub);
 EXPORT_SYMBOL(usb_alloc_dev);
 EXPORT_SYMBOL(usb_free_dev);
 EXPORT_SYMBOL(usb_inc_dev_use);
diff -urN linux-2.5.4-pre2/fs/coda/inode.c linux/fs/coda/inode.c
--- linux-2.5.4-pre2/fs/coda/inode.c	Wed Jan 23 15:32:20 2002
+++ linux/fs/coda/inode.c	Thu Feb  7 16:09:58 2002
@@ -33,7 +33,6 @@
 #include <linux/coda_cache.h>
 
 /* VFS super_block ops */
-static struct super_block *coda_read_super(struct super_block *, void *, int);
 static void coda_read_inode(struct inode *);
 static void coda_clear_inode(struct inode *);
 static void coda_put_super(struct super_block *);
@@ -140,8 +139,7 @@
 	return idx;
 }
 
-static struct super_block * coda_read_super(struct super_block *sb, 
-					    void *data, int silent)
+static int coda_fill_super(struct super_block *sb, void *data, int silent)
 {
         struct inode *root = 0; 
 	struct coda_sb_info *sbi = NULL;
@@ -161,17 +159,17 @@
 	vc = &coda_comms[idx];
 	if (!vc->vc_inuse) {
 		printk("coda_read_super: No pseudo device\n");
-		return NULL;
+		return -EINVAL;
 	}
 
         if ( vc->vc_sb ) {
 		printk("coda_read_super: Device already mounted\n");
-		return NULL;
+		return -EBUSY;
 	}
 
 	sbi = kmalloc(sizeof(struct coda_sb_info), GFP_KERNEL);
 	if(!sbi) {
-		return NULL;
+		return -ENOMEM;
 	}
 
 	vc->vc_sb = sb;
@@ -192,7 +190,7 @@
 	        printk("coda_read_super: coda_get_rootfid failed with %d\n",
 		       error);
 		goto error;
-	}	  
+	}
 	printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));
 	
 	/* make root inode */
@@ -205,7 +203,7 @@
 	printk("coda_read_super: rootinode is %ld dev %x\n", 
 	       root->i_ino, kdev_val(root->i_dev));
 	sb->s_root = d_alloc_root(root);
-        return sb;
+        return 0;
 
  error:
 	if (sbi) {
@@ -216,7 +214,7 @@
 	if (root)
                 iput(root);
 
-        return NULL;
+        return -EINVAL;
 }
 
 static void coda_put_super(struct super_block *sb)
@@ -313,5 +311,14 @@
 
 /* init_coda: used by filesystems.c to register coda */
 
-DECLARE_FSTYPE( coda_fs_type, "coda", coda_read_super, 0);
+static struct super_block *coda_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, coda_fill_super);
+}
 
+struct file_system_type coda_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"coda",
+	get_sb:		coda_get_sb,
+};
diff -urN linux-2.5.4-pre2/fs/lockd/svc.c linux/fs/lockd/svc.c
--- linux-2.5.4-pre2/fs/lockd/svc.c	Mon Jan 28 15:11:45 2002
+++ linux/fs/lockd/svc.c	Thu Feb  7 16:09:58 2002
@@ -304,7 +304,7 @@
 	 * Wait for the lockd process to exit, but since we're holding
 	 * the lockd semaphore, we can't wait around forever ...
 	 */
-	current->work.sigpending = 0;
+	clear_thread_flag(TIF_SIGPENDING);
 	interruptible_sleep_on_timeout(&lockd_exit, HZ);
 	if (nlmsvc_pid) {
 		printk(KERN_WARNING 
diff -urN linux-2.5.4-pre2/fs/minix/inode.c linux/fs/minix/inode.c
--- linux-2.5.4-pre2/fs/minix/inode.c	Wed Jan 23 15:32:20 2002
+++ linux/fs/minix/inode.c	Thu Feb  7 16:09:58 2002
@@ -163,8 +163,7 @@
 	return 0;
 }
 
-static struct super_block *minix_read_super(struct super_block *s, void *data,
-				     int silent)
+static int minix_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct buffer_head *bh;
 	struct buffer_head **map;
@@ -273,7 +272,7 @@
  	else if (sbi->s_mount_state & MINIX_ERROR_FS)
 		printk ("MINIX-fs: mounting file system with errors, "
 			"running fsck is recommended.\n");
-	return s;
+	return 0;
 
 out_iput:
 	iput(root_inode);
@@ -314,7 +313,7 @@
 out_bad_sb:
 	printk("MINIX-fs: unable to read superblock\n");
  out:
-	return NULL;
+	return -EINVAL;
 }
 
 static int minix_statfs(struct super_block *sb, struct statfs *buf)
@@ -558,7 +557,18 @@
 		V2_minix_truncate(inode);
 }
 
-static DECLARE_FSTYPE_DEV(minix_fs_type,"minix",minix_read_super);
+static struct super_block *minix_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super);
+}
+
+static struct file_system_type minix_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"minix",
+	get_sb:		minix_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 static int __init init_minix_fs(void)
 {
diff -urN linux-2.5.4-pre2/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- linux-2.5.4-pre2/fs/ncpfs/inode.c	Thu Feb  7 16:09:52 2002
+++ linux/fs/ncpfs/inode.c	Thu Feb  7 16:09:58 2002
@@ -300,8 +300,7 @@
 	clear_inode(inode);
 }
 
-struct super_block *
-ncp_read_super(struct super_block *sb, void *raw_data, int silent)
+static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 {
 	struct ncp_mount_data_kernel data;
 	struct ncp_server *server;
@@ -434,7 +433,7 @@
 	ncp_unlock_server(server);
 	if (error < 0)
 		goto out_no_connect;
-	DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
+	DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
 
 #ifdef CONFIG_NCPFS_PACKET_SIGNING
 	if (ncp_negotiate_size_and_options(server, default_bufsize,
@@ -486,31 +485,31 @@
         root_inode = ncp_iget(sb, &finfo);
         if (!root_inode)
 		goto out_no_root;
-	DPRINTK("ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
+	DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
 	sb->s_root = d_alloc_root(root_inode);
         if (!sb->s_root)
 		goto out_no_root;
 	sb->s_root->d_op = &ncp_dentry_operations;
-	return sb;
+	return 0;
 
 out_no_root:
-	printk(KERN_ERR "ncp_read_super: get root inode failed\n");
+	printk(KERN_ERR "ncp_fill_super: get root inode failed\n");
 	iput(root_inode);
 	goto out_disconnect;
 out_no_bufsize:
-	printk(KERN_ERR "ncp_read_super: could not get bufsize\n");
+	printk(KERN_ERR "ncp_fill_super: could not get bufsize\n");
 out_disconnect:
 	ncp_lock_server(server);
 	ncp_disconnect(server);
 	ncp_unlock_server(server);
 	goto out_free_packet;
 out_no_connect:
-	printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error);
+	printk(KERN_ERR "ncp_fill_super: Failed connection, error=%d\n", error);
 out_free_packet:
 	vfree(server->packet);
 	goto out_free_server;
 out_no_packet:
-	printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
+	printk(KERN_ERR "ncp_fill_super: could not alloc packet\n");
 out_free_server:
 #ifdef CONFIG_NCPFS_NLS
 	unload_nls(server->nls_io);
@@ -527,16 +526,16 @@
 out_bad_file2:
 	fput(ncp_filp);
 out_bad_file:
-	printk(KERN_ERR "ncp_read_super: invalid ncp socket\n");
+	printk(KERN_ERR "ncp_fill_super: invalid ncp socket\n");
 	goto out;
 out_bad_mount:
-	printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n",
+	printk(KERN_INFO "ncp_fill_super: kernel requires mount version %d\n",
 		NCP_MOUNT_VERSION);
 	goto out;
 out_no_data:
-	printk(KERN_ERR "ncp_read_super: missing data argument\n");
+	printk(KERN_ERR "ncp_fill_super: missing data argument\n");
 out:
-	return NULL;
+	return -EINVAL;
 }
 
 static void ncp_put_super(struct super_block *sb)
@@ -750,7 +749,17 @@
 int ncp_current_malloced;
 #endif
 
-static DECLARE_FSTYPE(ncp_fs_type, "ncpfs", ncp_read_super, 0);
+static struct super_block *ncp_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, ncp_fill_super);
+}
+
+static struct file_system_type ncp_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"ncpfs",
+	get_sb:		ncp_get_sb,
+};
 
 static int __init init_ncp_fs(void)
 {
diff -urN linux-2.5.4-pre2/fs/nfsd/export.c linux/fs/nfsd/export.c
--- linux-2.5.4-pre2/fs/nfsd/export.c	Mon Jan 28 15:11:45 2002
+++ linux/fs/nfsd/export.c	Thu Feb  7 16:09:58 2002
@@ -468,7 +468,7 @@
 		return 0;
 	}
 
-	current->work.sigpending = 0;
+	clear_thread_flag(TIF_SIGPENDING);
 	want_lock++;
 	while (hash_count || hash_lock) {
 		interruptible_sleep_on(&hash_wait);
diff -urN linux-2.5.4-pre2/fs/proc/array.c linux/fs/proc/array.c
--- linux-2.5.4-pre2/fs/proc/array.c	Tue Jan 15 11:07:01 2002
+++ linux/fs/proc/array.c	Thu Feb  7 16:09:58 2002
@@ -391,7 +391,7 @@
 		task->nswap,
 		task->cnswap,
 		task->exit_signal,
-		task->cpu);
+		task->thread_info->cpu);
 	if(mm)
 		mmput(mm);
 	return res;
diff -urN linux-2.5.4-pre2/fs/proc/base.c linux/fs/proc/base.c
--- linux-2.5.4-pre2/fs/proc/base.c	Thu Feb  7 16:09:52 2002
+++ linux/fs/proc/base.c	Thu Feb  7 16:09:58 2002
@@ -1035,7 +1035,7 @@
 
 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_INO);
 
-	free_task_struct(task);
+	put_task_struct(task);
 
 	if (!inode)
 		goto out;
@@ -1057,7 +1057,7 @@
 	if (PROC_I(inode)->file)
 		fput(PROC_I(inode)->file);
 	if (proc_task(inode))
-		free_task_struct(proc_task(inode));
+		put_task_struct(proc_task(inode));
 }
 
 #define PROC_NUMBUF 10
diff -urN linux-2.5.4-pre2/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- linux-2.5.4-pre2/fs/smbfs/inode.c	Mon Jan 28 13:20:34 2002
+++ linux/fs/smbfs/inode.c	Thu Feb  7 16:09:58 2002
@@ -460,8 +460,7 @@
 	}
 }
 
-struct super_block *
-smb_read_super(struct super_block *sb, void *raw_data, int silent)
+int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
 {
 	struct smb_sb_info *server = &sb->u.smbfs_sb;
 	struct smb_mount_data_kernel *mnt;
@@ -561,7 +560,7 @@
 		goto out_no_root;
 	smb_new_dentry(sb->s_root);
 
-	return sb;
+	return 0;
 
 out_no_root:
 	iput(root_inode);
@@ -573,15 +572,15 @@
 	smb_vfree(server->packet);
 out_no_mem:
 	if (!server->mnt)
-		printk(KERN_ERR "smb_read_super: allocation failure\n");
+		printk(KERN_ERR "smb_fill_super: allocation failure\n");
 	goto out_fail;
 out_wrong_data:
 	printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver);
 	goto out_fail;
 out_no_data:
-	printk(KERN_ERR "smb_read_super: missing data argument\n");
+	printk(KERN_ERR "smb_fill_super: missing data argument\n");
 out_fail:
-	return NULL;
+	return -EINVAL;
 }
 
 static int
@@ -706,7 +705,17 @@
 int smb_current_vmalloced;
 #endif
 
-static DECLARE_FSTYPE( smb_fs_type, "smbfs", smb_read_super, 0);
+static struct super_block *smb_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_nodev(fs_type, flags, data, smb_fill_super);
+}
+
+static struct file_system_type smb_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"smbfs",
+	get_sb:		smb_get_sb,
+};
 
 static int __init init_smb_fs(void)
 {
diff -urN linux-2.5.4-pre2/fs/smbfs/proto.h linux/fs/smbfs/proto.h
--- linux-2.5.4-pre2/fs/smbfs/proto.h	Tue Oct  2 17:03:34 2001
+++ linux/fs/smbfs/proto.h	Thu Feb  7 16:09:58 2002
@@ -53,7 +53,6 @@
 extern void smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr);
 extern void smb_invalidate_inodes(struct smb_sb_info *server);
 extern int smb_revalidate_inode(struct dentry *dentry);
-extern struct super_block *smb_read_super(struct super_block *sb, void *raw_data, int silent);
 extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
 /* file.c */
 extern struct address_space_operations smb_file_aops;
diff -urN linux-2.5.4-pre2/fs/super.c linux/fs/super.c
--- linux-2.5.4-pre2/fs/super.c	Thu Feb  7 16:09:52 2002
+++ linux/fs/super.c	Thu Feb  7 16:09:58 2002
@@ -797,11 +797,6 @@
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, fill_super);
 }
-static struct super_block *__get_sb_nodev(struct file_system_type *fs_type,
-	int flags, char *dev_name, void * data)
-{
-	return get_sb_nodev(fs_type, flags, data, fill_super);
-}
 
 struct vfsmount *
 do_kern_mount(const char *fstype, int flags, char *name, void *data)
@@ -820,8 +815,6 @@
 		sb = type->get_sb(type, flags, name, data);
 	else if (type->fs_flags & FS_REQUIRES_DEV)
 		sb = __get_sb_bdev(type, flags, name, data);
-	else
-		sb = __get_sb_nodev(type, flags, name, data);
 	if (IS_ERR(sb))
 		goto out_mnt;
 	if (type->fs_flags & FS_NOMOUNT)
diff -urN linux-2.5.4-pre2/fs/sysv/ChangeLog linux/fs/sysv/ChangeLog
--- linux-2.5.4-pre2/fs/sysv/ChangeLog	Thu Jan 24 22:05:04 2002
+++ linux/fs/sysv/ChangeLog	Thu Feb  7 16:09:58 2002
@@ -1,13 +1,18 @@
+Thu Feb  7 2002  Alexander Viro  <viro@math.psu.edu>
+
+	* super.c: switched to ->get_sb()
+	* ChangeLog: fixed dates ;-)
+
 2002-01-24  David S. Miller  <davem@redhat.com>
 
 	* inode.c: Include linux/init.h
 
-Mon Jan 21 2001  Alexander Viro  <viro@math.psu.edu>
+Mon Jan 21 2002  Alexander Viro  <viro@math.psu.edu>
 	* ialloc.c (sysv_new_inode): zero SYSV_I(inode)->i_data out.
 	* i_vnode renamed to vfs_inode.  Sorry, but let's keep that
 	  consistent.
 
-Sat Jan 19 2001  Christoph Hellwig  <hch@infradead.org>
+Sat Jan 19 2002  Christoph Hellwig  <hch@infradead.org>
 
 	* include/linux/sysv_fs.h (SYSV_I): Get fs-private inode data using
 		list_entry() instead of inode->u.
@@ -19,7 +24,7 @@
 		in the case of failed register_filesystem for V7.
 	(exit_sysv_fs): Destroy inode cache.
 
-Sat Jan 19 2001  Christoph Hellwig  <hch@infradead.org>
+Sat Jan 19 2002  Christoph Hellwig  <hch@infradead.org>
 
 	* include/linux/sysv_fs.h: Include <linux/sysv_fs_i.h>, declare SYSV_I().
 	* dir.c (sysv_find_entry): Use SYSV_I() instead of ->u.sysv_i to
@@ -32,7 +37,7 @@
 	* symlink.c (sysv_readlink): Likewise.
 	(sysv_follow_link): Likewise.
 
-Fri Jan  4 2001  Alexander Viro  <viro@math.psu.edu>
+Fri Jan  4 2002  Alexander Viro  <viro@math.psu.edu>
 
 	* ialloc.c (sysv_free_inode): Use sb->s_id instead of bdevname().
 	* inode.c (sysv_read_inode): Likewise.
diff -urN linux-2.5.4-pre2/fs/sysv/super.c linux/fs/sysv/super.c
--- linux-2.5.4-pre2/fs/sysv/super.c	Wed Jan 23 15:32:20 2002
+++ linux/fs/sysv/super.c	Thu Feb  7 16:09:58 2002
@@ -340,8 +340,7 @@
 	return 1;
 }
 
-static struct super_block *sysv_read_super(struct super_block *sb,
-					   void *data, int silent)
+static int sysv_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct buffer_head *bh1;
 	struct buffer_head *bh = NULL;
@@ -397,7 +396,7 @@
 		sb->sv_bh1 = bh1;
 		sb->sv_bh2 = bh;
 		if (complete_read_super(sb, silent, size))
-			return sb;
+			return 0;
 	}
 
 	brelse(bh1);
@@ -405,7 +404,7 @@
 	sb_set_blocksize(sb, BLOCK_SIZE);
 	printk("oldfs: cannot read superblock\n");
 failed:
-	return NULL;
+	return -EINVAL;
 
 Eunknown:
 	brelse(bh);
@@ -421,8 +420,7 @@
 	goto failed;
 }
 
-static struct super_block *v7_read_super(struct super_block *sb,void *data,
-				  int silent)
+static int v7_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct buffer_head *bh, *bh2 = NULL;
 	struct v7_super_block *v7sb;
@@ -466,18 +464,41 @@
 	sb->sv_bh1 = bh;
 	sb->sv_bh2 = bh;
 	if (complete_read_super(sb, silent, 1))
-		return sb;
+		return 0;
 
 failed:
 	brelse(bh2);
 	brelse(bh);
-	return NULL;
+	return -EINVAL;
 }
 
 /* Every kernel module contains stuff like this. */
 
-static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super);
-static DECLARE_FSTYPE_DEV(v7_fs_type, "v7", v7_read_super);
+static struct super_block *sysv_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super);
+}
+
+static struct super_block *v7_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super);
+}
+
+static struct file_system_type sysv_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"sysv",
+	get_sb:		sysv_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
+
+static struct file_system_type v7_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"v7",
+	get_sb:		v7_get_sb,
+	fs_flags:	FS_REQUIRES_DEV,
+};
 
 extern int sysv_init_icache(void) __init;
 extern void sysv_destroy_icache(void);
diff -urN linux-2.5.4-pre2/include/asm-alpha/scatterlist.h linux/include/asm-alpha/scatterlist.h
--- linux-2.5.4-pre2/include/asm-alpha/scatterlist.h	Fri Oct 12 15:35:54 2001
+++ linux/include/asm-alpha/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -4,11 +4,6 @@
 #include <asm/page.h>
   
 struct scatterlist {
-	/* This will disappear in 2.5.x */
-	char *address;
-
-	/* These two are only valid if ADDRESS member of this
-	   struct is NULL.  */
 	struct page *page;
 	unsigned int offset;
 
diff -urN linux-2.5.4-pre2/include/asm-arm/scatterlist.h linux/include/asm-arm/scatterlist.h
--- linux-2.5.4-pre2/include/asm-arm/scatterlist.h	Sat Jan  5 12:44:39 2002
+++ linux/include/asm-arm/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -4,9 +4,8 @@
 #include <asm/types.h>
 
 struct scatterlist {
-	char		*address;	/* virtual address		 */
-	struct page	*page;		/* Location for highmem page, if any */
-	unsigned int	offset;		/* for highmem, page offset	 */
+	struct page	*page;		/* buffer page			 */
+	unsigned int	offset;		/* buffer offset		 */
 	dma_addr_t	dma_address;	/* dma address			 */
 	unsigned int	length;		/* length			 */
 	char		*__address;	/* for set_dma_addr		 */
diff -urN linux-2.5.4-pre2/include/asm-i386/current.h linux/include/asm-i386/current.h
--- linux-2.5.4-pre2/include/asm-i386/current.h	Fri Aug 14 16:35:22 1998
+++ linux/include/asm-i386/current.h	Thu Feb  7 16:09:58 2002
@@ -1,14 +1,14 @@
 #ifndef _I386_CURRENT_H
 #define _I386_CURRENT_H
 
+#include <asm/thread_info.h>
+
 struct task_struct;
 
 static inline struct task_struct * get_current(void)
 {
-	struct task_struct *current;
-	__asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));
-	return current;
- }
+	return current_thread_info()->task;
+}
  
 #define current get_current()
 
diff -urN linux-2.5.4-pre2/include/asm-i386/floppy.h linux/include/asm-i386/floppy.h
--- linux-2.5.4-pre2/include/asm-i386/floppy.h	Tue Jan 29 21:41:15 2002
+++ linux/include/asm-i386/floppy.h	Thu Feb  7 16:09:58 2002
@@ -216,7 +216,7 @@
 {
 	if(can_use_virtual_dma == 2) {
 		if((unsigned int) addr >= (unsigned int) high_memory ||
-		   virt_to_bus(addr) >= 0x1000000 ||
+		   isa_virt_to_bus(addr) >= 0x1000000 ||
 		   _CROSS_64KB(addr, size, 0))
 			use_virtual_dma = 1;
 		else
@@ -252,7 +252,7 @@
 	doing_pdma = 0;
 	clear_dma_ff(FLOPPY_DMA);
 	set_dma_mode(FLOPPY_DMA,mode);
-	set_dma_addr(FLOPPY_DMA,virt_to_bus(addr));
+	set_dma_addr(FLOPPY_DMA,isa_virt_to_bus(addr));
 	set_dma_count(FLOPPY_DMA,size);
 	enable_dma(FLOPPY_DMA);
 	return 0;
diff -urN linux-2.5.4-pre2/include/asm-i386/hw_irq.h linux/include/asm-i386/hw_irq.h
--- linux-2.5.4-pre2/include/asm-i386/hw_irq.h	Tue Jan 29 21:41:09 2002
+++ linux/include/asm-i386/hw_irq.h	Thu Feb  7 16:09:58 2002
@@ -116,7 +116,8 @@
 
 #define GET_CURRENT \
 	"movl %esp, %ebx\n\t" \
-	"andl $-8192, %ebx\n\t"
+	"andl $-8192, %ebx\n\t" \
+	"movl (%ebx),%ebx\n\t"
 
 /*
  *	SMP has a few special interrupts for IPI messages
diff -urN linux-2.5.4-pre2/include/asm-i386/i387.h linux/include/asm-i386/i387.h
--- linux-2.5.4-pre2/include/asm-i386/i387.h	Tue Jan 29 21:42:09 2002
+++ linux/include/asm-i386/i387.h	Thu Feb  7 16:09:58 2002
@@ -28,16 +28,17 @@
 
 
 #define unlazy_fpu( tsk ) do { \
-	if ( tsk->flags & PF_USEDFPU ) \
+	if (test_thread_flag(TIF_USEDFPU)) \
 		save_init_fpu( tsk ); \
 } while (0)
 
-#define clear_fpu( tsk ) do { \
-	if ( tsk->flags & PF_USEDFPU ) { \
-		asm volatile("fwait"); \
-		tsk->flags &= ~PF_USEDFPU; \
-		stts(); \
-	} \
+#define clear_fpu( tsk )			\
+do {						\
+	if (test_thread_flag(TIF_USEDFPU)) {	\
+		asm volatile("fwait");		\
+		clear_thread_flag(TIF_USEDFPU);	\
+		stts();				\
+	}					\
 } while (0)
 
 /*
diff -urN linux-2.5.4-pre2/include/asm-i386/io.h linux/include/asm-i386/io.h
--- linux-2.5.4-pre2/include/asm-i386/io.h	Tue Jan 29 21:41:17 2002
+++ linux/include/asm-i386/io.h	Thu Feb  7 16:09:58 2002
@@ -95,11 +95,20 @@
 extern void iounmap(void *addr);
 
 /*
- * IO bus memory addresses are also 1:1 with the physical address
+ * ISA I/O bus memory addresses are 1:1 with the physical address.
  */
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-#define page_to_bus page_to_phys
+#define isa_virt_to_bus virt_to_phys
+#define isa_page_to_bus page_to_phys
+#define isa_bus_to_virt phys_to_virt
+
+/*
+ * However PCI ones are not necessarily 1:1 and therefore these interfaces
+ * are forbidden in portable PCI drivers.
+ */
+extern unsigned long virt_to_bus_not_defined_use_pci_map(volatile void *addr);
+#define virt_to_bus virt_to_bus_not_defined_use_pci_map
+extern unsigned long bus_to_virt_not_defined_use_pci_map(volatile void *addr);
+#define bus_to_virt bus_to_virt_not_defined_use_pci_map
 
 /*
  * readX/writeX() are used to access memory mapped devices. On some
diff -urN linux-2.5.4-pre2/include/asm-i386/pci.h linux/include/asm-i386/pci.h
--- linux-2.5.4-pre2/include/asm-i386/pci.h	Thu Feb  7 16:09:52 2002
+++ linux/include/asm-i386/pci.h	Thu Feb  7 16:09:58 2002
@@ -75,7 +75,7 @@
 	if (direction == PCI_DMA_NONE)
 		BUG();
 	flush_write_buffers();
-	return virt_to_bus(ptr);
+	return virt_to_phys(ptr);
 }
 
 /* Unmap a single streaming mode DMA translation.  The dma_addr and size
@@ -144,22 +144,14 @@
 
 	if (direction == PCI_DMA_NONE)
 		BUG();
- 
- 	/*
- 	 * temporary 2.4 hack
- 	 */
- 	for (i = 0; i < nents; i++ ) {
- 		if (sg[i].address && sg[i].page)
- 			BUG();
- 		else if (!sg[i].address && !sg[i].page)
- 			BUG();
- 
- 		if (sg[i].address)
- 			sg[i].dma_address = virt_to_bus(sg[i].address);
- 		else
- 			sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
- 	}
- 
+
+	for (i = 0; i < nents; i++ ) {
+		if (!sg[i].page)
+			BUG();
+
+		sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
+	}
+
 	flush_write_buffers();
 	return nents;
 }
@@ -233,7 +225,7 @@
 static __inline__ dma64_addr_t
 pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
 {
-	return ((dma64_addr_t) page_to_bus(page) +
+	return ((dma64_addr_t) page_to_phys(page) +
 		(dma64_addr_t) offset);
 }
 
diff -urN linux-2.5.4-pre2/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- linux-2.5.4-pre2/include/asm-i386/processor.h	Tue Jan 29 21:41:09 2002
+++ linux/include/asm-i386/processor.h	Thu Feb  7 16:09:58 2002
@@ -444,16 +444,8 @@
 }
 
 unsigned long get_wchan(struct task_struct *p);
-#define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
-#define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-
-#define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
-#define free_task_struct(p) free_pages((unsigned long) (p), 1)
-#define get_task_struct(tsk)      atomic_inc(&virt_to_page(tsk)->count)
-
-#define init_task	(init_task_union.task)
-#define init_stack	(init_task_union.stack)
+#define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1019])
+#define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1022])
 
 struct microcode {
 	unsigned int hdrver;
diff -urN linux-2.5.4-pre2/include/asm-i386/scatterlist.h linux/include/asm-i386/scatterlist.h
--- linux-2.5.4-pre2/include/asm-i386/scatterlist.h	Fri Oct 12 15:35:54 2001
+++ linux/include/asm-i386/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -2,13 +2,10 @@
 #define _I386_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to, NULL for
-			 * highmem page */
-    struct page * page; /* Location for highmem page, if any */
-    unsigned int offset;/* for highmem, page offset */
-
-    dma_addr_t dma_address;
-    unsigned int length;
+    struct page		*page;
+    unsigned int	offset;
+    dma_addr_t		dma_address;
+    unsigned int	length;
 };
 
 #define ISA_DMA_THRESHOLD (0x00ffffff)
diff -urN linux-2.5.4-pre2/include/asm-i386/smp.h linux/include/asm-i386/smp.h
--- linux-2.5.4-pre2/include/asm-i386/smp.h	Tue Jan 29 21:41:12 2002
+++ linux/include/asm-i386/smp.h	Thu Feb  7 16:09:58 2002
@@ -105,7 +105,7 @@
  * so this is correct in the x86 case.
  */
 
-#define smp_processor_id() (current->cpu)
+#define smp_processor_id() (current_thread_info()->cpu)
 
 static __inline int hard_smp_processor_id(void)
 {
diff -urN linux-2.5.4-pre2/include/asm-i386/thread_info.h linux/include/asm-i386/thread_info.h
--- linux-2.5.4-pre2/include/asm-i386/thread_info.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/thread_info.h	Thu Feb  7 16:09:58 2002
@@ -0,0 +1,113 @@
+/* thread_info.h: i386 low-level thread information
+ *
+ * Copyright (C) 2002  David Howells (dhowells@redhat.com)
+ * - Incorporating suggestions made by Linus Torvalds and Dave Miller
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#endif
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants must also be changed
+ */
+#ifndef __ASSEMBLY__
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	__u32			flags;		/* low level flags */
+	__u32			cpu;		/* current CPU */
+
+	mm_segment_t		addr_limit;	/* thread address space:
+					 	   0-0xBFFFFFFF for user-thead
+						   0-0xFFFFFFFF for kernel-thread
+						*/
+
+	__u8			supervisor_stack[0];
+};
+
+#else /* !__ASSEMBLY__ */
+
+/* offsets into the thread_info struct for assembly code access */
+#define TI_TASK		0x00000000
+#define TI_EXEC_DOMAIN	0x00000004
+#define TI_FLAGS	0x00000008
+#define TI_CPU		0x0000000C
+#define TI_ADDR_LIMIT	0x00000010
+
+#endif
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ */
+#ifndef __ASSEMBLY__
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	task:		&tsk,			\
+	exec_domain:	&default_exec_domain,	\
+	flags:		0,			\
+	cpu:		0,			\
+	addr_limit:	KERNEL_DS,		\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+	struct thread_info *ti;
+	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~8191UL));
+	return ti;
+}
+
+/* thread information allocation */
+#define THREAD_SIZE (2*PAGE_SIZE)
+#define alloc_thread_info() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#define get_thread_info(ti) get_task_struct((ti)->l_task)
+#define put_thread_info(ti) put_task_struct((ti)->l_task)
+
+#else /* !__ASSEMBLY__ */
+
+/* how to get the thread information struct from ASM */
+#define GET_THREAD_INFO(reg) \
+	movl $-8192, reg; \
+	andl %esp, reg
+
+#endif
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
+#define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
+
+#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_USEDFPU		(1<<TIF_USEDFPU)
+#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+
+#define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
+#define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff -urN linux-2.5.4-pre2/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h
--- linux-2.5.4-pre2/include/asm-i386/uaccess.h	Tue Jan 29 21:41:15 2002
+++ linux/include/asm-i386/uaccess.h	Thu Feb  7 16:09:58 2002
@@ -27,14 +27,14 @@
 #define USER_DS		MAKE_MM_SEG(PAGE_OFFSET)
 
 #define get_ds()	(KERNEL_DS)
-#define get_fs()	(current->addr_limit)
-#define set_fs(x)	(current->addr_limit = (x))
+#define get_fs()	(current_thread_info()->addr_limit)
+#define set_fs(x)	(current_thread_info()->addr_limit = (x))
 
 #define segment_eq(a,b)	((a).seg == (b).seg)
 
 extern int __verify_write(const void *, unsigned long);
 
-#define __addr_ok(addr) ((unsigned long)(addr) < (current->addr_limit.seg))
+#define __addr_ok(addr) ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
 
 /*
  * Uhhuh, this needs 33-bit arithmetic. We have a carry..
@@ -43,7 +43,7 @@
 	unsigned long flag,sum; \
 	asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
 		:"=&r" (flag), "=r" (sum) \
-		:"1" (addr),"g" ((int)(size)),"g" (current->addr_limit.seg)); \
+		:"1" (addr),"g" ((int)(size)),"g" (current_thread_info()->addr_limit.seg)); \
 	flag; })
 
 #ifdef CONFIG_X86_WP_WORKS_OK
diff -urN linux-2.5.4-pre2/include/asm-i386/xor.h linux/include/asm-i386/xor.h
--- linux-2.5.4-pre2/include/asm-i386/xor.h	Fri Sep 14 14:25:21 2001
+++ linux/include/asm-i386/xor.h	Thu Feb  7 16:09:58 2002
@@ -20,7 +20,7 @@
 
 #define FPU_SAVE							\
   do {									\
-	if (!(current->flags & PF_USEDFPU))				\
+	if (!test_thread_flag(TIF_USEDFPU))				\
 		__asm__ __volatile__ (" clts;\n");			\
 	__asm__ __volatile__ ("fsave %0; fwait": "=m"(fpu_save[0]));	\
   } while (0)
@@ -28,7 +28,7 @@
 #define FPU_RESTORE							\
   do {									\
 	__asm__ __volatile__ ("frstor %0": : "m"(fpu_save[0]));		\
-	if (!(current->flags & PF_USEDFPU))				\
+	if (!test_thread_flag(TIF_USEDFPU))				\
 		stts();							\
   } while (0)
 
diff -urN linux-2.5.4-pre2/include/asm-ia64/scatterlist.h linux/include/asm-ia64/scatterlist.h
--- linux-2.5.4-pre2/include/asm-ia64/scatterlist.h	Tue Nov 13 09:01:16 2001
+++ linux/include/asm-ia64/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -7,8 +7,6 @@
  */
 
 struct scatterlist {
-	/* This will disappear in 2.5.x: */
-	char *address;		/* location data is to be transferred to, NULL for highmem page */
 	char *orig_address;	/* for use by swiotlb */
 
 	/* These two are only valid if ADDRESS member of this struct is NULL.  */
diff -urN linux-2.5.4-pre2/include/asm-m68k/scatterlist.h linux/include/asm-m68k/scatterlist.h
--- linux-2.5.4-pre2/include/asm-m68k/scatterlist.h	Fri Oct 12 15:35:54 2001
+++ linux/include/asm-m68k/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -2,7 +2,8 @@
 #define _M68K_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
+    struct page *page;
+    unsigned int offset;
     unsigned int length;
     unsigned long dvma_address;
 };
diff -urN linux-2.5.4-pre2/include/asm-mips/scatterlist.h linux/include/asm-mips/scatterlist.h
--- linux-2.5.4-pre2/include/asm-mips/scatterlist.h	Fri Oct 12 15:35:54 2001
+++ linux/include/asm-mips/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -2,7 +2,8 @@
 #define __ASM_MIPS_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
+    struct page *page;
+    unsigned int offset;
     unsigned int length;
     
     __u32 dvma_address;
diff -urN linux-2.5.4-pre2/include/asm-mips64/scatterlist.h linux/include/asm-mips64/scatterlist.h
--- linux-2.5.4-pre2/include/asm-mips64/scatterlist.h	Fri Oct 12 15:35:54 2001
+++ linux/include/asm-mips64/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -2,7 +2,8 @@
 #define __ASM_MIPS64_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
+    struct page *page;
+    unsigned int offset;
     unsigned int length;
     
     __u32 dvma_address;
diff -urN linux-2.5.4-pre2/include/asm-parisc/scatterlist.h linux/include/asm-parisc/scatterlist.h
--- linux-2.5.4-pre2/include/asm-parisc/scatterlist.h	Fri Oct 12 15:35:54 2001
+++ linux/include/asm-parisc/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -2,7 +2,8 @@
 #define _ASM_PARISC_SCATTERLIST_H
 
 struct scatterlist {
-	char *  address;    /* Location data is to be transferred to */
+	struct page *page;
+	unsigned int offset;
 	unsigned int length;
 
 	/* an IOVA can be 64-bits on some PA-Risc platforms. */
diff -urN linux-2.5.4-pre2/include/asm-ppc/pci.h linux/include/asm-ppc/pci.h
--- linux-2.5.4-pre2/include/asm-ppc/pci.h	Tue Jan 15 11:48:13 2002
+++ linux/include/asm-ppc/pci.h	Thu Feb  7 16:09:58 2002
@@ -157,15 +157,10 @@
 	 * temporary 2.4 hack
 	 */
 	for (i = 0; i < nents; i++) {
-		if (sg[i].address && sg[i].page)
-			BUG();
-		else if (!sg[i].address && !sg[i].page)
+		if (!sg[i].page)
 			BUG();
 
-		if (sg[i].address)
-			sg[i].dma_address = virt_to_bus(sg[i].address);
-		else
-			sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
+		sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
 	}
 
 	return nents;
diff -urN linux-2.5.4-pre2/include/asm-ppc/scatterlist.h linux/include/asm-ppc/scatterlist.h
--- linux-2.5.4-pre2/include/asm-ppc/scatterlist.h	Sun Oct 21 10:13:07 2001
+++ linux/include/asm-ppc/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -8,10 +8,8 @@
 #include <asm/dma.h>
 
 struct scatterlist {
-	char *address;		/* Location data is to be transferred to,
-				 * or NULL for highmem page */
-	struct page * page;	/* Location for highmem page, if any */
-	unsigned int offset;	/* for highmem, page offset */
+	struct page * page;
+	unsigned int offset;
 
 	dma_addr_t dma_address;	/* phys/bus dma address		 */
 	unsigned int length;	/* length			 */
diff -urN linux-2.5.4-pre2/include/asm-s390/scatterlist.h linux/include/asm-s390/scatterlist.h
--- linux-2.5.4-pre2/include/asm-s390/scatterlist.h	Fri Oct 12 15:35:54 2001
+++ linux/include/asm-s390/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -2,7 +2,8 @@
 #define _ASMS390X_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
+    struct page *page;
+    unsigned int offset;
     unsigned int length;
 };
 
diff -urN linux-2.5.4-pre2/include/asm-s390x/scatterlist.h linux/include/asm-s390x/scatterlist.h
--- linux-2.5.4-pre2/include/asm-s390x/scatterlist.h	Fri Oct 12 15:35:54 2001
+++ linux/include/asm-s390x/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -2,7 +2,8 @@
 #define _ASMS390X_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
+    struct page *page;
+    unsigned int offset;
     unsigned int length;
 };
 
diff -urN linux-2.5.4-pre2/include/asm-sh/pci.h linux/include/asm-sh/pci.h
--- linux-2.5.4-pre2/include/asm-sh/pci.h	Tue Jan 15 11:48:13 2002
+++ linux/include/asm-sh/pci.h	Thu Feb  7 16:09:58 2002
@@ -149,7 +149,7 @@
 	int i;
 
 	for (i=0; i<nents; i++)
-		dma_cache_wback_inv(sg[i].address, sg[i].length);
+		dma_cache_wback_inv(page_address(sg[i].page) + sg[i].offset, sg[i].length);
 #endif
 	if (direction == PCI_DMA_NONE)
                 BUG();
@@ -206,7 +206,7 @@
 	int i;
 
 	for (i=0; i<nelems; i++)
-		dma_cache_wback_inv(sg[i].address, sg[i].length);
+		dma_cache_wback_inv(page_address(sg[i].page) + sg[i].offset, sg[i].length);
 #endif
 }
 
diff -urN linux-2.5.4-pre2/include/asm-sh/scatterlist.h linux/include/asm-sh/scatterlist.h
--- linux-2.5.4-pre2/include/asm-sh/scatterlist.h	Thu Jan 24 12:08:15 2002
+++ linux/include/asm-sh/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -2,8 +2,6 @@
 #define __ASM_SH_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to, NULL for
-			 * highmem page */
     struct page * page; /* Location for highmem page, if any */
     unsigned int offset;/* for highmem, page offset */
     dma_addr_t dma_address;
diff -urN linux-2.5.4-pre2/include/asm-sparc/scatterlist.h linux/include/asm-sparc/scatterlist.h
--- linux-2.5.4-pre2/include/asm-sparc/scatterlist.h	Tue Oct 30 15:08:11 2001
+++ linux/include/asm-sparc/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -1,16 +1,10 @@
-/* $Id: scatterlist.h,v 1.7 2001/10/30 04:34:57 davem Exp $ */
+/* $Id: scatterlist.h,v 1.8 2001/12/17 07:05:15 davem Exp $ */
 #ifndef _SPARC_SCATTERLIST_H
 #define _SPARC_SCATTERLIST_H
 
 #include <linux/types.h>
 
 struct scatterlist {
-	/* This will disappear in 2.5.x */
-	char *address;
-
-	/* These two are only valid if ADDRESS member of this
-	 * struct is NULL.
-	 */
 	struct page *page;
 	unsigned int offset;
 
diff -urN linux-2.5.4-pre2/include/asm-sparc64/scatterlist.h linux/include/asm-sparc64/scatterlist.h
--- linux-2.5.4-pre2/include/asm-sparc64/scatterlist.h	Fri Oct 12 15:35:54 2001
+++ linux/include/asm-sparc64/scatterlist.h	Thu Feb  7 16:09:58 2002
@@ -1,23 +1,17 @@
-/* $Id: scatterlist.h,v 1.10 2001/10/09 02:24:35 davem Exp $ */
+/* $Id: scatterlist.h,v 1.11 2001/12/17 07:05:15 davem Exp $ */
 #ifndef _SPARC64_SCATTERLIST_H
 #define _SPARC64_SCATTERLIST_H
 
 #include <asm/page.h>
 
 struct scatterlist {
-	/* This will disappear in 2.5.x */
-	char *address;
+	struct page	*page;
+	unsigned int	offset;
 
-	/* These two are only valid if ADDRESS member of this
-	 * struct is NULL.
-	 */
-	struct page *page;
-	unsigned int offset;
+	unsigned int	length;
 
-	unsigned int length;
-
-	dma_addr_t dma_address;
-	__u32 dma_length;
+	dma_addr_t	dma_address;
+	__u32		dma_length;
 };
 
 #define sg_dma_address(sg)	((sg)->dma_address)
diff -urN linux-2.5.4-pre2/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.5.4-pre2/include/linux/fs.h	Thu Feb  7 16:09:52 2002
+++ linux/include/linux/fs.h	Thu Feb  7 16:09:58 2002
@@ -964,16 +964,13 @@
 	int flags, void *data,
 	int (*fill_super)(struct super_block *, void *, int));
 
-#define DECLARE_FSTYPE(var,type,read,flags) \
+#define DECLARE_FSTYPE_DEV(var,type,read) \
 struct file_system_type var = { \
 	name:		type, \
 	read_super:	read, \
-	fs_flags:	flags, \
+	fs_flags:	FS_REQUIRES_DEV, \
 	owner:		THIS_MODULE, \
 }
-
-#define DECLARE_FSTYPE_DEV(var,type,read) \
-	DECLARE_FSTYPE(var,type,read,FS_REQUIRES_DEV)
 
 /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
 #define fops_get(fops) \
diff -urN linux-2.5.4-pre2/include/linux/gameport.h linux/include/linux/gameport.h
--- linux-2.5.4-pre2/include/linux/gameport.h	Thu Feb  7 16:09:52 2002
+++ linux/include/linux/gameport.h	Thu Feb  7 16:09:58 2002
@@ -2,11 +2,9 @@
 #define _GAMEPORT_H
 
 /*
- * $Id: gameport.h,v 1.11 2001/04/26 10:24:46 vojtech Exp $
+ * $Id: gameport.h,v 1.20 2002/01/03 08:55:05 vojtech Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
 /*
@@ -26,21 +24,27 @@
  *
  * Should you need to contact me, the author, you can do so either by
  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
-#include <linux/sched.h>
-#include <linux/delay.h>
 #include <asm/io.h>
+#include <linux/input.h>
 
 struct gameport;
 
 struct gameport {
 
-	void *private;
-
+	void *private;	/* Private pointer for joystick drivers */
+	void *driver;	/* Private pointer for gameport drivers */
+	char *name;
+	char *phys;
 	int number;
 
+	unsigned short idbus;
+	unsigned short idvendor;
+	unsigned short idproduct;
+	unsigned short idversion;
+
 	int io;
 	int speed;
 	int fuzz;
@@ -59,6 +63,7 @@
 struct gameport_dev {
 
 	void *private;
+	char *name;
 
 	void (*connect)(struct gameport *, struct gameport_dev *dev);
 	void (*disconnect)(struct gameport *);
@@ -74,8 +79,8 @@
 void gameport_register_port(struct gameport *gameport);
 void gameport_unregister_port(struct gameport *gameport);
 #else
-static void __inline__ gameport_register_port(struct gameport *gameport) { return; }
-static void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
+void __inline__ gameport_register_port(struct gameport *gameport) { return; }
+void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
 #endif
 
 void gameport_register_device(struct gameport_dev *dev);
@@ -94,6 +99,7 @@
 #define GAMEPORT_ID_VENDOR_MICROSOFT	0x0007
 #define GAMEPORT_ID_VENDOR_THRUSTMASTER	0x0008
 #define GAMEPORT_ID_VENDOR_GRAVIS	0x0009
+#define GAMEPORT_ID_VENDOR_GUILLEMOT	0x000a
 
 static __inline__ void gameport_trigger(struct gameport *gameport)
 {
@@ -134,7 +140,7 @@
 
 static __inline__ void wait_ms(unsigned int ms)
 {
-	current->state = TASK_UNINTERRUPTIBLE;
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(1 + ms * HZ / 1000);
 }
 
diff -urN linux-2.5.4-pre2/include/linux/init_task.h linux/include/linux/init_task.h
--- linux-2.5.4-pre2/include/linux/init_task.h	Tue Jan 29 21:42:47 2002
+++ linux/include/linux/init_task.h	Thu Feb  7 16:09:58 2002
@@ -35,14 +35,6 @@
 	siglock:	SPIN_LOCK_UNLOCKED 		\
 }
 
-#define INIT_TASK_WORK				\
-{						\
-	need_resched:	0,			\
-	syscall_trace:	0,			\
-	sigpending:	0,			\
-	notify_resume:	0,			\
-}
-
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -50,10 +42,8 @@
 #define INIT_TASK(tsk)	\
 {									\
     state:		0,						\
+    thread_info:	&init_thread_info,				\
     flags:		0,						\
-    work:		INIT_TASK_WORK,					\
-    addr_limit:		KERNEL_DS,					\
-    exec_domain:	&default_exec_domain,				\
     lock_depth:		-1,						\
     __nice:		DEF_USER_NICE,					\
     policy:		SCHED_OTHER,					\
diff -urN linux-2.5.4-pre2/include/linux/input.h linux/include/linux/input.h
--- linux-2.5.4-pre2/include/linux/input.h	Wed Sep 12 15:34:06 2001
+++ linux/include/linux/input.h	Thu Feb  7 16:09:58 2002
@@ -2,11 +2,9 @@
 #define _INPUT_H
 
 /*
- * $Id: input.h,v 1.34 2001/05/28 09:06:44 vojtech Exp $
+ * $Id: input.h,v 1.57 2002/01/02 11:59:56 vojtech Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
 /*
@@ -17,7 +15,7 @@
  *
  * 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
+ * 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
@@ -25,8 +23,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #ifdef __KERNEL__
@@ -64,17 +62,20 @@
 #define EVIOCSREP		_IOW('E', 0x03, int[2])			/* get repeat settings */
 #define EVIOCGKEYCODE		_IOR('E', 0x04, int[2])			/* get keycode */
 #define EVIOCSKEYCODE		_IOW('E', 0x04, int[2])			/* set keycode */
-#define EVIOCGKEY		_IOR('E', 0x05, int[2])			/* get key value */
+
 #define EVIOCGNAME(len)		_IOC(_IOC_READ, 'E', 0x06, len)		/* get device name */
-#define EVIOCGBUS		_IOR('E', 0x07, short[4])		/* get bus address */
+#define EVIOCGPHYS(len)		_IOC(_IOC_READ, 'E', 0x07, len)		/* get physical location */
+#define EVIOCGUNIQ(len)		_IOC(_IOC_READ, 'E', 0x08, len)		/* get unique identifier */
+
+#define EVIOCGKEY(len)		_IOC(_IOC_READ, 'E', 0x18, len)		/* get global keystate */
+#define EVIOCGLED(len)		_IOC(_IOC_READ, 'E', 0x19, len)		/* get all LEDs */
+#define EVIOCGSND(len)		_IOC(_IOC_READ, 'E', 0x1a, len)		/* get all sounds status */
 
 #define EVIOCGBIT(ev,len)	_IOC(_IOC_READ, 'E', 0x20 + ev, len)	/* get event bits */
 #define EVIOCGABS(abs)		_IOR('E', 0x40 + abs, int[5])		/* get abs value/limits */
 
 #define EVIOCSFF		_IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))	/* send a force effect to a force feedback device */
 #define EVIOCRMFF		_IOW('E', 0x81, int)			/* Erase a force effect */
-#define EVIOCSGAIN		_IOW('E', 0x82, unsigned short)		/* Set overall gain */
-#define EVIOCSAUTOCENTER	_IOW('E', 0x83, unsigned short)		/* Enable or disable auto-centering */
 #define EVIOCGEFFECTS		_IOR('E', 0x84, int)			/* Report number of effects playable at the same time */
 
 /*
@@ -90,6 +91,8 @@
 #define EV_SND			0x12
 #define EV_REP			0x14
 #define EV_FF			0x15
+#define EV_PWR			0x16
+#define EV_FF_STATUS		0x17
 #define EV_MAX			0x1f
 
 /*
@@ -304,8 +307,23 @@
 #define KEY_PROG4		203
 #define KEY_SUSPEND		205
 #define KEY_CLOSE		206
+#define KEY_PLAY		207
+#define KEY_FASTFORWARD		208
+#define KEY_BASSBOOST		209
+#define KEY_PRINT		210
+#define KEY_HP			211
+#define KEY_CAMERA		212
+#define KEY_SOUND		213
+#define KEY_QUESTION		214
+#define KEY_EMAIL		215
+#define KEY_CHAT		216
+#define KEY_SEARCH		217
+#define KEY_CONNECT		218
+#define KEY_FINANCE		219
+#define KEY_SPORT		220
+#define KEY_SHOP		221
 
-#define KEY_UNKNOWN		220
+#define KEY_UNKNOWN		240
 
 #define BTN_MISC		0x100
 #define BTN_0			0x100
@@ -415,14 +433,16 @@
 #define ABS_DISTANCE		0x19
 #define ABS_TILT_X		0x1a
 #define ABS_TILT_Y		0x1b
-#define ABS_MISC		0x1c
-#define ABS_MAX			0x1f
+#define ABS_VOLUME		0x20
+#define ABS_MISC		0x28
+#define ABS_MAX			0x3f
 
 /*
  * Misc events
  */
 
 #define MSC_SERIAL		0x00
+#define MSC_PULSELED		0x01
 #define MSC_MAX			0x07
 
 /*
@@ -468,6 +488,7 @@
 #define BUS_PCI			0x01
 #define BUS_ISAPNP		0x02
 #define BUS_USB			0x03
+#define BUS_HIL			0x04
 
 #define BUS_ISA			0x10
 #define BUS_I8042		0x11
@@ -480,32 +501,42 @@
 #define BUS_I2C			0x18
 
 /*
+ * Values describing the status of an effect
+ */
+#define FF_STATUS_STOPPED	0x00
+#define FF_STATUS_PLAYING	0x01
+#define FF_STATUS_MAX		0x01
+
+/*
  * Structures used in ioctls to upload effects to a device
  * The first structures are not passed directly by using ioctls.
  * They are sub-structures of the actually sent structure (called ff_effect)
+ *
+ * Ranges:
+ *  0 <= __u16 <= 65535
+ *  -32767 <= __s16 <= +32767     ! Not -32768 for lower bound !
  */
 
 struct ff_replay {
-	__u16 length;		/* Duration of an effect */
+	__u16 length;		/* Duration of an effect in ms. All other times are also expressed in ms */
 	__u16 delay;		/* Time to wait before to start playing an effect */
 };
 
 struct ff_trigger {
 	__u16 button;		/* Number of button triggering an effect */
-	__u16 interval;		/* Time to wait before an effect can be re-triggered */
+	__u16 interval;		/* Time to wait before an effect can be re-triggered (ms) */
 };
 
 struct ff_shape {
-	__u16 attack_length;	/* Duration of attack */
-	__s16 attack_level;	/* Level at beginning of attack */
-	__u16 fade_length;	/* Duration of fade */
-	__s16 fade_level;	/* Level at end of fade */
+	__u16 attack_length;	/* Duration of attack (ms) */
+	__u16 attack_level;	/* Level at beginning of attack */
+	__u16 fade_length;	/* Duration of fade (ms) */
+	__u16 fade_level;	/* Level at end of fade */
 };
 
 /* FF_CONSTANT */
 struct ff_constant_effect {
-	__s16 level;		/* Strength of effect */
-	__u16 direction;	/* Direction of effect (see periodic effects) */
+	__s16 level;		/* Strength of effect. Negative values are OK */
 	struct ff_shape shape;
 };
 
@@ -514,12 +545,13 @@
 /* Axis along which effect must be created. If null, the field named direction
  * is used
  * It is a bit array (ie to enable axes X and Y, use BIT(ABS_X) | BIT(ABS_Y)
+ * It overrides the value of ff_effect::direction, which is used only if
+ * axis == 0
  */
 	__u16 axis;
-	__u16 direction;
 
-	__s16 right_saturation; /* Max level when joystick is on the right */
-	__s16 left_saturation;  /* Max level when joystick in on the left */
+	__u16 right_saturation; /* Max level when joystick is on the right */
+	__u16 left_saturation;	/* Max level when joystick in on the left */
 
 	__s16 right_coeff;	/* Indicates how fast the force grows when the
 				   joystick moves to the right */
@@ -533,12 +565,10 @@
 /* FF_PERIODIC */
 struct ff_periodic_effect {
 	__u16 waveform;		/* Kind of wave (sine, square...) */
-	__u16 period;
+	__u16 period;		/* in ms */
 	__s16 magnitude;	/* Peak value */
 	__s16 offset;		/* Mean value of wave (roughly) */
 	__u16 phase;		/* 'Horizontal' shift */
-	__u16 direction;	/* Direction. 0 deg -> 0x0000
-					     90 deg -> 0x4000 */
 
 	struct ff_shape shape;
 };
@@ -549,10 +579,17 @@
 struct ff_effect {
 	__u16 type;
 /* Following field denotes the unique id assigned to an effect.
- * It is set by the driver.
+ * If user sets if to -1, a new effect is created, and its id is returned in the same field
+ * Else, the user sets it to the effect id it wants to update.
  */
 	__s16 id;
 
+	__u16 direction;	/* Direction. 0 deg -> 0x0000 (down)
+					     90 deg -> 0x4000 (left)
+					    180 deg -> 0x8000 (up)
+					    270 deg -> 0xC000 (right)
+				*/
+
 	struct ff_trigger trigger;
 	struct ff_replay replay;
 
@@ -564,7 +601,7 @@
 };
 
 /*
- * Buttons that can trigger effects.  Use for example FF_BTN(BTN_TRIGGER) to
+ * Buttons that can trigger effects. Use for example FF_BTN(BTN_TRIGGER) to
  * access the bitmap.
  */
 
@@ -625,8 +662,11 @@
 
 	void *private;
 
-	int number;
 	char *name;
+	char *phys;
+	char *uniq;
+	int number;
+
 	unsigned short idbus;
 	unsigned short idvendor;
 	unsigned short idproduct;
@@ -649,6 +689,9 @@
 	unsigned int repeat_key;
 	struct timer_list timer;
 
+	struct pm_dev *pm_dev;
+	int state;
+
 	int abs[ABS_MAX + 1];
 	int rep[REP_MAX + 1];
 
@@ -661,8 +704,12 @@
 	int absfuzz[ABS_MAX + 1];
 	int absflat[ABS_MAX + 1];
 
+	int only_one_writer;
+
 	int (*open)(struct input_dev *dev);
 	void (*close)(struct input_dev *dev);
+	int (*accept)(struct input_dev *dev, struct file *file);
+	int (*flush)(struct input_dev *dev, struct file *file);
 	int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 	int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
 	int (*erase_effect)(struct input_dev *dev, int effect_id);
@@ -671,16 +718,63 @@
 	struct input_dev *next;
 };
 
+/*
+ * Structure for hotplug & device<->driver matching.
+ */
+
+#define INPUT_DEVICE_ID_MATCH_BUS	1
+#define INPUT_DEVICE_ID_MATCH_VENDOR	2
+#define INPUT_DEVICE_ID_MATCH_PRODUCT	4
+#define INPUT_DEVICE_ID_MATCH_VERSION	8
+
+#define INPUT_DEVICE_ID_MATCH_EVBIT	0x010
+#define INPUT_DEVICE_ID_MATCH_KEYBIT	0x020
+#define INPUT_DEVICE_ID_MATCH_RELBIT	0x040
+#define INPUT_DEVICE_ID_MATCH_ABSBIT	0x080
+#define INPUT_DEVICE_ID_MATCH_MSCIT	0x100
+#define INPUT_DEVICE_ID_MATCH_LEDBIT	0x200
+#define INPUT_DEVICE_ID_MATCH_SNDBIT	0x400
+#define INPUT_DEVICE_ID_MATCH_FFBIT	0x800
+
+#define INPUT_DEVICE_ID_MATCH_DEVICE\
+	(INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
+#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
+	(INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
+
+struct input_device_id {
+
+	unsigned long flags;
+
+	unsigned short idbus;
+	unsigned short idvendor;
+	unsigned short idproduct;
+	unsigned short idversion;
+
+	unsigned long evbit[NBITS(EV_MAX)];
+	unsigned long keybit[NBITS(KEY_MAX)];
+	unsigned long relbit[NBITS(REL_MAX)];
+	unsigned long absbit[NBITS(ABS_MAX)];
+	unsigned long mscbit[NBITS(MSC_MAX)];
+	unsigned long ledbit[NBITS(LED_MAX)];
+	unsigned long sndbit[NBITS(SND_MAX)];
+	unsigned long ffbit[NBITS(FF_MAX)];
+
+	unsigned long driver_info;
+};
+
 struct input_handler {
 
 	void *private;
 
 	void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
-	struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev);
+	struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id);
 	void (*disconnect)(struct input_handle *handle);
 
 	struct file_operations *fops;
 	int minor;
+	char *name;
+
+	struct input_device_id *id_table;
 
 	struct input_handle *handle;
 	struct input_handler *next;
@@ -691,6 +785,7 @@
 	void *private;
 
 	int open;
+	char *name;
 
 	struct input_dev *dev;
 	struct input_handler *handler;
@@ -708,6 +803,9 @@
 int input_open_device(struct input_handle *);
 void input_close_device(struct input_handle *);
 
+int input_accept_process(struct input_handle *handle, struct file *file);
+int input_flush_device(struct input_handle* handle, struct file* file);
+
 devfs_handle_t input_register_minor(char *name, int minor, int minor_base);
 void input_unregister_minor(devfs_handle_t handle);
 
@@ -716,6 +814,8 @@
 #define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c))
 #define input_report_rel(a,b,c) input_event(a, EV_REL, b, c)
 #define input_report_abs(a,b,c) input_event(a, EV_ABS, b, c)
+#define input_report_ff(a,b,c)	input_event(a, EV_FF, b, c)
+#define input_report_ff_status(a,b,c)	input_event(a, EV_FF_STATUS, b, c)
 
 #endif
 #endif
diff -urN linux-2.5.4-pre2/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h
--- linux-2.5.4-pre2/include/linux/ncp_fs.h	Wed Jan 23 15:32:20 2002
+++ linux/include/linux/ncp_fs.h	Thu Feb  7 16:09:58 2002
@@ -228,7 +228,6 @@
 
 /* linux/fs/ncpfs/inode.c */
 int ncp_notify_change(struct dentry *, struct iattr *);
-struct super_block *ncp_read_super(struct super_block *, void *, int);
 struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *);
 void ncp_update_inode(struct inode *, struct ncp_entry_info *);
 void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
diff -urN linux-2.5.4-pre2/include/linux/pm.h linux/include/linux/pm.h
--- linux-2.5.4-pre2/include/linux/pm.h	Tue Jan 29 21:41:12 2002
+++ linux/include/linux/pm.h	Thu Feb  7 16:09:58 2002
@@ -103,8 +103,8 @@
 	void		*data;
 
 	unsigned long	 flags;
-	int		 state;
-	int		 prev_state;
+	unsigned long	 state;
+	unsigned long	 prev_state;
 
 	struct list_head entry;
 };
diff -urN linux-2.5.4-pre2/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.5.4-pre2/include/linux/sched.h	Thu Feb  7 16:09:52 2002
+++ linux/include/linux/sched.h	Thu Feb  7 16:09:58 2002
@@ -13,6 +13,7 @@
 #include <linux/times.h>
 #include <linux/timex.h>
 #include <linux/rbtree.h>
+#include <linux/thread_info.h>
 
 #include <asm/system.h>
 #include <asm/semaphore.h>
@@ -229,37 +230,15 @@
 
 typedef struct prio_array prio_array_t;
 
-/* this struct must occupy one 32-bit chunk so that is can be read in one go */
-struct task_work {
-	__s8	need_resched;
-	__u8	syscall_trace;	/* count of syscall interceptors */
-	__u8	sigpending;
-	__u8	notify_resume;	/* request for notification on
-				   userspace execution resumption */
-} __attribute__((packed));
-
 struct task_struct {
-	/*
-	 * offsets of these are hardcoded elsewhere - touch with care
-	 */
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
+	struct thread_info *thread_info;
+	atomic_t usage;
 	unsigned long flags;	/* per process flags, defined below */
-	volatile struct task_work work;
-
-	mm_segment_t addr_limit;	/* thread address space:
-					 	0-0xBFFFFFFF for user-thead
-						0-0xFFFFFFFF for kernel-thread
-					 */
-	struct exec_domain *exec_domain;
-	long __pad;
 	unsigned long ptrace;
 
 	int lock_depth;		/* Lock depth */
 
-	/*
-	 * offset 32 begins here on 32-bit platforms.
-	 */
-	unsigned int cpu;
 	int prio;
 	long __nice;
 	list_t run_list;
@@ -368,6 +347,11 @@
 	void *journal_info;
 };
 
+extern void __put_task_struct(struct task_struct *tsk);
+#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
+#define put_task_struct(tsk) \
+do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
+
 /*
  * Per process flags
  */
@@ -384,17 +368,14 @@
 #define PF_FREE_PAGES	0x00002000	/* per process page freeing */
 #define PF_NOIO		0x00004000	/* avoid generating further I/O */
 
-#define PF_USEDFPU	0x00100000	/* task used FPU this quantum (SMP) */
-
 /*
  * Ptrace flags
  */
 
 #define PT_PTRACED	0x00000001
-#define PT_SYSCALLTRACE	0x00000002	/* T if syscall_trace is +1 for ptrace() */
-#define PT_DTRACE	0x00000004	/* delayed trace (used on m68k, i386) */
-#define PT_TRACESYSGOOD	0x00000008
-#define PT_PTRACE_CAP	0x00000010	/* ptracer can follow suid-exec */
+#define PT_DTRACE	0x00000002	/* delayed trace (used on m68k, i386) */
+#define PT_TRACESYSGOOD	0x00000004
+#define PT_PTRACE_CAP	0x00000008	/* ptracer can follow suid-exec */
 
 /*
  * Limit the stack by to some sane default: root can always
@@ -470,16 +451,17 @@
  */
 extern struct exec_domain	default_exec_domain;
 
-#ifndef INIT_TASK_SIZE
-# define INIT_TASK_SIZE	2048*sizeof(long)
+#ifndef INIT_THREAD_SIZE
+# define INIT_THREAD_SIZE	2048*sizeof(long)
 #endif
 
-union task_union {
-	struct task_struct task;
-	unsigned long stack[INIT_TASK_SIZE/sizeof(long)];
+union thread_union {
+	struct thread_info thread_info;
+	unsigned long stack[INIT_THREAD_SIZE/sizeof(long)];
 };
 
-extern union task_union init_task_union;
+extern union thread_union init_thread_union;
+extern struct task_struct init_task;
 
 extern struct   mm_struct init_mm;
 extern struct task_struct *init_tasks[NR_CPUS];
@@ -584,22 +566,6 @@
 extern int do_sigaction(int, const struct k_sigaction *, struct k_sigaction *);
 extern int do_sigaltstack(const stack_t *, stack_t *, unsigned long);
 
-static inline int signal_pending(struct task_struct *p)
-{
-	return (p->work.sigpending != 0);
-}
-  
-static inline int need_resched(void)
-{
-	return unlikely(current->work.need_resched != 0);
-}
-
-static inline void cond_resched(void)
-{
-	if (need_resched())
-		schedule();
-}
-
 /*
  * Re-calculate pending state from the set of locally pending
  * signals, globally pending signals, and blocked signals.
@@ -630,15 +596,6 @@
 	return ready !=	0;
 }
 
-/* Reevaluate whether the task has signals pending delivery.
-   This is required every time the blocked sigset_t changes.
-   All callers should have t->sigmask_lock.  */
-
-static inline void recalc_sigpending(struct task_struct *t)
-{
-	t->work.sigpending = has_pending_signals(&t->pending.signal, &t->blocked);
-}
-
 /* True if we are on the alternate signal stack.  */
 
 static inline int on_sig_stack(unsigned long sp)
@@ -886,6 +843,72 @@
 	dput(root);
 	mntput(rootmnt);
 	return res;
+}
+
+/* set thread flags in other task's structures
+ * - see asm/thread_info.h for TIF_xxxx flags available
+ */
+static inline void set_tsk_thread_flag(struct task_struct *tsk, int flag)
+{
+	set_ti_thread_flag(tsk->thread_info,flag);
+}
+
+static inline void clear_tsk_thread_flag(struct task_struct *tsk, int flag)
+{
+	clear_ti_thread_flag(tsk->thread_info,flag);
+}
+
+static inline int test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag)
+{
+	return test_and_set_ti_thread_flag(tsk->thread_info,flag);
+}
+
+static inline int test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag)
+{
+	return test_and_clear_ti_thread_flag(tsk->thread_info,flag);
+}
+
+static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag)
+{
+	return test_ti_thread_flag(tsk->thread_info,flag);
+}
+
+static inline void set_tsk_need_resched(struct task_struct *tsk)
+{
+	set_tsk_thread_flag(tsk,TIF_NEED_RESCHED);
+}
+
+static inline void clear_tsk_need_resched(struct task_struct *tsk)
+{
+	clear_tsk_thread_flag(tsk,TIF_NEED_RESCHED);
+}
+
+static inline int signal_pending(struct task_struct *p)
+{
+	return unlikely(test_tsk_thread_flag(p,TIF_SIGPENDING));
+}
+  
+static inline int need_resched(void)
+{
+	return unlikely(test_thread_flag(TIF_NEED_RESCHED));
+}
+
+static inline void cond_resched(void)
+{
+	if (need_resched())
+		schedule();
+}
+
+/* Reevaluate whether the task has signals pending delivery.
+   This is required every time the blocked sigset_t changes.
+   Athread cathreaders should have t->sigmask_lock.  */
+
+static inline void recalc_sigpending(struct task_struct *t)
+{
+	if (has_pending_signals(&t->pending.signal, &t->blocked))
+		set_thread_flag(TIF_SIGPENDING);
+	else
+		clear_thread_flag(TIF_SIGPENDING);
 }
 
 #endif /* __KERNEL__ */
diff -urN linux-2.5.4-pre2/include/linux/serio.h linux/include/linux/serio.h
--- linux-2.5.4-pre2/include/linux/serio.h	Sun Aug 12 11:13:59 2001
+++ linux/include/linux/serio.h	Thu Feb  7 16:09:58 2002
@@ -2,31 +2,29 @@
 #define _SERIO_H
 
 /*
- * $Id: serio.h,v 1.11 2001/05/29 02:58:50 jsimmons Exp $
+ * $Id: serio.h,v 1.21 2001/12/19 05:15:21 skids Exp $
  *
- * Copyright (C) 1999 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (C) 1999-2001 Vojtech Pavlik
  */
 
 /*
  * 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 
+ * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
+ *
  * Should you need to contact me, the author, you can do so either by
  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 /*
@@ -42,23 +40,31 @@
 
 	void *private;
 	void *driver;
+	char *name;
+	char *phys;
+	int number;
+
+	unsigned short idbus;
+	unsigned short idvendor;
+	unsigned short idproduct;
+	unsigned short idversion;
 
 	unsigned long type;
-	int number;
 
 	int (*write)(struct serio *, unsigned char);
 	int (*open)(struct serio *);
 	void (*close)(struct serio *);
 
 	struct serio_dev *dev;
-
 	struct serio *next;
 };
 
 struct serio_dev {
 
 	void *private;
+	char *name;
 
+	void (*write_wakeup)(struct serio *);
 	void (*interrupt)(struct serio *, unsigned char, unsigned int);
 	void (*connect)(struct serio *, struct serio_dev *dev);
 	void (*disconnect)(struct serio *);
@@ -80,6 +86,13 @@
 	return serio->write(serio, data);
 }
 
+static __inline__ void serio_dev_write_wakeup(struct serio *serio)
+{
+	if (serio->dev && serio->dev->write_wakeup) {
+		serio->dev->write_wakeup(serio);
+	}
+}
+
 #define SERIO_TIMEOUT	1
 #define SERIO_PARITY	2
 
@@ -87,6 +100,7 @@
 #define SERIO_XT	0x00000000UL
 #define SERIO_8042	0x01000000UL
 #define SERIO_RS232	0x02000000UL
+#define SERIO_HIL_MLC	0x03000000UL
 
 #define SERIO_PROTO	0xFFUL
 #define SERIO_MSC	0x01
@@ -108,6 +122,9 @@
 #define SERIO_STOWAWAY	0x20
 #define SERIO_H3600	0x21
 #define SERIO_PS2SER	0x22
+#define SERIO_TWIDKBD	0x23
+#define SERIO_TWIDJOY	0x24
+#define SERIO_HIL	0x25
 
 #define SERIO_ID	0xff00UL
 #define SERIO_EXTRA	0xff0000UL
diff -urN linux-2.5.4-pre2/include/linux/thread_info.h linux/include/linux/thread_info.h
--- linux-2.5.4-pre2/include/linux/thread_info.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/thread_info.h	Thu Feb  7 16:09:58 2002
@@ -0,0 +1,82 @@
+/* thread_info.h: common low-level thread information accessors
+ *
+ * Copyright (C) 2002  David Howells (dhowells@redhat.com)
+ * - Incorporating suggestions made by Linus Torvalds
+ */
+
+#ifndef _LINUX_THREAD_INFO_H
+#define _LINUX_THREAD_INFO_H
+
+#include <asm/thread_info.h>
+#include <asm/bitops.h>
+
+#ifdef __KERNEL__
+
+/*
+ * flag set/clear/test wrappers
+ * - pass TIF_xxxx constants to these functions
+ */
+
+static inline void set_thread_flag(int flag)
+{
+	set_bit(flag,&current_thread_info()->flags);
+}
+
+static inline void clear_thread_flag(int flag)
+{
+	clear_bit(flag,&current_thread_info()->flags);
+}
+
+static inline int test_and_set_thread_flag(int flag)
+{
+	return test_and_set_bit(flag,&current_thread_info()->flags);
+}
+
+static inline int test_and_clear_thread_flag(int flag)
+{
+	return test_and_clear_bit(flag,&current_thread_info()->flags);
+}
+
+static inline int test_thread_flag(int flag)
+{
+	return test_bit(flag,&current_thread_info()->flags);
+}
+
+static inline void set_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	set_bit(flag,&ti->flags);
+}
+
+static inline void clear_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	clear_bit(flag,&ti->flags);
+}
+
+static inline int test_and_set_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_and_set_bit(flag,&ti->flags);
+}
+
+static inline int test_and_clear_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_and_clear_bit(flag,&ti->flags);
+}
+
+static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_bit(flag,&ti->flags);
+}
+
+static inline void set_need_resched(void)
+{
+	set_thread_flag(TIF_NEED_RESCHED);
+}
+
+static inline void clear_need_resched(void)
+{
+	set_thread_flag(TIF_NEED_RESCHED);
+}
+
+#endif
+
+#endif /* _LINUX_THREAD_INFO_H */
diff -urN linux-2.5.4-pre2/include/linux/usb.h linux/include/linux/usb.h
--- linux-2.5.4-pre2/include/linux/usb.h	Thu Feb  7 16:09:52 2002
+++ linux/include/linux/usb.h	Thu Feb  7 16:09:58 2002
@@ -1,6 +1,8 @@
 #ifndef __LINUX_USB_H
 #define __LINUX_USB_H
 
+#include <linux/device.h>
+
 /* USB constants */
 
 /*
@@ -260,6 +262,7 @@
 	int max_altsetting;             /* total memory allocated */
  
 	struct usb_driver *driver;	/* driver */
+	struct device dev;		/* interface specific device info */
 	void *private_data;
 };
 
@@ -945,6 +948,7 @@
 extern void usb_free_bus(struct usb_bus *);
 extern void usb_register_bus(struct usb_bus *);
 extern void usb_deregister_bus(struct usb_bus *);
+extern int usb_register_root_hub(struct usb_device *usb_dev, struct device *parent_dev);
 
 extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
 extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
@@ -1040,6 +1044,8 @@
 
 	struct usb_device *parent;
 	struct usb_bus *bus;		/* Bus we're part of */
+
+	struct device dev;		/* Generic device interface */
 
 	struct usb_device_descriptor descriptor;/* Descriptor */
 	struct usb_config_descriptor *config;	/* All of the configs */
diff -urN linux-2.5.4-pre2/include/linux/zconf.h linux/include/linux/zconf.h
--- linux-2.5.4-pre2/include/linux/zconf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/zconf.h	Thu Feb  7 16:09:58 2002
@@ -0,0 +1,90 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+#if defined(__GNUC__) || defined(__386__) || defined(i386)
+#  ifndef __32BIT__
+#    define __32BIT__
+#  endif
+#endif
+
+#if defined(__STDC__) || defined(__cplusplus)
+#  ifndef STDC
+#    define STDC
+#  endif
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  define MAX_MEM_LEVEL 9
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef FAR
+#   define FAR
+#endif
+
+typedef unsigned char  Byte;  /* 8 bits */
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+typedef Byte  FAR Bytef;
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+typedef void FAR *voidpf;
+typedef void     *voidp;
+
+#include <linux/types.h> /* for off_t */
+#include <linux/unistd.h>    /* for SEEK_* and off_t */
+#define z_off_t  off_t
+
+#endif /* _ZCONF_H */
diff -urN linux-2.5.4-pre2/include/linux/zutil.h linux/include/linux/zutil.h
--- linux-2.5.4-pre2/include/linux/zutil.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/zutil.h	Thu Feb  7 16:09:58 2002
@@ -0,0 +1,126 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: zutil.h,v 1.1 2000/01/01 03:32:23 davem Exp $ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include <linux/zlib.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+        /* Common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+         /* functions */
+
+typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
+				       uInt len));
+
+
+                        /* checksum functions */
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+static inline uLong zlib_adler32(uLong adler,
+				 const Bytef *buf,
+				 uInt len)
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+	    buf += 16;
+            k -= 16;
+        }
+        if (k != 0) do {
+            s1 += *buf++;
+	    s2 += s1;
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
+
+#endif /* _Z_UTIL_H */
diff -urN linux-2.5.4-pre2/kernel/exec_domain.c linux/kernel/exec_domain.c
--- linux-2.5.4-pre2/kernel/exec_domain.c	Sat Nov 24 14:27:27 2001
+++ linux/kernel/exec_domain.c	Thu Feb  7 16:09:58 2002
@@ -67,8 +67,8 @@
 	}
 	set_personality(pers);
 
-	if (current->exec_domain->handler != default_handler)
-		current->exec_domain->handler(segment, regp);
+	if (current_thread_info()->exec_domain->handler != default_handler)
+		current_thread_info()->exec_domain->handler(segment, regp);
 	else
 		send_sig(SIGSEGV, current, 1);
 }
@@ -162,7 +162,7 @@
 	struct exec_domain	*ep, *oep;
 
 	ep = lookup_exec_domain(personality);
-	if (ep == current->exec_domain) {
+	if (ep == current_thread_info()->exec_domain) {
 		current->personality = personality;
 		return 0;
 	}
@@ -190,8 +190,8 @@
 	 */
 
 	current->personality = personality;
-	oep = current->exec_domain;
-	current->exec_domain = ep;
+	oep = current_thread_info()->exec_domain;
+	current_thread_info()->exec_domain = ep;
 	set_fs_altroot();
 
 	put_exec_domain(oep);
diff -urN linux-2.5.4-pre2/kernel/exit.c linux/kernel/exit.c
--- linux-2.5.4-pre2/kernel/exit.c	Mon Jan 28 13:06:33 2002
+++ linux/kernel/exit.c	Thu Feb  7 16:09:58 2002
@@ -65,7 +65,7 @@
 	__restore_flags(flags);
 
 	p->pid = 0;
-	free_task_struct(p);
+	put_task_struct(p);
 }
 
 /*
@@ -529,7 +529,7 @@
 	if (current->leader)
 		disassociate_ctty(1);
 
-	put_exec_domain(tsk->exec_domain);
+	put_exec_domain(tsk->thread_info->exec_domain);
 	if (tsk->binfmt && tsk->binfmt->module)
 		__MOD_DEC_USE_COUNT(tsk->binfmt->module);
 
diff -urN linux-2.5.4-pre2/kernel/fork.c linux/kernel/fork.c
--- linux-2.5.4-pre2/kernel/fork.c	Thu Feb  7 16:09:52 2002
+++ linux/kernel/fork.c	Thu Feb  7 16:09:58 2002
@@ -28,6 +28,8 @@
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 
+static kmem_cache_t *task_struct_cachep;
+
 /* The idle threads do not count.. */
 int nr_threads;
 
@@ -70,6 +72,14 @@
 
 void __init fork_init(unsigned long mempages)
 {
+	/* create a slab on which task_structs can be allocated */
+	task_struct_cachep =
+		kmem_cache_create("task_struct",
+				  sizeof(struct task_struct),0,
+				  SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (!task_struct_cachep)
+		panic("fork_init(): cannot create task_struct SLAB cache");
+
 	/*
 	 * The default maximum number of threads is set to a safe
 	 * value: the thread structures can take up at most half
@@ -81,6 +91,35 @@
 	init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
 }
 
+struct task_struct *dup_task_struct(struct task_struct *orig)
+{
+	struct task_struct *tsk;
+	struct thread_info *ti;
+
+	ti = alloc_thread_info();
+	if (!ti) return NULL;
+
+	tsk = kmem_cache_alloc(task_struct_cachep,GFP_ATOMIC);
+	if (!tsk) {
+		free_thread_info(ti);
+		return NULL;
+	}
+
+	*ti = *orig->thread_info;
+	*tsk = *orig;
+	tsk->thread_info = ti;
+	ti->task = tsk;
+	atomic_set(&tsk->usage,1);
+
+	return tsk;
+}
+
+void __put_task_struct(struct task_struct *tsk)
+{
+	free_thread_info(tsk->thread_info);
+	kmem_cache_free(task_struct_cachep,tsk);
+}
+
 /* Protects next_safe and last_pid. */
 spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED;
 
@@ -546,7 +585,7 @@
 {
 	unsigned long new_flags = p->flags;
 
-	new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU);
+	new_flags &= ~PF_SUPERPRIV;
 	new_flags |= PF_FORKNOEXEC;
 	if (!(clone_flags & CLONE_PTRACE))
 		p->ptrace = 0;
@@ -585,12 +624,10 @@
 	}
 
 	retval = -ENOMEM;
-	p = alloc_task_struct();
+	p = dup_task_struct(current);
 	if (!p)
 		goto fork_out;
 
-	*p = *current;
-
 	retval = -EAGAIN;
 	if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur) {
 		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE))
@@ -608,7 +645,7 @@
 	if (nr_threads >= max_threads)
 		goto bad_fork_cleanup_count;
 	
-	get_exec_domain(p->exec_domain);
+	get_exec_domain(p->thread_info->exec_domain);
 
 	if (p->binfmt && p->binfmt->module)
 		__MOD_INC_USE_COUNT(p->binfmt->module);
@@ -631,7 +668,7 @@
 	}
 	spin_lock_init(&p->alloc_lock);
 
-	p->work.sigpending = 0;
+	clear_tsk_thread_flag(p,TIF_SIGPENDING);
 	init_sigpending(&p->pending);
 
 	p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
@@ -755,7 +792,7 @@
 		 * Let the child process run first, to avoid most of the
 		 * COW overhead when the child exec()s afterwards.
 		 */
-		current->work.need_resched = 1;
+		set_need_resched();
 
 fork_out:
 	return retval;
@@ -771,14 +808,14 @@
 bad_fork_cleanup_files:
 	exit_files(p); /* blocking */
 bad_fork_cleanup:
-	put_exec_domain(p->exec_domain);
+	put_exec_domain(p->thread_info->exec_domain);
 	if (p->binfmt && p->binfmt->module)
 		__MOD_DEC_USE_COUNT(p->binfmt->module);
 bad_fork_cleanup_count:
 	atomic_dec(&p->user->processes);
 	free_uid(p->user);
 bad_fork_free:
-	free_task_struct(p);
+	put_task_struct(p);
 	goto fork_out;
 }
 
diff -urN linux-2.5.4-pre2/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.5.4-pre2/kernel/ksyms.c	Thu Feb  7 16:09:52 2002
+++ linux/kernel/ksyms.c	Thu Feb  7 16:09:58 2002
@@ -563,7 +563,8 @@
 
 /* init task, for moving kthread roots - ought to export a function ?? */
 
-EXPORT_SYMBOL(init_task_union);
+EXPORT_SYMBOL(init_task);
+EXPORT_SYMBOL(init_thread_union);
 
 EXPORT_SYMBOL(tasklist_lock);
 EXPORT_SYMBOL(pidhash);
diff -urN linux-2.5.4-pre2/kernel/pm.c linux/kernel/pm.c
--- linux-2.5.4-pre2/kernel/pm.c	Sat Dec 29 17:30:07 2001
+++ linux/kernel/pm.c	Thu Feb  7 16:09:58 2002
@@ -154,7 +154,7 @@
 int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
 {
 	int status = 0;
-	int prev_state, next_state;
+	unsigned long prev_state, next_state;
 
 	if (in_interrupt())
 		BUG();
@@ -163,7 +163,7 @@
 	case PM_SUSPEND:
 	case PM_RESUME:
 		prev_state = dev->state;
-		next_state = (int) data;
+		next_state = (unsigned long) data;
 		if (prev_state != next_state) {
 			if (dev->callback)
 				status = (*dev->callback)(dev, rqst, data);
diff -urN linux-2.5.4-pre2/kernel/sched.c linux/kernel/sched.c
--- linux-2.5.4-pre2/kernel/sched.c	Mon Jan 28 15:12:47 2002
+++ linux/kernel/sched.c	Thu Feb  7 16:09:58 2002
@@ -51,7 +51,7 @@
 
 #define cpu_rq(cpu)		(runqueues + (cpu))
 #define this_rq()		cpu_rq(smp_processor_id())
-#define task_rq(p)		cpu_rq((p)->cpu)
+#define task_rq(p)		cpu_rq((p)->thread_info->cpu)
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 #define rt_task(p)		((p)->policy != SCHED_OTHER)
 
@@ -192,13 +192,19 @@
 
 static inline void resched_task(task_t *p)
 {
-	int need_resched;
+#ifdef CONFIG_SMP
+	int need_resched, nrpolling;
+
+	/* minimise the chance of sending an interrupt to poll_idle() */
+	nrpolling = test_tsk_thread_flag(p,TIF_POLLING_NRFLAG);
+	need_resched = test_and_set_tsk_thread_flag(p,TIF_NEED_RESCHED);
+	nrpolling |= test_tsk_thread_flag(p,TIF_POLLING_NRFLAG);
 
-	need_resched = p->work.need_resched;
-	wmb();
-	p->work.need_resched = 1;
-	if (!need_resched && (p->cpu != smp_processor_id()))
-		smp_send_reschedule(p->cpu);
+	if (!need_resched && !nrpolling && (p->thread_info->cpu != smp_processor_id()))
+		smp_send_reschedule(p->thread_info->cpu);
+#else
+	set_tsk_need_resched(p);
+#endif
 }
 
 #ifdef CONFIG_SMP
@@ -236,7 +242,7 @@
 void sched_task_migrated(task_t *new_task)
 {
 	wait_task_inactive(new_task);
-	new_task->cpu = smp_processor_id();
+	new_task->thread_info->cpu = smp_processor_id();
 	wake_up_process(new_task);
 }
 
@@ -299,7 +305,7 @@
 		current->sleep_avg = current->sleep_avg * PARENT_FORK_PENALTY / 100;
 	}
 	spin_lock_irq(&rq->lock);
-	p->cpu = smp_processor_id();
+	p->thread_info->cpu = smp_processor_id();
 	activate_task(p, rq);
 	spin_unlock_irq(&rq->lock);
 }
@@ -519,11 +525,11 @@
 	 */
 	dequeue_task(next, array);
 	busiest->nr_running--;
-	next->cpu = this_cpu;
+	next->thread_info->cpu = this_cpu;
 	this_rq->nr_running++;
 	enqueue_task(next, this_rq->active);
 	if (next->prio < current->prio)
-		current->work.need_resched = 1;
+		set_need_resched();
 	if (!idle && --imbalance) {
 		if (array == busiest->expired) {
 			array = busiest->active;
@@ -572,7 +578,7 @@
 #endif
 	/* Task might have expired already, but not scheduled off yet */
 	if (p->array != rq->active) {
-		p->work.need_resched = 1;
+		set_tsk_need_resched(p);
 		return;
 	}
 	spin_lock(&rq->lock);
@@ -583,7 +589,7 @@
 		 */
 		if ((p->policy == SCHED_RR) && !--p->time_slice) {
 			p->time_slice = NICE_TO_TIMESLICE(p->__nice);
-			p->work.need_resched = 1;
+			set_tsk_need_resched(p);
 
 			/* put it at the end of the queue: */
 			dequeue_task(p, rq->active);
@@ -603,7 +609,7 @@
 		p->sleep_avg--;
 	if (!--p->time_slice) {
 		dequeue_task(p, rq->active);
-		p->work.need_resched = 1;
+		set_tsk_need_resched(p);
 		p->prio = effective_prio(p);
 		p->time_slice = NICE_TO_TIMESLICE(p->__nice);
 
@@ -684,7 +690,7 @@
 
 switch_tasks:
 	prefetch(next);
-	prev->work.need_resched = 0;
+	clear_tsk_need_resched(prev);
 
 	if (likely(prev != next)) {
 		rq->nr_switches++;
@@ -1316,9 +1322,9 @@
 	idle->array = NULL;
 	idle->prio = MAX_PRIO;
 	idle->state = TASK_RUNNING;
-	idle->cpu = cpu;
+	idle->thread_info->cpu = cpu;
 	double_rq_unlock(idle_rq, rq);
-	idle->work.need_resched = 1;
+	set_tsk_need_resched(idle);
 	__restore_flags(flags);
 }
 
diff -urN linux-2.5.4-pre2/kernel/signal.c linux/kernel/signal.c
--- linux-2.5.4-pre2/kernel/signal.c	Thu Feb  7 16:09:52 2002
+++ linux/kernel/signal.c	Thu Feb  7 16:09:58 2002
@@ -23,7 +23,7 @@
 #define DEBUG_SIG 0
 
 #if DEBUG_SIG
-#define SIG_SLAB_DEBUG	(SLAB_DEBUG_FREE | SLAB_RED_ZONE /* | SLAB_POISON */)
+#define SIG_SLAB_DEBUG	(SLAB_RED_ZONE /* | SLAB_POISON */)
 #else
 #define SIG_SLAB_DEBUG	0
 #endif
@@ -105,7 +105,7 @@
 void
 flush_signals(struct task_struct *t)
 {
-	t->work.sigpending = 0;
+	clear_tsk_thread_flag(t,TIF_SIGPENDING);
 	flush_sigqueue(&t->pending);
 }
 
@@ -119,7 +119,7 @@
 		if (atomic_dec_and_test(&sig->count))
 			kmem_cache_free(sigact_cachep, sig);
 	}
-	tsk->work.sigpending = 0;
+	clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
 	flush_sigqueue(&tsk->pending);
 	spin_unlock_irq(&tsk->sigmask_lock);
 }
@@ -275,7 +275,7 @@
 		if (current->notifier) {
 			if (sigismember(current->notifier_mask, sig)) {
 				if (!(current->notifier)(current->notifier_data)) {
-					current->work.sigpending = 0;
+					clear_thread_flag(TIF_SIGPENDING);
 					return 0;
 				}
 			}
@@ -494,7 +494,7 @@
  */
 static inline void signal_wake_up(struct task_struct *t)
 {
-	t->work.sigpending = 1;
+	set_tsk_thread_flag(t,TIF_SIGPENDING);
 
 #ifdef CONFIG_SMP
 	/*
@@ -507,7 +507,7 @@
 	 * process of changing - but no harm is done by that
 	 * other than doing an extra (lightweight) IPI interrupt.
 	 */
-	if ((t->state == TASK_RUNNING) && (t->cpu != smp_processor_id()))
+	if ((t->state == TASK_RUNNING) && (t->thread_info->cpu != smp_processor_id()))
 		kick_if_running(t);
 #endif
 	if (t->state & TASK_INTERRUPTIBLE) {
diff -urN linux-2.5.4-pre2/linux/zconf.h linux/linux/zconf.h
--- linux-2.5.4-pre2/linux/zconf.h	Tue Jan 29 21:30:49 2002
+++ linux/linux/zconf.h	Wed Dec 31 16:00:00 1969
@@ -1,90 +0,0 @@
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* @(#) $Id$ */
-
-#ifndef _ZCONF_H
-#define _ZCONF_H
-
-#if defined(__GNUC__) || defined(__386__) || defined(i386)
-#  ifndef __32BIT__
-#    define __32BIT__
-#  endif
-#endif
-
-#if defined(__STDC__) || defined(__cplusplus)
-#  ifndef STDC
-#    define STDC
-#  endif
-#endif
-
-/* The memory requirements for deflate are (in bytes):
-            (1 << (windowBits+2)) +  (1 << (memLevel+9))
- that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
-     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
-   The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-#  define MAX_MEM_LEVEL 9
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2.
- * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
- * created by gzip. (Files created by minigzip can still be extracted by
- * gzip.)
- */
-#ifndef MAX_WBITS
-#  define MAX_WBITS   15 /* 32K LZ77 window */
-#endif
-
-                        /* Type declarations */
-
-#ifndef OF /* function prototypes */
-#  ifdef STDC
-#    define OF(args)  args
-#  else
-#    define OF(args)  ()
-#  endif
-#endif
-
-#ifndef ZEXPORT
-#  define ZEXPORT
-#endif
-#ifndef ZEXPORTVA
-#  define ZEXPORTVA
-#endif
-#ifndef ZEXTERN
-#  define ZEXTERN extern
-#endif
-#ifndef FAR
-#   define FAR
-#endif
-
-typedef unsigned char  Byte;  /* 8 bits */
-typedef unsigned int   uInt;  /* 16 bits or more */
-typedef unsigned long  uLong; /* 32 bits or more */
-
-typedef Byte  FAR Bytef;
-typedef char  FAR charf;
-typedef int   FAR intf;
-typedef uInt  FAR uIntf;
-typedef uLong FAR uLongf;
-
-typedef void FAR *voidpf;
-typedef void     *voidp;
-
-#include <linux/types.h> /* for off_t */
-#include <linux/unistd.h>    /* for SEEK_* and off_t */
-#define z_off_t  off_t
-
-#endif /* _ZCONF_H */
diff -urN linux-2.5.4-pre2/linux/zutil.h linux/linux/zutil.h
--- linux-2.5.4-pre2/linux/zutil.h	Tue Jan 29 21:30:49 2002
+++ linux/linux/zutil.h	Wed Dec 31 16:00:00 1969
@@ -1,126 +0,0 @@
-/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* @(#) $Id: zutil.h,v 1.1 2000/01/01 03:32:23 davem Exp $ */
-
-#ifndef _Z_UTIL_H
-#define _Z_UTIL_H
-
-#include <linux/zlib.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-
-#ifndef local
-#  define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-typedef unsigned char  uch;
-typedef uch FAR uchf;
-typedef unsigned short ush;
-typedef ush FAR ushf;
-typedef unsigned long  ulg;
-
-        /* common constants */
-
-#ifndef DEF_WBITS
-#  define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
-#define STORED_BLOCK 0
-#define STATIC_TREES 1
-#define DYN_TREES    2
-/* The three kinds of block type */
-
-#define MIN_MATCH  3
-#define MAX_MATCH  258
-/* The minimum and maximum match lengths */
-
-#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
-
-        /* target dependencies */
-
-        /* Common defaults */
-
-#ifndef OS_CODE
-#  define OS_CODE  0x03  /* assume Unix */
-#endif
-
-         /* functions */
-
-typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
-				       uInt len));
-
-
-                        /* checksum functions */
-
-#define BASE 65521L /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
-#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
-#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
-#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
-#define DO16(buf)   DO8(buf,0); DO8(buf,8);
-
-/* ========================================================================= */
-/*
-     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
-   return the updated checksum. If buf is NULL, this function returns
-   the required initial value for the checksum.
-   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
-   much faster. Usage example:
-
-     uLong adler = adler32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       adler = adler32(adler, buffer, length);
-     }
-     if (adler != original_adler) error();
-*/
-static inline uLong zlib_adler32(uLong adler,
-				 const Bytef *buf,
-				 uInt len)
-{
-    unsigned long s1 = adler & 0xffff;
-    unsigned long s2 = (adler >> 16) & 0xffff;
-    int k;
-
-    if (buf == Z_NULL) return 1L;
-
-    while (len > 0) {
-        k = len < NMAX ? len : NMAX;
-        len -= k;
-        while (k >= 16) {
-            DO16(buf);
-	    buf += 16;
-            k -= 16;
-        }
-        if (k != 0) do {
-            s1 += *buf++;
-	    s2 += s1;
-        } while (--k);
-        s1 %= BASE;
-        s2 %= BASE;
-    }
-    return (s2 << 16) | s1;
-}
-
-#endif /* _Z_UTIL_H */
diff -urN linux-2.5.4-pre2/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- linux-2.5.4-pre2/net/sunrpc/sched.c	Mon Jan 28 15:11:45 2002
+++ linux/net/sunrpc/sched.c	Thu Feb  7 16:09:58 2002
@@ -1109,7 +1109,7 @@
 	unsigned long flags;
 
 	while (all_tasks) {
-		current->work.sigpending = 0;
+		clear_thread_flag(TIF_SIGPENDING);
 		rpc_killall_tasks(NULL);
 		__rpc_schedule();
 		if (all_tasks) {
@@ -1183,7 +1183,7 @@
 	 * Usually rpciod will exit very quickly, so we
 	 * wait briefly before checking the process id.
 	 */
-	current->work.sigpending = 0;
+	clear_thread_flag(TIF_SIGPENDING);
 	yield();
 	/*
 	 * Display a message if we're going to wait longer.
diff -urN linux-2.5.4-pre2/net/sunrpc/svc.c linux/net/sunrpc/svc.c
--- linux-2.5.4-pre2/net/sunrpc/svc.c	Mon Jan 28 15:11:45 2002
+++ linux/net/sunrpc/svc.c	Thu Feb  7 16:09:58 2002
@@ -185,7 +185,7 @@
 		progp->pg_name, proto == IPPROTO_UDP? "udp" : "tcp", port);
 
 	if (!port)
-		current->work.sigpending = 0;
+		clear_thread_flag(TIF_SIGPENDING);
 
 	for (i = 0; i < progp->pg_nvers; i++) {
 		if (progp->pg_vers[i] == NULL)
