## Automatically generated incremental diff
## From:   linux-2.2.15-pre1
## To:     linux-2.2.15-pre2
## Robot:  $Id: make-incremental-diff,v 1.7 2001/12/04 05:19:54 hpa Exp $

diff -urN linux-2.2.15-pre1/Makefile linux/Makefile
--- linux-2.2.15-pre1/Makefile	Tue Jan  4 10:12:10 2000
+++ linux/Makefile	Mon Dec  3 21:57:39 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
-SUBLEVEL = 14
-EXTRAVERSION = 
+SUBLEVEL = 15
+EXTRAVERSION = pre2
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
diff -urN linux-2.2.15-pre1/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile
--- linux-2.2.15-pre1/arch/alpha/kernel/Makefile	Tue Jan  4 10:12:11 2000
+++ linux/arch/alpha/kernel/Makefile	Mon Dec  3 21:57:39 2001
@@ -134,7 +134,7 @@
 	./check_asm > $(TOPDIR)/include/asm-alpha/asm_offsets.h
 
 check_asm: check_asm.c
-	gcc -o $@ $< -I$(TOPDIR)/include -D__KERNEL__ -ffixed-8
+	$(CC) -o $@ $< -I$(TOPDIR)/include -D__KERNEL__ -ffixed-8
 
 clean::
 	rm -f check_asm
diff -urN linux-2.2.15-pre1/arch/alpha/kernel/sys_nautilus.c linux/arch/alpha/kernel/sys_nautilus.c
--- linux-2.2.15-pre1/arch/alpha/kernel/sys_nautilus.c	Tue Jan  4 10:12:11 2000
+++ linux/arch/alpha/kernel/sys_nautilus.c	Mon Dec  3 21:57:39 2001
@@ -30,6 +30,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/reboot.h>
+#include <linux/mc146818rtc.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
diff -urN linux-2.2.15-pre1/arch/i386/Makefile linux/arch/i386/Makefile
--- linux-2.2.15-pre1/arch/i386/Makefile	Tue Oct 26 17:53:39 1999
+++ linux/arch/i386/Makefile	Mon Dec  3 21:57:39 2001
@@ -65,7 +65,7 @@
 vmlinux: arch/i386/vmlinux.lds
 
 arch/i386/vmlinux.lds: arch/i386/vmlinux.lds.S FORCE
-	gcc -E -C -P -I$(HPATH) -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds
+	$(CPP) -C -P -I$(HPATH) -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds
 
 FORCE: ;
 
diff -urN linux-2.2.15-pre1/arch/sparc/config.in linux/arch/sparc/config.in
--- linux-2.2.15-pre1/arch/sparc/config.in	Mon Dec  3 21:57:34 2001
+++ linux/arch/sparc/config.in	Mon Dec  3 21:57:39 2001
@@ -114,13 +114,13 @@
 #			bool '   AX.25 DAMA Master support' CONFIG_AX25_DAMA_MASTER
 			dep_tristate '   Amateur Radio NET/ROM protocol' CONFIG_NETROM $CONFIG_AX25
 			dep_tristate '   Amateur Radio X.25 PLP (Rose)' CONFIG_ROSE $CONFIG_AX25
+
+			comment 'AX.25 network device drivers'
+			dep_tristate 'Serial port KISS driver' CONFIG_MKISS $CONFIG_AX25
+			dep_tristate 'Serial port 6PACK driver' CONFIG_6PACK $CONFIG_AX25
 		fi
 	fi
-	if [ "$CONFIG_AX25" != "n" ]; then
-		comment 'AX.25 network device drivers'
-		dep_tristate 'Serial port KISS driver' CONFIG_MKISS $CONFIG_AX25
-		dep_tristate 'Serial port 6PACK driver' CONFIG_6PACK $CONFIG_AX25
-	fi
+
 	endmenu
 fi
 
@@ -158,7 +158,7 @@
 	mainmenu_option next_comment
 	comment 'SCSI low-level drivers'
 
-	bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
+	tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
 	tristate 'PTI Qlogic,ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
 	endmenu
 fi
diff -urN linux-2.2.15-pre1/arch/sparc/defconfig linux/arch/sparc/defconfig
--- linux-2.2.15-pre1/arch/sparc/defconfig	Tue Oct 26 17:53:39 1999
+++ linux/arch/sparc/defconfig	Mon Dec  3 21:57:39 2001
@@ -146,6 +146,11 @@
 # CONFIG_NET_SCHED is not set
 
 #
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
 # ISDN subsystem
 #
 # CONFIG_ISDN is not set
diff -urN linux-2.2.15-pre1/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- linux-2.2.15-pre1/arch/sparc/mm/srmmu.c	Tue Jan  4 10:12:13 2000
+++ linux/arch/sparc/mm/srmmu.c	Mon Dec  3 21:57:39 2001
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.187.2.7 1999/11/16 06:29:44 davem Exp $
+/* $Id: srmmu.c,v 1.187.2.8 1999/12/23 01:58:38 davem Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -1662,7 +1662,8 @@
 	srmmu_map[srmmu_bank].vbase = vbase;
 	srmmu_map[srmmu_bank].pbase = sp_banks[sp_entry].base_addr;
 	srmmu_map[srmmu_bank].size = sp_banks[sp_entry].num_bytes;
-	srmmu_bank++;
+	if (srmmu_map[srmmu_bank].size)
+		srmmu_bank++;
 	map_spbank_last_pa = pstart - SRMMU_PGDIR_SIZE;
 	return vstart;
 }
diff -urN linux-2.2.15-pre1/arch/sparc64/config.in linux/arch/sparc64/config.in
--- linux-2.2.15-pre1/arch/sparc64/config.in	Tue Jan  4 10:12:13 2000
+++ linux/arch/sparc64/config.in	Mon Dec  3 21:57:39 2001
@@ -131,6 +131,25 @@
 
 if [ "$CONFIG_NET" = "y" ]; then
 	source net/Config.in
+	mainmenu_option next_comment
+	comment 'Amateur Radio support'
+	bool 'Amateur Radio support' CONFIG_HAMRADIO
+	if [ "$CONFIG_HAMRADIO" != "n" ] ; then
+		comment 'Packet Radio protocols'
+		tristate 'Amateur Radio AX.25 Level 2 protocol' CONFIG_AX25
+		if [ "$CONFIG_AX25" != "n" ]; then
+			bool '   AX.25 DAMA Slave support' CONFIG_AX25_DAMA_SLAVE
+#			bool '   AX.25 DAMA Master support' CONFIG_AX25_DAMA_MASTER
+			dep_tristate '   Amateur Radio NET/ROM protocol' CONFIG_NETROM $CONFIG_AX25
+			dep_tristate '   Amateur Radio X.25 PLP (Rose)' CONFIG_ROSE $CONFIG_AX25
+
+			comment 'AX.25 network device drivers'
+			dep_tristate 'Serial port KISS driver' CONFIG_MKISS $CONFIG_AX25
+			dep_tristate 'Serial port 6PACK driver' CONFIG_6PACK $CONFIG_AX25
+		fi
+	fi
+
+	endmenu
 fi
 
 mainmenu_option next_comment
@@ -158,7 +177,7 @@
 	mainmenu_option next_comment
 	comment 'SCSI low-level drivers'
 
-	bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
+	tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
 	tristate 'PTI Qlogic,ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
 
 	if [ "$CONFIG_PCI" != "n" ]; then
diff -urN linux-2.2.15-pre1/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- linux-2.2.15-pre1/arch/sparc64/defconfig	Tue Jan  4 10:12:13 2000
+++ linux/arch/sparc64/defconfig	Mon Dec  3 21:57:39 2001
@@ -176,6 +176,11 @@
 # CONFIG_NET_SCHED is not set
 
 #
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
 # SCSI support
 #
 CONFIG_SCSI=y
diff -urN linux-2.2.15-pre1/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c
--- linux-2.2.15-pre1/arch/sparc64/kernel/signal32.c	Sun Jun 13 19:42:01 1999
+++ linux/arch/sparc64/kernel/signal32.c	Mon Dec  3 21:57:39 2001
@@ -1,4 +1,4 @@
-/*  $Id: signal32.c,v 1.47.2.1 1999/06/14 00:36:24 davem Exp $
+/*  $Id: signal32.c,v 1.47.2.3 1999/12/20 01:14:06 davem Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -1033,6 +1033,62 @@
 		err |= __put_user(0, &sf->fpu_save);
 	}
 	
+	/* Update the siginfo structure.  Is this good?  */
+	if (info->si_code == 0) {
+		info->si_signo = signr;
+		info->si_errno = 0;
+
+		switch (signr) {
+		case SIGSEGV:
+		case SIGILL:
+		case SIGFPE:
+		case SIGBUS:
+		case SIGEMT:
+			info->si_code = current->tss.sig_desc;
+			info->si_addr = (void *)current->tss.sig_address;
+			info->si_trapno = 0;
+			break;
+		default:
+			break;
+		}
+	}
+
+	err = __put_user (info->si_signo, &sf->info.si_signo);
+	err |= __put_user (info->si_errno, &sf->info.si_errno);
+	err |= __put_user (info->si_code, &sf->info.si_code);
+	if (info->si_code < 0)
+		err |= __copy_to_user (sf->info._sifields._pad, info->_sifields._pad, SI_PAD_SIZE);
+	else {
+		i = info->si_signo;
+		if (info->si_code == SI_USER)
+			i = SIGRTMIN;
+		switch (i) {
+		case SIGPOLL:
+			err |= __put_user (info->si_band, &sf->info.si_band);
+			err |= __put_user (info->si_fd, &sf->info.si_fd);
+			break;
+		case SIGCHLD:
+			err |= __put_user (info->si_pid, &sf->info.si_pid);
+			err |= __put_user (info->si_uid, &sf->info.si_uid);
+			err |= __put_user (info->si_status, &sf->info.si_status);
+			err |= __put_user (info->si_utime, &sf->info.si_utime);
+			err |= __put_user (info->si_stime, &sf->info.si_stime);
+			break;
+		case SIGSEGV:
+		case SIGILL:
+		case SIGFPE:
+		case SIGBUS:
+		case SIGEMT:
+			err |= __put_user ((long)info->si_addr, &sf->info.si_addr);
+			err |= __put_user (info->si_trapno, &sf->info.si_trapno);
+			break;
+		default:
+			err |= __put_user (info->si_pid, &sf->info.si_pid);
+			err |= __put_user (info->si_uid, &sf->info.si_uid);
+			break;
+		}
+	}
+	
 	/* Setup sigaltstack */
 	err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
 	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
@@ -1048,7 +1104,7 @@
 	case 1: seta.sig[1] = (oldset->sig[0] >> 32);
 	        seta.sig[0] = oldset->sig[0];
 	}
