]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.15pre2 2.2.15pre2
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:20:40 +0000 (15:20 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:20:40 +0000 (15:20 -0500)
o Fix RTC build problem with Nautilus (Michal Jaegermann)
o Quieten NFS debugging messages (Alan Cox)
o Fix bug in connect/listen handling in TCP (Dave Miller)
o Fix missing $(CC) cases (Pascal DuPuis)
o Fix SMP tcp hang (Andrea Arcangeli)
o Hopefully fixed PLIP (Alan Cox)
o Fix sigtimedwait bug (Christophe Blaess)
o Updated epic100 driver (Donald Becker)
| If it works cool, if not we back it off
o Sparc updates (Dave Miller)
| Fixes bugs with >258Mb on sun4d/sun4m
| si_addr is set in siginfo
| Fix signal type for FP/div events
| DP division FPU emulation fixes
| Fix sparc64 parport locking keyboard
| ESP can be built as a module
o Network fix kit (Dave Miller and co)
| Nagle improvements, TCP_CORK/FIN fix
| /proc/net/tcp reports type 4 for timer
| Fix TIME_WAIT logic
| Clean up timer performance
| Handle shutdown() in CLOSE_WAIT right
| Report state change on tcp_fin after setting
| new state
| Shutdown on close in write_err case  (Paul Russell)

42 files changed:
Makefile
arch/alpha/kernel/Makefile
arch/alpha/kernel/sys_nautilus.c
arch/i386/Makefile
arch/i386/vmlinux.lds [deleted file]
arch/sparc/config.in
arch/sparc/defconfig
arch/sparc/mm/srmmu.c
arch/sparc64/config.in
arch/sparc64/defconfig
arch/sparc64/kernel/signal32.c
arch/sparc64/kernel/traps.c
arch/sparc64/math-emu/sfp-machine.h
dmfe.c [deleted file]
drivers/misc/parport_ax.c
drivers/net/eepro100.c
drivers/net/epic100.c
drivers/net/plip.c
drivers/net/tulip.c
drivers/sbus/audio/dbri.c
drivers/scsi/esp.c
drivers/video/atyfb.c
fs/nfsd/nfsfh.c
include/asm-sparc64/floppy.h
include/asm-sparc64/io.h
include/asm-sparc64/ns87303.h
include/math-emu/op-1.h
include/net/tcp.h
kernel/signal.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/proc.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/proc.c
net/ipv6/tcp_ipv6.c
net/packet/af_packet.c

index 199ed284c73d9d575e6d038b705748e08d1c9588..314c824982d6fb09912a24f806805599ccf04f9b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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/)
 
index 5ba7155e57827b5dddb669d005f193accbf06b7e..2fd206fc9fb08e0231a3a88eb5042555e79fbb5f 100644 (file)
@@ -134,7 +134,7 @@ asm_offsets: check_asm
        ./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
index dc8c61c455035e4cbe3c0628c0d4ed8864423f66..9c7792f09b0d261b5de7aa4cfbb49630b420f831 100644 (file)
@@ -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>
index bcd555c3b5747be46d671b64ab7263d7ba2a1261..bb155b5141cfaae7dc09ce245cd4ea052a3dee7d 100644 (file)
@@ -65,7 +65,7 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 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 --git a/arch/i386/vmlinux.lds b/arch/i386/vmlinux.lds
deleted file mode 100644 (file)
index ecf90c2..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* ld script to make i386 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
- */
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
-SECTIONS
-{
-  . = 0xC0000000  + 0x100000;
-  _text = .;                   /* Text and read-only data */
-  .text : {
-       *(.text)
-       *(.fixup)
-       *(.gnu.warning)
-       } = 0x9090
-  .text.lock : { *(.text.lock) }       /* out-of-line lock text */
-  .rodata : { *(.rodata) }
-  .kstrtab : { *(.kstrtab) }
-
-  . = ALIGN(16);               /* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  __start___ksymtab = .;       /* Kernel symbol table */
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-
-  _etext = .;                  /* End of text section */
-
-  .data : {                    /* Data */
-       *(.data)
-       CONSTRUCTORS
-       }
-
-  _edata = .;                  /* End of data section */
-
-  . = ALIGN(8192);             /* init_task */
-  .data.init_task : { *(.data.init_task) }
-
-  . = ALIGN(4096);             /* Init code and data */
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(4096);
-  __init_end = .;
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-
-  __bss_start = .;             /* BSS */
-  .bss : {
-       *(.bss)
-       }
-  _end = . ;
-
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
-}
index b43b57acdc9b07ac79fc20dcfea454572eed03ff..46ac520242ccdf2ece43250a26f96b6c514c8d12 100644 (file)
@@ -114,13 +114,13 @@ if [ "$CONFIG_NET" = "y" ]; then
 #                      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 @@ if [ "$CONFIG_SCSI" != "n" ]; then
        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
