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/)
./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
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/reboot.h>
+#include <linux/mc146818rtc.h>
#include <asm/ptrace.h>
#include <asm/system.h>
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: ;
+++ /dev/null
-/* 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) }
-}
# 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
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
#
# CONFIG_NET_SCHED is not set
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
#
# ISDN subsystem
#
-/* $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)
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;
}
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
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
#
# CONFIG_NET_SCHED is not set
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
#
# SCSI support
#
-/* $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
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);
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]),
-/* $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)
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);
}
}
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)
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... */
_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)
+++ /dev/null
-/*
- 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 */
-/* $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
struct parport tmpport, *p;
unsigned long base;
unsigned long config;
- unsigned char tmp;
int irq, dma;
/* Pointer to NS87303 Configuration Registers */
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
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 =
/* 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>
#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>
#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");
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
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,
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,
/* 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 {
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. */
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);
/* 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;
&& (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."
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;
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. */
/* 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),
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
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);
}
/* 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;
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)
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);
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. */
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;
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);
/* 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);
/* 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) {
/* 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]),
/* 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"
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) {
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)
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;
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 */
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;
}
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;
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;
#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;
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);
{
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 "
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
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;
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;
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. */
#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;
}
}
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);
}
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
}
}
-\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
{
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);
/*
* 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
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,
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++;
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
* - 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.
#include <asm/idprom.h>
#include <asm/spinlock.h>
+#include <linux/module.h>
+
#define DEBUG_ESP
/* #define DEBUG_ESP_HME */
/* #define DEBUG_ESP_DATA */
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 */
-/* $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
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
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
/*
* 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
-/* $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)
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) {
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
/*
* 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];
-/* $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
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
-/* $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).
*
#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__ */
#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)
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;
* 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) &&
*/
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() */
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)))
*
* 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>
((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;
if (sk->prot->get_port(sk, snum) != 0)
return -EADDRINUSE;
+ sk->zapped = 0;
sk->sport = htons(sk->num);
sk->daddr = 0;
sk->dport = 0;
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
/* 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
*
/*
* 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
* 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>
{
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;
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;
}
(!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);
}
/*
*
* 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>
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);
*
* 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>
/* 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;
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);
}
/* 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.
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. */
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:
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
*
* 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>
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;
* 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;
*
* 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;
}
*
* 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>
} else {
/* Clean up time. */
tcp_set_state(sk, TCP_CLOSE);
+ sk->shutdown |= SHUTDOWN_MASK;
return 0;
}
return 1;
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)
* 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
*
* 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
if(sk->prot->get_port(sk, snum) != 0)
return -EADDRINUSE;
+ sk->zapped = 0;
sk->sport = ntohs(sk->num);
sk->dport = 0;
sk->daddr = 0;
* 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)
*
{
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;
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;
((!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;
* 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
*
* 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>