-	err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t));
+	err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t32));
 
 	err |= copy_in_user((u32 *)sf,
 			    (u32 *)(regs->u_regs[UREG_FP]),
diff -urN linux-2.2.15-pre1/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c
--- linux-2.2.15-pre1/arch/sparc64/kernel/traps.c	Tue Jan  4 10:12:13 2000
+++ linux/arch/sparc64/kernel/traps.c	Mon Dec  3 21:57:39 2001
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.58.2.2 1999/12/01 23:55:43 davem Exp $
+/* $Id: traps.c,v 1.58.2.3 1999/12/19 23:59:28 davem Exp $
  * arch/sparc64/kernel/traps.c
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -516,8 +516,22 @@
 		regs->tpc = regs->tnpc;
 		regs->tnpc += 4;
 	} else {
+		unsigned long fsr = current->tss.xfsr[0];
+
 		current->tss.sig_address = regs->tpc;
 		current->tss.sig_desc = SUBSIG_FPERROR;
+		if ((fsr & 0x1c000) == (1 << 14)) {
+			if (fsr & 0x01)
+				current->tss.sig_desc = SUBSIG_FPINEXACT;
+			else if (fsr & 0x02)
+				current->tss.sig_desc = SUBSIG_FPDIVZERO;
+			else if (fsr & 0x04)
+				current->tss.sig_desc = SUBSIG_FPUNFLOW;
+			else if (fsr & 0x08)
+				current->tss.sig_desc = SUBSIG_FPOVFLOW;
+			else if (fsr & 0x10)
+				current->tss.sig_desc = SUBSIG_FPINTOVFL;
+		}
 		send_sig(SIGFPE, current, 1);
 	}
 }
@@ -561,7 +575,9 @@
 
 void do_div0(struct pt_regs *regs)
 {
-	send_sig(SIGILL, current, 1);
+	current->tss.sig_address = regs->tpc;
+	current->tss.sig_desc = SUBSIG_IDIVZERO;
+	send_sig(SIGFPE, current, 1);
 }
 
 void instruction_dump (unsigned int *pc)
@@ -686,10 +702,12 @@
 	send_sig(SIGILL, current, 1);
 }
 
-void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
-		       unsigned long psr)
+void handle_hw_divzero(struct pt_regs *regs, unsigned long pc,
+		       unsigned long npc, unsigned long psr)
 {
-	send_sig(SIGILL, current, 1);
+	current->tss.sig_address = regs->tpc;
+	current->tss.sig_desc = SUBSIG_IDIVZERO;
+	send_sig(SIGFPE, current, 1);
 }
 
 /* Trap level 1 stuff or other traps we should never see... */
diff -urN linux-2.2.15-pre1/arch/sparc64/math-emu/sfp-machine.h linux/arch/sparc64/math-emu/sfp-machine.h
--- linux-2.2.15-pre1/arch/sparc64/math-emu/sfp-machine.h	Tue Jan  4 10:12:13 2000
+++ linux/arch/sparc64/math-emu/sfp-machine.h	Mon Dec  3 21:57:39 2001
@@ -37,7 +37,7 @@
   _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
 
 #define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
-#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
 #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv(Q,R,X,Y)
 
 #define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
diff -urN linux-2.2.15-pre1/dmfe.c linux/dmfe.c
--- linux-2.2.15-pre1/dmfe.c	Mon Dec  3 21:57:34 2001
+++ linux/dmfe.c	Wed Dec 31 16:00:00 1969
@@ -1,1594 +0,0 @@
-/*
-   dmfe.c: Version 1.27C 01/07/2000
-
-   A Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver for Linux. 
-   Copyright (C) 1997  Sten Wang
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   as published by the Free Software Foundation; either version 2
-   of the License, or (at your option) any later version.
-
-   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.
-
-
-   Compiler command:
-   "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall 
-   -Wstrict-prototypes -O6 -c dmfe.c"
-   OR
-   "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net -Wall 
-   -Wstrict-prototypes -O6 -c dmfe.c"
-
-   The following steps teach you how to active DM9102 board:
-   1. Used the upper compiler command to compile dmfe.c
-   2. insert dmfe module into kernel
-   "insmod dmfe"        ;;Auto Detection Mode
-   "insmod dmfe mode=0" ;;Force 10M Half Duplex
-   "insmod dmfe mode=1" ;;Force 100M Half Duplex
-   "insmod dmfe mode=4" ;;Force 10M Full Duplex
-   "insmod dmfe mode=5" ;;Force 100M Full Duplex
-   3. config a dm9102 network interface
-   "ifconfig eth0 172.22.3.18"
-   ^^^^^^^^^^^ your IP address
-   4. active the IP routing table
-   "route add -net 172.22.3.0 eth0"
-   5. Well done. Your DM9102 adapter actived now.
-
-   Author: Sten Wang, 886-3-5798797-8517, E-mail: sten_wang@davicom.com.tw
-
-   Date:   10/28,1998
-
-   (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
-   
-   Stripped out < 2.2 support, made io address an unsigned long,
-   		Alan Cox
-   		
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/malloc.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <asm/processor.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include <linux/version.h>
-
-/* Board/System/Debug information/definition ---------------- */
-#define PCI_DM9132_ID   0x91321282	/* Davicom DM9132 ID */
-#define PCI_DM9102_ID   0x91021282	/* Davicom DM9102 ID */
-#define PCI_DM9100_ID   0x91001282	/* Davicom DM9100 ID */
-
-#define DMFE_SUCC       0
-#define DM9102_IO_SIZE  0x80
-#define DM9102A_IO_SIZE 0x100
-#define TX_FREE_DESC_CNT 0x1	/* Tx packet count */
-#define TX_DESC_CNT     0x10	/* Allocated Tx descriptors */
-#define RX_DESC_CNT     0x10	/* Allocated Rx descriptors */
-#define DESC_ALL_CNT    TX_DESC_CNT+RX_DESC_CNT
-#define TX_BUF_ALLOC    0x600
-#define RX_ALLOC_SIZE   0x620
-#define DM910X_RESET    1
-#define CR6_DEFAULT     0x00280000	/* SF, HD */
-#define CR7_DEFAULT     0x1a2cd
-#define CR15_DEFAULT    0x06	/* TxJabber RxWatchdog */
-#define TDES0_ERR_MASK  0x4302	/* TXJT, LC, EC, FUE */
-#define MAX_PACKET_SIZE 1514
-#define DMFE_MAX_MULTICAST 14
-#define RX_MAX_TRAFFIC  0x14000
-#define MAX_CHECK_PACKET 0x8000
-
-#define DMFE_10MHF      0
-#define DMFE_100MHF     1
-#define DMFE_10MFD      4
-#define DMFE_100MFD     5
-#define DMFE_AUTO       8
-
-#define DMFE_TIMER_WUT  jiffies+(HZ*2)/2	/* timer wakeup time : 1 second */
-#define DMFE_TX_TIMEOUT HZ*2	/* tx packet time-out time 2 s" */
-
-#define DMFE_DBUG(dbug_now, msg, vaule) if (dmfe_debug || dbug_now) printk("DBUG: %s %x\n", msg, vaule)
-
-#define DELAY_5US udelay(5)	/* udelay scale 1 usec */
-
-#define DELAY_1US udelay(1)	/* udelay scale 1 usec */
-
-#define SHOW_MEDIA_TYPE(mode) printk("\n<WARN> Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
-
-
-/* CR9 definition: SROM/MII */
-#define CR9_SROM_READ   0x4800
-#define CR9_SRCS        0x1
-#define CR9_SRCLK       0x2
-#define CR9_CRDOUT      0x8
-#define SROM_DATA_0     0x0
-#define SROM_DATA_1     0x4
-#define PHY_DATA_1      0x20000
-#define PHY_DATA_0      0x00000
-#define MDCLKH          0x10000
-
-#define SROM_CLK_WRITE(data, ioaddr) outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);DELAY_5US;outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr);DELAY_5US;outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);DELAY_5US;
-
-#define CHK_IO_SIZE(pci_id, dev_rev) ( (pci_id==PCI_DM9132_ID) || (dev_rev >= 0x02000030) ) ? DM9102A_IO_SIZE: DM9102_IO_SIZE
-
-
-/* Structure/enum declaration ------------------------------- */
-struct tx_desc {
-	u32 tdes0, tdes1, tdes2, tdes3;
-	u32 tx_skb_ptr;
-	u32 tx_buf_ptr;
-	u32 next_tx_desc;
-	u32 reserved;
-};
-
-struct rx_desc {
-	u32 rdes0, rdes1, rdes2, rdes3;
-	u32 rx_skb_ptr;
-	u32 rx_buf_ptr;
-	u32 next_rx_desc;
-	u32 reserved;
-};
-
-struct dmfe_board_info {
-	u32 chip_id;		/* Chip vendor/Device ID */
-	u32 chip_revesion;	/* Chip revesion */
-	struct device *next_dev;	/* next device */
-
-	struct pci_dev *net_dev;/* PCI device */
-
-	unsigned long ioaddr;	/* I/O base address */
-	u32 cr0_data;
-	u32 cr5_data;
-	u32 cr6_data;
-	u32 cr7_data;
-	u32 cr15_data;
-
-/* descriptor pointer */
-	unsigned char *buf_pool_ptr;	/* Tx buffer pool memory */
-	unsigned char *buf_pool_start;	/* Tx buffer pool align dword */
-	unsigned char *desc_pool_ptr;	/* descriptor pool memory */
-	struct tx_desc *first_tx_desc;
-	struct tx_desc *tx_insert_ptr;
-	struct tx_desc *tx_remove_ptr;
-	struct rx_desc *first_rx_desc;
-	struct rx_desc *rx_insert_ptr;
-	struct rx_desc *rx_ready_ptr;	/* packet come pointer */
-	u32 tx_packet_cnt;	/* transmitted packet count */
-	u32 rx_avail_cnt;	/* available rx descriptor count */
-	u32 interval_rx_cnt;	/* rx packet count a callback time */
-
-	u16 phy_id2;		/* Phyxcer ID2 */
-
-	u8 media_mode;		/* user specify media mode */
-	u8 op_mode;		/* real work media mode */
-	u8 phy_addr;
-	u8 link_failed;		/* Ever link failed */
-	u8 wait_reset;		/* Hardware failed, need to reset */
-	u8 in_reset_state;	/* Now driver in reset routine */
-	u8 rx_error_cnt;	/* recievd abnormal case count */
-	u8 dm910x_chk_mode;	/* Operating mode check */
-	struct timer_list timer;
-	struct enet_statistics stats;	/* statistic counter */
-	unsigned char srom[128];
-};
-
-enum dmfe_offsets {
-	DCR0 = 0, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20, DCR5 = 0x28,
-	DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48, DCR10 = 0x50, DCR11 = 0x58,
-	DCR12 = 0x60, DCR13 = 0x68, DCR14 = 0x70, DCR15 = 0x78
-};
-
-enum dmfe_CR6_bits {
-	CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80, CR6_FDM = 0x200,
-	CR6_TXSC = 0x2000, CR6_STI = 0x100000, CR6_SFT = 0x200000, CR6_RXA = 0x40000000,
-	CR6_NO_PURGE = 0x20000000
-};
-
-/* Global variable declaration ----------------------------- */
-static int dmfe_debug = 0;
-static unsigned char dmfe_media_mode = 8;
-static struct device *dmfe_root_dev = NULL;	/* First device */
-static u32 dmfe_cr6_user_set = 0;
-
-/* For module input parameter */
-static int debug = 0;
-static u32 cr6set = 0;
-static unsigned char mode = 8;
-static u8 chkmode = 1;
-
-unsigned long CrcTable[256] =
-{
-	0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
-	0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
-	0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
-	0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
-	0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
-	0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
-	0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
-	0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
-	0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
-	0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
-	0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
-	0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
-	0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
-	0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
-	0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
-	0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
-	0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
-	0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
-	0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
-	0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
-	0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
-	0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
-	0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
-	0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
-	0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
-	0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
-	0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
-	0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
-	0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
-	0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
-	0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
-	0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
-	0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
-	0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
-	0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
-	0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
-	0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
-	0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
-	0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
-	0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
-	0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
-	0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
-	0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
-	0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
-	0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
-	0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
-	0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
-	0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
-	0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
-	0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
-	0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
-	0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
-	0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
-	0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
-	0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
-	0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
-	0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
-	0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
-	0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
-	0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
-	0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
-	0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
-	0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
-	0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
-};
-
-/* function declaration ------------------------------------- */
-static int dmfe_probe(struct device *);
-static int dmfe_open(struct device *);
-static int dmfe_start_xmit(struct sk_buff *, struct device *);
-static int dmfe_stop(struct device *);
-static struct enet_statistics *dmfe_get_stats(struct device *);
-static void dmfe_set_filter_mode(struct device *);
-static int dmfe_do_ioctl(struct device *, struct ifreq *, int);
-static u16 read_srom_word(long, int);
-static void dmfe_interrupt(int, void *, struct pt_regs *);
-static void dmfe_descriptor_init(struct dmfe_board_info *, u32);
-static void allocated_rx_buffer(struct dmfe_board_info *);
-static void update_cr6(u32, u32);
-static void send_filter_frame(struct device *, int);
-static void dm9132_id_table(struct device *, int);
-static u16 phy_read(u32, u8, u8, u32);
-static void phy_write(u32, u8, u8, u16, u32);
-static void phy_write_1bit(u32, u32);
-static u16 phy_read_1bit(u32);
-static void dmfe_sense_speed(struct dmfe_board_info *);
-static void dmfe_process_mode(struct dmfe_board_info *);
-static void dmfe_timer(unsigned long);
-static void dmfe_rx_packet(struct device *, struct dmfe_board_info *);
-static void dmfe_reused_skb(struct dmfe_board_info *, struct sk_buff *);
-static void dmfe_dynamic_reset(struct device *);
-static void dmfe_free_rxbuffer(struct dmfe_board_info *);
-static void dmfe_init_dm910x(struct device *);
-static unsigned long cal_CRC(unsigned char *, unsigned int, u8);
-
-/* DM910X network baord routine ---------------------------- */
-
-/*
-   Search DM910X board ,allocate space and register it
- */
-int dmfe_probe(struct device *dev)
-{
-	u32 pci_iobase;
-	u16 dm9102_count = 0;
-	u8 pci_irqline;
-	static int index = 0;	/* For multiple call */
-	struct dmfe_board_info *db;	/* Point a board information structure */
-	int i;
-	struct pci_dev *net_dev = NULL;
-
-	DMFE_DBUG(0, "dmfe_probe()", 0);
-
-	if (!pci_present())
-		return -ENODEV;
-
-	index = 0;
-	while ((net_dev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, net_dev)))
-	{
-		u32 pci_id;
-		u32 dev_rev;
-		u8 pci_cmd;
-
-		index++;
-		if (pci_read_config_dword(net_dev, PCI_VENDOR_ID, &pci_id) != DMFE_SUCC)
-			continue;
-
-		if ((pci_id != PCI_DM9102_ID) && (pci_id != PCI_DM9132_ID))
-			continue;
-
-		/* read PCI IO base address and IRQ to check */
-		pci_read_config_dword(net_dev, PCI_BASE_ADDRESS_0, &pci_iobase);
-		pci_read_config_byte(net_dev, PCI_INTERRUPT_LINE, &pci_irqline);
-		pci_iobase &= ~0x7f;	/* mask off bit0~6 */
-
-		/* Enable Master/IO access, Disable memory access */
-		pci_read_config_byte(net_dev, PCI_COMMAND, &pci_cmd);
-		pci_cmd |= PCI_COMMAND_IO + PCI_COMMAND_MASTER;
-		pci_cmd &= ~PCI_COMMAND_MEMORY;
-		pci_write_config_byte(net_dev, PCI_COMMAND, pci_cmd);
-
-		/* Set Latency Timer 80h */
-		pci_write_config_byte(net_dev, PCI_LATENCY_TIMER, 0x80);
-
-		/* Read Chip revesion */
-		pci_read_config_dword(net_dev, 8, &dev_rev);
-
-		/* IO range check */
-		if (check_region(pci_iobase, CHK_IO_SIZE(pci_id, dev_rev))) {
-			printk(KERN_ERR "dmfe: I/O conflict : IO=%x Range=%x\n", pci_iobase, CHK_IO_SIZE(pci_id, dev_rev));
-			continue;
-		}
-		/* Interrupt check */
-		if (pci_irqline == 0) {
-			printk(KERN_ERR "dmfe: Interrupt wrong : IRQ=%d\n", pci_irqline);
-			continue;
-		}
-		/* Found DM9102 card and PCI resource allocated OK */
-		dm9102_count++;	/* Found a DM9102 card */
-
-		/* Init network device */
-		dev = init_etherdev(dev, 0);
-		
-		if(dev==NULL)
-		{
-			printk(KERN_ERR "dmfe: out of memory.\n");
-			continue;
-		}
-
-		/* Allocated board information structure */
-		db = (void *) (kmalloc(sizeof(*db), GFP_KERNEL | GFP_DMA));
-		
-		if(db==NULL)
-		{
-			printk(KERN_ERR "dmfe: out of memory.\n");
-			continue;
-		}
-		
-		memset(db, 0, sizeof(*db));
-		dev->priv = db;	/* link device and board info */
-		db->next_dev = dmfe_root_dev;
-		dmfe_root_dev = dev;
-
-		db->chip_id = pci_id;	/* keep Chip vandor/Device ID */
-		db->ioaddr = pci_iobase;
-		db->chip_revesion = dev_rev;
-
-		db->net_dev = net_dev;
-
-		dev->base_addr = pci_iobase;
-		dev->irq = pci_irqline;
-		dev->open = &dmfe_open;
-		dev->hard_start_xmit = &dmfe_start_xmit;
-		dev->stop = &dmfe_stop;
-		dev->get_stats = &dmfe_get_stats;
-		dev->set_multicast_list = &dmfe_set_filter_mode;
-		dev->do_ioctl = &dmfe_do_ioctl;
-
-		request_region(pci_iobase, CHK_IO_SIZE(pci_id, dev_rev), dev->name);
-
-		/* read 64 word srom data */
-		for (i = 0; i < 64; i++)
-			((u16 *) db->srom)[i] = read_srom_word(pci_iobase, i);
-
-		/* Set Node address */
-		for (i = 0; i < 6; i++)
-			dev->dev_addr[i] = db->srom[20 + i];
-
-		dev = 0;	/* NULL device */
-	}
-
-	if (!dm9102_count)
-		printk(KERN_WARNING "Can't find DM910X board or resource error\n");
-
-	return dm9102_count ? 0 : -ENODEV;
-}
-
-/*
-   Open the interface.
-   The interface is opened whenever "ifconfig" actives it.
- */
-static int dmfe_open(struct device *dev)
-{
-	struct dmfe_board_info *db = dev->priv;
-
-	DMFE_DBUG(0, "dmfe_open", 0);
-
-	if (request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev))
-		return -EAGAIN;
-
-	/* Allocated Tx/Rx descriptor memory */
-	db->desc_pool_ptr = kmalloc(sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, GFP_KERNEL | GFP_DMA);
-	if (db->desc_pool_ptr == NULL)
-		return -ENOMEM;
-	if ((u32) db->desc_pool_ptr & 0x1f)
-		db->first_tx_desc = (struct tx_desc *) (((u32) db->desc_pool_ptr & ~0x1f) + 0x20);
-	else
-		db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
-
-	/* Allocated Tx buffer memory */
-	db->buf_pool_ptr = kmalloc(TX_BUF_ALLOC * TX_DESC_CNT + 4, GFP_KERNEL | GFP_DMA);
-	if (db->buf_pool_ptr == NULL) {
-		kfree(db->desc_pool_ptr);
-		return -ENOMEM;
-	}
-	if ((u32) db->buf_pool_ptr & 0x3)
-		db->buf_pool_start = (char *) (((u32) db->buf_pool_ptr & ~0x3) + 0x4);
-	else
-		db->buf_pool_start = db->buf_pool_ptr;
-
-	/* system variable init */
-	db->cr6_data = CR6_DEFAULT | dmfe_cr6_user_set;
-	db->tx_packet_cnt = 0;
-	db->rx_avail_cnt = 0;
-	db->link_failed = 0;
-	db->wait_reset = 0;
-	db->in_reset_state = 0;
-	db->rx_error_cnt = 0;
-
-	if (!chkmode || (db->chip_id == PCI_DM9132_ID) || (db->chip_revesion >= 0x02000030)) {
-		//db->cr6_data &= ~CR6_SFT;         /* Used Tx threshold */
-		//db->cr6_data |= CR6_NO_PURGE;     /* No purge if rx unavailable */
-		db->cr0_data = 0xc00000;	/* TX/RX desc burst mode */
-		db->dm910x_chk_mode = 4;	/* Enter the normal mode */
-	} else {
-		db->cr0_data = 0;
-		db->dm910x_chk_mode = 1;	/* Enter the check mode */
-	}
-
-	/* Initilize DM910X board */
-	dmfe_init_dm910x(dev);
-
-	/* Active System Interface */
-	dev->tbusy = 0;		/* Can transmit packet */
-	dev->start = 1;		/* interface ready */
-	MOD_INC_USE_COUNT;
-
-	/* set and active a timer process */
-	init_timer(&db->timer);
-	db->timer.expires = DMFE_TIMER_WUT;
-	db->timer.data = (unsigned long) dev;
-	db->timer.function = &dmfe_timer;
-	add_timer(&db->timer);
-
-	return 0;
-}
-
-/* Initilize DM910X board
-   Reset DM910X board
-   Initilize TX/Rx descriptor chain structure
-   Send the set-up frame
-   Enable Tx/Rx machine
- */
-static void dmfe_init_dm910x(struct device *dev)
-{
-	struct dmfe_board_info *db = dev->priv;
-	unsigned long ioaddr = db->ioaddr;
-
-	DMFE_DBUG(0, "dmfe_init_dm910x()", 0);
-
-	/* Reset DM910x board : need 32 PCI clock to complete */
-	outl(DM910X_RESET, ioaddr + DCR0);	/* RESET MAC */
-	DELAY_5US;
-	outl(db->cr0_data, ioaddr + DCR0);
-
-	outl(0x180, ioaddr + DCR12);	/* Let bit 7 output port */
-	outl(0x80, ioaddr + DCR12);	/* RESET DM9102 phyxcer */
-	outl(0x0, ioaddr + DCR12);	/* Clear RESET signal */
-
-	/* Phy addr : DM910(A)2/DM9132/9801, phy address = 1 */
-	db->phy_addr = 1;
-
-/* Media Mode Check */
-	db->media_mode = dmfe_media_mode;
-	if (db->media_mode & DMFE_AUTO)
-		dmfe_sense_speed(db);
-	else
-		db->op_mode = db->media_mode;
-	dmfe_process_mode(db);
-
-	/* Initiliaze Transmit/Receive decriptor and CR3/4 */
-	dmfe_descriptor_init(db, ioaddr);
-
-	/* Init CR6 to program DM910x operation */
-	update_cr6(db->cr6_data, ioaddr);
-
-	/* Send setup frame */
-	if (db->chip_id == PCI_DM9132_ID)
-		dm9132_id_table(dev, dev->mc_count);	/* DM9132 */
-	else
-		send_filter_frame(dev, dev->mc_count);	/* DM9102/DM9102A */
-
-	/* Init CR5/CR7, interrupt active bit */
-	outl(0xffffffff, ioaddr + DCR5);	/* clear all CR5 status */
-	db->cr7_data = CR7_DEFAULT;
-	outl(db->cr7_data, ioaddr + DCR7);
-
-/* Init CR15, Tx jabber and Rx watchdog timer */
-	db->cr15_data = CR15_DEFAULT;
-	outl(db->cr15_data, ioaddr + DCR15);
-
-	/* Enable DM910X Tx/Rx function */
-	db->cr6_data |= CR6_RXSC | CR6_TXSC;
-	update_cr6(db->cr6_data, ioaddr);
-
-}
-
-
-/*
-   Hardware start transmission.
-   Send a packet to media from the upper layer.
- */
-static int dmfe_start_xmit(struct sk_buff *skb, struct device *dev)
-{
-	struct dmfe_board_info *db = dev->priv;
-	struct tx_desc *txptr;
-
-	DMFE_DBUG(0, "dmfe_start_xmit", 0);
-
-	if ((dev->tbusy == 1) && (db->tx_packet_cnt != 0))
-		return 1;
-	else
-		dev->tbusy = 0;
-
-	/* Too large packet check */
-	if (skb->len > MAX_PACKET_SIZE) {
-		dev_kfree_skb(skb);
-		return 0;
-	}
-	/* No Tx resource check, it never happen nromally */
-	if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) {
-		printk(KERN_ERR "dmfe: No Tx resource, enter xmit() again \n");
-		dev_kfree_skb(skb);
-		dev->tbusy = 1;
-		return -EBUSY;
-	}
-	/* transmit this packet */
-	txptr = db->tx_insert_ptr;
-	memcpy((char *) txptr->tx_buf_ptr, (char *) skb->data, skb->len);
-	txptr->tdes1 = 0xe1000000 | skb->len;
-	txptr->tdes0 = 0x80000000;	/* set owner bit to DM910X */
-
-	/* Point to next transmit free descriptor */
-	db->tx_insert_ptr = (struct tx_desc *) txptr->next_tx_desc;
-
-	/* transmit counter increase 1 */
-	db->tx_packet_cnt++;
-	db->stats.tx_packets++;
-
-	/* issue Tx polling command */
-	outl(0x1, dev->base_addr + DCR1);
-
-	/* Tx resource check */
-	if (db->tx_packet_cnt >= TX_FREE_DESC_CNT)
-		dev->tbusy = 1;
-
-	/* Set transmit time stamp */
-	dev->trans_start = jiffies;	/* saved the time stamp */
-
-	/* free this SKB */
-	dev_kfree_skb(skb);
-	return 0;
-}
-
-/*
-   Stop the interface.
-   The interface is stopped when it is brought.
- */
-
-static int dmfe_stop(struct device *dev)
-{
-	struct dmfe_board_info *db = dev->priv;
-	unsigned long ioaddr = dev->base_addr;
-
-	DMFE_DBUG(0, "dmfe_stop", 0);
-
-	/* disable system */
-	dev->start = 0;		/* interface disable */
-	dev->tbusy = 1;		/* can't transmit */
-
-	/* Reset & stop DM910X board */
-	outl(DM910X_RESET, ioaddr + DCR0);
-	DELAY_5US;
-
-	/* deleted timer */
-	del_timer(&db->timer);
-
-	/* free interrupt */
-	free_irq(dev->irq, dev);
-
-	/* free allocated rx buffer */
-	dmfe_free_rxbuffer(db);
-
-	/* free all descriptor memory and buffer memory */
-	kfree(db->desc_pool_ptr);
-	kfree(db->buf_pool_ptr);
-
-	MOD_DEC_USE_COUNT;
-
-	return 0;
-}
-
-/*
-   DM9102 insterrupt handler
-   receive the packet to upper layer, free the transmitted packet
- */
-
-static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct device *dev = dev_id;
-	struct tx_desc *txptr;
-	struct dmfe_board_info *db;
-	unsigned long ioaddr;
-
-	if (!dev) {
-		DMFE_DBUG(1, "dmfe_interrupt() without device arg", 0);
-		return;
-	}
-	if (dev->interrupt) {
-		DMFE_DBUG(1, "dmfe_interrupt() re-entry ", 0);
-		return;
-	}
-	/* A real interrupt coming */
-	dev->interrupt = 1;	/* Lock interrupt */
-	db = (struct dmfe_board_info *) dev->priv;
-	ioaddr = dev->base_addr;
-
-	DMFE_DBUG(0, "dmfe_interrupt()", 0);
-
-/* Disable all interrupt in CR7 to solve the interrupt edge problem */
-	outl(0, ioaddr + DCR7);
-
-/* Got DM910X status */
-	db->cr5_data = inl(ioaddr + DCR5);
-	outl(db->cr5_data, ioaddr + DCR5);
-	/* printk("CR5=%x\n", db->cr5_data); */
-
-	/* Check system status */
-	if (db->cr5_data & 0x2000) {
-		/* system bus error happen */
-		DMFE_DBUG(1, "System bus error happen. CR5=", db->cr5_data);
-		dev->tbusy = 1;
-		db->wait_reset = 1;	/* Need to RESET */
-		outl(0, ioaddr + DCR7);		/* disable all interrupt */
-		dev->interrupt = 0;	/* unlock interrupt */
-		return;
-	}
-	/* Free the transmitted descriptor */
-	txptr = db->tx_remove_ptr;
-	while (db->tx_packet_cnt) {
-		/* printk("tdes0=%x\n", txptr->tdes0); */
-		if (txptr->tdes0 & 0x80000000)
-			break;
-
-		/* Transmit statistic counter */
-		if (txptr->tdes0 != 0x7fffffff) {
-			/* printk("tdes0=%x\n", txptr->tdes0); */
-			db->stats.collisions += (txptr->tdes0 >> 3) & 0xf;
-			db->stats.tx_bytes += txptr->tdes1 & 0x7ff;
-			if (txptr->tdes0 & TDES0_ERR_MASK)
-				db->stats.tx_errors++;
-		}
-		txptr = (struct tx_desc *) txptr->next_tx_desc;
-		db->tx_packet_cnt--;
-	}
-	db->tx_remove_ptr = (struct tx_desc *) txptr;
-
-	if (dev->tbusy && (db->tx_packet_cnt < TX_FREE_DESC_CNT)) {
-		dev->tbusy = 0;	/* free a resource */
-		mark_bh(NET_BH);	/* active bottom half */
-	}
-	/* Received the coming packet */
-	if (db->rx_avail_cnt)
-		dmfe_rx_packet(dev, db);
-
-	/* reallocated rx descriptor buffer */
-	if (db->rx_avail_cnt < RX_DESC_CNT)
-		allocated_rx_buffer(db);
-
-	/* Mode Check */
-	if (db->dm910x_chk_mode & 0x2) {
-		db->dm910x_chk_mode = 0x4;
-		db->cr6_data |= 0x100;
-		update_cr6(db->cr6_data, db->ioaddr);
-	}
-	dev->interrupt = 0;	/* release interrupt lock */
-
-	/* Restore CR7 to enable interrupt mask */
-	if (db->interval_rx_cnt > RX_MAX_TRAFFIC)
-		db->cr7_data = 0x1a28d;
-	else
-		db->cr7_data = 0x1a2cd;
-	outl(db->cr7_data, ioaddr + DCR7);
-}
-
-/*
-   Receive the come packet and pass to upper layer
- */
- 
-static void dmfe_rx_packet(struct device *dev, struct dmfe_board_info *db)
-{
-	struct rx_desc *rxptr;
-	struct sk_buff *skb;
-	int rxlen;
-
-	rxptr = db->rx_ready_ptr;
-
-	while (db->rx_avail_cnt) {
-		if (rxptr->rdes0 & 0x80000000)	/* packet owner check */
-			break;
-
-		db->rx_avail_cnt--;
-		db->interval_rx_cnt++;
-
-		if ((rxptr->rdes0 & 0x300) != 0x300) {
-			/* A packet without First/Last flag */
-			/* reused this SKB */
-			DMFE_DBUG(0, "Reused SK buffer, rdes0", rxptr->rdes0);
-			dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
-			/* db->rx_error_cnt++; */
-		} else {
-			/* A packet with First/Last flag */
-			rxlen = ((rxptr->rdes0 >> 16) & 0x3fff) - 4;	/* skip CRC */
-
-			if (rxptr->rdes0 & 0x8000) {	/* error summary bit check */
-				/* This is a error packet */
-				/* printk("rdes0 error : %x \n", rxptr->rdes0); */
-				db->stats.rx_errors++;
-				if (rxptr->rdes0 & 1)
-					db->stats.rx_fifo_errors++;
-				if (rxptr->rdes0 & 2)
-					db->stats.rx_crc_errors++;
-				if (rxptr->rdes0 & 0x80)
-					db->stats.rx_length_errors++;
-			}
-			if (!(rxptr->rdes0 & 0x8000) ||
-			    ((db->cr6_data & CR6_PM) && (rxlen > 6))) {
-				skb = (struct sk_buff *) rxptr->rx_skb_ptr;
-
-				/* Received Packet CRC check need or not */
-				if ((db->dm910x_chk_mode & 1) && (cal_CRC(skb->tail, rxlen, 1) != (*(unsigned long *) (skb->tail + rxlen)))) {
-					/* Found a error received packet */
-					dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
-					db->dm910x_chk_mode = 3;
-				} else {
-					/* A good packet coming, send to upper layer */
-					skb->dev = dev;
-					skb_put(skb, rxlen);
-					skb->protocol = eth_type_trans(skb, dev);
-					netif_rx(skb);	/* Send to upper layer */
-					dev->last_rx = jiffies;
-					db->stats.rx_packets++;
-					db->stats.rx_bytes += rxlen;
-				}
-			} else {
-				/* Reuse SKB buffer when the packet is error */
-				DMFE_DBUG(0, "Reused SK buffer, rdes0", rxptr->rdes0);
-				dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
-			}
-		}
-
-		rxptr = (struct rx_desc *) rxptr->next_rx_desc;
-	}
-
-	db->rx_ready_ptr = rxptr;
-
-}
-
-/*
-   Get statistics from driver.
- */
-static struct enet_statistics *dmfe_get_stats(struct device *dev)
-{
-	struct dmfe_board_info *db = (struct dmfe_board_info *) dev->priv;
-	DMFE_DBUG(0, "dmfe_get_stats", 0);
-	return &db->stats;
-}
-
-/*
-   Set DM910X multicast address
- */
-
-static void dmfe_set_filter_mode(struct device *dev)
-{
-	struct dmfe_board_info *db = dev->priv;
-
-	DMFE_DBUG(0, "dmfe_set_filter_mode()", 0);
-
-	if (dev->flags & IFF_PROMISC) {
-		DMFE_DBUG(0, "Enable PROM Mode", 0);
-		db->cr6_data |= CR6_PM | CR6_PBF;
-		update_cr6(db->cr6_data, db->ioaddr);
-		return;
-	}
-	if (dev->flags & IFF_ALLMULTI || dev->mc_count > DMFE_MAX_MULTICAST) {
-		DMFE_DBUG(0, "Pass all multicast address", dev->mc_count);
-		db->cr6_data &= ~(CR6_PM | CR6_PBF);
-		db->cr6_data |= CR6_PAM;
-		return;
-	}
-	DMFE_DBUG(0, "Set multicast address", dev->mc_count);
-	if (db->chip_id == PCI_DM9132_ID)
-		dm9132_id_table(dev, dev->mc_count);	/* DM9132 */
-	else
-		send_filter_frame(dev, dev->mc_count);	/* DM9102/DM9102A */
-}
-
-/*
-   Process the upper socket ioctl command
- */
-
-static int dmfe_do_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
-{
-	DMFE_DBUG(0, "dmfe_do_ioctl()", 0);
-	return -EINVAL;
-}
-
-/*
-   A periodic timer routine
-   Dynamic media sense, allocated Rx buffer...
- */
- 
-static void dmfe_timer(unsigned long data)
-{
-	u32 tmp_cr8;
-	unsigned char tmp_cr12;
-	struct device *dev = (struct device *) data;
-	struct dmfe_board_info *db = (struct dmfe_board_info *) dev->priv;
-
-	DMFE_DBUG(0, "dmfe_timer()", 0);
-
-	/* Do reset now */
-	if (db->in_reset_state)
-		return;
-
-	/* Operating Mode Check */
-	if ((db->dm910x_chk_mode & 0x1) && (db->stats.rx_packets > MAX_CHECK_PACKET)) {
-		db->dm910x_chk_mode = 0x4;
-	}
-	/* Dynamic reset DM910X : system error or transmit time-out */
-	tmp_cr8 = inl(db->ioaddr + DCR8);
-	if ((db->interval_rx_cnt == 0) && (tmp_cr8)) {
-		db->wait_reset = 1;
-		/* printk("CR8 %x, Interval Rx %x\n", tmp_cr8, db->interval_rx_cnt); */
-	}
-	/* Receiving Traffic check */
-	if (db->interval_rx_cnt > RX_MAX_TRAFFIC)
-		db->cr7_data = 0x1a28d;
-	else
-		db->cr7_data = 0x1a2cd;
-	outl(db->cr7_data, db->ioaddr + DCR7);
-
-	db->interval_rx_cnt = 0;
-
-	if (db->wait_reset | (db->tx_packet_cnt &&
-			      ((jiffies - dev->trans_start) > DMFE_TX_TIMEOUT)) | (db->rx_error_cnt > 3)) {
-		/*
-		   printk("wait_reset %x, tx cnt %x, rx err %x, time %x\n", db->wait_reset, db->tx_packet_cnt, db->rx_error_cnt, jiffies-dev->trans_start);
-		 */
-		DMFE_DBUG(0, "Warn!! Warn!! Tx/Rx moniotr step1", db->tx_packet_cnt);
-		dmfe_dynamic_reset(dev);
-		db->timer.expires = DMFE_TIMER_WUT;
-		add_timer(&db->timer);
-		return;
-	}
-	db->rx_error_cnt = 0;	/* Clear previos counter */
-
-	/* Link status check, Dynamic media type change */
-	if (db->chip_id == PCI_DM9132_ID)
-		tmp_cr12 = inb(db->ioaddr + DCR9 + 3);	/* DM9132 */
-	else
-		tmp_cr12 = inb(db->ioaddr + DCR12);	/* DM9102/DM9102A */
-
-	if (((db->chip_id == PCI_DM9102_ID) && (db->chip_revesion == 0x02000030)) ||
-	    ((db->chip_id == PCI_DM9132_ID) && (db->chip_revesion == 0x02000010))) {
-		/* DM9102A Chip */
-		if (tmp_cr12 & 2)
-			tmp_cr12 = 0x0;		/* Link failed */
-		else
-			tmp_cr12 = 0x3;		/* Link OK */
-	}
-	if (!(tmp_cr12 & 0x3) && !db->link_failed) {
-		/* Link Failed */
-		DMFE_DBUG(0, "Link Failed", tmp_cr12);
-		db->link_failed = 1;
-		phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);	/* reset Phy */
-
-		/* 10/100M link failed, used 1M Home-Net */
-		db->cr6_data |= 0x00040000;	/* CR6 bit18 = 1, select Home-Net */
-		db->cr6_data &= ~0x00000200;	/* CR6 bit9 =0, half duplex mode */
-		update_cr6(db->cr6_data, db->ioaddr);
-
-		/* For DM9801 : PHY ID1 0181h, PHY ID2 B900h */
-		db->phy_id2 = phy_read(db->ioaddr, db->phy_addr, 3, db->chip_id);
-		if (db->phy_id2 == 0xb900)
-			phy_write(db->ioaddr, db->phy_addr, 25, 0x7e08, db->chip_id);
-	} else if ((tmp_cr12 & 0x3) && db->link_failed) {
-		DMFE_DBUG(0, "Link link OK", tmp_cr12);
-		db->link_failed = 0;
-
-		/* CR6 bit18=0, select 10/100M */
-		db->cr6_data &= ~0x00040000;
-		update_cr6(db->cr6_data, db->ioaddr);
-
-		/* Auto Sense Speed */
-		if (db->media_mode & DMFE_AUTO)
-			dmfe_sense_speed(db);
-		dmfe_process_mode(db);
-		update_cr6(db->cr6_data, db->ioaddr);
-		/* SHOW_MEDIA_TYPE(db->op_mode); */
-	}
-	/* reallocated rx descriptor buffer */
-	if (db->rx_avail_cnt < RX_DESC_CNT)
-		allocated_rx_buffer(db);
-
-	/* Timer active again */
-	db->timer.expires = DMFE_TIMER_WUT;
-	add_timer(&db->timer);
-}
-
-/*
-   Dynamic reset the DM910X board
-   Stop DM910X board
-   Free Tx/Rx allocated memory
-   Reset DM910X board
-   Re-initialize DM910X board
- */
-
-static void dmfe_dynamic_reset(struct device *dev)
-{
-	struct dmfe_board_info *db = dev->priv;
-
-	DMFE_DBUG(0, "dmfe_dynamic_reset()", 0);
-
-	/* Enter dynamic reset route */
-	db->in_reset_state = 1;
-
-	/* Disable upper layer interface */
-	dev->tbusy = 1;		/* transmit packet disable */
-	dev->start = 0;		/* interface not ready */
-
-	db->cr6_data &= ~(CR6_RXSC | CR6_TXSC);		/* Disable Tx/Rx */
-	update_cr6(db->cr6_data, dev->base_addr);
-
-	/* Free Rx Allocate buffer */
-	dmfe_free_rxbuffer(db);
-
-	/* system variable init */
-	db->tx_packet_cnt = 0;
-	db->rx_avail_cnt = 0;
-	db->link_failed = 0;
-	db->wait_reset = 0;
-	db->rx_error_cnt = 0;
-
-	/* Re-initilize DM910X board */
-	dmfe_init_dm910x(dev);
-
-	/* Restart upper layer interface */
-	dev->tbusy = 0;		/* Can transmit packet */
-	dev->start = 1;		/* interface ready */
-
-	/* Leave dynamic reser route */
-	db->in_reset_state = 0;
-}
-
-/*
-   free all allocated rx buffer 
- */
-static void dmfe_free_rxbuffer(struct dmfe_board_info *db)
-{
-	DMFE_DBUG(0, "dmfe_free_rxbuffer()", 0);
-
-	/* free allocated rx buffer */
-	while (db->rx_avail_cnt) {
-		dev_kfree_skb((void *) (db->rx_ready_ptr->rx_skb_ptr));
-		db->rx_ready_ptr = (struct rx_desc *) db->rx_ready_ptr->next_rx_desc;
-		db->rx_avail_cnt--;
-	}
-}
-
-/*
-   Reused the SK buffer
- */
-
-static void dmfe_reused_skb(struct dmfe_board_info *db, struct sk_buff *skb)
-{
-	struct rx_desc *rxptr = db->rx_insert_ptr;
-
-	if (!(rxptr->rdes0 & 0x80000000)) {
-		rxptr->rx_skb_ptr = (u32) skb;
-		rxptr->rdes2 = virt_to_bus(skb->tail);
-		rxptr->rdes0 = 0x80000000;
-		db->rx_avail_cnt++;
-		db->rx_insert_ptr = (struct rx_desc *) rxptr->next_rx_desc;
-	} else
-		DMFE_DBUG(0, "SK Buffer reused method error", db->rx_avail_cnt);
-}
-
-/*
-   Initialize transmit/Receive descriptor 
-   Using Chain structure, and allocated Tx/Rx buffer
- */
-static void dmfe_descriptor_init(struct dmfe_board_info *db, unsigned long ioaddr)
-{
-	struct tx_desc *tmp_tx;
-	struct rx_desc *tmp_rx;
-	unsigned char *tmp_buf;
-	int i;
-
-	DMFE_DBUG(0, "dmfe_descriptor_init()", 0);
-
-	/* tx descriptor start pointer */
-	db->tx_insert_ptr = db->first_tx_desc;
-	db->tx_remove_ptr = db->first_tx_desc;
-	outl(virt_to_bus(db->first_tx_desc), ioaddr + DCR4);	/* Init CR4 */
-
-	/* rx descriptor start pointer */
-	db->first_rx_desc = (struct rx_desc *)
-	    ((u32) db->first_tx_desc + sizeof(struct rx_desc) * TX_DESC_CNT);
-	db->rx_insert_ptr = db->first_rx_desc;
-	db->rx_ready_ptr = db->first_rx_desc;
-	outl(virt_to_bus(db->first_rx_desc), ioaddr + DCR3);	/* Init CR3 */
-
-	/* Init Transmit chain */
-	tmp_buf = db->buf_pool_start;
-	for (tmp_tx = db->first_tx_desc, i = 0; i < TX_DESC_CNT; i++, tmp_tx++) {
-		tmp_tx->tx_buf_ptr = (u32) tmp_buf;
-		tmp_tx->tdes0 = 0;
-		tmp_tx->tdes1 = 0x81000000;	/* IC, chain */
-		tmp_tx->tdes2 = (u32) virt_to_bus(tmp_buf);
-		tmp_tx->tdes3 = (u32) virt_to_bus(tmp_tx) + sizeof(struct tx_desc);
-		tmp_tx->next_tx_desc = (u32) ((u32) tmp_tx + sizeof(struct tx_desc));
-		tmp_buf = (unsigned char *) ((u32) tmp_buf + TX_BUF_ALLOC);
-	}
-	(--tmp_tx)->tdes3 = (u32) virt_to_bus(db->first_tx_desc);
-	tmp_tx->next_tx_desc = (u32) db->first_tx_desc;
-
-	/* Init Receive descriptor chain */
-	for (tmp_rx = db->first_rx_desc, i = 0; i < RX_DESC_CNT; i++, tmp_rx++) {
-		tmp_rx->rdes0 = 0;
-		tmp_rx->rdes1 = 0x01000600;
-		tmp_rx->rdes3 = (u32) virt_to_bus(tmp_rx) + sizeof(struct rx_desc);
-		tmp_rx->next_rx_desc = (u32) ((u32) tmp_rx + sizeof(struct rx_desc));
-	}
-	(--tmp_rx)->rdes3 = (u32) virt_to_bus(db->first_rx_desc);
-	tmp_rx->next_rx_desc = (u32) db->first_rx_desc;
-
-	/* pre-allocated Rx buffer */
-	allocated_rx_buffer(db);
-}
-
-/*
-   Update CR6 vaule
-   Firstly stop DM910X , then written value and start
- */
-
-static void update_cr6(u32 cr6_data, unsigned long ioaddr)
-{
-	u32 cr6_tmp;
-
-	cr6_tmp = cr6_data & ~0x2002;	/* stop Tx/Rx */
-	outl(cr6_tmp, ioaddr + DCR6);
-	DELAY_5US;
-	outl(cr6_data, ioaddr + DCR6);
-	cr6_tmp = inl(ioaddr + DCR6);
-	/* printk("CR6 update %x ", cr6_tmp); */
-}
-
-/* Send a setup frame for DM9132
-   This setup frame initilize DM910X addres filter mode
- */
-
-static void dm9132_id_table(struct device *dev, int mc_cnt)
-{
-	struct dev_mc_list *mcptr;
-	u16 *addrptr;
-	unsigned long ioaddr = dev->base_addr + 0xc0;	/* ID Table */
-	u32 hash_val;
-	u16 i, hash_table[4];
-
-	DMFE_DBUG(0, "dm9132_id_table()", 0);
-
-	/* Node address */
-	addrptr = (u16 *) dev->dev_addr;
-	outw(addrptr[0], ioaddr);
-	ioaddr += 4;
-	outw(addrptr[1], ioaddr);
-	ioaddr += 4;
-	outw(addrptr[2], ioaddr);
-	ioaddr += 4;
-
-	/* Clear Hash Table */
-	for (i = 0; i < 4; i++)
-		hash_table[i] = 0x0;
-
-	/* broadcast address */
-	hash_table[3] = 0x8000;
-
-	/* the multicast address in Hash Table : 64 bits */
-	for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
-		hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f;
-		hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
-	}
-
-	/* Write the hash table to MAC MD table */
-	for (i = 0; i < 4; i++, ioaddr += 4) {
-		outw(hash_table[i], ioaddr);
-	}
-}
-
-/* Send a setup frame for DM9102/DM9102A
-   This setup frame initilize DM910X addres filter mode
- */
-
-static void send_filter_frame(struct device *dev, int mc_cnt)
-{
-	struct dmfe_board_info *db = dev->priv;
-	struct dev_mc_list *mcptr;
-	struct tx_desc *txptr;
-	u16 *addrptr;
-	u32 *suptr;
-	int i;
-
-	DMFE_DBUG(0, "send_filetr_frame()", 0);
-
-	txptr = db->tx_insert_ptr;
-	suptr = (u32 *) txptr->tx_buf_ptr;
-
-	/* Node address */
-	addrptr = (u16 *) dev->dev_addr;
-	*suptr++ = addrptr[0];
-	*suptr++ = addrptr[1];
-	*suptr++ = addrptr[2];
-
-	/* broadcast address */
-	*suptr++ = 0xffff;
-	*suptr++ = 0xffff;
-	*suptr++ = 0xffff;
-
-	/* fit the multicast address */
-	for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
-		addrptr = (u16 *) mcptr->dmi_addr;
-		*suptr++ = addrptr[0];
-		*suptr++ = addrptr[1];
-		*suptr++ = addrptr[2];
-	}
-
-	for (; i < 14; i++) {
-		*suptr++ = 0xffff;
-		*suptr++ = 0xffff;
-		*suptr++ = 0xffff;
-	}
-
-	/* prepare the setup frame */
-	db->tx_packet_cnt++;
-	dev->tbusy = 1;
-	txptr->tdes1 = 0x890000c0;
-	txptr->tdes0 = 0x80000000;
-	db->tx_insert_ptr = (struct tx_desc *) txptr->next_tx_desc;
-
-	update_cr6(db->cr6_data | 0x2000, dev->base_addr);
-	outl(0x1, dev->base_addr + DCR1);
-	update_cr6(db->cr6_data, dev->base_addr);
-	dev->trans_start = jiffies;
-
-}
-
-/*
-   Allocate rx buffer,
-   As possible as allocated maxiumn Rx buffer
- */
-
-static void allocated_rx_buffer(struct dmfe_board_info *db)
-{
-	struct rx_desc *rxptr;
-	struct sk_buff *skb;
-
-	rxptr = db->rx_insert_ptr;
-
-	while (db->rx_avail_cnt < RX_DESC_CNT) {
-		if ((skb = alloc_skb(RX_ALLOC_SIZE, GFP_ATOMIC)) == NULL)
-			break;
-		rxptr->rx_skb_ptr = (u32) skb;
-		rxptr->rdes2 = virt_to_bus(skb->tail);
-		rxptr->rdes0 = 0x80000000;
-		rxptr = (struct rx_desc *) rxptr->next_rx_desc;
-		db->rx_avail_cnt++;
-	}
-
-	db->rx_insert_ptr = rxptr;
-}
-
-/*
-   Read one word data from the serial ROM
- */
-
-static u16 read_srom_word(unsigned long ioaddr, int offset)
-{
-	int i;
-	u16 srom_data = 0;
-	unsigned long cr9_ioaddr = ioaddr + DCR9;
-
-	outl(CR9_SROM_READ, cr9_ioaddr);
-	outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
-
-	/* Send the Read Command 110b */
-	SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
-	SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
-	SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);
-
-	/* Send the offset */
-	for (i = 5; i >= 0; i--) {
-		srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
-		SROM_CLK_WRITE(srom_data, cr9_ioaddr);
-	}
-
-	outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
-
-	for (i = 16; i > 0; i--) {
-		outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
-		DELAY_5US;
-		srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);
-		outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
-		DELAY_5US;
-	}
-
-	outl(CR9_SROM_READ, cr9_ioaddr);
-	return srom_data;
-}
-
-/*
-   Auto sense the media mode
- */
-static void dmfe_sense_speed(struct dmfe_board_info *db)
-{
-	int i;
-	u16 phy_mode;
-
-	for (i = 1000; i; i--) {
-		DELAY_5US;
-		phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
-		if ((phy_mode & 0x24) == 0x24)
-			break;
-	}
-
-	if (i) {
-		if (db->chip_id == PCI_DM9132_ID)	/* DM9132 */
-			phy_mode = phy_read(db->ioaddr, db->phy_addr, 7, db->chip_id) & 0xf000;
-		else		/* DM9102/DM9102A */
-			phy_mode = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) & 0xf000;
-		/* printk("Phy_mode %x ",phy_mode); */
-		switch (phy_mode) {
-		case 0x1000:
-			db->op_mode = DMFE_10MHF;
-			break;
-		case 0x2000:
-			db->op_mode = DMFE_10MFD;
-			break;
-		case 0x4000:
-			db->op_mode = DMFE_100MHF;
-			break;
-		case 0x8000:
-			db->op_mode = DMFE_100MFD;
-			break;
-		default:
-			db->op_mode = DMFE_10MHF;
-			DMFE_DBUG(0, "Media Type error, phy reg17", phy_mode);
-			break;
-		}
-	} else {
-		db->op_mode = DMFE_10MHF;
-		DMFE_DBUG(0, "Link Failed :", phy_mode);
-	}
-}
-
-/*
-   Process op-mode
-   AUTO mode : PHY controller in Auto-negotiation Mode
-   Force mode: PHY controller in force mode with HUB
-   N-way force capability with SWITCH
- */
-static void dmfe_process_mode(struct dmfe_board_info *db)
-{
-	u16 phy_reg;
-
-	/* Full Duplex Mode Check */
-	db->cr6_data &= ~CR6_FDM;	/* Clear Full Duplex Bit */
-	if (db->op_mode & 0x4)
-		db->cr6_data |= CR6_FDM;
-
-	if (!(db->media_mode & DMFE_AUTO)) {	/* Force Mode Check */
-		/* User force the media type */
-		phy_reg = phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id);
-		/* printk("Nway phy_reg5 %x ",phy_reg); */
-		if (phy_reg & 0x1) {
-			/* parter own the N-Way capability */
-			phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x1e0;
-			switch (db->op_mode) {
-			case DMFE_10MHF:
-				phy_reg |= 0x20;
-				break;
-			case DMFE_10MFD:
-				phy_reg |= 0x40;
-				break;
-			case DMFE_100MHF:
-				phy_reg |= 0x80;
-				break;
-			case DMFE_100MFD:
-				phy_reg |= 0x100;
-				break;
-			}
-			phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
-		} else {
-			/* parter without the N-Way capability */
-			switch (db->op_mode) {
-			case DMFE_10MHF:
-				phy_reg = 0x0;
-				break;
-			case DMFE_10MFD:
-				phy_reg = 0x100;
-				break;
-			case DMFE_100MHF:
-				phy_reg = 0x2000;
-				break;
-			case DMFE_100MFD:
-				phy_reg = 0x2100;
-				break;
-			}
-			phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
-		}
-	}
-}
-
-/*
-   Write a word to Phy register
- */
-static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id)
-{
-	u16 i;
-	unsigned long ioaddr;
-
-	if (chip_id == PCI_DM9132_ID) {
-		ioaddr = iobase + 0x80 + offset * 4;
-		outw(phy_data, ioaddr);
-	} else {
-		/* DM9102/DM9102A Chip */
-		ioaddr = iobase + DCR9;
-
-		/* Send 33 synchronization clock to Phy controller */
-		for (i = 0; i < 35; i++)
-			phy_write_1bit(ioaddr, PHY_DATA_1);
-
-		/* Send start command(01) to Phy */
-		phy_write_1bit(ioaddr, PHY_DATA_0);
-		phy_write_1bit(ioaddr, PHY_DATA_1);
-
-		/* Send write command(01) to Phy */
-		phy_write_1bit(ioaddr, PHY_DATA_0);
-		phy_write_1bit(ioaddr, PHY_DATA_1);
-
-		/* Send Phy addres */
-		for (i = 0x10; i > 0; i = i >> 1)
-			phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
-
-		/* Send register addres */
-		for (i = 0x10; i > 0; i = i >> 1)
-			phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);
-
-		/* written trasnition */
-		phy_write_1bit(ioaddr, PHY_DATA_1);
-		phy_write_1bit(ioaddr, PHY_DATA_0);
-
-		/* Write a word data to PHY controller */
-		for (i = 0x8000; i > 0; i >>= 1)
-			phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0);
-	}
-}
-
-/*
-   Read a word data from phy register
- */
-static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
-{
-	int i;
-	u16 phy_data;
-	unsigned long ioaddr;
-
-	if (chip_id == PCI_DM9132_ID) {
-		/* DM9132 Chip */
-		ioaddr = iobase + 0x80 + offset * 4;
-		phy_data = inw(ioaddr);
-	} else {
-		/* DM9102/DM9102A Chip */
-
-		ioaddr = iobase + DCR9;
-		/* Send 33 synchronization clock to Phy controller */
-		for (i = 0; i < 35; i++)
-			phy_write_1bit(ioaddr, PHY_DATA_1);
-
-		/* Send start command(01) to Phy */
-		phy_write_1bit(ioaddr, PHY_DATA_0);
-		phy_write_1bit(ioaddr, PHY_DATA_1);
-
-		/* Send read command(10) to Phy */
-		phy_write_1bit(ioaddr, PHY_DATA_1);
-		phy_write_1bit(ioaddr, PHY_DATA_0);
-
-		/* Send Phy addres */
-		for (i = 0x10; i > 0; i = i >> 1)
-			phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
-
-		/* Send register addres */
-		for (i = 0x10; i > 0; i = i >> 1)
-			phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);
-
-		/* Skip transition state */
-		phy_read_1bit(ioaddr);
-
-		/* read 16bit data */
-		for (phy_data = 0, i = 0; i < 16; i++) {
-			phy_data <<= 1;
-			phy_data |= phy_read_1bit(ioaddr);
-		}
-	}
-
-	return phy_data;
-}
-
-/*
-   Write one bit data to Phy Controller
- */
-static void phy_write_1bit(unsigned long ioaddr, u32 phy_data)
-{
-	outl(phy_data, ioaddr);	/* MII Clock Low */
-	DELAY_1US;
-	outl(phy_data | MDCLKH, ioaddr);	/* MII Clock High */
-	DELAY_1US;
-	outl(phy_data, ioaddr);	/* MII Clock Low */
-	DELAY_1US;
-}
-
-/*
-   Read one bit phy data from PHY controller
- */
-static u16 phy_read_1bit(unsigned long ioaddr)
-{
-	u16 phy_data;
-
-	outl(0x50000, ioaddr);
-	DELAY_1US;
-	phy_data = (inl(ioaddr) >> 19) & 0x1;
-	outl(0x40000, ioaddr);
-	DELAY_1US;
-
-	return phy_data;
-}
-
-/*
-   Calculate the CRC valude of the Rx packet
-   flag = 1 : return the reverse CRC (for the received packet CRC)
-   0 : return the normal CRC (for Hash Table index)
- */
-unsigned long cal_CRC(unsigned char *Data, unsigned int Len, u8 flag)
-{
-	unsigned long Crc = 0xffffffff;
-
-	while (Len--) {
-		Crc = CrcTable[(Crc ^ *Data++) & 0xFF] ^ (Crc >> 8);
-	}
-
-	if (flag)
-		return ~Crc;
-	else
-		return Crc;
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");
-MODULE_DESCRIPTION("Davicom DM910X fast ethernet driver");
-MODULE_PARM(debug, "i");
-MODULE_PARM(mode, "i");
-MODULE_PARM(cr6set, "i");
-MODULE_PARM(chkmode, "i");
-
-/* Description: 
-   when user used insmod to add module, system invoked init_module()
-   to initilize and register.
- */
-int init_module(void)
-{
-	DMFE_DBUG(0, "init_module() ", debug);
-
-	if (debug)
-		dmfe_debug = debug;	/* set debug flag */
-	if (cr6set)
-		dmfe_cr6_user_set = cr6set;
-
-	switch (mode) {
-	case 0:
-	case 1:
-	case 4:
-	case 5:
-		dmfe_media_mode = mode;
-		break;
-	default:
-		dmfe_media_mode = 8;
-		break;
-	}
-
-	return dmfe_probe(0);	/* search board and register */
-}
-
-/* Description: 
-   when user used rmmod to delete module, system invoked clean_module()
-   to  un-register device.
- */
-void cleanup_module(void)
-{
-	struct device *next_dev;
-	struct dmfe_board_info *db;
-
-	DMFE_DBUG(0, "clean_module()", 0);
-
-	while (dmfe_root_dev) {
-		next_dev = ((struct dmfe_board_info *) dmfe_root_dev->priv)->next_dev;
-		unregister_netdev(dmfe_root_dev);
-		db = dmfe_root_dev->priv;
-		release_region(dmfe_root_dev->base_addr, CHK_IO_SIZE(db->chip_id, db->chip_revesion));
-		kfree(db);	/* free board information */
-		kfree(dmfe_root_dev);	/* free device structure */
-		dmfe_root_dev = next_dev;
-	}
-
-	DMFE_DBUG(0, "clean_module() exit", 0);
-}
-
-#endif				/* MODULE */
diff -urN linux-2.2.15-pre1/drivers/misc/parport_ax.c linux/drivers/misc/parport_ax.c
--- linux-2.2.15-pre1/drivers/misc/parport_ax.c	Mon Mar 15 16:11:30 1999
+++ linux/drivers/misc/parport_ax.c	Mon Dec  3 21:57:39 2001
@@ -1,4 +1,4 @@
-/* $Id: parport_ax.c,v 1.17 1999/01/20 06:18:54 davem Exp $
+/* $Id: parport_ax.c,v 1.17.2.1 2000/01/09 18:29:28 ecd Exp $
  * Parallel-port routines for Sun Ultra/AX architecture
  * 
  * Author: Eddie C. Dost <ecd@skynet.be>
@@ -30,13 +30,6 @@
 #include <asm/irq.h>
 
 
-/*
- * Define this if you have Devices which don't support short
- * host read/write cycles.
- */
-#undef HAVE_SLOW_DEVICES
-
-
 #define DATA		0x00
 #define STATUS		0x01
 #define CONTROL		0x02
@@ -513,7 +506,6 @@
 	struct parport tmpport, *p;
 	unsigned long base;
 	unsigned long config;
-	unsigned char tmp;
 	int irq, dma;
 
 	/* Pointer to NS87303 Configuration Registers */
@@ -523,29 +515,15 @@
 	tmpport.base = dev->base_address[0];
 	tmpport.ops = &parport_ax_ops;
 
+	/* Configure IRQ to Push Pull, Level Low */
 	/* Enable ECP mode, set bit 2 of the CTR first */
 	tmpport.ops->write_control(&tmpport, 0x04);
-	tmp = ns87303_readb(config, PCR);
-	tmp |= (PCR_EPP_IEEE | PCR_ECP_ENABLE | PCR_ECP_CLK_ENA);
-	ns87303_writeb(config, PCR, tmp);
+	ns87303_modify(config, PCR,
+		       PCR_EPP_ENABLE | PCR_IRQ_ODRAIN,
+		       PCR_ECP_ENABLE | PCR_ECP_CLK_ENA | PCR_IRQ_POLAR);
 
 	/* LPT CTR bit 5 controls direction of parallel port */
-	tmp = ns87303_readb(config, PTR);
-	tmp |= PTR_LPT_REG_DIR;
-	ns87303_writeb(config, PTR, tmp);
-
-	/* Configure IRQ to Push Pull, Level Low */
-	tmp = ns87303_readb(config, PCR);
-	tmp &= ~(PCR_IRQ_ODRAIN);
-	tmp |= PCR_IRQ_POLAR;
-	ns87303_writeb(config, PCR, tmp);
-
-#ifndef HAVE_SLOW_DEVICES
-	/* Enable Zero Wait State for ECP */
-	tmp = ns87303_readb(config, FCR);
-	tmp |= FCR_ZWS_ENA;
-	ns87303_writeb(config, FCR, tmp);
-#endif
+	ns87303_modify(config, PTR, 0, PTR_LPT_REG_DIR);
 
 	/*
 	 * Now continue initializing the port
diff -urN linux-2.2.15-pre1/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- linux-2.2.15-pre1/drivers/net/eepro100.c	Mon Dec  3 21:57:34 2001
+++ linux/drivers/net/eepro100.c	Mon Dec  3 21:57:39 2001
@@ -20,6 +20,11 @@
 		http://cesdis.gsfc.nasa.gov/linux/misc/modules.html
 	There is a Majordomo mailing list based at
 		linux-eepro100@cesdis.gsfc.nasa.gov
+	
+	This driver also contains updates by Andrey Savochkin and others.
+	For this specific driver variant please use linux-kernel for 
+	bug reports.
+
 */
 
 static const char *version =
diff -urN linux-2.2.15-pre1/drivers/net/epic100.c linux/drivers/net/epic100.c
--- linux-2.2.15-pre1/drivers/net/epic100.c	Thu Apr 29 11:53:41 1999
+++ linux/drivers/net/epic100.c	Mon Dec  3 21:57:39 2001
@@ -1,6 +1,6 @@
 /* epic100.c: A SMC 83c170 EPIC/100 Fast Ethernet driver for Linux. */
 /*
-	Written/copyright 1997-1998 by Donald Becker.
+	Written/copyright 1997-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
 	of the GNU Public License, incorporated herein by reference.
@@ -18,44 +18,46 @@
 */
 
 static const char *version =
-"epic100.c:v1.04 8/23/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
+"epic100.c:v1.07h 8/18/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
 
-/* A few user-configurable values. */
+/* User-tunable values. */
 
-/* Keep the ring sizes a power of two for efficiency.
-   Making the Tx ring too large decreases the effectiveness of channel
-   bonding and packet priority.
-   There are no ill effects from too-large receive rings. */
-#define TX_RING_SIZE	16
-#define RX_RING_SIZE	32
+static int debug = 1;
+#define epic_debug debug
+
+/* Used to pass the full-duplex flag, etc. */
+#define MAX_UNITS 8
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
 static int rx_copybreak = 200;
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 10;
+static int max_interrupt_work = 32;
 
 /* Operational parameters that usually are not changed. */
+/* Keep the ring sizes a power of two for efficiency.
+   Making the Tx ring too large decreases the effectiveness of channel
+   bonding and packet priority.
+   There are no ill effects from too-large receive rings. */
+#define TX_RING_SIZE	16
+#define RX_RING_SIZE	32
+
 /* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  ((2000*HZ)/1000)
+#define TX_TIMEOUT  (2*HZ)
 
 #define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
 
 /* Bytes transferred to chip before transmission starts. */
-#define TX_FIFO_THRESH 256		/* Rounded down to 4 byte units. */
+/* Initial threshold, increased on underflow, rounded down to 4 byte units. */
+#define TX_FIFO_THRESH 256
 #define RX_FIFO_THRESH 1		/* 0-3, 0==32, 64,96, or 3==128 bytes  */
 
+#include <linux/config.h>
 #include <linux/version.h>		/* Evil, but neccessary */
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
 
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -65,16 +67,12 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#if LINUX_VERSION_CODE >= 0x20155
-#define PCI_SUPPORT_VER2
-#else
-#include <linux/bios32.h>
-#endif
 #include <linux/delay.h>
 
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/spinlock.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -89,7 +87,6 @@
 
 #define RUN_AT(x) (jiffies + (x))
 
-#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115)
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
 MODULE_PARM(debug, "i");
@@ -97,26 +94,12 @@
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(max_interrupt_work, "i");
-#endif
-#if LINUX_VERSION_CODE < 0x20123
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define	net_device_stats enet_statistics
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else  /* Grrr, unneeded incompatible change. */
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#endif
+
+static char kernel_version[] = UTS_RELEASE;
 
 /* The I/O extent. */
 #define EPIC_TOTAL_SIZE 0x100
 
-#define epic_debug debug
-static int epic_debug = 1;
-
 /*
 				Theory of Operation
 
@@ -154,6 +137,12 @@
 static struct device *epic_probe1(int pci_bus, int pci_devfn,
 								  struct device *dev, long ioaddr, int irq,
 								  int chip_id, int card_idx);
+#ifdef USE_IO
+#define EPIC_USE_IO
+#define EPIC_IOTYPE PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR0
+#else
+#define EPIC_IOTYPE PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR1
+#endif
 
 enum pci_flags_bit {
 	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -166,14 +155,33 @@
 	int io_size, min_latency;
 	struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
 							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
-} chip_tbl[] = {
+} static chip_tbl[] = {
 	{"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff,
-	 PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
+	 EPIC_IOTYPE, EPIC_TOTAL_SIZE, 32, epic_probe1},
 	{"SMSC EPIC/C 83c175", 0x10B8, 0x0006, 0x7fff,
-	 PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
+	 EPIC_IOTYPE, EPIC_TOTAL_SIZE, 32, epic_probe1},
 	{0,},
 };
 
+/* This matches the table above. */
+static enum { MII_PWRDWN=1, TYPE2_INTR=2 } chip_features[] ={
+	TYPE2_INTR, TYPE2_INTR | MII_PWRDWN, };
+
+#ifndef USE_IO
+#undef inb
+#undef inw
+#undef inl
+#undef outb
+#undef outw
+#undef outl
+#define inb readb
+#define inw readw
+#define inl readl
+#define outb writeb
+#define outw writew
+#define outl writel
+#endif
+
 /* Offsets to registers, using the (ugh) SMC names. */
 enum epic_registers {
   COMMAND=0, INTSTAT=4, INTMASK=8, GENCTL=0x0C, NVCTL=0x10, EECTL=0x14,
@@ -188,13 +196,21 @@
 
 /* Interrupt register bits, using my own meaningful names. */
 enum IntrStatus {
-  TxIdle=0x40000, RxIdle=0x20000, IntrSummary=0x010000,
-  PCIBusErr170=0x7000, PCIBusErr175=0x1000, PhyEvent175=0x8000,
-  RxStarted=0x0800, RxEarlyWarn=0x0400, CntFull=0x0200, TxUnderrun=0x0100,
-  TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,
-  RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,
+	TxIdle=0x40000, RxIdle=0x20000, IntrSummary=0x010000,
+	PCIBusErr170=0x7000, PCIBusErr175=0x1000, PhyEvent175=0x8000,
+	RxStarted=0x0800, RxEarlyWarn=0x0400, CntFull=0x0200, TxUnderrun=0x0100,
+	TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,
+	RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,
+};
+enum CommandBits {
+	StopRx=1, StartRx=2, TxQueued=4, RxQueued=8,
+	StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80,
 };
 
+static u16 media2miictl[16] = {
+	0, 0x0C00, 0x0C00, 0x2000,  0x0100, 0x2100, 0, 0,
+	0, 0, 0, 0,  0, 0, 0, 0 };
+
 /* The EPIC100 Rx and Tx buffer descriptors. */
 
 struct epic_tx_desc {
@@ -228,16 +244,22 @@
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
 
 	/* Ring pointers. */
-	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
-	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
+	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;
+	struct descriptor  *last_rx_desc;
+	long last_rx_time;				/* Last Rx, in jiffies. */
 
 	u8 pci_bus, pci_dev_fn;				/* PCI bus location. */
-	u16 chip_id;
+	u16 chip_flags;
 
 	struct net_device_stats stats;
 	struct timer_list timer;			/* Media selection timer. */
+	int tx_threshold;
 	unsigned char mc_filter[8];
 	signed char phys[4];				/* MII device addresses. */
+	int mii_phy_cnt;
 	unsigned int tx_full:1;				/* The Tx queue is full. */
 	unsigned int full_duplex:1;			/* Current duplex setting. */
 	unsigned int force_fd:1;			/* Full-duplex operation requested. */
@@ -248,11 +270,6 @@
 	int pad0, pad1;						/* Used for 8-byte alignment */
 };
 
-/* Used to pass the full-duplex flag, etc. */
-#define MAX_UNITS 8
-static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-
 static int epic_open(struct device *dev);
 static int read_eeprom(long ioaddr, int location);
 static int mdio_read(long ioaddr, int phy_id, int location);
@@ -273,19 +290,19 @@
 /* A list of all installed EPIC devices, for removing the driver module. */
 static struct device *root_epic_dev = NULL;
 
-#ifndef CARDBUS
+#if !defined(CARDBUS)  && !defined(HAS_PCI_NETIF)
 int epic100_probe(struct device *dev)
 {
 	int cards_found = 0;
-	int chip_idx, irq;
+	int chip_idx, irq, pci_flags;
 	u16 pci_command, new_command;
 	unsigned char pci_bus, pci_device_fn;
+	long ioaddr;
 
-#ifdef PCI_SUPPORT_VER2
 	struct pci_dev *pcidev = NULL;
 	while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev))
 			!= NULL) {
-		long pci_ioaddr = pcidev->base_address[0] & ~3;
+		long pciaddr;
 		int vendor = pcidev->vendor;
 		int device = pcidev->device;
 
@@ -294,59 +311,33 @@
 				&& (device & chip_tbl[chip_idx].device_id_mask) ==
 				chip_tbl[chip_idx].device_id)
 				break;