index b6afe289772e373b6ed6b6ca76afcf2a42276075..4b0afd3628212124acf5149c88ed15859d388902 100644 (file)
@@ -145,6 +145,11 @@ CONFIG_ATALK=m
 #
 # CONFIG_NET_SCHED is not set
 
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
 #
 # ISDN subsystem
 #
index 4d103826ef1fc74e3948ddf7ad2e2c18e18459ac..b2e9441424b1373866908646b3e6bdba91858b1b 100644 (file)
@@ -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 @@ __initfunc(static unsigned long map_spbank(unsigned long vbase, int sp_entry))
        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;
 }
index d5a3e6775e88e082f715b18fdd19489a6a2bccf9..f1c2417f501698df6bacc6f9e80aa3cb0c4f42cc 100644 (file)
@@ -131,6 +131,25 @@ endmenu
 
 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 @@ if [ "$CONFIG_SCSI" != "n" ]; then
        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
index 690653a835d20869425a9b92665745e3956ddfe8..a9f3272b110395c46ec6deefd8239681a2c9072f 100644 (file)
@@ -175,6 +175,11 @@ CONFIG_ATALK=m
 #
 # CONFIG_NET_SCHED is not set
 
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
 #
 # SCSI support
 #
index 5834cfcfc035daff1b057d1a3c2fe92703f8a160..a61a06c9081bd668f1cc4f68002f8d9ee592955b 100644 (file)
@@ -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 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs
                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 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs
        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]),
index 2fe05199fb082d964d70185aea381eb148e76721..f04404bfaaed0260c0e7ed5881bebe624b70f81f 100644 (file)
@@ -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 @@ void do_fpe_common(struct pt_regs *regs)
                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_tof(struct pt_regs *regs)
 
 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 @@ void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long n
        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... */
index d6b7265162fa983ef91549eb3fca3aaaf6abbfc4..f9ebd5be99536525166130b187746c875d093b0a 100644 (file)
@@ -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 --git a/dmfe.c b/dmfe.c
deleted file mode 100644 (file)
index 7ee2469..0000000
--- a/dmfe.c
+++ /dev/null
@@ -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 */
index 8b5652c5701920ca5760d5271caa8597637105d6..59c9a18b62fceedbfb1e810ddcb36926fa06a12e 100644 (file)
@@ -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>
 #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 @@ init_one_port(struct linux_ebus_device *dev)
        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 @@ init_one_port(struct linux_ebus_device *dev)
        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
index 496e75757937a3e111ea78132e140830484adf3a..dd9d6cdffe2db0da0d20df744f3809c9669f03bb 100644 (file)
                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 =