-		if (chip_tbl[chip_idx].vendor_id == 0 		/* Compiled out! */
-			||	check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
+		if (chip_tbl[chip_idx].vendor_id == 0)		/* Compiled out! */
 			continue;
+
+		pci_flags = chip_tbl[chip_idx].pci_flags;
+		pciaddr = pcidev->base_address[pci_flags & PCI_ADDR0 ? 0 : 1];
 		pci_bus = pcidev->bus->number;
 		pci_device_fn = pcidev->devfn;
 		irq = pcidev->irq;
-#else
-	int pci_index;
-
-	if ( ! pcibios_present())
-		return -ENODEV;
-
-	for (pci_index = 0; pci_index < 0xff; pci_index++) {
-		u8 pci_irq_line;
-		u16 vendor, device;
-		u32 pci_ioaddr;
-
-		if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
-								pci_index, &pci_bus, &pci_device_fn)
-			!= PCIBIOS_SUCCESSFUL)
-			break;
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_VENDOR_ID, &vendor);
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_DEVICE_ID, &device);
-
-		for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
-			if (vendor == chip_tbl[chip_idx].vendor_id
-				&& (device & chip_tbl[chip_idx].device_id_mask) ==
-				chip_tbl[chip_idx].device_id)
-				break;
-		if (chip_tbl[chip_idx].vendor_id == 0) 		/* Compiled out! */
-			continue;
-
-		pcibios_read_config_dword(pci_bus, pci_device_fn,
-								  PCI_BASE_ADDRESS_0, &pci_ioaddr);
-		pcibios_read_config_byte(pci_bus, pci_device_fn,
-								 PCI_INTERRUPT_LINE, &pci_irq_line);
-		/* Remove I/O space marker in bit 0. */
-		pci_ioaddr &= ~3;
-		irq = pci_irq_line;
 
-		if (check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
+		if ((pciaddr & PCI_BASE_ADDRESS_SPACE_IO)) {
+			ioaddr = pciaddr & PCI_BASE_ADDRESS_IO_MASK;
+			if (check_region(ioaddr, chip_tbl[chip_idx].io_size))
+				continue;
+		} else if ((ioaddr = (long)ioremap(pciaddr & PCI_BASE_ADDRESS_MEM_MASK,
+										   chip_tbl[chip_idx].io_size)) == 0) {
+			printk(KERN_INFO "Failed to map PCI address %#x.\n",
+				   (int)pciaddr);
 			continue;
-#endif
+		}
 
 		/* EPIC-specific code: Soft-reset the chip ere setting as master. */
-		outl(0x0001, pci_ioaddr + GENCTL);
+		outl(0x0001, ioaddr + GENCTL);
 
 		/* Activate the card: fix for brain-damaged Win98 BIOSes. */
 		pcibios_read_config_word(pci_bus, pci_device_fn,
 								 PCI_COMMAND, &pci_command);
-		new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+		new_command = pci_command | (pci_flags & 7);
 		if (pci_command != new_command) {
 			printk(KERN_INFO "  The PCI BIOS has not enabled Ethernet"
 				   " device %4.4x-%4.4x."
@@ -356,9 +347,8 @@
 									  PCI_COMMAND, new_command);
 		}
 
-		dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, pci_ioaddr,
-									   irq, chip_idx, cards_found);
-
+		dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr,
+										irq, chip_idx, cards_found);
 		/* Check the latency timer. */
 		if (dev) {
 			u8 pci_latency;
@@ -402,9 +392,12 @@
 
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
-	printk(KERN_INFO "%s: SMC EPIC/100 at %#lx, IRQ %d, ",
-		   dev->name, ioaddr, dev->irq);
+	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
+		   dev->name, chip_tbl[chip_idx].name, ioaddr, dev->irq);
 