index 1c5d85721f1e38f952fcda3bf463dd649e6e72dc..dafb14b4ec70c1022fbb18f7edc8eef0c690c319 100644 (file)
@@ -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.
 */
 
 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 @@ static int max_interrupt_work = 10;
 #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 @@ static int max_interrupt_work = 10;
 
 #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(options, "1-" __MODULE_STRING(8) "i");
 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 @@ IVc. Errata
 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 @@ struct chip_info {
        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 @@ enum epic_registers {
 
 /* 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 epic_private {
        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 @@ struct epic_private {
        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 @@ static void set_rx_mode(struct device *dev);
 /* 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 @@ int epic100_probe(struct device *dev)
                                && (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 @@ int epic100_probe(struct device *dev)
                                                                          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 @@ static struct device *epic_probe1(int pci_bus, int pci_devfn,
 
        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 @@ static struct device *epic_probe1(int pci_bus, int pci_devfn,
 
        /* 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 @@ static struct device *epic_probe1(int pci_bus, int pci_devfn,
 
        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 @@ static struct device *epic_probe1(int pci_bus, int pci_devfn,
                                           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 @@ static struct device *epic_probe1(int pci_bus, int pci_devfn,
        }
 
        /* 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 @@ static struct device *epic_probe1(int pci_bus, int pci_devfn,
    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 @@ static int read_eeprom(long ioaddr, int location)
        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 @@ static int read_eeprom(long ioaddr, int location)
        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 @@ epic_open(struct device *dev)
        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 @@ epic_open(struct device *dev)
           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(TX_FIFO_THRESH, 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);
+               outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
+
+       
+       ep->tx_threshold = TX_FIFO_THRESH;
+       outl(ep->tx_threshold, ioaddr + TxThresh);
+
+       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 @@ epic_open(struct device *dev)
 
        /* 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 @@ static void epic_pause(struct device *dev)
        /* 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 @@ static void epic_restart(struct device *dev)
        /* 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 @@ static void epic_restart(struct device *dev)
 
        /* 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 @@ static void epic_timer(unsigned long data)
        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 @@ static void epic_timer(unsigned long data)
                                   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 @@ static void epic_tx_timeout(struct device *dev)
                           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 @@ epic_init_ring(struct device *dev)
        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 @@ static int
 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 @@ epic_start_xmit(struct sk_buff *skb, struct device *dev)
           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 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                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;
-
-                       for (dirty_tx = ep->dirty_tx; dirty_tx < ep->cur_tx; dirty_tx++) {
+                       unsigned int dirty_tx, cur_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 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 #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 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 
                        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 @@ static int epic_rx(struct device *dev)
 {
        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 @@ static int epic_rx(struct device *dev)
                        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 @@ static int epic_rx(struct device *dev)
                                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 @@ static int epic_rx(struct device *dev)
                        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 @@ static int epic_close(struct device *dev)
                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 @@ static int epic_close(struct device *dev)
 #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 @@ static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                }
                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 @@ static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                }
                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
@@ -1318,93 +1335,6 @@ static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        }
 }
 
-\f
-#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 */
-
 \f
 #ifdef MODULE
 
@@ -1412,29 +1342,23 @@ 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 @@ void cleanup_module(void)
 /*
  * 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
index 2777a08a6dd4dd013538f5eec6a4b6b20039fb97..15b2e6ebca7b78f2be7736c47ef38a52c8bd6147 100644 (file)
@@ -507,6 +507,61 @@ plip_receive(unsigned short nibble_timeout, unsigned short status_addr,
        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 @@ plip_receive_packet(struct device *dev, struct net_local *nl,
 
        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++;
index 4d1f812cc45142d7d720158738d1e610971cfb3b..3cae0558de2349a353913cd50362f24268ddce1c 100644 (file)
 
        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
index b68d3ef4e5b098d9d41cee0d93b7d669a8d0d4ae..10307d9783fc244f6ad34e5bd08434089e83c8dd 100644 (file)
@@ -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.
index 29f09a0d92ae011653e36ca40b3f9c1ca17f34ae..c427810e9cb5f025b032cef6c9a41981987f7e50 100644 (file)
@@ -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 @@ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
        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 */
index 388bde873e798e31a17b2f210402c996d9297348..e0f111b50bd1ac14f77d9487ab881cb2c7ce7b15 100644 (file)
@@ -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
index ef0da39cc9d6d4622c75f647894bece35d37fe50..a28f746d9ad9533647b6340f6bd72cb63ddc2406 100644 (file)
@@ -861,12 +861,12 @@ static struct dentry *lookup_by_inode(struct dentry *parent, ino_t ino)
        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 @@ printk("lookup_by_inode: found %s\n", dirent.name);
        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 @@ out_five:
        /*
         * 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
index 626e557a57d9d360424b577bcfa7589340427866..4507be2f0cc7c00c50b0fdf532346bca84657c31 100644 (file)
@@ -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 @@ __initfunc(static unsigned long sun_floppy_init(void))
                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 @@ __initfunc(static unsigned long sun_floppy_init(void))
                        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 @@ __initfunc(static unsigned long sun_floppy_init(void))
                         * 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];
index c9e3c84609d72845fee7a103956009d8e5757572..50a5f2a62adc4b09e422158d273d1d4adf671f27 100644 (file)
@@ -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 insw(unsigned long addr, void *dst, unsigned long count);
 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
index cfd159a5a80b95f7b8a98df814923297d003eb14..b081a2c98c41b589765bdbf9968baa3a93b0f830 100644 (file)
@@ -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
 #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__ */
index 48bf4ce7e2d6a84d914927eaaadc33da87095fad..53e0fce1b18d435657fd25d2a022d7ff9eda57cb 100644 (file)
 
 #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)
 
index 0e7e4bb6e37d4e5804703b0beb37580e45c47b66..857093ff322e9035ec972c79d485206e5d940556 100644 (file)
@@ -777,10 +777,16 @@ static __inline__ int tcp_packets_in_flight(struct tcp_opt *tp)
        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 @@ static __inline__ int tcp_snd_test(struct sock *sk, struct sk_buff *skb)
         *      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__ int tcp_snd_test(struct sock *sk, struct sk_buff *skb)
  */
 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() */
index 545c63b70815856bfbb4bff48a5fb125cfd36d32..97e3f2ef78f93a13d3d57abecda048468965440b 100644 (file)
@@ -740,11 +740,11 @@ sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
 
        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)))