+#if defined(HAS_PCI_NETIF)
+	acpi_set_pwr_state(pci_bus, pci_devfn, ACPI_D0);
+#endif
 	/* Bring the chip out of low-power mode. */
 	outl(0x4200, ioaddr + GENCTL);
 	/* Magic?!  If we don't set this bit the MII interface won't work. */
@@ -418,13 +411,13 @@
 
 	/* This could also be read from the EEPROM. */
 	for (i = 0; i < 3; i++)
-		((u16 *)dev->dev_addr)[i] = inw(ioaddr + LAN0 + i*4);
+		((u16 *)dev->dev_addr)[i] = le16_to_cpu(inw(ioaddr + LAN0 + i*4));
 
 	for (i = 0; i < 5; i++)
 		printk("%2.2x:", dev->dev_addr[i]);
 	printk("%2.2x.\n", dev->dev_addr[i]);
 
-	if (epic_debug > 1) {
+	if (epic_debug > 2) {
 		printk(KERN_DEBUG "%s: EEPROM contents\n", dev->name);
 		for (i = 0; i < 64; i++)
 			printk(" %4.4x%s", read_eeprom(ioaddr, i),
@@ -444,11 +437,7 @@
 
 	ep->pci_bus = pci_bus;
 	ep->pci_dev_fn = pci_devfn;
-#if defined(PCI_SUPPORT_VER2)
-	ep->chip_id = pci_find_slot(pci_bus, pci_devfn)->device;
-#else
-	ep->chip_id = chip_tbl[chip_idx].device_id;
-#endif
+	ep->chip_flags = chip_features[chip_idx];
 
 	/* Find the connected MII xcvrs.
 	   Doing this in open() would allow detecting external xcvrs later, but
@@ -469,6 +458,7 @@
 					   mdio_read(ioaddr, phy, 5));
 			}
 		}
+		ep->mii_phy_cnt = phy_idx;
 		if (phy_idx == 0) {
 			printk(KERN_WARNING "%s: ***WARNING***: No MII transceiver found!\n",
 				   dev->name);
@@ -478,13 +468,13 @@
 	}
 
 	/* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
-	if (ep->chip_id == 6)
+	if (ep->chip_flags & MII_PWRDWN)
 		outl(inl(ioaddr + NVCTL) & ~0x483C, ioaddr + NVCTL);
 	outl(0x0008, ioaddr + GENCTL);
 
 	/* The lower four bits are the media type. */
 	ep->force_fd = duplex;
-	ep->default_port = option;
+	dev->if_port = ep->default_port = option;
 	if (ep->default_port)
 		ep->medialock = 1;
 
@@ -514,11 +504,7 @@
    No extra delay is needed with 33Mhz PCI, but 66Mhz is untested.
  */
 
-#ifdef _LINUX_DELAY_H
-#define eeprom_delay(nanosec)	udelay(1)
-#else
-#define eeprom_delay(nanosec)	do { ; } while (0)
-#endif
+#define eeprom_delay()	inl(ee_addr)
 
 /* The EEPROM commands include the alway-set leading bit. */
 #define EE_WRITE_CMD	(5 << 6)
@@ -532,7 +518,7 @@
 	int retval = 0;
 	long ee_addr = ioaddr + EECTL;
 	int read_cmd = location |
-		(inl(ee_addr) & 0x40) ? EE_READ64_CMD : EE_READ256_CMD;
+		(inl(ee_addr) & 0x40 ? EE_READ64_CMD : EE_READ256_CMD);
 
 	outl(EE_ENB & ~EE_CS, ee_addr);
 	outl(EE_ENB, ee_addr);
@@ -541,18 +527,18 @@
 	for (i = 12; i >= 0; i--) {
 		short dataval = (read_cmd & (1 << i)) ? EE_WRITE_1 : EE_WRITE_0;
 		outl(EE_ENB | dataval, ee_addr);
-		eeprom_delay(100);
+		eeprom_delay();
 		outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay(150);
+		eeprom_delay();
 	}
 	outl(EE_ENB, ee_addr);
 
 	for (i = 16; i > 0; i--) {
 		outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay(100);
+		eeprom_delay();
 		retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
 		outl(EE_ENB, ee_addr);
-		eeprom_delay(100);
+		eeprom_delay();
 	}
 
 	/* Terminate the EEPROM access. */
@@ -594,13 +580,13 @@
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int i;
-	int mii_reg5;
+
 	ep->full_duplex = ep->force_fd;
 
 	/* Soft reset the chip. */
 	outl(0x4001, ioaddr + GENCTL);
 
-	if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, "SMC EPIC/100", dev))
+	if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, dev->name, dev))
 		return -EAGAIN;
 
 	MOD_INC_USE_COUNT;
@@ -617,30 +603,49 @@
 	   wiring on the Ositech CardBus card.
 	*/
 	outl(0x12, ioaddr + MIICfg);
-	if (ep->chip_id == 6)
+	if (ep->chip_flags & MII_PWRDWN)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
 #if defined(__powerpc__) || defined(__sparc__)		/* Big endian */
+	outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+	inl(ioaddr + GENCTL);
 	outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
 #else
+	outl(0x4412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+	inl(ioaddr + GENCTL);
 	outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
 #endif
 
 	for (i = 0; i < 3; i++)
-		outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
+		outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
 
-	outl(TX_FIFO_THRESH, ioaddr + TxThresh);
+	
+	ep->tx_threshold = TX_FIFO_THRESH;
+	outl(ep->tx_threshold, ioaddr + TxThresh);
 
-	mii_reg5 = mdio_read(ioaddr, 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(ioaddr, ep->phys[0], 0, 0x1200);
-		if (epic_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);
+	if (media2miictl[dev->if_port & 15]) {
+		if (ep->mii_phy_cnt)
+			mdio_write(ioaddr, ep->phys[0], 0, media2miictl[dev->if_port&15]);
+		if (dev->if_port == 1) {
+			if (epic_debug > 1)
+				printk(KERN_INFO "%s: Using the 10base2 transceiver, MII "
+					   "status %4.4x.\n",
+					   dev->name, mdio_read(ioaddr, ep->phys[0], 1));
+			outl(0x13, ioaddr + MIICfg);
+		}
+	} else {
+		int mii_reg5 = mdio_read(ioaddr, 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(ioaddr, ep->phys[0], 0, 0x1200);
+			if (epic_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);
+		}
 	}
 
 	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
@@ -649,15 +654,15 @@
 
 	/* Start the chip's Rx process. */
 	set_rx_mode(dev);
-	outl(0x000A, ioaddr + COMMAND);
+	outl(StartRx | RxQueued, ioaddr + COMMAND);
 
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
 
 	/* Enable interrupts by setting the interrupt mask. */
-	outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun | TxDone
+	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
+		 | CntFull | TxUnderrun | TxDone | TxEmpty
 		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
 		 ioaddr + INTMASK);
 
@@ -688,7 +693,7 @@
 	/* Disable interrupts by clearing the interrupt mask. */
 	outl(0x00000000, ioaddr + INTMASK);
 	/* Stop the chip's Tx and Rx DMA processes. */
-	outw(0x0061, ioaddr + COMMAND);
+	outw(StopRx | StopTxDMA | StopRxDMA, ioaddr + COMMAND);
 
 	/* Update the error counts. */
 	if (inw(ioaddr + COMMAND) != 0xffff) {
@@ -716,19 +721,20 @@
 	/* Duplicate code from epic_open(). */
 	outl(0x0008, ioaddr + TEST1);
 
-#if defined(__powerpc__)		/* Big endian */
+#if defined(__powerpc__) || defined(__sparc__)		/* Big endian */
 	outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
 #else
 	outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
 #endif
-	outl(0x12, ioaddr + MIICfg);
-	if (ep->chip_id == 6)
+	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
+	if (ep->chip_flags & MII_PWRDWN)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
 	for (i = 0; i < 3; i++)
-		outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
+		outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
 
-	outl(TX_FIFO_THRESH, ioaddr + TxThresh);
+	ep->tx_threshold = TX_FIFO_THRESH;
+	outl(ep->tx_threshold, ioaddr + TxThresh);
 	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	outl(virt_to_bus(&ep->rx_ring[ep->cur_rx%RX_RING_SIZE]), ioaddr + PRxCDAR);
 	outl(virt_to_bus(&ep->tx_ring[ep->dirty_tx%TX_RING_SIZE]),
@@ -736,11 +742,11 @@
 
 	/* Start the chip's Rx process. */
 	set_rx_mode(dev);
-	outl(0x000A, ioaddr + COMMAND);
+	outl(StartRx | RxQueued, ioaddr + COMMAND);
 
 	/* Enable interrupts by setting the interrupt mask. */
-	outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun | TxDone
+	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
+		 | CntFull | TxUnderrun | TxDone | TxEmpty
 		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
 		 ioaddr + INTMASK);
 	printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
@@ -755,17 +761,25 @@
 	struct device *dev = (struct device *)data;
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	long ioaddr = dev->base_addr;
-	int next_tick = 0;
-	int mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5);
+	int next_tick = 60*HZ;
+	int mii_reg5 = ep->mii_phy_cnt ? mdio_read(ioaddr, ep->phys[0], 5) : 0;
 
 	if (epic_debug > 3) {
-		printk(KERN_DEBUG "%s: Media selection tick, Tx status %8.8x.\n",
+		printk(KERN_DEBUG "%s: Media monitor tick, Tx status %8.8x.\n",
 			   dev->name, inl(ioaddr + TxSTAT));
 		printk(KERN_DEBUG "%s: Other registers are IntMask %4.4x "
 			   "IntStatus %4.4x RxStatus %4.4x.\n",
 			   dev->name, inl(ioaddr + INTMASK), inl(ioaddr + INTSTAT),
 			   inl(ioaddr + RxSTAT));
 	}
+
+	if (ep->cur_tx - ep->dirty_tx > TX_RING_SIZE/2  &&
+		jiffies - dev->trans_start > TX_TIMEOUT) {
+		printk(KERN_WARNING "%s: Tx hung, %d vs. %d.\n",
+			   dev->name, ep->cur_tx, ep->dirty_tx);
+		epic_tx_timeout(dev);
+	}
+
 	if (! ep->force_fd  &&  mii_reg5 != 0xffff) {
 		int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
 		if (ep->full_duplex != duplex) {
@@ -775,13 +789,10 @@
 				   ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
 			outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 		}
-		next_tick = 60*HZ;
 	}
 
-	if (next_tick) {
-		ep->timer.expires = RUN_AT(next_tick);
-		add_timer(&ep->timer);
-	}
+	ep->timer.expires = RUN_AT(next_tick);
+	add_timer(&ep->timer);
 }
 
 static void epic_tx_timeout(struct device *dev)
@@ -795,19 +806,17 @@
 			   dev->name, inw(ioaddr + TxSTAT));
 		if (epic_debug > 1) {
 			printk(KERN_DEBUG "%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
-			 dev->name, ep->dirty_tx, ep->cur_tx);
+				   dev->name, ep->dirty_tx, ep->cur_tx);
 		}
 	}
 	if (inw(ioaddr + TxSTAT) & 0x10) {		/* Tx FIFO underflow. */
 		ep->stats.tx_fifo_errors++;
-		/* Restart the transmit process. */
-		outl(0x0080, ioaddr + COMMAND);
+		outl(RestartTx, ioaddr + COMMAND);
+	} else {
+		epic_restart(dev);
+		outl(TxQueued, dev->base_addr + COMMAND);
 	}
 