index e37eb6bd7eb0bde5d2687c61a6ac722b2a8612aa..f6911d796d9cfb0c23787b650af10b123882af3a 100644 (file)
@@ -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 @@ int inet_listen(struct socket *sock, int backlog)
                                ((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 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        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 @@ int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
                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
index d81c1beeb93934fcc43e204abe7306e030ca128f..0fbb8efc8e8a2f4c72108b9f8ccb35d9060a1611 100644 (file)
@@ -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
  *
index 41b42a52f0b91be5f162b70ca3f141fb8dafcfdc..24f48681502719f38b3799dd79339d7673ec2526 100644 (file)
@@ -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
index 1640a05607527eb57bf58a468e1d6de563b98703..d4c854eb87ee3601c60a7eff7da64561b2e1b77f 100644 (file)
@@ -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 @@ static inline void get__sock(struct sock *sp, char *tmpbuf, int i, int format)
 {
        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 @@ static inline void get__sock(struct sock *sp, char *tmpbuf, int i, int format)
                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 @@ static inline void get__sock(struct sock *sp, char *tmpbuf, int i, int format)
                (!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);       
 }
 
 /*
index 68b7e5e77859f379d2d15923b884e8e2d3b3e489..e33e93895c3ce6af818032f1e6ad3b1e965c63d3 100644 (file)
@@ -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 @@ void tcp_shutdown(struct sock *sk, int how)
                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);
index 7f5cc4e7ebbc183b12f2acb2632672363f06ea00..4bf48a53c0541ed9d2fe11c5f5733ca0a10f07bd 100644 (file)
@@ -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 @@ extern __inline__ int tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
 /* 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 @@ static void tcp_reset(struct sock *sk)
                        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 @@ tcp_timewait_state_process(struct tcp_tw_bucket *tw, struct sk_buff *skb,
        }
 
        /* 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_timewait_state_process(struct tcp_tw_bucket *tw, struct sk_buff *skb,
                        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 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
 
        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 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
                        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
index d0a0ac96b686a26d37fc06690cc2d83a25f5a75d..9817b475c7dc9d87023ec6556bc81bf8cf06d2a8 100644 (file)
@@ -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 @@ void tcp_send_skb(struct sock *sk, struct sk_buff *skb, int force_queue)
        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 @@ void tcp_write_xmit(struct sock *sk)
                 * 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 @@ void tcp_send_ack(struct sock *sk)
                         *
                         * 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;
                }
index 7529a441444f45f9283937813d3e0c683f7c8f79..44e9e55f836cec1908224b41d3fe9067350205e8 100644 (file)
@@ -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 @@ static int tcp_write_err(struct sock *sk, int force)
        } 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_err(struct sock *sk, int force)
 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)
index 65f1129c61a5dbb35dac610053c44c98913bbc4f..e75ad90ab9163d74e2c288fbed0cae9089007b5f 100644 (file)
@@ -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
index 29881d9c22eea39cd48ef3085b13abcbcba0d928..2cdf9e3f463b85118332892a39b5fe2eef7042fe 100644 (file)
@@ -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 @@ static int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        if(sk->prot->get_port(sk, snum) != 0)
                return -EADDRINUSE;
 
+       sk->zapped = 0;
        sk->sport = ntohs(sk->num);
        sk->dport = 0;
        sk->daddr = 0;
index 31f6a2f5571650d16acfa19f7d89599de08a2551..235ba6c8dd2cd0590ac51c138bea1316d09ebb26 100644 (file)
@@ -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 @@ static int get__netinfo6(struct proto *pro, char *buffer, int format, char **sta
 {
        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 @@ static int get__netinfo6(struct proto *pro, char *buffer, int format, char **sta
                        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 @@ static int get__netinfo6(struct proto *pro, char *buffer, int format, char **sta
                        ((!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;
index 393a1d61156e5dacd3684d9d4e27979f66355717..49ff05d8c6992ccf93fa63503e0b9c7e6dd52313 100644 (file)
@@ -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
index a043c6b0b45630fcb12034da0a00717c67e10f13..0a9a6a55e0313d92b8e1d98a9c5d60fe28438549 100644 (file)
@@ -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>