-	/* Perhaps stop and restart the chip's Tx processes . */
-	/* Trigger a transmit demand. */
-	outl(0x0004, dev->base_addr + COMMAND);
-
 	dev->trans_start = jiffies;
 	ep->stats.tx_errors++;
 	return;
@@ -821,8 +830,10 @@
 	int i;
 
 	ep->tx_full = 0;
-	ep->cur_rx = ep->cur_tx = 0;
-	ep->dirty_rx = ep->dirty_tx = 0;
+	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;
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		ep->rx_ring[i].status = 0x8000;		/* Owned by Epic chip */
@@ -859,15 +870,15 @@
 epic_start_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct epic_private *ep = (struct epic_private *)dev->priv;
-	int entry;
-	u32 flag;
+	int entry, free_count;
+	u32 ctrl_word;
+	long flags;
 
 	/* Block a timer-based transmit from overlapping.  This could better be
 	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start < TX_TIMEOUT)
-			return 1;
-		epic_tx_timeout(dev);
+		if (jiffies - dev->trans_start > TX_TIMEOUT)
+			epic_tx_timeout(dev);
 		return 1;
 	}
 
@@ -875,42 +886,41 @@
 	   with the "ownership" bits last. */
 
 	/* Calculate the next Tx descriptor entry. */
-	entry = ep->cur_tx % TX_RING_SIZE;
+	spin_lock_irqsave(&ep->lock, flags);
+	free_count = ep->cur_tx - ep->dirty_tx;
+	entry = ep->cur_tx++ % TX_RING_SIZE;
 
 	ep->tx_skbuff[entry] = skb;
 	ep->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
 	ep->tx_ring[entry].bufaddr = virt_to_bus(skb->data);
 	ep->tx_ring[entry].buflength = skb->len;
 
-	/* tx_bytes counting -- Nolan Leake */	
-	ep->stats.tx_bytes += ep->tx_ring[entry].txlength;
-	
-	if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
-	  flag = 0x10; /* No interrupt */
-	  clear_bit(0, (void*)&dev->tbusy);
-	} else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) {
-	  flag = 0x14; /* Tx-done intr. */
-	  clear_bit(0, (void*)&dev->tbusy);
-	} else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) {
-	  flag = 0x10; /* No Tx-done intr. */
-	  clear_bit(0, (void*)&dev->tbusy);
+	if (free_count < TX_RING_SIZE/2) {/* Typical path */
+		ctrl_word = 0x10; /* No interrupt */
+	} else if (free_count == TX_RING_SIZE/2) {
+		ctrl_word = 0x14; /* Tx-done intr. */
+	} else if (free_count < TX_RING_SIZE - 1) {
+		ctrl_word = 0x10; /* No Tx-done intr. */
 	} else {
-	  /* Leave room for two additional entries. */
-	  flag = 0x14; /* Tx-done intr. */
-	  ep->tx_full = 1;
+		/* Leave room for an additional entry. */
+		ctrl_word = 0x14; /* Tx-done intr. */
+		ep->tx_full = 1;
 	}
 
-	ep->tx_ring[entry].control = flag;
+	ep->tx_ring[entry].control = ctrl_word;
 	ep->tx_ring[entry].status = 0x8000;	/* Pass ownership to the chip. */
-	ep->cur_tx++;
+
+	if ( ! ep->tx_full)
+		clear_bit(0, (void*)&dev->tbusy);
+	spin_unlock_irqrestore(&ep->lock, flags);
 	/* Trigger an immediate transmit demand. */
-	outl(0x0004, dev->base_addr + COMMAND);
+	outl(TxQueued, dev->base_addr + COMMAND);
 
 	dev->trans_start = jiffies;
 	if (epic_debug > 4)
 		printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, "
 			   "flag %2.2x Tx status %8.8x.\n",
-			   dev->name, (int)skb->len, entry, flag,
+			   dev->name, (int)skb->len, entry, ctrl_word,
 			   inl(dev->base_addr + TxSTAT));
 
 	return 0;
@@ -947,19 +957,26 @@
 		outl(status & 0x00007fff, ioaddr + INTSTAT);
 
 		if (epic_debug > 4)
-			printk("%s: interrupt  interrupt=%#8.8x new intstat=%#8.8x.\n",
+			printk(KERN_DEBUG "%s: interrupt  interrupt=%#8.8x new "
+				   "intstat=%#8.8x.\n",
 				   dev->name, status, inl(ioaddr + INTSTAT));
 
 		if ((status & IntrSummary) == 0)
 			break;
 
-		if (status & (RxDone | RxStarted | RxEarlyWarn))
+		if (status & (RxDone | RxStarted | RxEarlyWarn | RxOverflow))
 			epic_rx(dev);
 
 		if (status & (TxEmpty | TxDone)) {
-			int dirty_tx;
+			unsigned int dirty_tx, cur_tx;
 
-			for (dirty_tx = ep->dirty_tx; dirty_tx < ep->cur_tx; dirty_tx++) {
+			/* Note: if this lock becomes a problem we can narrow the locked
+			   region at the cost of occasionally grabbing the lock more
+			   times. */
+			spin_lock(&ep->lock);
+			cur_tx = ep->cur_tx;
+			dirty_tx = ep->dirty_tx;
+			for (; cur_tx - dirty_tx > 0; dirty_tx++) {
 				int entry = dirty_tx % TX_RING_SIZE;
 				int txstatus = ep->tx_ring[entry].status;
 
@@ -987,34 +1004,35 @@
 #endif
 					ep->stats.collisions += (txstatus >> 8) & 15;
 					ep->stats.tx_packets++;
+					ep->stats.tx_bytes += ep->tx_ring[entry].txlength;
 				}
 
 				/* Free the original skb. */
-				DEV_FREE_SKB(ep->tx_skbuff[entry]);
+				dev_kfree_skb(ep->tx_skbuff[entry]);
 				ep->tx_skbuff[entry] = 0;
 			}
 
 #ifndef final_version
-			if (ep->cur_tx - dirty_tx > TX_RING_SIZE) {
+			if (cur_tx - dirty_tx > TX_RING_SIZE) {
 				printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
-					   dev->name, dirty_tx, ep->cur_tx, ep->tx_full);
+					   dev->name, dirty_tx, cur_tx, ep->tx_full);
 				dirty_tx += TX_RING_SIZE;
 			}
 #endif
-
-			if (ep->tx_full && dev->tbusy
-				&& dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) {
+			ep->dirty_tx = dirty_tx;
+			if (ep->tx_full
+				&& cur_tx - dirty_tx < TX_RING_SIZE + 2) {
 				/* The ring is no longer full, clear tbusy. */
 				ep->tx_full = 0;
 				clear_bit(0, (void*)&dev->tbusy);
+				spin_unlock(&ep->lock);
 				mark_bh(NET_BH);
-			}
-
-			ep->dirty_tx = dirty_tx;
+			} else
+				spin_unlock(&ep->lock);
 		}
 
 		/* Check uncommon events all at once. */
-		if (status & (CntFull | TxUnderrun | RxOverflow |
+		if (status & (CntFull | TxUnderrun | RxOverflow | RxFull |
 					  PCIBusErr170 | PCIBusErr175)) {
 			if (status == 0xffffffff) /* Chip failed or removed (CardBus). */
 				break;
@@ -1025,13 +1043,15 @@
 
 			if (status & TxUnderrun) { /* Tx FIFO underflow. */
 				ep->stats.tx_fifo_errors++;
-				outl(1536, ioaddr + TxThresh);
+				outl(ep->tx_threshold += 128, ioaddr + TxThresh);
 				/* Restart the transmit process. */
-				outl(0x0080, ioaddr + COMMAND);
+				outl(RestartTx, ioaddr + COMMAND);
 			}
 			if (status & RxOverflow) {		/* Missed a Rx frame. */
 				ep->stats.rx_errors++;
 			}
+			if (status & (RxOverflow | RxFull))
+				outw(RxQueued, ioaddr + COMMAND);
 			if (status & PCIBusErr170) {
 				printk(KERN_ERR "%s: PCI Bus Error!  EPIC status %4.4x.\n",
 					   dev->name, status);
@@ -1067,17 +1087,20 @@
 {
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	int entry = ep->cur_rx % RX_RING_SIZE;
+	int rx_work_limit = ep->dirty_rx + RX_RING_SIZE - ep->cur_rx;
 	int work_done = 0;
 
 	if (epic_debug > 4)
 		printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry,
 			   ep->rx_ring[entry].status);
 	/* If we own the next entry, it's a new packet. Send it up. */
-	while (ep->rx_ring[entry].status >= 0  &&  ep->rx_skbuff[entry]) {
+	while (ep->rx_ring[entry].status >= 0) {
 		int status = ep->rx_ring[entry].status;
 
 		if (epic_debug > 4)
 			printk(KERN_DEBUG "  epic_rx() status was %8.8x.\n", status);
+		if (--rx_work_limit < 0)
+			break;
 		if (status & 0x2006) {
 			if (status & 0x2000) {
 				printk(KERN_WARNING "%s: Oversized Ethernet frame spanned "
@@ -1092,6 +1115,12 @@
 			short pkt_len = ep->rx_ring[entry].rxlength - 4;
 			struct sk_buff *skb;
 
+			if (pkt_len > PKT_BUF_SZ - 4) {
+				printk(KERN_ERR "%s: Oversized Ethernet frame, status %x "
+					   "%d bytes.\n",
+					   dev->name, pkt_len, status);
+				pkt_len = 1514;
+			}
 			/* Check if the packet is long enough to accept without copying
 			   to a minimally-sized skbuff. */
 			if (pkt_len < rx_copybreak
@@ -1106,7 +1135,6 @@
 				memcpy(skb_put(skb, pkt_len),
 					   bus_to_virt(ep->rx_ring[entry].bufaddr), pkt_len);
 #endif
-				ep->rx_ring[entry].status = 0x8000;
 			} else {
 				skb_put(skb = ep->rx_skbuff[entry], pkt_len);
 				ep->rx_skbuff[entry] = NULL;
@@ -1114,8 +1142,9 @@
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
 			ep->stats.rx_packets++;
-			/* rx_bytes counting -- Nolan Leake */
+#if LINUX_VERSION_CODE > 0x20127
 			ep->stats.rx_bytes += pkt_len;
+#endif
 		}
 		work_done++;
 		entry = (++ep->cur_rx) % RX_RING_SIZE;
@@ -1152,18 +1181,8 @@
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
 			   dev->name, inl(ioaddr + INTSTAT));
 
-	/* Disable interrupts by clearing the interrupt mask. */
-	outl(0x00000000, ioaddr + INTMASK);
-	/* Stop the chip's Tx and Rx DMA processes. */
-	outw(0x0061, ioaddr + COMMAND);
-
-	/* Update the error counts. */
-	ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
-	ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
-	ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
-
+	epic_pause(dev);
 	del_timer(&ep->timer);
-
 	free_irq(dev->irq, dev);
 
 	/* Free all the skbuffs in the Rx queue. */
@@ -1177,21 +1196,19 @@
 #if LINUX_VERSION_CODE < 0x20100
 			skb->free = 1;
 #endif
-			DEV_FREE_SKB(skb);
+			dev_kfree_skb(skb);
 		}
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		if (ep->tx_skbuff[i])
-			DEV_FREE_SKB(ep->tx_skbuff[i]);
+			dev_kfree_skb(ep->tx_skbuff[i]);
 		ep->tx_skbuff[i] = 0;
 	}
 
-
 	/* Green! Leave the chip in low-power mode. */
 	outl(0x0008, ioaddr + GENCTL);
 
 	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
@@ -1292,14 +1309,14 @@
 		}
 		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
 		if (! dev->start) {
-#ifdef notdef
+#ifdef notdef					/* Leave on if the ioctl() is used. */
 			outl(0x0008, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
 #endif
 		}
 		return 0;
 	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
-		if (!suser())
+		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		if (! dev->start) {
 			outl(0x0200, ioaddr + GENCTL);
@@ -1307,7 +1324,7 @@
 		}
 		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
 		if (! dev->start) {
-#ifdef notdef
+#ifdef notdef					/* Leave on if the ioctl() is used. */
 			outl(0x0008, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
 #endif
@@ -1319,122 +1336,29 @@
 }
 
 
-#ifdef CARDBUS
-
-#include <pcmcia/driver_ops.h>
-
-static dev_node_t *epic_attach(dev_locator_t *loc)
-{
-	struct device *dev;
-	u16 dev_id;
-	u32 io;
-	u8 bus, devfn, irq;
-
-	if (loc->bus != LOC_PCI) return NULL;
-	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
-	printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn);
-	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
-	pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
-	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
-	io &= ~3;
-	if (io == 0 || irq == 0) {
-		printk(KERN_ERR "The EPIC/C CardBus Ethernet interface was not "
-			   "assigned an %s.\n" KERN_ERR "  It will not be activated.\n",
-			   io == 0 ? "I/O address" : "IRQ");
-		return NULL;
-	}
-	dev = epic_probe1(bus, devfn, NULL, io, irq, 2, -1);
-	if (dev) {
-		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
-		strcpy(node->dev_name, dev->name);
-		node->major = node->minor = 0;
-		node->next = NULL;
-		MOD_INC_USE_COUNT;
-		return node;
-	}
-	return NULL;
-}
-
-static void epic_suspend(dev_node_t *node)
-{
-	struct device **devp, **next;
-	printk(KERN_INFO "epic_suspend(%s)\n", node->dev_name);
-	for (devp = &root_epic_dev; *devp; devp = next) {
-		next = &((struct epic_private *)(*devp)->priv)->next_module;
-		if (strcmp((*devp)->name, node->dev_name) == 0) break;
-	}
-	if (*devp) {
-		long ioaddr = (*devp)->base_addr;
-		epic_pause(*devp);
-		/* Put the chip into low-power mode. */
-		outl(0x0008, ioaddr + GENCTL);
-	}
-}
-static void epic_resume(dev_node_t *node)
-{
-	struct device **devp, **next;
-	printk(KERN_INFO "epic_resume(%s)\n", node->dev_name);
-	for (devp = &root_epic_dev; *devp; devp = next) {
-		next = &((struct epic_private *)(*devp)->priv)->next_module;
-		if (strcmp((*devp)->name, node->dev_name) == 0) break;
-	}
-	if (*devp) {
-		epic_restart(*devp);
-	}
-}
-static void epic_detach(dev_node_t *node)
-{
-	struct device **devp, **next;
-	printk(KERN_INFO "epic_detach(%s)\n", node->dev_name);
-	for (devp = &root_epic_dev; *devp; devp = next) {
-		next = &((struct epic_private *)(*devp)->priv)->next_module;
-		if (strcmp((*devp)->name, node->dev_name) == 0) break;
-	}
-	if (*devp) {
-		unregister_netdev(*devp);
-		kfree(*devp);
-		*devp = *next;
-		kfree(node);
-		MOD_DEC_USE_COUNT;
-	}
-}
-
-struct driver_operations epic_ops = {
-	"epic_cb", epic_attach, epic_suspend, epic_resume, epic_detach
-};
-
-#endif  /* Cardbus support */
-
-
 #ifdef MODULE
 
 int init_module(void)
 {
 	if (epic_debug)
 		printk(KERN_INFO "%s", version);
-
-#ifdef CARDBUS
-	register_driver(&epic_ops);
-	return 0;
-#else
 	return epic100_probe(0);
-#endif
 }
 
 void cleanup_module(void)
 {
 	struct device *next_dev;
 
-#ifdef CARDBUS
-	unregister_driver(&epic_ops);
-#endif
-
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_epic_dev) {
 		struct epic_private *ep = (struct epic_private *)root_epic_dev->priv;
 		next_dev = ep->next_module;
 		unregister_netdev(root_epic_dev);
+#ifdef EPIC_USE_IO
 		release_region(root_epic_dev->base_addr, EPIC_TOTAL_SIZE);
+#else
+		iounmap((char *)root_epic_dev->base_addr);
+#endif
 		kfree(root_epic_dev);
 		root_epic_dev = next_dev;
 		kfree(ep);
@@ -1446,7 +1370,7 @@
 /*
  * Local variables:
  *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- *  cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c -o epic_cb.o -I/usr/src/pcmcia-cs-3.0.5/include/"
+ *  cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c -o epic_cb.o -I/usr/src/pcmcia-cs-3.0.13/include/"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4
diff -urN linux-2.2.15-pre1/drivers/net/plip.c linux/drivers/net/plip.c
--- linux-2.2.15-pre1/drivers/net/plip.c	Tue Jan  4 10:12:17 2000
+++ linux/drivers/net/plip.c	Mon Dec  3 21:57:39 2001
@@ -507,6 +507,61 @@
 	return OK;
 }
 
+/*
+ *	Determine the packet's protocol ID. The rule here is that we 
+ *	assume 802.3 if the type field is short enough to be a length.
+ *	This is normal practice and works for any 'now in use' protocol.
+ *
+ *	PLIP is ethernet ish but the daddr might not be valid if unicast.
+ *	PLIP fortunately has no bus architecture (its Point-to-point).
+ *
+ *	We can't fix the daddr thing as that quirk (more bug) is embedded
+ *	in far too many old systems not all even running Linux.
+ */
+ 
+static unsigned short plip_type_trans(struct sk_buff *skb, struct device *dev)
+{
+	struct ethhdr *eth;
+	unsigned char *rawp;
+	
+	skb->mac.raw=skb->data;
+	skb_pull(skb,dev->hard_header_len);
+	eth= skb->mac.ethernet;
+	
+	if(*eth->h_dest&1)
+	{
+		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
+			skb->pkt_type=PACKET_BROADCAST;
+		else
+			skb->pkt_type=PACKET_MULTICAST;
+	}
+	
+	/*
+	 *	This ALLMULTI check should be redundant by 1.4
+	 *	so don't forget to remove it.
+	 */
+	 
+	if (ntohs(eth->h_proto) >= 1536)
+		return eth->h_proto;
+		
+	rawp = skb->data;
+	
+	/*
+	 *	This is a magic hack to spot IPX packets. Older Novell breaks
+	 *	the protocol design and runs IPX over 802.3 without an 802.2 LLC
+	 *	layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
+	 *	won't work for fault tolerant netware but does for the rest.
+	 */
+	if (*(unsigned short *)rawp == 0xFFFF)
+		return htons(ETH_P_802_3);
+		
+	/*
+	 *	Real 802.2 LLC
+	 */
+	return htons(ETH_P_802_2);
+}
+
+
 /* PLIP_RECEIVE_PACKET --- receive a packet */
 static int
 plip_receive_packet(struct device *dev, struct net_local *nl,
@@ -595,7 +650,7 @@
 
 	case PLIP_PK_DONE:
 		/* Inform the upper layer for the arrival of a packet. */
-		rcv->skb->protocol=eth_type_trans(rcv->skb, dev);
+		rcv->skb->protocol=plip_type_trans(rcv->skb, dev);
 		netif_rx(rcv->skb);
 		nl->enet_stats.rx_bytes += rcv->length.h;
 		nl->enet_stats.rx_packets++;
diff -urN linux-2.2.15-pre1/drivers/net/tulip.c linux/drivers/net/tulip.c
--- linux-2.2.15-pre1/drivers/net/tulip.c	Tue Jan  4 10:12:18 2000
+++ linux/drivers/net/tulip.c	Mon Dec  3 21:57:39 2001
@@ -15,6 +15,10 @@
 
 	Support and updates available at
 	http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
+	
+	This driver also contains updates by Wolfgang Walter and others.
+	For this specific driver variant please use linux-kernel for 
+	bug reports.
 */
 
 #define SMP_CHECK
diff -urN linux-2.2.15-pre1/drivers/sbus/audio/dbri.c linux/drivers/sbus/audio/dbri.c
--- linux-2.2.15-pre1/drivers/sbus/audio/dbri.c	Tue Jan  4 10:12:18 2000
+++ linux/drivers/sbus/audio/dbri.c	Mon Dec  3 21:57:39 2001
@@ -17,6 +17,7 @@
  *   - Data sheet of the T7903, a newer but very similar ISA bus equivalent
  *     available from the Lucent (formarly AT&T microelectronics) home
  *     page.
+ *   - http://www.freesoft.org/Linux/DBRI (PDF data sheet)
  * - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec
  *   Interfaces: CHI, Audio In & Out, 2 bits parallel
  *   Documentation: from the Crystal Semiconductor home page.
diff -urN linux-2.2.15-pre1/drivers/scsi/esp.c linux/drivers/scsi/esp.c
--- linux-2.2.15-pre1/drivers/scsi/esp.c	Tue Jan  4 10:12:20 2000
+++ linux/drivers/scsi/esp.c	Mon Dec  3 21:57:39 2001
@@ -39,6 +39,8 @@
 #include <asm/idprom.h>
 #include <asm/spinlock.h>
 
+#include <linux/module.h>
+
 #define DEBUG_ESP
 /* #define DEBUG_ESP_HME */
 /* #define DEBUG_ESP_DATA */
@@ -4313,3 +4315,11 @@
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 #endif
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = SCSI_SPARC_ESP;
+
+#include "scsi_module.c"
+
+EXPORT_NO_SYMBOLS;
+#endif /* MODULE */
diff -urN linux-2.2.15-pre1/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- linux-2.2.15-pre1/drivers/video/atyfb.c	Tue Jan  4 10:12:22 2000
+++ linux/drivers/video/atyfb.c	Mon Dec  3 21:57:39 2001
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.106.2.6 1999/10/14 08:44:47 davem Exp $
+/*  $Id: atyfb.c,v 1.106.2.7 1999/11/19 00:12:29 davem Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *	Copyright (C) 1997-1998  Geert Uytterhoeven
diff -urN linux-2.2.15-pre1/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
--- linux-2.2.15-pre1/fs/nfsd/nfsfh.c	Mon Dec  3 21:57:34 2001
+++ linux/fs/nfsd/nfsfh.c	Mon Dec  3 21:57:39 2001
@@ -861,12 +861,12 @@
 	dirent.ino = ino;
 	error = get_parent_ino(parent, &dirent);
 	if (error) {
-#ifdef NFSD_PARANOIA
+#ifdef NFSD_PARANOIA_EXTREME
 printk("lookup_by_inode: ino %ld not found in %s\n", ino, parent->d_name.name);
 #endif
 		goto no_entry;
 	}
-#ifdef NFSD_PARANOIA
+#ifdef NFSD_PARANOIA_EXTREME
 printk("lookup_by_inode: found %s\n", dirent.name);
 #endif
 
@@ -874,13 +874,13 @@
 	if (!IS_ERR(dentry)) {
 		if (dentry->d_inode && dentry->d_inode->i_ino == ino)
 			goto out;
-#ifdef NFSD_PARANOIA
+#ifdef NFSD_PARANOIA_EXTREME
 printk("lookup_by_inode: %s/%s inode mismatch??\n",
 parent->d_name.name, dentry->d_name.name);
 #endif
 		dput(dentry);
 	} else {
-#ifdef NFSD_PARANOIA
+#ifdef NFSD_PARANOIA_EXTREME
 printk("lookup_by_inode: %s lookup failed, error=%ld\n",
 dirent.name, PTR_ERR(dentry));
 #endif
@@ -1091,7 +1091,7 @@
 	/*
 	 * Stage 5: Search the whole volume, Yea Right.
 	 */
-#ifdef NFSD_PARANOIA
+#ifdef NFSD_PARANOIA_EXTREME
 printk("find_fh_dentry: %s/%u dir/%u not found!\n",
        kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino, fh->fh_dirino);
 #endif
diff -urN linux-2.2.15-pre1/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h
--- linux-2.2.15-pre1/include/asm-sparc64/floppy.h	Wed Aug 25 17:29:52 1999
+++ linux/include/asm-sparc64/floppy.h	Mon Dec  3 21:57:39 2001
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.18.2.2 1999/08/09 21:07:41 ecd Exp $
+/* $Id: floppy.h,v 1.18.2.3 2000/01/09 18:29:32 ecd Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -574,7 +574,6 @@
 		struct linux_ebus_device *edev = 0;
 		unsigned long config = 0;
 		unsigned long auxio_reg;
-		unsigned char cfg;
 
 		for_each_ebus(ebus) {
 			for_each_ebusdev(edev, ebus) {
@@ -678,9 +677,7 @@
 			return sun_floppy_types[0];
 
 		/* Enable PC-AT mode. */
-		cfg = ns87303_readb(config, ASC);
-		cfg |= 0xc0;
-		ns87303_writeb(config, ASC, cfg);
+		ns87303_modify(config, ASC, 0, 0xc0);
 
 #ifdef PCI_FDC_SWAP_DRIVES
 		/*
@@ -691,15 +688,9 @@
 			 * Set the drive exchange bit in FCR on NS87303,
 			 * make shure other bits are sane before doing so.
 			 */
-			cfg = ns87303_readb(config, FER);
-			cfg &= ~(FER_EDM);
-			ns87303_writeb(config, FER, cfg);
-			cfg = ns87303_readb(config, ASC);
-			cfg &= ~(ASC_DRV2_SEL);
-			ns87303_writeb(config, ASC, cfg);
-			cfg = ns87303_readb(config, FCR);
-			cfg |= FCR_LDE;
-			ns87303_writeb(config, FCR, cfg);
+			ns87303_modify(config, FER, FER_EDM, 0);
+			ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
+			ns87303_modify(config, FCR, 0, FCR_LDE);
 
 			cfg = sun_floppy_types[0];
 			sun_floppy_types[0] = sun_floppy_types[1];
diff -urN linux-2.2.15-pre1/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h
--- linux-2.2.15-pre1/include/asm-sparc64/io.h	Sun Oct  4 10:22:44 1998
+++ linux/include/asm-sparc64/io.h	Mon Dec  3 21:57:39 2001
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.19 1998/08/23 05:41:46 ecd Exp $ */
+/* $Id: io.h,v 1.19.2.1 2000/01/14 03:55:36 davem Exp $ */
 #ifndef __SPARC64_IO_H
 #define __SPARC64_IO_H
 
@@ -120,12 +120,66 @@
 extern void insl(unsigned long addr, void *dst, unsigned long count);
 
 /* Memory functions, same as I/O accesses on Ultra. */
-#define readb(addr)		inb((unsigned long)(addr))
-#define readw(addr)		inw((unsigned long)(addr))
-#define readl(addr)		inl((unsigned long)(addr))
-#define writeb(b, addr)		outb((b), (unsigned long)(addr))
-#define writew(w, addr)		outw((w), (unsigned long)(addr))
-#define writel(l, addr)		outl((l), (unsigned long)(addr))
+extern __inline__ unsigned int _readb(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduba [%1] %2, %0"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PL));
+
+	return ret;
+}
+
+extern __inline__ unsigned int _readw(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduha [%1] %2, %0"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PL));
+
+	return ret;
+}
+
+extern __inline__ unsigned int _readl(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduwa [%1] %2, %0"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PL));
+
+	return ret;
+}
+
+extern __inline__ void _writeb(unsigned char b, unsigned long addr)
+{
+	__asm__ __volatile__("stba %0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (b), "r" (addr), "i" (ASI_PL));
+}
+
+extern __inline__ void _writew(unsigned short w, unsigned long addr)
+{
+	__asm__ __volatile__("stha %0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (w), "r" (addr), "i" (ASI_PL));
+}
+
+extern __inline__ void _writel(unsigned int l, unsigned long addr)
+{
+	__asm__ __volatile__("stwa %0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (l), "r" (addr), "i" (ASI_PL));
+}
+
+#define readb(addr)		_readb((unsigned long)(addr))
+#define readw(addr)		_readw((unsigned long)(addr))
+#define readl(addr)		_readl((unsigned long)(addr))
+#define writeb(b, addr)		_writeb((b), (unsigned long)(addr))
+#define writew(w, addr)		_writew((w), (unsigned long)(addr))
+#define writel(l, addr)		_writel((l), (unsigned long)(addr))
 
 /*
  * Memcpy to/from I/O space is just a regular memory operation on
diff -urN linux-2.2.15-pre1/include/asm-sparc64/ns87303.h linux/include/asm-sparc64/ns87303.h
--- linux-2.2.15-pre1/include/asm-sparc64/ns87303.h	Sun Oct  4 10:22:44 1998
+++ linux/include/asm-sparc64/ns87303.h	Mon Dec  3 21:57:39 2001
@@ -1,4 +1,4 @@
-/* $Id: ns87303.h,v 1.2 1998/09/13 15:38:50 ecd Exp $
+/* $Id: ns87303.h,v 1.2.2.1 2000/01/09 18:29:33 ecd Exp $
  * ns87303.h: Configuration Register Description for the
  *            National Semiconductor PC87303 (SuperIO).
  *
@@ -45,7 +45,7 @@
 #define FCR_LDE		0x10	/* Logical Drive Exchange                    */
 #define FCR_ZWS_ENA	0x20	/* Enable short host read/write in ECP/EPP   */
 
-/* Printer Controll Register (PCR) bits */
+/* Printer Control Register (PCR) bits */
 #define PCR_EPP_ENABLE	0x01
 #define PCR_EPP_IEEE	0x02	/* Enable EPP Version 1.9 (IEEE 1284)        */
 #define PCR_ECP_ENABLE	0x04
@@ -61,27 +61,51 @@
 #define ASC_LPT_IRQ7	0x01	/* Allways use IRQ7 for LPT                  */
 #define ASC_DRV2_SEL	0x02	/* Logical Drive Exchange controlled by TDR  */
 
+#define FER_RESERVED	0x00
+#define FAR_RESERVED	0x00
+#define PTR_RESERVED	0x73
+#define FCR_RESERVED	0xc4
+#define PCR_RESERVED	0x10
+#define KRR_RESERVED	0x00
+#define PMC_RESERVED	0x98
+#define TUP_RESERVED	0xfb
+#define SIP_RESERVED	0x00
+#define ASC_RESERVED	0x18
+#define CS0CF0_RESERVED	0x00
+#define CS0CF1_RESERVED	0x08
+#define CS1CF0_RESERVED	0x00
+#define CS1CF1_RESERVED	0x08
+
 #ifdef __KERNEL__
 
 #include <asm/system.h>
 #include <asm/io.h>
 
-static __inline__ void ns87303_writeb(unsigned long port, int index,
-				     unsigned char value)
+static __inline__ int ns87303_modify(unsigned long port, unsigned int index,
+				     unsigned char clr, unsigned char set)
 {
+	static unsigned char reserved[] = {
+		FER_RESERVED, FAR_RESERVED, PTR_RESERVED, FCR_RESERVED,
+		PCR_RESERVED, KRR_RESERVED, PMC_RESERVED, TUP_RESERVED,
+		SIP_RESERVED, ASC_RESERVED, CS0CF0_RESERVED, CS0CF1_RESERVED,
+		CS1CF0_RESERVED, CS1CF1_RESERVED
+	};
 	unsigned long flags;
+	unsigned char value;
+
+	if (index > 0x0d)
+		return -EINVAL;
 
 	save_flags(flags); cli();
 	outb(index, port);
+	value = inb(port + 1);
+	value &= ~(reserved[index] | clr);
+	value |= set;
 	outb(value, port + 1);
 	outb(value, port + 1);
 	restore_flags(flags);
-}
 
-static __inline__ unsigned char ns87303_readb(unsigned long port, int index)
-{
-	outb(index, port);
-	return inb(port + 1);
+	return 0;
 }
 
 #endif /* __KERNEL__ */
diff -urN linux-2.2.15-pre1/include/math-emu/op-1.h linux/include/math-emu/op-1.h
--- linux-2.2.15-pre1/include/math-emu/op-1.h	Tue Jan  4 10:12:25 2000
+++ linux/include/math-emu/op-1.h	Mon Dec  3 21:57:39 2001
@@ -199,25 +199,25 @@
 
 #define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y)				\
   do {									\
-    _FP_W_TYPE _nh, _nl, _q, _r;					\
+    _FP_W_TYPE _nh, _nl, _q, _r, _y;					\
 									\
     /* Normalize Y -- i.e. make the most significant bit set.  */	\
-    Y##_f <<= _FP_WFRACXBITS_##fs - 1;					\
+    _y = Y##_f << _FP_WFRACXBITS_##fs;					\
 									\
     /* Shift X op correspondingly high, that is, up one full word.  */	\
-    if (X##_f <= Y##_f)							\
+    if (X##_f < Y##_f)							\
       {									\
+	R##_e--;							\
 	_nl = 0;							\
 	_nh = X##_f;							\
       }									\
     else								\
       {									\
-	R##_e++;							\
-	_nl = X##_f << (_FP_W_TYPE_SIZE-1);				\
+	_nl = X##_f << (_FP_W_TYPE_SIZE - 1);				\
 	_nh = X##_f >> 1;						\
       }									\
     									\
-    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);				\
+    udiv_qrnnd(_q, _r, _nh, _nl, _y);					\
     R##_f = _q | (_r != 0);						\
   } while (0)
 
diff -urN linux-2.2.15-pre1/include/net/tcp.h linux/include/net/tcp.h
--- linux-2.2.15-pre1/include/net/tcp.h	Tue Jan  4 10:12:25 2000
+++ linux/include/net/tcp.h	Mon Dec  3 21:57:39 2001
@@ -777,10 +777,16 @@
 	return tp->packets_out - tp->fackets_out + tp->retrans_out;
 }
 
+/* Is SKB at the tail of the write queue? */
+static __inline__ int tcp_skb_is_last(struct sock *sk, struct sk_buff *skb)
+{
+	return (skb->next == (struct sk_buff*)&sk->write_queue);
+}
+
 /* This checks if the data bearing packet SKB (usually tp->send_head)
  * should be put on the wire right now.
  */
-static __inline__ int tcp_snd_test(struct sock *sk, struct sk_buff *skb)
+static __inline__ int tcp_snd_test(struct sock *sk, struct sk_buff *skb, int tail)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	int nagle_check = 1;
@@ -796,20 +802,26 @@
 	 *	c) We are retransmiting [Nagle]
 	 *	d) We have too many packets 'in flight'
 	 *
-	 * 	Don't use the nagle rule for urgent data (or
-	 *	for the final FIN -DaveM).
+	 * 	FIN overrides nagle, even for the TCP_CORK
+	 *	case. -DaveM
+	 *
+	 *	Also, Nagle rule does not apply to frames, which
+	 *	sit in the middle of queue (they have no chances
+	 *	to get new data) and if room at tail of skb is
+	 *	not enough to save something seriously (<32 for now).
 	 */
-	if ((sk->nonagle == 2 && (skb->len < tp->mss_cache)) ||
-	    (!sk->nonagle &&
-	     skb->len < (tp->mss_cache >> 1) &&
-	     tp->packets_out &&
-	     !(TCP_SKB_CB(skb)->flags & (TCPCB_FLAG_URG|TCPCB_FLAG_FIN))))
-		nagle_check = 0;
+	if (!(TCP_SKB_CB(skb)->flags & (TCPCB_FLAG_URG|TCPCB_FLAG_FIN))) {
+		if ((sk->nonagle == 2 && (skb->len < tp->mss_cache)) ||
+		    (!sk->nonagle &&
+		     skb->len < (tp->mss_cache >> 1) &&
+		     tp->packets_out))
+			nagle_check = 0;
+	}
 
 	/* Don't be strict about the congestion window for the
 	 * final FIN frame.  -DaveM
 	 */
-	return (nagle_check &&
+	return ((!tail || nagle_check || skb_tailroom(skb) < 32) &&
 		((tcp_packets_in_flight(tp) < tp->snd_cwnd) ||
 		 (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) &&
 		!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) &&
@@ -822,8 +834,10 @@
  */
 static __inline__ void tcp_push_pending_frames(struct sock *sk, struct tcp_opt *tp)
 {
-	if(tp->send_head) {
-		if(tcp_snd_test(sk, tp->send_head))
+	struct sk_buff *skb = tp->send_head;
+
+	if(skb) {
+		if(tcp_snd_test(sk, skb, tcp_skb_is_last(sk, skb)))
 			tcp_write_xmit(sk);
 		else if(tp->packets_out == 0 && !tp->pending) {
 			/* We held off on this in tcp_send_skb() */
diff -urN linux-2.2.15-pre1/kernel/signal.c linux/kernel/signal.c
--- linux-2.2.15-pre1/kernel/signal.c	Tue Jan  4 10:12:26 2000
+++ linux/kernel/signal.c	Mon Dec  3 21:57:39 2001
@@ -740,11 +740,11 @@
 
 	if (copy_from_user(&these, uthese, sizeof(these)))
 		return -EFAULT;
-	else {
-		/* Invert the set of allowed signals to get those we
-		   want to block.  */
-		signotset(&these);
-	}
+	/* Invert the set of allowed signals to get those we
+	   want to block.  */
+
+	sigdelsetmask (&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
+	signotset(&these);
 
 	if (uts) {
 		if (copy_from_user(&ts, uts, sizeof(ts)))
diff -urN linux-2.2.15-pre1/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- linux-2.2.15-pre1/net/ipv4/af_inet.c	Mon Aug  9 12:05:13 1999
+++ linux/net/ipv4/af_inet.c	Mon Dec  3 21:57:39 2001
@@ -5,7 +5,7 @@
  *
  *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.87.2.5 1999/08/08 08:43:10 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.87.2.6 2000/01/13 04:28:16 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -309,6 +309,7 @@
 				((struct tcp_bind_bucket*)sk->prev)->fastreuse = 0;
 		}
 
+		sk->zapped = 0;
 		dst_release(xchg(&sk->dst_cache, NULL));
 		sk->prot->hash(sk);
 		sk->socket->flags |= SO_ACCEPTCON;
@@ -546,6 +547,7 @@
 	if (sk->prot->get_port(sk, snum) != 0)
 		return -EADDRINUSE;
 
+	sk->zapped = 0;
 	sk->sport = htons(sk->num);
 	sk->daddr = 0;
 	sk->dport = 0;
@@ -626,6 +628,7 @@
 		if (inet_autobind(sk) != 0)
 			return(-EAGAIN);
 
+		sk->zapped = 0;
 		err = sk->prot->connect(sk, uaddr, addr_len);
 		/* Note: there is a theoretical race here when an wake up
 		   occurred before inet_wait_for_connect is entered. In 2.3
diff -urN linux-2.2.15-pre1/net/ipv4/arp.c linux/net/ipv4/arp.c
--- linux-2.2.15-pre1/net/ipv4/arp.c	Tue Jan  4 10:12:26 2000
+++ linux/net/ipv4/arp.c	Mon Dec  3 21:57:39 2001
@@ -1,6 +1,6 @@
 /* linux/net/inet/arp.c
  *
- * Version:	$Id: arp.c,v 1.77.2.4 1999/09/23 19:03:36 davem Exp $
+ * Version:	$Id: arp.c,v 1.77.2.5 1999/12/14 10:32:39 davem Exp $
  *
  * Copyright (C) 1994 by Florian  La Roche
  *
diff -urN linux-2.2.15-pre1/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- linux-2.2.15-pre1/net/ipv4/devinet.c	Tue Jan  4 10:12:26 2000
+++ linux/net/ipv4/devinet.c	Mon Dec  3 21:57:39 2001
@@ -1,7 +1,7 @@
 /*
  *	NET3	IP device support routines.
  *
- *	Version: $Id: devinet.c,v 1.28.2.2 1999/08/07 10:56:18 davem Exp $
+ *	Version: $Id: devinet.c,v 1.28.2.3 1999/12/14 10:32:42 davem Exp $
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
diff -urN linux-2.2.15-pre1/net/ipv4/proc.c linux/net/ipv4/proc.c
--- linux-2.2.15-pre1/net/ipv4/proc.c	Mon Feb  8 09:26:29 1999
+++ linux/net/ipv4/proc.c	Mon Dec  3 21:57:39 2001
@@ -7,7 +7,7 @@
  *		PROC file system.  It is mainly used for debugging and
  *		statistics.
  *
- * Version:	$Id: proc.c,v 1.34 1999/02/08 11:20:34 davem Exp $
+ * Version:	$Id: proc.c,v 1.34.2.1 2000/01/14 01:22:20 davem Exp $
  *
  * Authors:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -78,7 +78,7 @@
 {
 	unsigned long  dest, src;
 	unsigned short destp, srcp;
-	int timer_active, timer_active1, timer_active2;
+	int timer_active;
 	int tw_bucket = 0;
 	unsigned long timer_expires;
 	struct tcp_opt *tp = &sp->tp_pinfo.af_tcp;
@@ -105,27 +105,29 @@
 		int slot_dist;
 
 		tw_bucket	= 1;
-		timer_active1	= timer_active2 = 0;
 		timer_active	= 3;
 		slot_dist	= tw->death_slot;
-		if(slot_dist > tcp_tw_death_row_slot)
-			slot_dist = (TCP_TWKILL_SLOTS - slot_dist) + tcp_tw_death_row_slot;
+		if(slot_dist >= tcp_tw_death_row_slot)
+			slot_dist = slot_dist - tcp_tw_death_row_slot;
 		else
-			slot_dist = tcp_tw_death_row_slot - slot_dist;
+			slot_dist = (TCP_TWKILL_SLOTS - tcp_tw_death_row_slot) + slot_dist;
 		timer_expires	= jiffies + (slot_dist * TCP_TWKILL_PERIOD);
 	} else {
-		timer_active1 = del_timer(&tp->retransmit_timer);
-		timer_active2 = del_timer(&sp->timer);
-		if (!timer_active1) tp->retransmit_timer.expires=0;
-		if (!timer_active2) sp->timer.expires=0;
 		timer_active	= 0;
 		timer_expires	= (unsigned) -1;
 	}
-	if (timer_active1 && tp->retransmit_timer.expires < timer_expires) {
+	if (tp->retransmit_timer.prev != NULL &&
+	    tp->retransmit_timer.expires < timer_expires) {
 		timer_active	= 1;
 		timer_expires	= tp->retransmit_timer.expires;
 	}
-	if (timer_active2 && sp->timer.expires < timer_expires) {
+	if (tp->probe_timer.prev != NULL &&
+	    tp->probe_timer.expires < timer_expires) {
+		timer_active	= 4;
+		timer_expires	= tp->probe_timer.expires;
+	}
+	if (sp->timer.prev != NULL &&
+	    sp->timer.expires < timer_expires) {
 		timer_active	= 2;
 		timer_expires	= sp->timer.expires;
 	}
@@ -147,9 +149,6 @@
 		(!tw_bucket && sp->socket) ? sp->socket->inode->i_uid : 0,
 		(!tw_bucket && timer_active) ? sp->timeout : 0,
 		(!tw_bucket && sp->socket) ? sp->socket->inode->i_ino : 0);
-	
-	if (timer_active1) add_timer(&tp->retransmit_timer);
-	if (timer_active2) add_timer(&sp->timer);	
 }
 
 /*
diff -urN linux-2.2.15-pre1/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- linux-2.2.15-pre1/net/ipv4/tcp.c	Tue Jan  4 10:12:26 2000
+++ linux/net/ipv4/tcp.c	Mon Dec  3 21:57:39 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.140.2.5 1999/09/23 19:21:16 davem Exp $
+ * Version:	$Id: tcp.c,v 1.140.2.7 2000/01/13 23:44:00 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1448,12 +1448,11 @@
 		return;
 
 	/* If we've already sent a FIN, or it's a closed state, skip this. */
-	if ((1 << sk->state) &
-	    (TCPF_ESTABLISHED|TCPF_SYN_SENT|TCPF_SYN_RECV|TCPF_CLOSE_WAIT)) {
+	if ((1 << sk->state) & (TCPF_ESTABLISHED|TCPF_SYN_RECV|TCPF_SYN_SENT)) {
 		lock_sock(sk);
 
 		/* Clear out any half completed packets.  FIN if needed. */
-		if (tcp_close_state(sk,0))
+		if (tcp_close_state(sk,sk->state == TCP_CLOSE_WAIT))
 			tcp_send_fin(sk);
 
 		release_sock(sk);
diff -urN linux-2.2.15-pre1/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- linux-2.2.15-pre1/net/ipv4/tcp_input.c	Tue Jan  4 10:12:27 2000
+++ linux/net/ipv4/tcp_input.c	Mon Dec  3 21:57:39 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.164.2.8 1999/09/23 19:21:23 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.164.2.11 2000/01/13 04:27:59 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -270,10 +270,12 @@
 /* When we get a reset we do this. */
 static void tcp_reset(struct sock *sk)
 {
+	unsigned char orig_state = sk->state;
+
 	sk->zapped = 1;
 
 	/* We want the right error as BSD sees it (and indeed as we do). */
-	switch (sk->state) {
+	switch (orig_state) {
 		case TCP_SYN_SENT:
 			sk->err = ECONNREFUSED;
 			break;
@@ -284,6 +286,16 @@
 			sk->err = ECONNRESET;
 	};
 	tcp_set_state(sk, TCP_CLOSE);
+	if (orig_state == TCP_SYN_SENT) {
+		/* Back out identity changes done by connect.
+		 * The move to TCP_CLOSE has unhashed us and
+		 * killed the bind bucket reference, making this
+		 * safe. -DaveM
+		 */
+		sk->dport = 0;
+		sk->daddr = 0;
+		sk->num = 0;
+	}
 	sk->shutdown = SHUTDOWN_MASK;
 	if (!sk->dead) 
 		sk->state_change(sk);
@@ -988,7 +1000,7 @@
 	}
 
 	/* Check RST or SYN */
-	if(th->rst || th->syn) {
+	if(th->rst) {
 		/* This is TIME_WAIT assasination, in two flavors.
 		 * Oh well... nobody has a sufficient solution to this
 		 * protocol bug yet.
@@ -997,8 +1009,6 @@
 			tcp_tw_deschedule(tw);
 			tcp_timewait_kill(tw);
 		}
-		if(!th->rst)
-			return TCP_TW_RST; /* toss a reset back */
 		return 0;
 	} else {
 		/* In this case we must reset the TIMEWAIT timer. */
@@ -1129,11 +1139,6 @@
 
 	tcp_send_ack(sk);
 
-	if (!sk->dead) {
-		sk->state_change(sk);
-		sock_wake_async(sk->socket, 1);
-	}
-
 	switch(sk->state) {
 		case TCP_SYN_RECV:
 		case TCP_ESTABLISHED:
@@ -1177,6 +1182,11 @@
 			printk("tcp_fin: Impossible, sk->state=%d\n", sk->state);
 			break;
 	};
+
+	if (!sk->dead) {
+		sk->state_change(sk);
+		sock_wake_async(sk->socket, 1);
+	}
 }
 
 /* These routines update the SACK block as out-of-order packets arrive or
diff -urN linux-2.2.15-pre1/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- linux-2.2.15-pre1/net/ipv4/tcp_output.c	Mon Dec  3 21:57:34 2001
+++ linux/net/ipv4/tcp_output.c	Mon Dec  3 21:57:39 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_output.c,v 1.108.2.1 1999/05/14 23:07:36 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.108.2.5 2000/01/14 01:22:18 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -165,7 +165,7 @@
 	tp->write_seq += (TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq);
 	__skb_queue_tail(&sk->write_queue, skb);
 
-	if (!force_queue && tp->send_head == NULL && tcp_snd_test(sk, skb)) {
+	if (!force_queue && tp->send_head == NULL && tcp_snd_test(sk, skb, 1)) {
 		/* Send it out now. */
 		TCP_SKB_CB(skb)->when = tcp_time_stamp;
 		tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
@@ -341,7 +341,8 @@
 		 * b) not exceeding our congestion window.
 		 * c) not retransmitting [Nagle]
 		 */
-		while((skb = tp->send_head) && tcp_snd_test(sk, skb)) {
+		while((skb = tp->send_head) &&
+		      tcp_snd_test(sk, skb, tcp_skb_is_last(sk, skb))) {
 			if (skb->len > mss_now) {
 				if (tcp_fragment(sk, skb, mss_now))
 					break;
@@ -1040,10 +1041,14 @@
 			 *
 			 * This is the one possible way that we can delay an
 			 * ACK and have tp->ato indicate that we are in
-			 * quick ack mode, so clear it.
+			 * quick ack mode, so clear it.  It is also the only
+			 * possible way for ato to be zero, when ACK'ing a
+			 * SYNACK because we've taken no ATO measurement yet.
 			 */
-			if(tcp_in_quickack_mode(tp))
+			if (tcp_in_quickack_mode(tp))
 				tcp_exit_quickack_mode(tp);
+			if (!tp->ato)
+				tp->ato = tp->rto;
 			tcp_send_delayed_ack(tp, HZ/2);
 			return;
 		}
diff -urN linux-2.2.15-pre1/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- linux-2.2.15-pre1/net/ipv4/tcp_timer.c	Tue Jan  4 10:12:27 2000
+++ linux/net/ipv4/tcp_timer.c	Mon Dec  3 21:57:39 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_timer.c,v 1.62.2.4 1999/09/23 19:21:39 davem Exp $
+ * Version:	$Id: tcp_timer.c,v 1.62.2.6 2000/01/13 04:28:06 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -131,6 +131,7 @@
 	} else {
 		/* Clean up time. */
 		tcp_set_state(sk, TCP_CLOSE);
+		sk->shutdown |= SHUTDOWN_MASK;
 		return 0;
 	}
 	return 1;
@@ -140,26 +141,46 @@
 static int tcp_write_timeout(struct sock *sk)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+	unsigned char orig_state = sk->state;
+	int ret;
 
 	/* Look for a 'soft' timeout. */
-	if ((sk->state == TCP_ESTABLISHED &&
+	if ((orig_state == TCP_ESTABLISHED &&
 	     tp->retransmits && (tp->retransmits % TCP_QUICK_TRIES) == 0) ||
-	    (sk->state != TCP_ESTABLISHED && tp->retransmits > sysctl_tcp_retries1)) {
+	    (orig_state != TCP_ESTABLISHED && tp->retransmits > sysctl_tcp_retries1)) {
 		dst_negative_advice(&sk->dst_cache);
 	}
 	
 	/* Have we tried to SYN too many times (repent repent 8)) */
-	if(tp->retransmits > sysctl_tcp_syn_retries && sk->state==TCP_SYN_SENT) {
+	if(tp->retransmits > sysctl_tcp_syn_retries && orig_state==TCP_SYN_SENT) {
 		tcp_write_err(sk, 1);
+
 		/* Don't FIN, we got nothing back */
-		return 0;
+		ret = 0;
+	} else {
+		/* Has it gone just too far? */
+		if (tp->retransmits > sysctl_tcp_retries2) 
+			ret = tcp_write_err(sk, 0);
+		else
+			ret = 1;
 	}
 
-	/* Has it gone just too far? */
-	if (tp->retransmits > sysctl_tcp_retries2) 
-		return tcp_write_err(sk, 0);
+	/* Did we timeout a connecting socket?  The check must be
+	 * like this just in case someone sets syn_retries larger
+	 * than retries2, which is silly but handle it.  -DaveM
+	 */
+	if (orig_state == TCP_SYN_SENT && sk->state == TCP_CLOSE) {
+		/* Back out identity changes done by connect.
+		 * The move to TCP_CLOSE has unhashed us and
+		 * killed the bind bucket reference, making this
+		 * safe. -DaveM
+		 */
+		sk->dport = 0;
+		sk->daddr = 0;
+		sk->num = 0;
+	}
 
-	return 1;
+	return ret;
 }
 
 void tcp_delack_timer(unsigned long data)
diff -urN linux-2.2.15-pre1/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- linux-2.2.15-pre1/net/ipv6/addrconf.c	Tue Jan  4 10:12:27 2000
+++ linux/net/ipv6/addrconf.c	Mon Dec  3 21:57:39 2001
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: addrconf.c,v 1.48.2.1 1999/06/28 10:39:39 davem Exp $
+ *	$Id: addrconf.c,v 1.48.2.2 1999/12/14 10:32:53 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
diff -urN linux-2.2.15-pre1/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
--- linux-2.2.15-pre1/net/ipv6/af_inet6.c	Mon Aug  9 12:04:41 1999
+++ linux/net/ipv6/af_inet6.c	Mon Dec  3 21:57:39 2001
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
- *	$Id: af_inet6.c,v 1.43.2.1 1999/06/20 20:15:06 davem Exp $
+ *	$Id: af_inet6.c,v 1.43.2.2 2000/01/13 04:28:23 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -243,6 +243,7 @@
 	if(sk->prot->get_port(sk, snum) != 0)
 		return -EADDRINUSE;
 
+	sk->zapped = 0;
 	sk->sport = ntohs(sk->num);
 	sk->dport = 0;
 	sk->daddr = 0;
diff -urN linux-2.2.15-pre1/net/ipv6/proc.c linux/net/ipv6/proc.c
--- linux-2.2.15-pre1/net/ipv6/proc.c	Thu Aug 27 19:33:09 1998
+++ linux/net/ipv6/proc.c	Mon Dec  3 21:57:39 2001
@@ -7,7 +7,7 @@
  *		PROC file system.  This is very similar to the IPv4 version,
  *		except it reports the sockets in the INET6 address family.
  *
- * Version:	$Id: proc.c,v 1.9 1998/08/26 12:05:11 davem Exp $
+ * Version:	$Id: proc.c,v 1.9.2.1 2000/01/14 01:22:24 davem Exp $
  *
  * Authors:	David S. Miller (davem@caip.rutgers.edu)
  *
@@ -32,7 +32,7 @@
 {
 	struct sock *sp;
 	struct tcp_opt *tp;
-	int timer_active, timer_active1, timer_active2;
+	int timer_active;
 	unsigned long timer_expires;
 	struct in6_addr *dest, *src;
 	unsigned short destp, srcp;
@@ -76,29 +76,31 @@
 			extern int tcp_tw_death_row_slot;
 			int slot_dist;
 
-			timer_active1	= timer_active2 = 0;
 			timer_active	= 3;
 			slot_dist	= tw->death_slot;
-			if(slot_dist > tcp_tw_death_row_slot)
-				slot_dist = (TCP_TWKILL_SLOTS - slot_dist) + tcp_tw_death_row_slot;
+			if(slot_dist >= tcp_tw_death_row_slot)
+				slot_dist = slot_dist - tcp_tw_death_row_slot;
 			else
-				slot_dist = tcp_tw_death_row_slot - slot_dist;
+				slot_dist = (TCP_TWKILL_SLOTS - tcp_tw_death_row_slot) + slot_dist;
 			timer_expires	= jiffies + (slot_dist * TCP_TWKILL_PERIOD);
 		} else {
-			timer_active1 = del_timer(&tp->retransmit_timer);
-			timer_active2 = del_timer(&sp->timer);
-			if(!timer_active1) tp->retransmit_timer.expires = 0;
-			if(!timer_active2) sp->timer.expires = 0;
 			timer_active = 0;
 			timer_expires = (unsigned) -1;
 		}
-		if(timer_active1 && tp->retransmit_timer.expires < timer_expires) {
-			timer_active = timer_active1;
-			timer_expires = tp->retransmit_timer.expires;
+		if (tp->retransmit_timer.prev != NULL &&
+		    tp->retransmit_timer.expires < timer_expires) {
+			timer_active	= 1;
+			timer_expires	= tp->retransmit_timer.expires;
 		}
-		if(timer_active2 && sp->timer.expires < timer_expires) {
-			timer_active = timer_active2;
-			timer_expires = sp->timer.expires;
+		if (tp->probe_timer.prev != NULL &&
+		    tp->probe_timer.expires < timer_expires) {
+			timer_active	= 4;
+			timer_expires	= tp->probe_timer.expires;
+		}
+		if (sp->timer.prev != NULL &&
+		    sp->timer.expires < timer_expires) {
+			timer_active	= 2;
+			timer_expires	= sp->timer.expires;
 		}
 		if(timer_active == 0)
 			timer_expires = jiffies;
@@ -128,8 +130,6 @@
 			((!tw_bucket && sp->socket) ?
 			 sp->socket->inode->i_ino : 0));
 
-		if(timer_active1) add_timer(&tp->retransmit_timer);
-		if(timer_active2) add_timer(&sp->timer);
 		len += sprintf(buffer+len, "%-148s\n", tmpbuf);
 		if(len >= length)
 			break;
diff -urN linux-2.2.15-pre1/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- linux-2.2.15-pre1/net/ipv6/tcp_ipv6.c	Tue Jan  4 10:12:27 2000
+++ linux/net/ipv6/tcp_ipv6.c	Mon Dec  3 21:57:39 2001
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.104.2.10 1999/09/23 19:21:46 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.104.2.11 1999/12/03 09:30:29 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
diff -urN linux-2.2.15-pre1/net/packet/af_packet.c linux/net/packet/af_packet.c
--- linux-2.2.15-pre1/net/packet/af_packet.c	Tue Jan  4 10:12:27 2000
+++ linux/net/packet/af_packet.c	Mon Dec  3 21:57:39 2001
@@ -5,7 +5,7 @@
  *
  *		PACKET - implements raw packet sockets.
  *
- * Version:	$Id: af_packet.c,v 1.19 1999/03/21 05:23:03 davem Exp $
+ * Version:	$Id: af_packet.c,v 1.19.2.1 1999/12/04 05:45:02 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
