Commit 5ae2c9cf authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/sparc-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 54689d55 3a4ec59d
Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters
============================================================== ==============================================================
September 16, 2002 November 19, 2002
Contents Contents
...@@ -19,7 +19,7 @@ In This Release ...@@ -19,7 +19,7 @@ In This Release
=============== ===============
This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of
Adapters, version 2.1.x. This driver includes support for Itanium(TM)-based Adapters, version 2.2.x. This driver includes support for Itanium(TM)-based
systems. systems.
...@@ -94,8 +94,9 @@ For the latest Intel PRO/100 network driver for Linux, see: ...@@ -94,8 +94,9 @@ For the latest Intel PRO/100 network driver for Linux, see:
Command Line Parameters Command Line Parameters
======================= =======================
The following optional parameters are used by entering them on the command If the driver is built as a module, the following optional parameters are
line with the modprobe or insmod command using this syntax: used by entering them on the command line with the modprobe or insmod command
using this syntax:
modprobe e100 [<option>=<VAL1>,<VAL2>,...] modprobe e100 [<option>=<VAL1>,<VAL2>,...]
......
Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters
=============================================================== ===============================================================
October 12, 2002 January 8, 2003
Contents Contents
...@@ -20,27 +20,11 @@ In This Release ...@@ -20,27 +20,11 @@ In This Release
=============== ===============
This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family
of Adapters, version 4.4.x. This driver includes support for of Adapters, version 5.0.x. This driver includes support for
Itanium(TM)-based systems. Itanium(TM)-based systems.
This release version includes the following:
- Support for the ethtool 1.6 interface. A third-party application can use
the ethtool interface to get and set driver parameters.
- Zero copy. This feature provides faster data throughput. Enabled by
default in supporting kernels. It is not supported on the Intel(R)
PRO/1000 Gigabit Server Adapter.
Features include:
- Support for the 82545 and 82546-based adapters listed below
- Wake on LAN* support via ethtool for 82540, 82544, 82545, and 82546-
based adapters
- Adaptive IFS for increased performance at half duplex
Native VLANs are now available with supported kernels.
Supported Adapters Supported Adapters
...@@ -65,6 +49,7 @@ release: ...@@ -65,6 +49,7 @@ release:
82544 PRO/1000 T Desktop Adapter A62947-xxx 82544 PRO/1000 T Desktop Adapter A62947-xxx
82540 PRO/1000 MT Desktop Adapter A78408-xxx 82540 PRO/1000 MT Desktop Adapter A78408-xxx
82541 C91016-xxx
82545 PRO/1000 MT Server Adapter A92165-xxx 82545 PRO/1000 MT Server Adapter A92165-xxx
...@@ -77,26 +62,32 @@ release: ...@@ -77,26 +62,32 @@ release:
82546 PRO/1000 MF Dual Port Server Adapter A91620-xxx 82546 PRO/1000 MF Dual Port Server Adapter A91620-xxx
To verify your Intel adapter is supported, find the board ID number on the To verify your Intel adapter is supported, find the board ID number on the
adapter. Look for a label that has a barcode and a number in the format of adapter. Look for a label that has a barcode and a number in the format
123456-001 (six digits hyphen three digits). Match this to the list of A12345-001. Match this to the list of numbers above.
numbers above.
For more information on how to identify your adapter, go to the Adapter & For more information on how to identify your adapter, go to the Adapter &
Driver ID Guide at: Driver ID Guide at:
http://support.intel.com/support/network/adapter/pro100/21397.htm http://support.intel.com/support/network/adapter/pro100/21397.htm
For the latest Intel network drivers for Linux, go to: For the latest Intel network drivers for Linux, refer to the following
http://appsr.intel.com/scripts-df/support_intel.asp http://downloadfinder.intel.com/scripts-df/support_intel.asp
Command Line Parameters Command Line Parameters
======================= =======================
If the driver is built as a module, the following optional parameters are If the driver is built as a module, the following optional parameters are
used by entering them on the command line with the modprobe or insmod command. used by entering them on the command line with the modprobe or insmod command
using this syntax:
modprobe e1000 [<option>=<VAL1>,<VAL2>,...]
insmod e1000 [<option>=<VAL1>,<VAL2>,...]
For example, with two PRO/1000 PCI adapters, entering: For example, with two PRO/1000 PCI adapters, entering:
insmod e1000 TxDescriptors=80,128 insmod e1000 TxDescriptors=80,128
...@@ -104,6 +95,9 @@ For example, with two PRO/1000 PCI adapters, entering: ...@@ -104,6 +95,9 @@ For example, with two PRO/1000 PCI adapters, entering:
loads the e1000 driver with 80 TX resources for the first adapter and 128 TX loads the e1000 driver with 80 TX resources for the first adapter and 128 TX
resources for the second adapter. resources for the second adapter.
The default value for each parameter is generally the recommended setting,
unless otherwise noted.
For more information about the AutoNeg, Duplex, and Speed parameters, see the For more information about the AutoNeg, Duplex, and Speed parameters, see the
"Speed and Duplex Configuration" section in this document. "Speed and Duplex Configuration" section in this document.
...@@ -129,6 +123,20 @@ Default: Read flow control settings from the EEPROM ...@@ -129,6 +123,20 @@ Default: Read flow control settings from the EEPROM
This parameter controls the automatic generation(Tx) and response(Rx) to This parameter controls the automatic generation(Tx) and response(Rx) to
Ethernet PAUSE frames. Ethernet PAUSE frames.
InterruptThrottleRate
Valid Range: 100-100000 (0=off, 1=dynamic)
Default Value: 1
This value represents the maximum number of interrupts per second the
controller generates. InterruptThrottleRate is another setting used in
interrupt moderation. Dynamic mode uses a heuristic algorithm to adjust
InterruptThrottleRate based on the current traffic load.
NOTE: InterruptThrottleRate takes precedence over the TxAbsIntDelay and
RxAbsIntDelay parameters. In other words, minimizing the receive
and/or transmit absolute delays does not force the controller to
generate more interrupts than what the Interrupt Throttle Rate
allows.
RxDescriptors RxDescriptors
Valid Range: 80-256 for 82542 and 82543-based adapters Valid Range: 80-256 for 82542 and 82543-based adapters
80-4096 for 82540, 82544, 82545, and 82546-based adapters 80-4096 for 82540, 82544, 82545, and 82546-based adapters
...@@ -176,7 +184,7 @@ Default Value: 0 (auto-negotiate at all supported speeds) ...@@ -176,7 +184,7 @@ Default Value: 0 (auto-negotiate at all supported speeds)
Speed forces the line speed to the specified value in megabits per second Speed forces the line speed to the specified value in megabits per second
(Mbps). If this parameter is not specified or is set to 0 and the link (Mbps). If this parameter is not specified or is set to 0 and the link
partner is set to auto-negotiate, the board will auto-detect the correct partner is set to auto-negotiate, the board will auto-detect the correct
speed. Duplex must also be set when Speed is set to either 10 or 100. speed. Duplex should also be set when Speed is set to either 10 or 100.
TxDescriptors TxDescriptors
Valid Range: 80-256 for 82542 and 82543-based adapters Valid Range: 80-256 for 82542 and 82543-based adapters
...@@ -205,7 +213,7 @@ Default Value: 64 ...@@ -205,7 +213,7 @@ Default Value: 64
along with TxIntDelay, may improve traffic throughput in specific along with TxIntDelay, may improve traffic throughput in specific
network conditions. network conditions.
XsumRX (not available on the PRO/1000 Gigabit Server Adapter) XsumRX (not available on the 82542-based adapter)
Valid Range: 0-1 Valid Range: 0-1
Default Value: 1 Default Value: 1
A value of '1' indicates that the driver should enable IP checksum A value of '1' indicates that the driver should enable IP checksum
...@@ -230,8 +238,8 @@ For copper-based boards, the keywords interact as follows: ...@@ -230,8 +238,8 @@ For copper-based boards, the keywords interact as follows:
If Speed = 1000, limited auto-negotiation is enabled and only 1000 Mbps is If Speed = 1000, limited auto-negotiation is enabled and only 1000 Mbps is
advertised (The 1000BaseT spec requires auto-negotiation.) advertised (The 1000BaseT spec requires auto-negotiation.)
If Speed = 10 or 100, then both Speed and Duplex must be set. Auto- If Speed = 10 or 100, then both Speed and Duplex should be set. Auto-
negotiation is disabled, and the AutoNeg parameter is ignored. Partner MUST negotiation is disabled, and the AutoNeg parameter is ignored. Partner SHOULD
also be forced. also be forced.
The AutoNeg parameter is used when more control is required over the auto- The AutoNeg parameter is used when more control is required over the auto-
...@@ -263,6 +271,12 @@ Additional Configurations ...@@ -263,6 +271,12 @@ Additional Configurations
ifconfig ethx mtu 9000 up ifconfig ethx mtu 9000 up
The maximum MTU setting for Jumbo Frames is 16110. This value coincides
with the maximum Jumbo Frames size of 16128.
NOTE: Jumbo Frames are supported at 1000 Mbps only. Using Jumbo Frames at
10 or 100 Mbps may result in poor performance or loss of link.
Known Issues Known Issues
============ ============
...@@ -279,7 +293,7 @@ Known Issues ...@@ -279,7 +293,7 @@ Known Issues
Support Support
======= =======
For general information and support, go to the Intel support website at: For general information, go to the Intel support website at:
http://support.intel.com http://support.intel.com
......
...@@ -923,10 +923,11 @@ M: scott.feldman@intel.com ...@@ -923,10 +923,11 @@ M: scott.feldman@intel.com
S: Supported S: Supported
INTEL PRO/1000 GIGABIT ETHERNET SUPPORT INTEL PRO/1000 GIGABIT ETHERNET SUPPORT
P: Chris Leech P: Jeb Cramer
M: christopher.leech@intel.com M: cramerj@intel.com
P: Scott Feldman P: Scott Feldman
M: scott.feldman@intel.com M: scott.feldman@intel.com
W: http://sourceforge.net/projects/e1000/
S: Supported S: Supported
INTERMEZZO FILE SYSTEM INTERMEZZO FILE SYSTEM
......
...@@ -73,10 +73,10 @@ NT_MASK = 0x00004000 ...@@ -73,10 +73,10 @@ NT_MASK = 0x00004000
VM_MASK = 0x00020000 VM_MASK = 0x00020000
/* /*
* ESP0 is at offset 4. 0x100 is the size of the TSS, and * ESP0 is at offset 4. 0x200 is the size of the TSS, and
* also thus the top-of-stack pointer offset of SYSENTER_ESP * also thus the top-of-stack pointer offset of SYSENTER_ESP
*/ */
TSS_ESP0_OFFSET = (4 - 0x100) TSS_ESP0_OFFSET = (4 - 0x200)
#ifdef CONFIG_PREEMPT #ifdef CONFIG_PREEMPT
#define preempt_stop cli #define preempt_stop cli
...@@ -479,23 +479,32 @@ device_not_available_emulate: ...@@ -479,23 +479,32 @@ device_not_available_emulate:
* by hand onto the new stack - while updating the return eip past * by hand onto the new stack - while updating the return eip past
* the instruction that would have done it for sysenter. * the instruction that would have done it for sysenter.
*/ */
#define CHECK_SYSENTER_EIP \ #define FIX_STACK(offset, ok, label) \
cmpl $sysenter_entry,(%esp); \ cmpw $__KERNEL_CS,4(%esp); \
jne 1f; \ jne ok; \
movl TSS_ESP0_OFFSET+12(%esp),%esp; \ label: \
movl TSS_ESP0_OFFSET+offset(%esp),%esp; \
pushfl; \ pushfl; \
pushl $__KERNEL_CS; \ pushl $__KERNEL_CS; \
pushl $sysenter_past_esp; \ pushl $sysenter_past_esp
1:
ENTRY(debug) ENTRY(debug)
CHECK_SYSENTER_EIP cmpl $sysenter_entry,(%esp)
jne debug_stack_correct
FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
debug_stack_correct:
pushl $0 pushl $0
pushl $do_debug pushl $do_debug
jmp error_code jmp error_code
ENTRY(nmi) ENTRY(nmi)
CHECK_SYSENTER_EIP cmpl $sysenter_entry,(%esp)
je nmi_stack_fixup
cmpl $debug - 1,(%esp)
jle nmi_stack_correct
cmpl $debug_esp_fix_insn,(%esp)
jle nmi_debug_stack_fixup
nmi_stack_correct:
pushl %eax pushl %eax
SAVE_ALL SAVE_ALL
movl %esp, %edx movl %esp, %edx
...@@ -505,6 +514,13 @@ ENTRY(nmi) ...@@ -505,6 +514,13 @@ ENTRY(nmi)
addl $8, %esp addl $8, %esp
RESTORE_ALL RESTORE_ALL
nmi_stack_fixup:
FIX_STACK(12,nmi_stack_correct, 1)
jmp nmi_stack_correct
nmi_debug_stack_fixup:
FIX_STACK(24,nmi_stack_correct, 1)
jmp nmi_stack_correct
ENTRY(int3) ENTRY(int3)
pushl $0 pushl $0
pushl $do_int3 pushl $do_int3
......
...@@ -56,6 +56,10 @@ ...@@ -56,6 +56,10 @@
v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org> v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
- Introduce driver model for EISA cards. - Introduce driver model for EISA cards.
*/ */
/*
FIXES for PC-9800:
Shu Iwanaga: 3c569B(PC-9801 C-bus) support
*/
#define DRV_NAME "3c509" #define DRV_NAME "3c509"
#define DRV_VERSION "1.19b" #define DRV_VERSION "1.19b"
...@@ -257,7 +261,7 @@ static struct mca_driver el3_mca_driver = { ...@@ -257,7 +261,7 @@ static struct mca_driver el3_mca_driver = {
}; };
#endif /* CONFIG_MCA */ #endif /* CONFIG_MCA */
#ifdef __ISAPNP__ #if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
static struct isapnp_device_id el3_isapnp_adapters[] __initdata = { static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090), ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
...@@ -350,7 +354,7 @@ static void el3_common_remove (struct net_device *dev) ...@@ -350,7 +354,7 @@ static void el3_common_remove (struct net_device *dev)
if (lp->pmdev) if (lp->pmdev)
pm_unregister(lp->pmdev); pm_unregister(lp->pmdev);
#endif #endif
#ifdef __ISAPNP__ #if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
if (lp->type == EL3_PNP) if (lp->type == EL3_PNP)
pnp_device_detach(to_pnp_dev(lp->dev)); pnp_device_detach(to_pnp_dev(lp->dev));
#endif #endif
...@@ -368,12 +372,12 @@ static int __init el3_probe(int card_idx) ...@@ -368,12 +372,12 @@ static int __init el3_probe(int card_idx)
int ioaddr, irq, if_port; int ioaddr, irq, if_port;
u16 phys_addr[3]; u16 phys_addr[3];
static int current_tag; static int current_tag;
#ifdef __ISAPNP__ #if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
static int pnp_cards; static int pnp_cards;
struct pnp_dev *idev = NULL; struct pnp_dev *idev = NULL;
#endif /* __ISAPNP__ */ #endif /* __ISAPNP__ */
#ifdef __ISAPNP__ #if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
if (nopnp == 1) if (nopnp == 1)
goto no_pnp; goto no_pnp;
...@@ -421,6 +425,9 @@ static int __init el3_probe(int card_idx) ...@@ -421,6 +425,9 @@ static int __init el3_probe(int card_idx)
no_pnp: no_pnp:
#endif /* __ISAPNP__ */ #endif /* __ISAPNP__ */
#ifdef CONFIG_X86_PC9800
id_port = 0x71d0;
#else
/* Select an open I/O location at 0x1*0 to do contention select. */ /* Select an open I/O location at 0x1*0 to do contention select. */
for ( ; id_port < 0x200; id_port += 0x10) { for ( ; id_port < 0x200; id_port += 0x10) {
if (check_region(id_port, 1)) if (check_region(id_port, 1))
...@@ -435,6 +442,7 @@ static int __init el3_probe(int card_idx) ...@@ -435,6 +442,7 @@ static int __init el3_probe(int card_idx)
printk(" WARNING: No I/O port available for 3c509 activation.\n"); printk(" WARNING: No I/O port available for 3c509 activation.\n");
return -ENODEV; return -ENODEV;
} }
#endif /* CONFIG_X86_PC9800 */
/* Next check for all ISA bus boards by sending the ID sequence to the /* Next check for all ISA bus boards by sending the ID sequence to the
ID_PORT. We find cards past the first by setting the 'current_tag' ID_PORT. We find cards past the first by setting the 'current_tag'
on cards as they are found. Cards with their tag set will not on cards as they are found. Cards with their tag set will not
...@@ -465,7 +473,7 @@ static int __init el3_probe(int card_idx) ...@@ -465,7 +473,7 @@ static int __init el3_probe(int card_idx)
phys_addr[i] = htons(id_read_eeprom(i)); phys_addr[i] = htons(id_read_eeprom(i));
} }
#ifdef __ISAPNP__ #if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
if (nopnp == 0) { if (nopnp == 0) {
/* The ISA PnP 3c509 cards respond to the ID sequence. /* The ISA PnP 3c509 cards respond to the ID sequence.
This check is needed in order not to register them twice. */ This check is needed in order not to register them twice. */
...@@ -490,9 +498,19 @@ static int __init el3_probe(int card_idx) ...@@ -490,9 +498,19 @@ static int __init el3_probe(int card_idx)
{ {
unsigned int iobase = id_read_eeprom(8); unsigned int iobase = id_read_eeprom(8);
if_port = iobase >> 14; if_port = iobase >> 14;
#ifdef CONFIG_X86_PC9800
ioaddr = 0x40d0 + ((iobase & 0x1f) << 8);
#else
ioaddr = 0x200 + ((iobase & 0x1f) << 4); ioaddr = 0x200 + ((iobase & 0x1f) << 4);
#endif
} }
irq = id_read_eeprom(9) >> 12; irq = id_read_eeprom(9) >> 12;
#ifdef CONFIG_X86_PC9800
if (irq == 7)
irq = 6;
else if (irq == 15)
irq = 13;
#endif
if (!(dev = init_etherdev(NULL, sizeof(struct el3_private)))) if (!(dev = init_etherdev(NULL, sizeof(struct el3_private))))
return -ENOMEM; return -ENOMEM;
...@@ -522,7 +540,11 @@ static int __init el3_probe(int card_idx) ...@@ -522,7 +540,11 @@ static int __init el3_probe(int card_idx)
outb(0xd0 + ++current_tag, id_port); outb(0xd0 + ++current_tag, id_port);
/* Activate the adaptor at the EEPROM location. */ /* Activate the adaptor at the EEPROM location. */
#ifdef CONFIG_X86_PC9800
outb((ioaddr >> 8) | 0xe0, id_port);
#else
outb((ioaddr >> 4) | 0xe0, id_port); outb((ioaddr >> 4) | 0xe0, id_port);
#endif
EL3WINDOW(0); EL3WINDOW(0);
if (inw(ioaddr) != 0x6d50) { if (inw(ioaddr) != 0x6d50) {
...@@ -534,7 +556,7 @@ static int __init el3_probe(int card_idx) ...@@ -534,7 +556,7 @@ static int __init el3_probe(int card_idx)
/* Free the interrupt so that some other card can use it. */ /* Free the interrupt so that some other card can use it. */
outw(0x0f00, ioaddr + WN0_IRQ); outw(0x0f00, ioaddr + WN0_IRQ);
#ifdef __ISAPNP__ #if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
found: /* PNP jumps here... */ found: /* PNP jumps here... */
#endif /* __ISAPNP__ */ #endif /* __ISAPNP__ */
...@@ -543,7 +565,7 @@ static int __init el3_probe(int card_idx) ...@@ -543,7 +565,7 @@ static int __init el3_probe(int card_idx)
dev->irq = irq; dev->irq = irq;
dev->if_port = if_port; dev->if_port = if_port;
lp = dev->priv; lp = dev->priv;
#ifdef __ISAPNP__ #if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
lp->dev = &idev->dev; lp->dev = &idev->dev;
#endif #endif
...@@ -1388,6 +1410,12 @@ el3_up(struct net_device *dev) ...@@ -1388,6 +1410,12 @@ el3_up(struct net_device *dev)
outw(0x0001, ioaddr + 4); outw(0x0001, ioaddr + 4);
/* Set the IRQ line. */ /* Set the IRQ line. */
#ifdef CONFIG_X86_PC9800
if (dev->irq == 6)
dev->irq = 7;
else if (dev->irq == 13)
dev->irq = 15;
#endif
outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ); outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
/* Set the station address in window 2 each time opened. */ /* Set the station address in window 2 each time opened. */
...@@ -1550,7 +1578,7 @@ MODULE_PARM_DESC(debug, "debug level (0-6)"); ...@@ -1550,7 +1578,7 @@ MODULE_PARM_DESC(debug, "debug level (0-6)");
MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)"); MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)");
MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt"); MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
#ifdef __ISAPNP__ #if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
MODULE_PARM(nopnp, "i"); MODULE_PARM(nopnp, "i");
MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)"); MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters); MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
......
...@@ -123,7 +123,8 @@ struct ei_device { ...@@ -123,7 +123,8 @@ struct ei_device {
#define inb_p(port) in_8(port) #define inb_p(port) in_8(port)
#define outb_p(val,port) out_8(port,val) #define outb_p(val,port) out_8(port,val)
#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE) #elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE) || \
defined(CONFIG_NET_CBUS)
#define EI_SHIFT(x) (ei_local->reg_offset[x]) #define EI_SHIFT(x) (ei_local->reg_offset[x])
#else #else
#define EI_SHIFT(x) (x) #define EI_SHIFT(x) (x)
......
...@@ -663,7 +663,7 @@ config EL16 ...@@ -663,7 +663,7 @@ config EL16
as <file:Documentation/networking/net-modules.txt>. as <file:Documentation/networking/net-modules.txt>.
config EL3 config EL3
tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support" tristate "3c509/3c529 (MCA)/3c569B (98)/3c579 \"EtherLink III\" support"
depends on NET_VENDOR_3COM && (ISA || EISA || MCA) depends on NET_VENDOR_3COM && (ISA || EISA || MCA)
---help--- ---help---
If you have a network (Ethernet) card belonging to the 3Com If you have a network (Ethernet) card belonging to the 3Com
...@@ -932,7 +932,7 @@ config NI65 ...@@ -932,7 +932,7 @@ config NI65
source "drivers/net/tulip/Kconfig" source "drivers/net/tulip/Kconfig"
config AT1700 config AT1700
tristate "AT1700/1720 support (EXPERIMENTAL)" tristate "AT1700/1720/RE1000Plus(C-Bus) support (EXPERIMENTAL)"
depends on NET_ETHERNET && (ISA || MCA) && EXPERIMENTAL depends on NET_ETHERNET && (ISA || MCA) && EXPERIMENTAL
---help--- ---help---
If you have a network (Ethernet) card of this type, say Y and read If you have a network (Ethernet) card of this type, say Y and read
...@@ -978,7 +978,7 @@ config HP100 ...@@ -978,7 +978,7 @@ config HP100
config NET_ISA config NET_ISA
bool "Other ISA cards" bool "Other ISA cards"
depends on NET_ETHERNET && ISA depends on NET_ETHERNET && ISA && !X86_PC9800
---help--- ---help---
If your network (Ethernet) card hasn't been mentioned yet and its If your network (Ethernet) card hasn't been mentioned yet and its
bus system (that's the way the cards talks to the other components bus system (that's the way the cards talks to the other components
...@@ -1176,6 +1176,55 @@ config SK_G16 ...@@ -1176,6 +1176,55 @@ config SK_G16
the Ethernet-HOWTO, available from the Ethernet-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>. <http://www.linuxdoc.org/docs.html#howto>.
config NET_CBUS
bool "NEC PC-9800 C-bus cards"
depends on NET_ETHERNET && ISA && X86_PC9800
---help---
If your network (Ethernet) card hasn't been mentioned yet and its
bus system (that's the way the cards talks to the other components
of your computer) is NEC PC-9800 C-Bus, say Y.
config NE2K_CBUS
tristate "Most NE2000-based Ethernet support"
depends on NET_CBUS
config NE2K_CBUS_EGY98
bool "Melco EGY-98 support"
depends on NE2K_CBUS
config NE2K_CBUS_LGY98
bool "Melco LGY-98 support"
depends on NE2K_CBUS
config NE2K_CBUS_ICM
bool "ICM IF-27xxET support"
depends on NE2K_CBUS
config NE2K_CBUS_IOLA98
bool "I-O DATA LA-98 support"
depends on NE2K_CBUS
config NE2K_CBUS_CNET98EL
bool "Contec C-NET(98)E/L support"
depends on NE2K_CBUS
config NE2K_CBUS_CNET98EL_IO_BASE
hex "C-NET(98)E/L I/O base address (0xaaed or 0x55ed)"
depends on NE2K_CBUS_CNET98EL
default "0xaaed"
config NE2K_CBUS_ATLA98
bool "Allied Telesis LA-98 Support"
depends on NE2K_CBUS
config NE2K_CBUS_BDN
bool "ELECOM Laneed LD-BDN[123]A Support"
depends on NE2K_CBUS
config NE2K_CBUS_NEC108
bool "NEC PC-9801-108 Support"
depends on NE2K_CBUS
config SKMC config SKMC
tristate "SKnet MCA support" tristate "SKnet MCA support"
depends on NET_ETHERNET && MCA depends on NET_ETHERNET && MCA
...@@ -1904,6 +1953,7 @@ config E1000 ...@@ -1904,6 +1953,7 @@ config E1000
82544 PRO/1000 XF Server Adapter A50484-xxx 82544 PRO/1000 XF Server Adapter A50484-xxx
82544 PRO/1000 T Desktop Adapter A62947-xxx 82544 PRO/1000 T Desktop Adapter A62947-xxx
82540 PRO/1000 MT Desktop Adapter A78408-xxx 82540 PRO/1000 MT Desktop Adapter A78408-xxx
82541 PRO/1000 MT Desktop Adapter C91016-xxx
82545 PRO/1000 MT Server Adapter A92165-xxx 82545 PRO/1000 MT Server Adapter A92165-xxx
82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx 82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx
82545 PRO/1000 MF Server Adapter A91622-xxx 82545 PRO/1000 MF Server Adapter A91622-xxx
......
...@@ -81,6 +81,7 @@ obj-$(CONFIG_ARM_ETHERH) += 8390.o ...@@ -81,6 +81,7 @@ obj-$(CONFIG_ARM_ETHERH) += 8390.o
obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_WD80x3) += wd.o 8390.o
obj-$(CONFIG_EL2) += 3c503.o 8390.o obj-$(CONFIG_EL2) += 3c503.o 8390.o
obj-$(CONFIG_NE2000) += ne.o 8390.o obj-$(CONFIG_NE2000) += ne.o 8390.o
obj-$(CONFIG_NE2K_CBUS) += ne2k_cbus.o 8390.o
obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o
obj-$(CONFIG_HPLAN) += hp.o 8390.o obj-$(CONFIG_HPLAN) += hp.o 8390.o
obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o
......
...@@ -19,6 +19,7 @@ obj-$(CONFIG_MACE) += crc32.o ...@@ -19,6 +19,7 @@ obj-$(CONFIG_MACE) += crc32.o
obj-$(CONFIG_MACMACE) += crc32.o obj-$(CONFIG_MACMACE) += crc32.o
obj-$(CONFIG_MIPS_AU1000_ENET) += crc32.o obj-$(CONFIG_MIPS_AU1000_ENET) += crc32.o
obj-$(CONFIG_NATSEMI) += crc32.o obj-$(CONFIG_NATSEMI) += crc32.o
obj-$(CONFIG_NE2K_CBUS) += crc32.o
obj-$(CONFIG_PCMCIA_FMVJ18X) += crc32.o obj-$(CONFIG_PCMCIA_FMVJ18X) += crc32.o
obj-$(CONFIG_PCMCIA_SMC91C92) += crc32.o obj-$(CONFIG_PCMCIA_SMC91C92) += crc32.o
obj-$(CONFIG_PCMCIA_XIRTULIP) += crc32.o obj-$(CONFIG_PCMCIA_XIRTULIP) += crc32.o
......
...@@ -233,7 +233,7 @@ static struct devprobe isa_probes[] __initdata = { ...@@ -233,7 +233,7 @@ static struct devprobe isa_probes[] __initdata = {
#ifdef CONFIG_E2100 /* Cabletron E21xx series. */ #ifdef CONFIG_E2100 /* Cabletron E21xx series. */
{e2100_probe, 0}, {e2100_probe, 0},
#endif #endif
#ifdef CONFIG_NE2000 /* ISA (use ne2k-pci for PCI cards) */ #if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS) /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */
{ne_probe, 0}, {ne_probe, 0},
#endif #endif
#ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */ #ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */
......
...@@ -34,6 +34,10 @@ ...@@ -34,6 +34,10 @@
only is it difficult to detect, it also moves around in I/O space in only is it difficult to detect, it also moves around in I/O space in
response to inb()s from other device probes! response to inb()s from other device probes!
*/ */
/*
99/03/03 Allied Telesis RE1000 Plus support by T.Hagawa
99/12/30 port to 2.3.35 by K.Takai
*/
#include <linux/config.h> #include <linux/config.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -76,10 +80,17 @@ static int fmv18x_probe_list[] __initdata = { ...@@ -76,10 +80,17 @@ static int fmv18x_probe_list[] __initdata = {
* ISA * ISA
*/ */
#ifndef CONFIG_X86_PC9800
static int at1700_probe_list[] __initdata = { static int at1700_probe_list[] __initdata = {
0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
}; };
#else /* CONFIG_X86_PC9800 */
static int at1700_probe_list[] __initdata = {
0x1d6, 0x1d8, 0x1da, 0x1d4, 0xd4, 0xd2, 0xd8, 0xd0, 0
};
#endif /* CONFIG_X86_PC9800 */
/* /*
* MCA * MCA
*/ */
...@@ -122,6 +133,7 @@ struct net_local { ...@@ -122,6 +133,7 @@ struct net_local {
/* Offsets from the base address. */ /* Offsets from the base address. */
#ifndef CONFIG_X86_PC9800
#define STATUS 0 #define STATUS 0
#define TX_STATUS 0 #define TX_STATUS 0
#define RX_STATUS 1 #define RX_STATUS 1
...@@ -136,6 +148,7 @@ struct net_local { ...@@ -136,6 +148,7 @@ struct net_local {
#define TX_START 10 #define TX_START 10
#define COL16CNTL 11 /* Controll Reg for 16 collisions */ #define COL16CNTL 11 /* Controll Reg for 16 collisions */
#define MODE13 13 #define MODE13 13
#define RX_CTRL 14
/* Configuration registers only on the '865A/B chips. */ /* Configuration registers only on the '865A/B chips. */
#define EEPROM_Ctrl 16 #define EEPROM_Ctrl 16
#define EEPROM_Data 17 #define EEPROM_Data 17
...@@ -144,8 +157,39 @@ struct net_local { ...@@ -144,8 +157,39 @@ struct net_local {
#define IOCONFIG 18 /* Either read the jumper, or move the I/O. */ #define IOCONFIG 18 /* Either read the jumper, or move the I/O. */
#define IOCONFIG1 19 #define IOCONFIG1 19
#define SAPROM 20 /* The station address PROM, if no EEPROM. */ #define SAPROM 20 /* The station address PROM, if no EEPROM. */
#define MODE24 24
#define RESET 31 /* Write to reset some parts of the chip. */ #define RESET 31 /* Write to reset some parts of the chip. */
#define AT1700_IO_EXTENT 32 #define AT1700_IO_EXTENT 32
#define PORT_OFFSET(o) (o)
#else /* CONFIG_X86_PC9800 */
#define STATUS (0x0000)
#define TX_STATUS (0x0000)
#define RX_STATUS (0x0001)
#define TX_INTR (0x0200)/* Bit-mapped interrupt enable registers. */
#define RX_INTR (0x0201)
#define TX_MODE (0x0400)
#define RX_MODE (0x0401)
#define CONFIG_0 (0x0600)/* Misc. configuration settings. */
#define CONFIG_1 (0x0601)
/* Run-time register bank 2 definitions. */
#define DATAPORT (0x0800)/* Word-wide DMA or programmed-I/O dataport. */
#define TX_START (0x0a00)
#define COL16CNTL (0x0a01)/* Controll Reg for 16 collisions */
#define MODE13 (0x0c01)
#define RX_CTRL (0x0e00)
/* Configuration registers only on the '865A/B chips. */
#define EEPROM_Ctrl (0x1000)
#define EEPROM_Data (0x1200)
#define CARDSTATUS 16 /* FMV-18x Card Status */
#define CARDSTATUS1 17 /* FMV-18x Card Status */
#define IOCONFIG (0x1400)/* Either read the jumper, or move the I/O. */
#define IOCONFIG1 (0x1600)
#define SAPROM 20 /* The station address PROM, if no EEPROM. */
#define MODE24 (0x1800)/* The station address PROM, if no EEPROM. */
#define RESET (0x1e01)/* Write to reset some parts of the chip. */
#define PORT_OFFSET(o) ({ int _o_ = (o); (_o_ & ~1) * 0x100 + (_o_ & 1); })
#endif /* CONFIG_X86_PC9800 */
#define TX_TIMEOUT 10 #define TX_TIMEOUT 10
...@@ -225,8 +269,20 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) ...@@ -225,8 +269,20 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
int slot, ret = -ENODEV; int slot, ret = -ENODEV;
struct net_local *lp; struct net_local *lp;
#ifndef CONFIG_X86_PC9800
if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name)) if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name))
return -EBUSY; return -EBUSY;
#else
for (i = 0; i < 0x2000; i += 0x0200) {
if (!request_region(ioaddr + i, 2, dev->name)) {
while (i > 0) {
i -= 0x0200;
release_region(ioaddr + i, 2);
}
return -EBUSY;
}
}
#endif
/* Resetting the chip doesn't reset the ISA interface, so don't bother. /* Resetting the chip doesn't reset the ISA interface, so don't bother.
That means we have to be careful with the register values we probe for. That means we have to be careful with the register values we probe for.
...@@ -317,10 +373,17 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) ...@@ -317,10 +373,17 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
/* Reset the internal state machines. */ /* Reset the internal state machines. */
outb(0, ioaddr + RESET); outb(0, ioaddr + RESET);
if (is_at1700) if (is_at1700) {
#ifndef CONFIG_X86_PC9800
irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04) irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04)
| (read_eeprom(ioaddr, 0)>>14)]; | (read_eeprom(ioaddr, 0)>>14)];
else { #else
{
char re1000plus_irqmap[4] = {3, 5, 6, 12};
irq = re1000plus_irqmap[inb(ioaddr + IOCONFIG1) >> 6];
}
#endif
} else {
/* Check PnP mode for FMV-183/184/183A/184A. */ /* Check PnP mode for FMV-183/184/183A/184A. */
/* This PnP routine is very poor. IO and IRQ should be known. */ /* This PnP routine is very poor. IO and IRQ should be known. */
if (inb(ioaddr + CARDSTATUS1) & 0x20) { if (inb(ioaddr + CARDSTATUS1) & 0x20) {
...@@ -392,18 +455,22 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) ...@@ -392,18 +455,22 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
/* Set the station address in bank zero. */ /* Set the station address in bank zero. */
outb(0x00, ioaddr + CONFIG_1); outb(0x00, ioaddr + CONFIG_1);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
outb(dev->dev_addr[i], ioaddr + 8 + i); outb(dev->dev_addr[i], ioaddr + PORT_OFFSET(8 + i));
/* Switch to bank 1 and set the multicast table to accept none. */ /* Switch to bank 1 and set the multicast table to accept none. */
outb(0x04, ioaddr + CONFIG_1); outb(0x04, ioaddr + CONFIG_1);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
outb(0x00, ioaddr + 8 + i); outb(0x00, ioaddr + PORT_OFFSET(8 + i));
/* Switch to bank 2 */ /* Switch to bank 2 */
/* Lock our I/O address, and set manual processing mode for 16 collisions. */ /* Lock our I/O address, and set manual processing mode for 16 collisions. */
outb(0x08, ioaddr + CONFIG_1); outb(0x08, ioaddr + CONFIG_1);
#ifndef CONFIG_X86_PC9800
outb(dev->if_port, ioaddr + MODE13); outb(dev->if_port, ioaddr + MODE13);
#else
outb(0, ioaddr + MODE13);
#endif
outb(0x00, ioaddr + COL16CNTL); outb(0x00, ioaddr + COL16CNTL);
if (net_debug) if (net_debug)
...@@ -447,7 +514,12 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) ...@@ -447,7 +514,12 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
kfree(dev->priv); kfree(dev->priv);
dev->priv = NULL; dev->priv = NULL;
err_out: err_out:
#ifndef CONFIG_X86_PC9800
release_region(ioaddr, AT1700_IO_EXTENT); release_region(ioaddr, AT1700_IO_EXTENT);
#else
for (i = 0; i < 0x2000; i += 0x0200)
release_region(ioaddr + i, 2);
#endif
return ret; return ret;
} }
...@@ -459,7 +531,11 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) ...@@ -459,7 +531,11 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
#define EE_DATA_READ 0x80 /* EEPROM chip data out, in reg. 17. */ #define EE_DATA_READ 0x80 /* EEPROM chip data out, in reg. 17. */
/* Delay between EEPROM clock transitions. */ /* Delay between EEPROM clock transitions. */
#ifndef CONFIG_X86_PC9800
#define eeprom_delay() do { } while (0) #define eeprom_delay() do { } while (0)
#else
#define eeprom_delay() __asm__ ("out%B0 %%al,%0" :: "N"(0x5f))
#endif
/* The EEPROM commands include the alway-set leading bit. */ /* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5 << 6) #define EE_WRITE_CMD (5 << 6)
...@@ -542,12 +618,12 @@ static void net_tx_timeout (struct net_device *dev) ...@@ -542,12 +618,12 @@ static void net_tx_timeout (struct net_device *dev)
inw (ioaddr + STATUS), inb (ioaddr + TX_STATUS) & 0x80 inw (ioaddr + STATUS), inb (ioaddr + TX_STATUS) & 0x80
? "IRQ conflict" : "network cable problem"); ? "IRQ conflict" : "network cable problem");
printk ("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n", printk ("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
dev->name, inw (ioaddr + 0), inw (ioaddr + 2), inw (ioaddr + 4), dev->name, inw(ioaddr + TX_STATUS), inw(ioaddr + TX_INTR), inw(ioaddr + TX_MODE),
inw (ioaddr + 6), inw (ioaddr + 8), inw (ioaddr + 10), inw(ioaddr + CONFIG_0), inw(ioaddr + DATAPORT), inw(ioaddr + TX_START),
inw (ioaddr + 12), inw (ioaddr + 14)); inw(ioaddr + MODE13 - 1), inw(ioaddr + RX_CTRL));
lp->stats.tx_errors++; lp->stats.tx_errors++;
/* ToDo: We should try to restart the adaptor... */ /* ToDo: We should try to restart the adaptor... */
outw (0xffff, ioaddr + 24); outw(0xffff, ioaddr + MODE24);
outw (0xffff, ioaddr + TX_STATUS); outw (0xffff, ioaddr + TX_STATUS);
outb (0x5a, ioaddr + CONFIG_0); outb (0x5a, ioaddr + CONFIG_0);
outb (0xe8, ioaddr + CONFIG_1); outb (0xe8, ioaddr + CONFIG_1);
...@@ -704,7 +780,7 @@ net_rx(struct net_device *dev) ...@@ -704,7 +780,7 @@ net_rx(struct net_device *dev)
dev->name, inb(ioaddr + RX_MODE), status); dev->name, inb(ioaddr + RX_MODE), status);
#ifndef final_version #ifndef final_version
if (status == 0) { if (status == 0) {
outb(0x05, ioaddr + 14); outb(0x05, ioaddr + RX_CTRL);
break; break;
} }
#endif #endif
...@@ -724,7 +800,7 @@ net_rx(struct net_device *dev) ...@@ -724,7 +800,7 @@ net_rx(struct net_device *dev)
dev->name, pkt_len); dev->name, pkt_len);
/* Prime the FIFO and then flush the packet. */ /* Prime the FIFO and then flush the packet. */
inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
outb(0x05, ioaddr + 14); outb(0x05, ioaddr + RX_CTRL);
lp->stats.rx_errors++; lp->stats.rx_errors++;
break; break;
} }
...@@ -734,7 +810,7 @@ net_rx(struct net_device *dev) ...@@ -734,7 +810,7 @@ net_rx(struct net_device *dev)
dev->name, pkt_len); dev->name, pkt_len);
/* Prime the FIFO and then flush the packet. */ /* Prime the FIFO and then flush the packet. */
inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
outb(0x05, ioaddr + 14); outb(0x05, ioaddr + RX_CTRL);
lp->stats.rx_dropped++; lp->stats.rx_dropped++;
break; break;
} }
...@@ -761,7 +837,7 @@ net_rx(struct net_device *dev) ...@@ -761,7 +837,7 @@ net_rx(struct net_device *dev)
if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40) if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
break; break;
inw(ioaddr + DATAPORT); /* dummy status read */ inw(ioaddr + DATAPORT); /* dummy status read */
outb(0x05, ioaddr + 14); outb(0x05, ioaddr + RX_CTRL);
} }
if (net_debug > 5) if (net_debug > 5)
...@@ -844,24 +920,28 @@ set_rx_mode(struct net_device *dev) ...@@ -844,24 +920,28 @@ set_rx_mode(struct net_device *dev)
outb(0x02, ioaddr + RX_MODE); /* Use normal mode. */ outb(0x02, ioaddr + RX_MODE); /* Use normal mode. */
} }
save_flags(flags); spin_lock_irqsave (&lp->lock, flags);
cli();
if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) { if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
int saved_bank = inw(ioaddr + CONFIG_0); int saved_bank = inw(ioaddr + CONFIG_0);
/* Switch to bank 1 and set the multicast table. */ /* Switch to bank 1 and set the multicast table. */
outw((saved_bank & ~0x0C00) | 0x0480, ioaddr + CONFIG_0); outw((saved_bank & ~0x0C00) | 0x0480, ioaddr + CONFIG_0);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
outb(mc_filter[i], ioaddr + 8 + i); outb(mc_filter[i], ioaddr + PORT_OFFSET(8 + i));
memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter)); memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
outw(saved_bank, ioaddr + CONFIG_0); outw(saved_bank, ioaddr + CONFIG_0);
} }
restore_flags(flags); spin_unlock_irqrestore (&lp->lock, flags);
return; return;
} }
#ifdef MODULE #ifdef MODULE
static struct net_device dev_at1700; static struct net_device dev_at1700;
#ifndef CONFIG_X86_PC9800
static int io = 0x260; static int io = 0x260;
#else
static int io = 0xd0;
#endif
static int irq; static int irq;
MODULE_PARM(io, "i"); MODULE_PARM(io, "i");
...@@ -901,7 +981,15 @@ cleanup_module(void) ...@@ -901,7 +981,15 @@ cleanup_module(void)
/* If we don't do this, we can't re-insmod it later. */ /* If we don't do this, we can't re-insmod it later. */
free_irq(dev_at1700.irq, NULL); free_irq(dev_at1700.irq, NULL);
#ifndef CONFIG_X86_PC9800
release_region(dev_at1700.base_addr, AT1700_IO_EXTENT); release_region(dev_at1700.base_addr, AT1700_IO_EXTENT);
#else
{
int i;
for (i = 0; i < 0x2000; i += 0x200)
release_region(dev_at1700.base_addr + i, 2);
}
#endif
} }
#endif /* MODULE */ #endif /* MODULE */
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -57,6 +57,8 @@ ...@@ -57,6 +57,8 @@
#include <linux/if.h> #include <linux/if.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/if_vlan.h>
#include <linux/mii.h>
#define E100_REGS_LEN 1 #define E100_REGS_LEN 1
/* /*
...@@ -301,6 +303,9 @@ struct driver_stats { ...@@ -301,6 +303,9 @@ struct driver_stats {
/* EEPROM bit definitions */ /* EEPROM bit definitions */
/*- EEPROM control register bits */ /*- EEPROM control register bits */
#define EEPROM_FLAG_ASF 0x8000
#define EEPROM_FLAG_GCL 0x4000
#define EN_TRNF 0x10 /* Enable turnoff */ #define EN_TRNF 0x10 /* Enable turnoff */
#define EEDO 0x08 /* EEPROM data out */ #define EEDO 0x08 /* EEPROM data out */
#define EEDI 0x04 /* EEPROM data in (set for writing data) */ #define EEDI 0x04 /* EEPROM data in (set for writing data) */
...@@ -319,6 +324,8 @@ struct driver_stats { ...@@ -319,6 +324,8 @@ struct driver_stats {
#define EEPROM_COMPATIBILITY_WORD 3 #define EEPROM_COMPATIBILITY_WORD 3
#define EEPROM_PWA_NO 8 #define EEPROM_PWA_NO 8
#define EEPROM_ID_WORD 0x0A #define EEPROM_ID_WORD 0x0A
#define EEPROM_CONFIG_ASF 0x0D
#define EEPROM_SMBUS_ADDR 0x90
#define EEPROM_SUM 0xbaba #define EEPROM_SUM 0xbaba
...@@ -358,7 +365,7 @@ struct driver_stats { ...@@ -358,7 +365,7 @@ struct driver_stats {
#define CB_STATUS_MASK BIT_12_15 /* CB Status Mask (4-bits) */ #define CB_STATUS_MASK BIT_12_15 /* CB Status Mask (4-bits) */
#define CB_STATUS_COMPLETE BIT_15 /* CB Complete Bit */ #define CB_STATUS_COMPLETE BIT_15 /* CB Complete Bit */
#define CB_STATUS_OK BIT_13 /* CB OK Bit */ #define CB_STATUS_OK BIT_13 /* CB OK Bit */
#define CB_STATUS_UNDERRUN BIT_12 /* CB A Bit */ #define CB_STATUS_VLAN BIT_12 /* CB Valn detected Bit */
#define CB_STATUS_FAIL BIT_11 /* CB Fail (F) Bit */ #define CB_STATUS_FAIL BIT_11 /* CB Fail (F) Bit */
/*misc command bits */ /*misc command bits */
...@@ -851,6 +858,7 @@ struct ethtool_lpbk_data{ ...@@ -851,6 +858,7 @@ struct ethtool_lpbk_data{
}; };
struct e100_private { struct e100_private {
struct vlan_group *vlgrp;
u32 flags; /* board management flags */ u32 flags; /* board management flags */
u32 tx_per_underrun; /* number of good tx frames per underrun */ u32 tx_per_underrun; /* number of good tx frames per underrun */
unsigned int tx_count; /* count of tx frames, so we can request an interrupt */ unsigned int tx_count; /* count of tx frames, so we can request an interrupt */
...@@ -886,7 +894,6 @@ struct e100_private { ...@@ -886,7 +894,6 @@ struct e100_private {
struct driver_stats drv_stats; struct driver_stats drv_stats;
u8 rev_id; /* adapter PCI revision ID */ u8 rev_id; /* adapter PCI revision ID */
unsigned long device_type; /* device type from e100_vendor.h */
unsigned int phy_addr; /* address of PHY component */ unsigned int phy_addr; /* address of PHY component */
unsigned int PhyId; /* ID of PHY component */ unsigned int PhyId; /* ID of PHY component */
...@@ -923,8 +930,6 @@ struct e100_private { ...@@ -923,8 +930,6 @@ struct e100_private {
struct cfg_params params; /* adapter's command line parameters */ struct cfg_params params; /* adapter's command line parameters */
char *id_string;
u32 speed_duplex_caps; /* adapter's speed/duplex capabilities */ u32 speed_duplex_caps; /* adapter's speed/duplex capabilities */
/* WOL params for ethtool */ /* WOL params for ethtool */
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -521,6 +521,25 @@ e100_config_wol(struct e100_private *bdp) ...@@ -521,6 +521,25 @@ e100_config_wol(struct e100_private *bdp)
spin_unlock_bh(&(bdp->config_lock)); spin_unlock_bh(&(bdp->config_lock));
} }
void
e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable)
{
spin_lock_bh(&(bdp->config_lock));
if (enable) {
if (!(bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) {
bdp->config[22] |= CB_CFIG_VLAN_DROP_ENABLE;
E100_CONFIG(bdp, 22);
}
} else {
if ((bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) {
bdp->config[22] &= ~CB_CFIG_VLAN_DROP_ENABLE;
E100_CONFIG(bdp, 22);
}
}
spin_unlock_bh(&(bdp->config_lock));
}
/** /**
* e100_config_loopback_mode * e100_config_loopback_mode
* @bdp: atapter's private data struct * @bdp: atapter's private data struct
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -163,5 +163,5 @@ extern void e100_config_force_dplx(struct e100_private *bdp); ...@@ -163,5 +163,5 @@ extern void e100_config_force_dplx(struct e100_private *bdp);
extern u8 e100_config_loopback_mode(struct e100_private *bdp, u8 mode); extern u8 e100_config_loopback_mode(struct e100_private *bdp, u8 mode);
extern u8 e100_config_dynamic_tbd(struct e100_private *bdp, u8 enable); extern u8 e100_config_dynamic_tbd(struct e100_private *bdp, u8 enable);
extern u8 e100_config_tcb_ext_enable(struct e100_private *bdp, u8 enable); extern u8 e100_config_tcb_ext_enable(struct e100_private *bdp, u8 enable);
extern void e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable);
#endif /* _E100_CONFIG_INC_ */ #endif /* _E100_CONFIG_INC_ */
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -46,7 +46,21 @@ ...@@ -46,7 +46,21 @@
/* Change Log /* Change Log
* *
* 2.1.29 12/20/02 * 2.2.21 02/11/03
* o Removed marketing brand strings. Instead, Using generic string
* "Intel(R) PRO/100 Network Connection" for all adapters.
* o Implemented ethtool -S option
* o Strip /proc/net/PRO_LAN_Adapters files for kernel driver
* o Bug fix: Read wrong byte in EEPROM when offset is odd number
* o Bug fix: PHY loopback test fails on ICH devices
* o Bug fix: System panic on e100_close when repeating Hot Remove and
* Add in a team
* o Bug fix: Linux Bonding driver claims adapter's link loss because of
* not updating last_rx field
* o Bug fix: e100 does not check validity of MAC address
* o New feature: added ICH5 support
*
* 2.1.27 11/20/02
* o Bug fix: Device command timeout due to SMBus processing during init * o Bug fix: Device command timeout due to SMBus processing during init
* o Bug fix: Not setting/clearing I (Interrupt) bit in tcb correctly * o Bug fix: Not setting/clearing I (Interrupt) bit in tcb correctly
* o Bug fix: Not using EEPROM WoL setting as default in ethtool * o Bug fix: Not using EEPROM WoL setting as default in ethtool
...@@ -62,15 +76,6 @@ ...@@ -62,15 +76,6 @@
* ifconfig down, rmmod and insmod * ifconfig down, rmmod and insmod
* *
* 2.1.24 10/7/02 * 2.1.24 10/7/02
* o Bug fix: Wrong files under /proc/net/PRO_LAN_Adapters/ when interface
* name is changed
* o Bug fix: Rx skb corruption when Rx polling code and Rx interrupt code
* are executing during stress traffic at shared interrupt system.
* Removed Rx polling code
* o Added detailed printk if selftest failed when insmod
* o Removed misleading printks
*
* 2.1.12 8/2/02
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -81,7 +86,8 @@ ...@@ -81,7 +86,8 @@
#include "e100_ucode.h" #include "e100_ucode.h"
#include "e100_config.h" #include "e100_config.h"
#include "e100_phy.h" #include "e100_phy.h"
#include "e100_vendor.h"
extern void e100_force_speed_duplex_to_phy(struct e100_private *bdp);
static char e100_gstrings_stats[][ETH_GSTRING_LEN] = { static char e100_gstrings_stats[][ETH_GSTRING_LEN] = {
"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
...@@ -127,7 +133,6 @@ static char *test_strings[] = { ...@@ -127,7 +133,6 @@ static char *test_strings[] = {
static int e100_ethtool_led_blink(struct net_device *, struct ifreq *); static int e100_ethtool_led_blink(struct net_device *, struct ifreq *);
#include <linux/mii.h>
static int e100_mii_ioctl(struct net_device *, struct ifreq *, int); static int e100_mii_ioctl(struct net_device *, struct ifreq *, int);
static unsigned char e100_delayed_exec_non_cu_cmd(struct e100_private *, static unsigned char e100_delayed_exec_non_cu_cmd(struct e100_private *,
...@@ -136,11 +141,15 @@ static void e100_free_nontx_list(struct e100_private *); ...@@ -136,11 +141,15 @@ static void e100_free_nontx_list(struct e100_private *);
static void e100_non_tx_background(unsigned long); static void e100_non_tx_background(unsigned long);
/* Global Data structures and variables */ /* Global Data structures and variables */
char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation"; char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation";
char e100_driver_version[]="2.1.29-k4"; char e100_driver_version[]="2.2.21-k1";
const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver"; const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
char e100_short_driver_name[] = "e100"; char e100_short_driver_name[] = "e100";
static int e100nics = 0; static int e100nics = 0;
static void e100_vlan_rx_register(struct net_device *netdev, struct vlan_group
*grp);
static void e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
...@@ -186,7 +195,6 @@ static void e100_print_brd_conf(struct e100_private *); ...@@ -186,7 +195,6 @@ static void e100_print_brd_conf(struct e100_private *);
static void e100_set_multi(struct net_device *); static void e100_set_multi(struct net_device *);
void e100_set_speed_duplex(struct e100_private *); void e100_set_speed_duplex(struct e100_private *);
char *e100_get_brand_msg(struct e100_private *);
static u8 e100_pci_setup(struct pci_dev *, struct e100_private *); static u8 e100_pci_setup(struct pci_dev *, struct e100_private *);
static u8 e100_sw_init(struct e100_private *); static u8 e100_sw_init(struct e100_private *);
static void e100_tco_workaround(struct e100_private *); static void e100_tco_workaround(struct e100_private *);
...@@ -220,6 +228,7 @@ static void e100_set_bool_option(struct e100_private *bdp, int, u32, int, ...@@ -220,6 +228,7 @@ static void e100_set_bool_option(struct e100_private *bdp, int, u32, int,
char *); char *);
unsigned char e100_wait_exec_cmplx(struct e100_private *, u32, u8, u8); unsigned char e100_wait_exec_cmplx(struct e100_private *, u32, u8, u8);
void e100_exec_cmplx(struct e100_private *, u32, u8); void e100_exec_cmplx(struct e100_private *, u32, u8);
static unsigned char e100_asf_enabled(struct e100_private *bdp);
/** /**
* e100_get_rx_struct - retrieve cell to hold skb buff from the pool * e100_get_rx_struct - retrieve cell to hold skb buff from the pool
...@@ -608,6 +617,8 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) ...@@ -608,6 +617,8 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
if (((bdp->pdev->device > 0x1030) if (((bdp->pdev->device > 0x1030)
&& (bdp->pdev->device < 0x103F)) && (bdp->pdev->device < 0x103F))
|| ((bdp->pdev->device >= 0x1050)
&& (bdp->pdev->device <= 0x1057))
|| (bdp->pdev->device == 0x2449) || (bdp->pdev->device == 0x2449)
|| (bdp->pdev->device == 0x2459) || (bdp->pdev->device == 0x2459)
|| (bdp->pdev->device == 0x245D)) { || (bdp->pdev->device == 0x245D)) {
...@@ -646,6 +657,9 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) ...@@ -646,6 +657,9 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
goto err_pci; goto err_pci;
} }
dev->vlan_rx_register = e100_vlan_rx_register;
dev->vlan_rx_add_vid = e100_vlan_rx_add_vid;
dev->vlan_rx_kill_vid = e100_vlan_rx_kill_vid;
dev->irq = pcid->irq; dev->irq = pcid->irq;
dev->open = &e100_open; dev->open = &e100_open;
dev->hard_start_xmit = &e100_xmit_frame; dev->hard_start_xmit = &e100_xmit_frame;
...@@ -655,9 +669,11 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) ...@@ -655,9 +669,11 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
dev->set_multicast_list = &e100_set_multi; dev->set_multicast_list = &e100_set_multi;
dev->set_mac_address = &e100_set_mac; dev->set_mac_address = &e100_set_mac;
dev->do_ioctl = &e100_ioctl; dev->do_ioctl = &e100_ioctl;
if (bdp->flags & USE_IPCB) {
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; if (bdp->flags & USE_IPCB)
} dev->features = NETIF_F_SG | NETIF_F_HW_CSUM |
NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
e100nics++; e100nics++;
e100_get_speed_duplex_caps(bdp); e100_get_speed_duplex_caps(bdp);
...@@ -668,25 +684,24 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) ...@@ -668,25 +684,24 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
memcpy(bdp->ifname, dev->name, IFNAMSIZ); memcpy(bdp->ifname, dev->name, IFNAMSIZ);
bdp->ifname[IFNAMSIZ-1] = 0; bdp->ifname[IFNAMSIZ-1] = 0;
bdp->device_type = ent->driver_data;
printk(KERN_NOTICE printk(KERN_NOTICE
"e100: %s: %s\n", "e100: %s: %s\n",
bdp->device->name, e100_get_brand_msg(bdp)); bdp->device->name, "Intel(R) PRO/100 Network Connection");
e100_print_brd_conf(bdp); e100_print_brd_conf(bdp);
bdp->id_string = e100_get_brand_msg(bdp);
bdp->wolsupported = 0; bdp->wolsupported = 0;
bdp->wolopts = 0; bdp->wolopts = 0;
/* Check if WoL is enabled on EEPROM */ /* Check if WoL is enabled on EEPROM */
if (e100_eeprom_read(bdp, EEPROM_ID_WORD) & BIT_5) { if (e100_eeprom_read(bdp, EEPROM_ID_WORD) & BIT_5) {
/* Magic Packet WoL is enabled on device by default */
/* if EEPROM WoL bit is TRUE */
bdp->wolsupported = WAKE_MAGIC;
bdp->wolopts = WAKE_MAGIC;
if (bdp->rev_id >= D101A4_REV_ID) if (bdp->rev_id >= D101A4_REV_ID)
bdp->wolsupported = WAKE_PHY | WAKE_MAGIC; bdp->wolsupported = WAKE_PHY | WAKE_MAGIC;
if (bdp->rev_id >= D101MA_REV_ID) if (bdp->rev_id >= D101MA_REV_ID)
bdp->wolsupported |= WAKE_UCAST | WAKE_ARP; bdp->wolsupported |= WAKE_UCAST | WAKE_ARP;
/* Magic Packet WoL is enabled on device by default */
/* if EEPROM WoL bit is TRUE */
bdp->wolopts = WAKE_MAGIC;
} }
printk(KERN_NOTICE "\n"); printk(KERN_NOTICE "\n");
...@@ -752,6 +767,34 @@ e100_remove1(struct pci_dev *pcid) ...@@ -752,6 +767,34 @@ e100_remove1(struct pci_dev *pcid)
--e100nics; --e100nics;
} }
static struct pci_device_id e100_id_table[] __devinitdata = {
{0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x1055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0x8086, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{0,} /* This has to be the last entry*/
};
MODULE_DEVICE_TABLE(pci, e100_id_table); MODULE_DEVICE_TABLE(pci, e100_id_table);
static struct pci_driver e100_driver = { static struct pci_driver e100_driver = {
...@@ -994,13 +1037,14 @@ e100_close(struct net_device *dev) ...@@ -994,13 +1037,14 @@ e100_close(struct net_device *dev)
{ {
struct e100_private *bdp = dev->priv; struct e100_private *bdp = dev->priv;
e100_disable_clear_intr(bdp);
free_irq(dev->irq, dev);
bdp->intr_mask = SCB_INT_MASK; bdp->intr_mask = SCB_INT_MASK;
e100_isolate_driver(bdp); e100_isolate_driver(bdp);
netif_carrier_off(bdp->device); netif_carrier_off(bdp->device);
bdp->cur_line_speed = 0; bdp->cur_line_speed = 0;
bdp->cur_dplx_mode = 0; bdp->cur_dplx_mode = 0;
free_irq(dev->irq, dev);
e100_clear_pools(bdp); e100_clear_pools(bdp);
return 0; return 0;
...@@ -1097,6 +1141,8 @@ e100_set_mac(struct net_device *dev, void *addr) ...@@ -1097,6 +1141,8 @@ e100_set_mac(struct net_device *dev, void *addr)
int rc = -1; int rc = -1;
struct sockaddr *p_sockaddr = (struct sockaddr *) addr; struct sockaddr *p_sockaddr = (struct sockaddr *) addr;
if (!is_valid_ether_addr(p_sockaddr->sa_data))
return -EADDRNOTAVAIL;
bdp = dev->priv; bdp = dev->priv;
if (e100_setup_iaaddr(bdp, (u8 *) (p_sockaddr->sa_data))) { if (e100_setup_iaaddr(bdp, (u8 *) (p_sockaddr->sa_data))) {
...@@ -1231,6 +1277,10 @@ e100_init(struct e100_private *bdp) ...@@ -1231,6 +1277,10 @@ e100_init(struct e100_private *bdp)
/* read the MAC address from the eprom */ /* read the MAC address from the eprom */
e100_rd_eaddr(bdp); e100_rd_eaddr(bdp);
if (!is_valid_ether_addr(bdp->device->dev_addr)) {
printk(KERN_ERR "e100: Invalid Ethernet address\n");
return false;
}
/* read NIC's part number */ /* read NIC's part number */
e100_rd_pwa_no(bdp); e100_rd_pwa_no(bdp);
...@@ -1670,6 +1720,11 @@ e100_watchdog(struct net_device *dev) ...@@ -1670,6 +1720,11 @@ e100_watchdog(struct net_device *dev)
} else { } else {
if (netif_running(dev)) if (netif_running(dev))
netif_stop_queue(dev); netif_stop_queue(dev);
/* When changing to non-autoneg, device may lose */
/* link with some switches. e100 will try to */
/* revover link by sending command to PHY layer */
if (bdp->params.e100_speed_duplex != E100_AUTONEG)
e100_force_speed_duplex_to_phy(bdp);
} }
rmb(); rmb();
...@@ -1793,7 +1848,8 @@ e100intr(int irq, void *dev_inst, struct pt_regs *regs) ...@@ -1793,7 +1848,8 @@ e100intr(int irq, void *dev_inst, struct pt_regs *regs)
bdp = dev->priv; bdp = dev->priv;
intr_status = readw(&bdp->scb->scb_status); intr_status = readw(&bdp->scb->scb_status);
if (!intr_status || (intr_status == 0xffff)) { /* If not my interrupt, just return */
if (!(intr_status & SCB_STATUS_ACK_MASK) || (intr_status == 0xffff)) {
return; return;
} }
...@@ -1993,16 +2049,14 @@ e100_rx_srv(struct e100_private *bdp) ...@@ -1993,16 +2049,14 @@ e100_rx_srv(struct e100_private *bdp)
} else { } else {
skb->ip_summed = CHECKSUM_NONE; skb->ip_summed = CHECKSUM_NONE;
} }
switch (netif_rx(skb)) {
case NET_RX_BAD: if(bdp->vlgrp && (rfd_status & CB_STATUS_VLAN)) {
case NET_RX_DROP: vlan_hwaccel_rx(skb, bdp->vlgrp, be16_to_cpu(rfd->vlanid));
case NET_RX_CN_MOD: } else {
case NET_RX_CN_HIGH: netif_rx(skb);
break;
default:
bdp->drv_stats.net_stats.rx_bytes += skb->len;
break;
} }
dev->last_rx = jiffies;
bdp->drv_stats.net_stats.rx_bytes += skb->len;
rfd_cnt++; rfd_cnt++;
} /* end of rfd loop */ } /* end of rfd loop */
...@@ -2096,6 +2150,11 @@ e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb) ...@@ -2096,6 +2150,11 @@ e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb)
tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE; tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE;
} }
if(bdp->vlgrp && vlan_tx_tag_present(skb)) {
(tcb->tcbu).ipcb.ip_activation_high |= IPCB_INSERTVLAN_ENABLE;
(tcb->tcbu).ipcb.vlan = cpu_to_be16(vlan_tx_tag_get(skb));
}
tcb->tcb_hdr.cb_status = 0; tcb->tcb_hdr.cb_status = 0;
tcb->tcb_thrshld = bdp->tx_thld; tcb->tcb_thrshld = bdp->tx_thld;
tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT); tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT);
...@@ -2114,7 +2173,8 @@ e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb) ...@@ -2114,7 +2173,8 @@ e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb)
if ((ip->protocol == IPPROTO_TCP) || if ((ip->protocol == IPPROTO_TCP) ||
(ip->protocol == IPPROTO_UDP)) { (ip->protocol == IPPROTO_UDP)) {
tcb->tcbu.ipcb.ip_activation_high =
tcb->tcbu.ipcb.ip_activation_high |=
IPCB_HARDWAREPARSING_ENABLE; IPCB_HARDWAREPARSING_ENABLE;
tcb->tcbu.ipcb.ip_schedule |= tcb->tcbu.ipcb.ip_schedule |=
IPCB_TCPUDP_CHECKSUM_ENABLE; IPCB_TCPUDP_CHECKSUM_ENABLE;
...@@ -2682,13 +2742,12 @@ e100_sw_reset(struct e100_private *bdp, u32 reset_cmd) ...@@ -2682,13 +2742,12 @@ e100_sw_reset(struct e100_private *bdp, u32 reset_cmd)
udelay(20); udelay(20);
} }
/* Mask off our interrupt line -- its unmasked after reset */ /* Mask off our interrupt line -- it is unmasked after reset */
e100_disable_clear_intr(bdp); e100_disable_clear_intr(bdp);
#ifdef E100_CU_DEBUG #ifdef E100_CU_DEBUG
bdp->last_cmd = 0; bdp->last_cmd = 0;
bdp->last_sub_cmd = 0; bdp->last_sub_cmd = 0;
#endif #endif
} }
/** /**
...@@ -2900,27 +2959,6 @@ e100_print_brd_conf(struct e100_private *bdp) ...@@ -2900,27 +2959,6 @@ e100_print_brd_conf(struct e100_private *bdp)
printk(KERN_NOTICE " cpu cycle saver enabled\n"); printk(KERN_NOTICE " cpu cycle saver enabled\n");
} }
/**
* e100_get_brand_msg
* @bdp: atapter's private data struct
*
* This routine checks if there is specified branding message for a given board
* type and returns a pointer to the string containing the branding message.
*/
char *
e100_get_brand_msg(struct e100_private *bdp)
{
int i;
for (i = 0; e100_vendor_info_array[i].idstr != NULL; i++) {
if (e100_vendor_info_array[i].device_type == bdp->device_type) {
return e100_vendor_info_array[i].idstr;
}
}
return e100_vendor_info_array[E100_ALL_BOARDS].idstr;
}
/** /**
* e100_pci_setup - setup the adapter's PCI information * e100_pci_setup - setup the adapter's PCI information
* @pcid: adapter's pci_dev struct * @pcid: adapter's pci_dev struct
...@@ -3004,12 +3042,17 @@ e100_isolate_driver(struct e100_private *bdp) ...@@ -3004,12 +3042,17 @@ e100_isolate_driver(struct e100_private *bdp)
void void
e100_set_speed_duplex(struct e100_private *bdp) e100_set_speed_duplex(struct e100_private *bdp)
{ {
if (netif_carrier_ok(bdp->device)) int carrier_ok;
/* Device may lose link with some siwtches when */
/* changing speed/duplex to non-autoneg. e100 */
/* needs to remember carrier state in order to */
/* start watchdog timer for recovering link */
if ((carrier_ok = netif_carrier_ok(bdp->device)))
e100_isolate_driver(bdp); e100_isolate_driver(bdp);
e100_phy_set_speed_duplex(bdp, true); e100_phy_set_speed_duplex(bdp, true);
e100_config_fc(bdp); /* re-config flow-control if necessary */ e100_config_fc(bdp); /* re-config flow-control if necessary */
e100_config(bdp); e100_config(bdp);
if (netif_carrier_ok(bdp->device)) if (carrier_ok)
e100_deisolate_driver(bdp, false); e100_deisolate_driver(bdp, false);
} }
...@@ -3426,6 +3469,7 @@ e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr) ...@@ -3426,6 +3469,7 @@ e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr)
u16 first_word, last_word; u16 first_word, last_word;
int i, max_len; int i, max_len;
void *ptr; void *ptr;
u8 *eeprom_data_bytes = (u8 *)eeprom_data;
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
...@@ -3461,7 +3505,9 @@ e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr) ...@@ -3461,7 +3505,9 @@ e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr)
if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd)))
return -EFAULT; return -EFAULT;
if (copy_to_user(usr_eeprom_ptr, eeprom_data, ecmd.len)) if(ecmd.offset & 1)
eeprom_data_bytes++;
if (copy_to_user(usr_eeprom_ptr, eeprom_data_bytes, ecmd.len))
return -EFAULT; return -EFAULT;
} else { } else {
if (ecmd.magic != E100_EEPROM_MAGIC) if (ecmd.magic != E100_EEPROM_MAGIC)
...@@ -3754,7 +3800,8 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) ...@@ -3754,7 +3800,8 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr)
return -EFAULT; return -EFAULT;
switch (info.string_set) { switch (info.string_set) {
case ETH_SS_TEST: case ETH_SS_TEST: {
int ret = 0;
if (info.len > E100_MAX_TEST_RES) if (info.len > E100_MAX_TEST_RES)
info.len = E100_MAX_TEST_RES; info.len = E100_MAX_TEST_RES;
strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC); strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC);
...@@ -3766,7 +3813,13 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) ...@@ -3766,7 +3813,13 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr)
sprintf(strings + i * ETH_GSTRING_LEN, "%-31s", sprintf(strings + i * ETH_GSTRING_LEN, "%-31s",
test_strings[i]); test_strings[i]);
} }
break; if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
ret = -EFAULT;
if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN))
ret = -EFAULT;
kfree(strings);
return ret;
}
case ETH_SS_STATS: { case ETH_SS_STATS: {
char *strings = NULL; char *strings = NULL;
void *addr = ifr->ifr_data; void *addr = ifr->ifr_data;
...@@ -3783,19 +3836,6 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) ...@@ -3783,19 +3836,6 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr)
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) {
kfree(strings);
return -EFAULT;
}
if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN)) {
kfree(strings);
return -EFAULT;
}
kfree(strings);
return 0;
} }
static int static int
...@@ -4022,6 +4062,45 @@ e100_non_tx_background(unsigned long ptr) ...@@ -4022,6 +4062,45 @@ e100_non_tx_background(unsigned long ptr)
spin_unlock_bh(&(bdp->bd_non_tx_lock)); spin_unlock_bh(&(bdp->bd_non_tx_lock));
} }
static void
e100_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
{
struct e100_private *bdp = netdev->priv;
e100_disable_clear_intr(bdp);
bdp->vlgrp = grp;
if(grp) {
/* enable VLAN tag insert/strip */
e100_config_vlan_drop(bdp, true);
} else {
/* disable VLAN tag insert/strip */
e100_config_vlan_drop(bdp, false);
}
e100_config(bdp);
e100_set_intr_mask(bdp);
}
static void
e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
{
/* We don't do Vlan filtering */
return;
}
static void
e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
{
struct e100_private *bdp = netdev->priv;
if(bdp->vlgrp)
bdp->vlgrp->vlan_devices[vid] = NULL;
/* We don't do Vlan filtering */
return;
}
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int static int
e100_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) e100_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
...@@ -4057,7 +4136,7 @@ e100_suspend(struct pci_dev *pcid, u32 state) ...@@ -4057,7 +4136,7 @@ e100_suspend(struct pci_dev *pcid, u32 state)
e100_do_wol(pcid, bdp); e100_do_wol(pcid, bdp);
/* If wol is enabled */ /* If wol is enabled */
if (bdp->wolopts) { if (bdp->wolopts || e100_asf_enabled(bdp)) {
pci_enable_wake(pcid, 3, 1); /* Enable PME for power state D3 */ pci_enable_wake(pcid, 3, 1); /* Enable PME for power state D3 */
pci_set_power_state(pcid, 3); /* Set power state to D3. */ pci_set_power_state(pcid, 3); /* Set power state to D3. */
} else { } else {
...@@ -4085,6 +4164,31 @@ e100_resume(struct pci_dev *pcid) ...@@ -4085,6 +4164,31 @@ e100_resume(struct pci_dev *pcid)
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
/**
* e100_asf_enabled - checks if ASF is configured on the current adaper
* by reading registers 0xD and 0x90 in the EEPROM
* @bdp: atapter's private data struct
*
* Returns: true if ASF is enabled
*/
static unsigned char
e100_asf_enabled(struct e100_private *bdp)
{
u16 asf_reg;
u16 smbus_addr_reg;
if ((bdp->pdev->device >= 0x1050) && (bdp->pdev->device <= 0x1055)) {
asf_reg = e100_eeprom_read(bdp, EEPROM_CONFIG_ASF);
if ((asf_reg & EEPROM_FLAG_ASF)
&& !(asf_reg & EEPROM_FLAG_GCL)) {
smbus_addr_reg =
e100_eeprom_read(bdp, EEPROM_SMBUS_ADDR);
if ((smbus_addr_reg & 0xFF) != 0xFE)
return true;
}
}
return false;
}
#ifdef E100_CU_DEBUG #ifdef E100_CU_DEBUG
unsigned char unsigned char
e100_cu_unknown_state(struct e100_private *bdp) e100_cu_unknown_state(struct e100_private *bdp)
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -636,7 +636,6 @@ e100_force_speed_duplex(struct e100_private *bdp) ...@@ -636,7 +636,6 @@ e100_force_speed_duplex(struct e100_private *bdp)
control &= ~BMCR_ANENABLE; control &= ~BMCR_ANENABLE;
control &= ~BMCR_LOOPBACK; control &= ~BMCR_LOOPBACK;
/* Check e100.c values */
switch (bdp->params.e100_speed_duplex) { switch (bdp->params.e100_speed_duplex) {
case E100_SPEED_10_HALF: case E100_SPEED_10_HALF:
control &= ~BMCR_SPEED100; control &= ~BMCR_SPEED100;
...@@ -682,6 +681,41 @@ e100_force_speed_duplex(struct e100_private *bdp) ...@@ -682,6 +681,41 @@ e100_force_speed_duplex(struct e100_private *bdp)
} while (true); } while (true);
} }
void
e100_force_speed_duplex_to_phy(struct e100_private *bdp)
{
u16 control;
e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control);
control &= ~BMCR_ANENABLE;
control &= ~BMCR_LOOPBACK;
switch (bdp->params.e100_speed_duplex) {
case E100_SPEED_10_HALF:
control &= ~BMCR_SPEED100;
control &= ~BMCR_FULLDPLX;
break;
case E100_SPEED_10_FULL:
control &= ~BMCR_SPEED100;
control |= BMCR_FULLDPLX;
break;
case E100_SPEED_100_HALF:
control |= BMCR_SPEED100;
control &= ~BMCR_FULLDPLX;
break;
case E100_SPEED_100_FULL:
control |= BMCR_SPEED100;
control |= BMCR_FULLDPLX;
break;
}
/* Send speed/duplex command to PHY layer. */
e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control);
}
/* /*
* Procedure: e100_set_fc * Procedure: e100_set_fc
* *
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
#include "e100.h" #include "e100.h"
#include <linux/mii.h>
/* /*
* Auto-polarity enable/disable * Auto-polarity enable/disable
* e100_autopolarity = 0 => disable auto-polarity * e100_autopolarity = 0 => disable auto-polarity
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -242,6 +242,9 @@ e100_diag_config_loopback(struct e100_private* bdp, ...@@ -242,6 +242,9 @@ e100_diag_config_loopback(struct e100_private* bdp,
*dynamic_tbd = e100_config_dynamic_tbd(bdp,*dynamic_tbd); *dynamic_tbd = e100_config_dynamic_tbd(bdp,*dynamic_tbd);
if (set_loopback) { if (set_loopback) {
/* ICH PHY loopback is broken */
if (bdp->flags & IS_ICH && loopback_mode == PHY_LOOPBACK)
loopback_mode = MAC_LOOPBACK;
/* Configure loopback on MAC */ /* Configure loopback on MAC */
e100_config_loopback_mode(bdp,loopback_mode); e100_config_loopback_mode(bdp,loopback_mode);
} else { } else {
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
......
/*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef E100_VENDOR_ID_INFO
#define E100_VENDOR_ID_INFO
/* ====================================================================== */
/* vendor_info */
/* ====================================================================== */
struct e100_vendor_info {
unsigned long device_type;
char *idstr;
};
enum e100_device_type {
E100_BRD_100TX = 1,
E100_BRD_100T4,
E100_BRD_10T,
E100_BRD_100WFM,
E100_BRD_82557,
E100_BRD_82557_WOL,
E100_BRD_82558,
E100_BRD_82558_WOL,
E100_BRD_100,
E100_BRD_100M,
E100_BRD_AOL2,
E100_BRD_AOL,
E100_PROS_M,
E100_PROS_AM,
E100_PROS_AM_AOL,
E100_PROS_DT,
E100_PRO_DT,
E100_PROM_DT,
E100_PRO_SRV,
E100_PRO_SRVP,
E100_PROS_SRV,
E100_PRO_DUAL,
E100_PROS_DUAL,
E100_PROP_DUAL,
E100_PROP_WOL,
E100_PROS_MOB,
E100_PRO_CB,
E100_PRO_CB_M,
E100_PROSR_MOB,
E100_PROS_MC,
E100_PROSR_MC,
E100_PROP_MC,
E100_PROSP_MC,
E100_PROP_MOB,
E100_PROSP_MOB,
E100_PRO_MINI,
E100_PRO_NET,
E100_PROS_NET,
E100_PROVM_NET,
E100_PROVE_D,
E100_82559_LOM,
E100_82559_LOM_AOL,
E100_82559_LOM_AOL2,
E100_82559_LOM_DELL,
E100_IBM_MDS,
E100_CMPQ_S,
E100_PROVE_DA,
E100_PROVM_DA,
E100_PROVE_LOM,
E100_PROVE_NET,
E100_82562,
E100_82551QM,
E100_ALL_BOARDS
};
struct e100_vendor_info e100_vendor_info_array[] = {
{ E100_BRD_100TX, "Intel(R) PRO/100B PCI Adapter (TX)"},
{ E100_BRD_100T4, "Intel(R) PRO/100B PCI Adapter (T4)"},
{ E100_BRD_10T, "Intel(R) PRO/10+ PCI Adapter"},
{ E100_BRD_100WFM, "Intel(R) PRO/100 WfM PCI Adapter"},
{ E100_BRD_82557, "Intel(R) 82557-based Integrated Ethernet PCI (10/100)"},
{ E100_BRD_82557_WOL, "Intel(R) 82557-based Integrated Ethernet with Wake on LAN*"},
{ E100_BRD_82558, "Intel(R) 82558-based Integrated Ethernet"},
{ E100_BRD_82558_WOL, "Intel(R) 82558-based Integrated Ethernet with Wake on LAN*"},
{ E100_BRD_100, "Intel(R) PRO/100+ PCI Adapter"},
{ E100_BRD_100M, "Intel(R) PRO/100+ Management Adapter"},
{ E100_BRD_AOL2, "Intel(R) PRO/100+ Alert on LAN* 2 Management Adapter"},
{ E100_82559_LOM_DELL, "Intel(R) 8255x Based Network Connection"},
{ E100_BRD_AOL, "Intel(R) PRO/100+ Alert on LAN* Management Adapter"},
{ E100_PROS_M, "Intel(R) PRO/100 S Management Adapter"},
{ E100_PROS_AM, "Intel(R) PRO/100 S Advanced Management Adapter"},
{ E100_PROS_AM_AOL, "Intel(R) PRO/100+ Management Adapter with Alert On LAN* GC"},
{ E100_PROS_DT, "Intel(R) PRO/100 S Desktop Adapter"},
{ E100_PRO_DT, "Intel(R) PRO/100 Desktop Adapter"},
{ E100_PROM_DT, "Intel(R) PRO/100 M Desktop Adapter"},
{ E100_PRO_SRV, "Intel(R) PRO/100+ Server Adapter"},
{ E100_PRO_SRVP, "Intel(R) PRO/100+ Server Adapter (PILA8470B)"},
{ E100_PROS_SRV, "Intel(R) PRO/100 S Server Adapter"},
{ E100_PRO_DUAL, "Intel(R) PRO/100 Dual Port Server Adapter"},
{ E100_PROS_DUAL, "Intel(R) PRO/100 S Dual Port Server Adapter"},
{ E100_PROP_DUAL, "Intel(R) PRO/100+ Dual Port Server Adapter"},
{ E100_PROP_WOL, "Intel(R) PRO/100+ Management Adapter with Alert On LAN* G Server"},
{ E100_PROS_MOB, "Intel(R) PRO/100 S Mobile Adapter"},
{ E100_PRO_CB, "Intel(R) PRO/100 CardBus II"},
{ E100_PRO_CB_M, "Intel(R) PRO/100 LAN+Modem56 CardBus II"},
{ E100_PROSR_MOB, "Intel(R) PRO/100 SR Mobile Adapter"},
{ E100_PROS_MC, "Intel(R) PRO/100 S Mobile Combo Adapter"},
{ E100_PROSR_MC, "Intel(R) PRO/100 SR Mobile Combo Adapter"},
{ E100_PROP_MC, "Intel(R) PRO/100 P Mobile Combo Adapter"},
{ E100_PROSP_MC, "Intel(R) PRO/100 SP Mobile Combo Adapter"},
{ E100_PROP_MOB, "Intel(R) PRO/100 P Mobile Adapter"},
{ E100_PROSP_MOB, "Intel(R) PRO/100 SP Mobile Adapter"},
{ E100_PRO_MINI, "Intel(R) PRO/100+ Mini PCI"},
{ E100_PRO_NET, "Intel(R) PRO/100 Network Connection" },
{ E100_PROS_NET, "Intel(R) PRO/100 S Network Connection" },
{ E100_PROVM_NET, "Intel(R) PRO/100 VM Network Connection"},
{ E100_PROVE_D, "Intel(R) PRO/100 VE Desktop Connection"},
{ E100_82559_LOM, "Intel(R) 82559 Fast Ethernet LAN on Motherboard"},
{ E100_82559_LOM_AOL, "Intel(R) 82559 Fast Ethernet LOM with Alert on LAN*" },
{ E100_82559_LOM_AOL2, "Intel(R) 82559 Fast Ethernet LOM with Alert on LAN* 2" },
{ E100_IBM_MDS, "IBM Mobile, Desktop & Server Adapters"},
{ E100_CMPQ_S, "Compaq Fast Ethernet Server Adapter" },
{ E100_PROVE_DA, "Intel(R) PRO/100 VE Desktop Adapter"},
{ E100_PROVM_DA, "Intel(R) PRO/100 VM Desktop Adapter"},
{ E100_PROVE_LOM, "Intel(R) PRO/100 VE Network ConnectionPLC LOM" },
{ E100_PROVE_NET, "Intel(R) PRO/100 VE Network Connection"},
{ E100_82562, "Intel(R)82562 based Fast Ethernet Connection"},
{ E100_82551QM, "Intel(R) PRO/100 M Mobile Connection"},
{ E100_ALL_BOARDS, "Intel(R) 8255x-based Ethernet Adapter"},
{0,NULL}
};
static struct pci_device_id e100_id_table[] __devinitdata = {
{0x8086, 0x1229, 0x8086, 0x0001, 0, 0, E100_BRD_100TX},
{0x8086, 0x1229, 0x8086, 0x0002, 0, 0, E100_BRD_100T4},
{0x8086, 0x1229, 0x8086, 0x0003, 0, 0, E100_BRD_10T},
{0x8086, 0x1229, 0x8086, 0x0004, 0, 0, E100_BRD_100WFM},
{0x8086, 0x1229, 0x8086, 0x0005, 0, 0, E100_BRD_82557},
{0x8086, 0x1229, 0x8086, 0x0006, 0, 0, E100_BRD_82557_WOL},
{0x8086, 0x1229, 0x8086, 0x0002, 0, 0, E100_BRD_100T4},
{0x8086, 0x1229, 0x8086, 0x0003, 0, 0, E100_BRD_10T},
{0x8086, 0x1229, 0x8086, 0x0004, 0, 0, E100_BRD_100WFM},
{0x8086, 0x1229, 0x8086, 0x0005, 0, 0, E100_BRD_82557},
{0x8086, 0x1229, 0x8086, 0x0006, 0, 0, E100_BRD_82557_WOL},
{0x8086, 0x1229, 0x8086, 0x0007, 0, 0, E100_BRD_82558},
{0x8086, 0x1229, 0x8086, 0x0008, 0, 0, E100_BRD_82558_WOL},
{0x8086, 0x1229, 0x8086, 0x0009, 0, 0, E100_BRD_100},
{0x8086, 0x1229, 0x8086, 0x000A, 0, 0, E100_BRD_100M},
{0x8086, 0x1229, 0x8086, 0x000B, 0, 0, E100_BRD_100},
{0x8086, 0x1229, 0x8086, 0x000C, 0, 0, E100_BRD_100M},
{0x8086, 0x1229, 0x8086, 0x000D, 0, 0, E100_BRD_AOL2},
{0x8086, 0x1229, 0x8086, 0x000E, 0, 0, E100_BRD_AOL},
{0x8086, 0x1229, 0x8086, 0x0010, 0, 0, E100_PROS_M},
{0x8086, 0x1229, 0x8086, 0x0011, 0, 0, E100_PROS_M},
{0x8086, 0x1229, 0x8086, 0x0012, 0, 0, E100_PROS_AM},
{0x8086, 0x1229, 0x8086, 0x0013, 0, 0, E100_PROS_AM},
{0x8086, 0x1229, 0x8086, 0x0030, 0, 0, E100_PROS_AM_AOL},
{0x8086, 0x1229, 0x8086, 0x0040, 0, 0, E100_PROS_DT},
{0x8086, 0x1229, 0x8086, 0x0041, 0, 0, E100_PROS_DT},
{0x8086, 0x1229, 0x8086, 0x0042, 0, 0, E100_PRO_DT},
{0x8086, 0x1229, 0x8086, 0x0050, 0, 0, E100_PROS_DT},
{0x8086, 0x1229, 0x8086, 0x0070, 0, 0, E100_PROM_DT},
{0x8086, 0x1229, 0x8086, 0x1009, 0, 0, E100_PRO_SRV},
{0x8086, 0x1229, 0x8086, 0x100C, 0, 0, E100_PRO_SRVP},
{0x8086, 0x1229, 0x8086, 0x1012, 0, 0, E100_PROS_SRV},
{0x8086, 0x1229, 0x8086, 0x1013, 0, 0, E100_PROS_SRV},
{0x8086, 0x1229, 0x8086, 0x1014, 0, 0, E100_PRO_DUAL},
{0x8086, 0x1229, 0x8086, 0x1015, 0, 0, E100_PROS_DUAL},
{0x8086, 0x1229, 0x8086, 0x1016, 0, 0, E100_PROS_DUAL},
{0x8086, 0x1229, 0x8086, 0x1017, 0, 0, E100_PROP_DUAL},
{0x8086, 0x1229, 0x8086, 0x1030, 0, 0, E100_PROP_WOL},
{0x8086, 0x1229, 0x8086, 0x1040, 0, 0, E100_PROS_SRV},
{0x8086, 0x1229, 0x8086, 0x1041, 0, 0, E100_PROS_SRV},
{0x8086, 0x1229, 0x8086, 0x1042, 0, 0, E100_PRO_SRV},
{0x8086, 0x1229, 0x8086, 0x1050, 0, 0, E100_PROS_SRV},
{0x8086, 0x1229, 0x8086, 0x10F0, 0, 0, E100_PROP_DUAL},
{0x8086, 0x1229, 0x8086, 0x10F0, 0, 0, E100_PROP_DUAL},
{0x8086, 0x1229, 0x8086, 0x2009, 0, 0, E100_PROS_MOB},
{0x8086, 0x1229, 0x8086, 0x200D, 0, 0, E100_PRO_CB},
{0x8086, 0x1229, 0x8086, 0x200E, 0, 0, E100_PRO_CB_M},
{0x8086, 0x1229, 0x8086, 0x200F, 0, 0, E100_PROSR_MOB},
{0x8086, 0x1229, 0x8086, 0x2010, 0, 0, E100_PROS_MC},
{0x8086, 0x1229, 0x8086, 0x2013, 0, 0, E100_PROSR_MC},
{0x8086, 0x1229, 0x8086, 0x2016, 0, 0, E100_PROS_MOB},
{0x8086, 0x1229, 0x8086, 0x2017, 0, 0, E100_PROS_MC},
{0x8086, 0x1229, 0x8086, 0x2018, 0, 0, E100_PROSR_MOB},
{0x8086, 0x1229, 0x8086, 0x2019, 0, 0, E100_PROSR_MC},
{0x8086, 0x1229, 0x8086, 0x2101, 0, 0, E100_PROP_MOB},
{0x8086, 0x1229, 0x8086, 0x2102, 0, 0, E100_PROSP_MOB},
{0x8086, 0x1229, 0x8086, 0x2103, 0, 0, E100_PROSP_MOB},
{0x8086, 0x1229, 0x8086, 0x2104, 0, 0, E100_PROSP_MOB},
{0x8086, 0x1229, 0x8086, 0x2105, 0, 0, E100_PROSP_MOB},
{0x8086, 0x1229, 0x8086, 0x2106, 0, 0, E100_PROP_MOB},
{0x8086, 0x1229, 0x8086, 0x2107, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x8086, 0x2108, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x8086, 0x2200, 0, 0, E100_PROP_MC},
{0x8086, 0x1229, 0x8086, 0x2201, 0, 0, E100_PROP_MC},
{0x8086, 0x1229, 0x8086, 0x2202, 0, 0, E100_PROSP_MC},
{0x8086, 0x1229, 0x8086, 0x2203, 0, 0, E100_PRO_MINI},
{0x8086, 0x1229, 0x8086, 0x2204, 0, 0, E100_PRO_MINI},
{0x8086, 0x1229, 0x8086, 0x2205, 0, 0, E100_PROSP_MC},
{0x8086, 0x1229, 0x8086, 0x2206, 0, 0, E100_PROSP_MC},
{0x8086, 0x1229, 0x8086, 0x2207, 0, 0, E100_PROSP_MC},
{0x8086, 0x1229, 0x8086, 0x2208, 0, 0, E100_PROP_MC},
{0x8086, 0x1229, 0x8086, 0x2408, 0, 0, E100_PRO_MINI},
{0x8086, 0x1229, 0x8086, 0x240F, 0, 0, E100_PRO_MINI},
{0x8086, 0x1229, 0x8086, 0x2411, 0, 0, E100_PRO_MINI},
{0x8086, 0x1229, 0x8086, 0x3400, 0, 0, E100_82559_LOM},
{0x8086, 0x1229, 0x8086, 0x3000, 0, 0, E100_82559_LOM},
{0x8086, 0x1229, 0x8086, 0x3001, 0, 0, E100_82559_LOM_AOL},
{0x8086, 0x1229, 0x8086, 0x3002, 0, 0, E100_82559_LOM_AOL2},
{0x8086, 0x1229, 0x8086, 0x3006, 0, 0, E100_PROS_NET},
{0x8086, 0x1229, 0x8086, 0x3007, 0, 0, E100_PROS_NET},
{0x8086, 0x1229, 0x8086, 0x3008, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x8086, 0x3010, 0, 0, E100_PROS_NET},
{0x8086, 0x1229, 0x8086, 0x3011, 0, 0, E100_PROS_NET},
{0x8086, 0x1229, 0x8086, 0x3012, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x1014, 0x005C, 0, 0, E100_IBM_MDS},
{0x8086, 0x1229, 0x1014, 0x305C, 0, 0, E100_IBM_MDS},
{0x8086, 0x1229, 0x1014, 0x405C, 0, 0, E100_IBM_MDS},
{0x8086, 0x1229, 0x1014, 0x605C, 0, 0, E100_IBM_MDS},
{0x8086, 0x1229, 0x1014, 0x505C, 0, 0, E100_IBM_MDS},
{0x8086, 0x1229, 0x1014, 0x105C, 0, 0, E100_IBM_MDS},
{0x8086, 0x1229, 0x1014, 0x805C, 0, 0, E100_IBM_MDS},
{0x8086, 0x1229, 0x1014, 0x705C, 0, 0, E100_IBM_MDS},
{0x8086, 0x1229, 0x1014, 0x01F1, 0, 0, E100_IBM_MDS},
{0x8086, 0x1229, 0x1014, 0x0232, 0, 0, E100_IBM_MDS},
{0x8086, 0x1229, 0x1014, 0x0207, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x1014, 0x023F, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x1014, 0x01BC, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x1014, 0x01CE, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x1014, 0x01DC, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x1014, 0x01EB, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x1014, 0x01EC, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x1014, 0x0202, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x1014, 0x0205, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x1014, 0x0217, 0, 0, E100_PRO_NET},
{0x8086, 0x1229, 0x0E11, 0xB01E, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB02F, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB04A, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB0C6, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB0C7, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB0D7, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB0DD, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB0DE, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB0E1, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB134, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB13C, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB144, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB163, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x0E11, 0xB164, 0, 0, E100_CMPQ_S},
{0x8086, 0x1229, 0x1028, PCI_ANY_ID, 0, 0, E100_82559_LOM_DELL},
{0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS},
{0x8086, 0x2449, 0x1014, 0x0265, 0, 0, E100_PROVE_D},
{0x8086, 0x2449, 0x1014, 0x0267, 0, 0, E100_PROVE_D},
{0x8086, 0x2449, 0x1014, 0x026A, 0, 0, E100_PROVE_D},
{0x8086, 0x2449, 0x8086, 0x3010, 0, 0, E100_PROVE_DA},
{0x8086, 0x2449, 0x8086, 0x3011, 0, 0, E100_PROVM_DA},
{0x8086, 0x2449, 0x8086, 0x3013, 0, 0, E100_PROVE_NET},
{0x8086, 0x2449, 0x8086, 0x3014, 0, 0, E100_PROVM_NET},
{0x8086, 0x2449, 0x8086, 0x3016, 0, 0, E100_PROP_MC},
{0x8086, 0x2449, 0x8086, 0x3017, 0, 0, E100_PROP_MOB},
{0x8086, 0x2449, 0x8086, 0x3018, 0, 0, E100_PRO_NET},
{0x8086, 0x2449, 0x0E11, PCI_ANY_ID, 0, 0, E100_PROVM_NET},
{0x8086, 0x2449, 0x1014, PCI_ANY_ID, 0, 0, E100_PROVE_D},
{0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS},
{0x8086, 0x1059, 0x1179, 0x0005, 0, 0, E100_82551QM},
{0x8086, 0x1059, 0x1033, 0x8191, 0, 0, E100_82551QM},
{0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_82551QM},
{0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS},
{0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS},
{0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS},
{0x8086, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVE_NET},
{0x8086, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVE_NET},
{0x8086, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET},
{0x8086, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET},
{0x8086, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET},
{0x8086, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVE_NET},
{0x8086, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVE_NET},
{0x8086, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET},
{0x8086, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET},
{0x8086, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVE_NET},
{0x8086, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET},
{0x8086, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_82562},
{0x8086, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_82562},
{0,} /* This has to be the last entry*/
};
#endif /* E100_VENDOR_ID_INFO */
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <net/checksum.h> #include <net/checksum.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/mii.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
...@@ -95,6 +96,15 @@ struct e1000_adapter; ...@@ -95,6 +96,15 @@ struct e1000_adapter;
#define E1000_RXBUFFER_8192 8192 #define E1000_RXBUFFER_8192 8192
#define E1000_RXBUFFER_16384 16384 #define E1000_RXBUFFER_16384 16384
/* SmartSpeed delimiters */
#define E1000_SMARTSPEED_DOWNSHIFT 3
#define E1000_SMARTSPEED_MAX 15
/* Packet Buffer allocations */
#define E1000_TX_FIFO_SIZE_SHIFT 0xA
#define E1000_TX_HEAD_ADDR_SHIFT 7
#define E1000_PBA_TX_MASK 0xFFFF0000
/* Flow Control High-Watermark: 43464 bytes */ /* Flow Control High-Watermark: 43464 bytes */
#define E1000_FC_HIGH_THRESH 0xA9C8 #define E1000_FC_HIGH_THRESH 0xA9C8
...@@ -107,10 +117,7 @@ struct e1000_adapter; ...@@ -107,10 +117,7 @@ struct e1000_adapter;
/* How many Tx Descriptors do we need to call netif_wake_queue ? */ /* How many Tx Descriptors do we need to call netif_wake_queue ? */
#define E1000_TX_QUEUE_WAKE 16 #define E1000_TX_QUEUE_WAKE 16
/* How many Rx Buffers do we bundle into one write to the hardware ? */ /* How many Rx Buffers do we bundle into one write to the hardware ? */
#define E1000_RX_BUFFER_WRITE 16 #define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
#define E1000_JUMBO_PBA 0x00000028
#define E1000_DEFAULT_PBA 0x00000030
#define AUTO_ALL_MODES 0 #define AUTO_ALL_MODES 0
#define E1000_EEPROM_APME 4 #define E1000_EEPROM_APME 4
...@@ -145,7 +152,8 @@ struct e1000_desc_ring { ...@@ -145,7 +152,8 @@ struct e1000_desc_ring {
}; };
#define E1000_DESC_UNUSED(R) \ #define E1000_DESC_UNUSED(R) \
((((R)->next_to_clean + (R)->count) - ((R)->next_to_use + 1)) % ((R)->count)) ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
(R)->next_to_clean - (R)->next_to_use - 1)
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) #define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) #define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
...@@ -155,6 +163,7 @@ struct e1000_desc_ring { ...@@ -155,6 +163,7 @@ struct e1000_desc_ring {
/* board specific private data structure */ /* board specific private data structure */
struct e1000_adapter { struct e1000_adapter {
struct timer_list tx_fifo_stall_timer;
struct timer_list watchdog_timer; struct timer_list watchdog_timer;
struct timer_list phy_info_timer; struct timer_list phy_info_timer;
struct vlan_group *vlgrp; struct vlan_group *vlgrp;
...@@ -163,6 +172,7 @@ struct e1000_adapter { ...@@ -163,6 +172,7 @@ struct e1000_adapter {
uint32_t rx_buffer_len; uint32_t rx_buffer_len;
uint32_t part_num; uint32_t part_num;
uint32_t wol; uint32_t wol;
uint32_t smartspeed;
uint16_t link_speed; uint16_t link_speed;
uint16_t link_duplex; uint16_t link_duplex;
spinlock_t stats_lock; spinlock_t stats_lock;
...@@ -177,7 +187,11 @@ struct e1000_adapter { ...@@ -177,7 +187,11 @@ struct e1000_adapter {
uint32_t txd_cmd; uint32_t txd_cmd;
uint32_t tx_int_delay; uint32_t tx_int_delay;
uint32_t tx_abs_int_delay; uint32_t tx_abs_int_delay;
int max_data_per_txd; uint32_t gotcl;
uint32_t tx_fifo_head;
uint32_t tx_head_addr;
uint32_t tx_fifo_size;
atomic_t tx_fifo_stall;
/* RX */ /* RX */
struct e1000_desc_ring rx_ring; struct e1000_desc_ring rx_ring;
...@@ -186,6 +200,10 @@ struct e1000_adapter { ...@@ -186,6 +200,10 @@ struct e1000_adapter {
uint32_t rx_int_delay; uint32_t rx_int_delay;
uint32_t rx_abs_int_delay; uint32_t rx_abs_int_delay;
boolean_t rx_csum; boolean_t rx_csum;
uint32_t gorcl;
/* Interrupt Throttle Rate */
uint32_t itr;
/* OS defined structs */ /* OS defined structs */
struct net_device *netdev; struct net_device *netdev;
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -38,6 +38,7 @@ extern char e1000_driver_version[]; ...@@ -38,6 +38,7 @@ extern char e1000_driver_version[];
extern int e1000_up(struct e1000_adapter *adapter); extern int e1000_up(struct e1000_adapter *adapter);
extern void e1000_down(struct e1000_adapter *adapter); extern void e1000_down(struct e1000_adapter *adapter);
extern void e1000_reset(struct e1000_adapter *adapter); extern void e1000_reset(struct e1000_adapter *adapter);
extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
static char e1000_gstrings_stats[][ETH_GSTRING_LEN] = { static char e1000_gstrings_stats[][ETH_GSTRING_LEN] = {
"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
...@@ -129,30 +130,9 @@ e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) ...@@ -129,30 +130,9 @@ e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
hw->autoneg = 1; hw->autoneg = 1;
hw->autoneg_advertised = 0x002F; hw->autoneg_advertised = 0x002F;
ecmd->advertising = 0x002F; ecmd->advertising = 0x002F;
} else { } else
hw->autoneg = 0; if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex))
switch(ecmd->speed + ecmd->duplex) {
case SPEED_10 + DUPLEX_HALF:
hw->forced_speed_duplex = e1000_10_half;
break;
case SPEED_10 + DUPLEX_FULL:
hw->forced_speed_duplex = e1000_10_full;
break;
case SPEED_100 + DUPLEX_HALF:
hw->forced_speed_duplex = e1000_100_half;
break;
case SPEED_100 + DUPLEX_FULL:
hw->forced_speed_duplex = e1000_100_full;
break;
case SPEED_1000 + DUPLEX_FULL:
hw->autoneg = 1;
hw->autoneg_advertised = ADVERTISE_1000_FULL;
break;
case SPEED_1000 + DUPLEX_HALF: /* not supported */
default:
return -EINVAL; return -EINVAL;
}
}
/* reset the link */ /* reset the link */
...@@ -165,16 +145,6 @@ e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) ...@@ -165,16 +145,6 @@ e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
return 0; return 0;
} }
static inline int
e1000_eeprom_size(struct e1000_hw *hw)
{
if((hw->mac_type > e1000_82544) &&
(E1000_READ_REG(hw, EECD) & E1000_EECD_SIZE))
return 512;
else
return 128;
}
static void static void
e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
struct ethtool_drvinfo *drvinfo) struct ethtool_drvinfo *drvinfo)
...@@ -186,7 +156,7 @@ e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, ...@@ -186,7 +156,7 @@ e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
drvinfo->n_stats = E1000_STATS_LEN; drvinfo->n_stats = E1000_STATS_LEN;
#define E1000_REGS_LEN 32 #define E1000_REGS_LEN 32
drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t); drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t);
drvinfo->eedump_len = e1000_eeprom_size(&adapter->hw); drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2;
} }
static void static void
...@@ -220,9 +190,8 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter, ...@@ -220,9 +190,8 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter,
struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff) struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff)
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
int max_len, first_word, last_word; int first_word, last_word;
int ret_val = 0; int ret_val = 0;
int i;
if(eeprom->len == 0) { if(eeprom->len == 0) {
ret_val = -EINVAL; ret_val = -EINVAL;
...@@ -231,22 +200,28 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter, ...@@ -231,22 +200,28 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter,
eeprom->magic = hw->vendor_id | (hw->device_id << 16); eeprom->magic = hw->vendor_id | (hw->device_id << 16);
max_len = e1000_eeprom_size(hw);
if(eeprom->offset > eeprom->offset + eeprom->len) { if(eeprom->offset > eeprom->offset + eeprom->len) {
ret_val = -EINVAL; ret_val = -EINVAL;
goto geeprom_error; goto geeprom_error;
} }
if((eeprom->offset + eeprom->len) > max_len) if((eeprom->offset + eeprom->len) > (hw->eeprom.word_size * 2))
eeprom->len = (max_len - eeprom->offset); eeprom->len = ((hw->eeprom.word_size * 2) - eeprom->offset);
first_word = eeprom->offset >> 1; first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1;
for(i = 0; i <= (last_word - first_word); i++) if(hw->eeprom.type == e1000_eeprom_spi)
e1000_read_eeprom(hw, first_word + i, &eeprom_buff[i]); ret_val = e1000_read_eeprom(hw, first_word,
last_word - first_word + 1,
eeprom_buff);
else {
uint16_t i;
for (i = 0; i < last_word - first_word + 1; i++)
if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
&eeprom_buff[i])))
break;
}
geeprom_error: geeprom_error:
return ret_val; return ret_val;
} }
...@@ -257,9 +232,8 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -257,9 +232,8 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
uint16_t *eeprom_buff; uint16_t *eeprom_buff;
int max_len, first_word, last_word;
void *ptr; void *ptr;
int i; int max_len, first_word, last_word, ret_val = 0;
if(eeprom->len == 0) if(eeprom->len == 0)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -267,7 +241,7 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -267,7 +241,7 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
return -EFAULT; return -EFAULT;
max_len = e1000_eeprom_size(hw); max_len = hw->eeprom.word_size * 2;
if((eeprom->offset + eeprom->len) > max_len) if((eeprom->offset + eeprom->len) > max_len)
eeprom->len = (max_len - eeprom->offset); eeprom->len = (max_len - eeprom->offset);
...@@ -283,30 +257,31 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -283,30 +257,31 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
if(eeprom->offset & 1) { if(eeprom->offset & 1) {
/* need read/modify/write of first changed EEPROM word */ /* need read/modify/write of first changed EEPROM word */
/* only the second byte of the word is being modified */ /* only the second byte of the word is being modified */
e1000_read_eeprom(hw, first_word, &eeprom_buff[0]); ret_val = e1000_read_eeprom(hw, first_word, 1,
&eeprom_buff[0]);
ptr++; ptr++;
} }
if((eeprom->offset + eeprom->len) & 1) { if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
/* need read/modify/write of last changed EEPROM word */ /* need read/modify/write of last changed EEPROM word */
/* only the first byte of the word is being modified */ /* only the first byte of the word is being modified */
e1000_read_eeprom(hw, last_word, ret_val = e1000_read_eeprom(hw, last_word, 1,
&eeprom_buff[last_word - first_word]); &eeprom_buff[last_word - first_word]);
} }
if(copy_from_user(ptr, user_data, eeprom->len)) { if((ret_val != 0) || copy_from_user(ptr, user_data, eeprom->len)) {
kfree(eeprom_buff); ret_val = -EFAULT;
return -EFAULT; goto seeprom_error;
} }
for(i = 0; i <= (last_word - first_word); i++) ret_val = e1000_write_eeprom(hw, first_word,
e1000_write_eeprom(hw, first_word + i, eeprom_buff[i]); last_word - first_word + 1, eeprom_buff);
/* Update the checksum over the first part of the EEPROM if needed */ /* Update the checksum over the first part of the EEPROM if needed */
if(first_word <= EEPROM_CHECKSUM_REG) if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
e1000_update_eeprom_checksum(hw); e1000_update_eeprom_checksum(hw);
seeprom_error:
kfree(eeprom_buff); kfree(eeprom_buff);
return ret_val;
return 0;
} }
static void static void
...@@ -333,8 +308,8 @@ e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) ...@@ -333,8 +308,8 @@ e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
/* Fall Through */ /* Fall Through */
default: default:
wol->supported = WAKE_UCAST | WAKE_MCAST wol->supported = WAKE_UCAST | WAKE_MCAST |
| WAKE_BCAST | WAKE_MAGIC; WAKE_BCAST | WAKE_MAGIC;
wol->wolopts = 0; wol->wolopts = 0;
if(adapter->wol & E1000_WUFC_EX) if(adapter->wol & E1000_WUFC_EX)
...@@ -368,7 +343,7 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) ...@@ -368,7 +343,7 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
/* Fall Through */ /* Fall Through */
default: default:
if(wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_PHY)) if(wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP; return -EOPNOTSUPP;
adapter->wol = 0; adapter->wol = 0;
...@@ -542,13 +517,12 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) ...@@ -542,13 +517,12 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
} }
case ETHTOOL_GEEPROM: { case ETHTOOL_GEEPROM: {
struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM}; struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM};
struct e1000_hw *hw = &adapter->hw;
uint16_t *eeprom_buff; uint16_t *eeprom_buff;
void *ptr; void *ptr;
int max_len, err = 0; int err = 0;
max_len = e1000_eeprom_size(&adapter->hw);
eeprom_buff = kmalloc(max_len, GFP_KERNEL); eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL);
if(eeprom_buff == NULL) if(eeprom_buff == NULL)
return -ENOMEM; return -ENOMEM;
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include "e1000_hw.h" #include "e1000_hw.h"
static int32_t e1000_set_phy_type(struct e1000_hw *hw);
static void e1000_phy_init_script(struct e1000_hw *hw);
static int32_t e1000_setup_fiber_link(struct e1000_hw *hw); static int32_t e1000_setup_fiber_link(struct e1000_hw *hw);
static int32_t e1000_setup_copper_link(struct e1000_hw *hw); static int32_t e1000_setup_copper_link(struct e1000_hw *hw);
static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw); static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw);
...@@ -42,16 +44,100 @@ static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl); ...@@ -42,16 +44,100 @@ static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);
static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, uint16_t count); static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, uint16_t count);
static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw); static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw);
static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw); static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw);
static int32_t e1000_write_eeprom_spi(struct e1000_hw *hw, uint16_t offset,
uint16_t words, uint16_t *data);
static int32_t e1000_write_eeprom_microwire(struct e1000_hw *hw,
uint16_t offset, uint16_t words,
uint16_t *data);
static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw);
static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd); static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd); static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count); static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count);
static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw); static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count);
static void e1000_setup_eeprom(struct e1000_hw *hw); static int32_t e1000_acquire_eeprom(struct e1000_hw *hw);
static void e1000_clock_eeprom(struct e1000_hw *hw); static void e1000_release_eeprom(struct e1000_hw *hw);
static void e1000_cleanup_eeprom(struct e1000_hw *hw);
static void e1000_standby_eeprom(struct e1000_hw *hw); static void e1000_standby_eeprom(struct e1000_hw *hw);
static int32_t e1000_id_led_init(struct e1000_hw * hw); static int32_t e1000_id_led_init(struct e1000_hw * hw);
/******************************************************************************
* Set the phy type member in the hw struct.
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
int32_t
e1000_set_phy_type(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_set_phy_type");
switch(hw->phy_id) {
case M88E1000_E_PHY_ID:
case M88E1000_I_PHY_ID:
case M88E1011_I_PHY_ID:
hw->phy_type = e1000_phy_m88;
break;
case IGP01E1000_I_PHY_ID:
hw->phy_type = e1000_phy_igp;
break;
default:
/* Should never have loaded on this device */
hw->phy_type = e1000_phy_undefined;
return -E1000_ERR_PHY_TYPE;
}
return E1000_SUCCESS;
}
/******************************************************************************
* IGP phy init script - initializes the GbE PHY
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
static void
e1000_phy_init_script(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_phy_init_script");
if(hw->phy_init_script) {
msec_delay(10);
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000);
e1000_write_phy_reg(hw,0x0000,0x0140);
msec_delay(5);
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F95);
e1000_write_phy_reg(hw,0x0015,0x0001);
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F71);
e1000_write_phy_reg(hw,0x0011,0xBD21);
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F79);
e1000_write_phy_reg(hw,0x0019,0x0018);
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F30);
e1000_write_phy_reg(hw,0x0010,0x1600);
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F31);
e1000_write_phy_reg(hw,0x0011,0x0014);
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F32);
e1000_write_phy_reg(hw,0x0012,0x161C);
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F94);
e1000_write_phy_reg(hw,0x0014,0x0003);
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F96);
e1000_write_phy_reg(hw,0x0016,0x003F);
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x2010);
e1000_write_phy_reg(hw,0x0010,0x0008);
e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000);
e1000_write_phy_reg(hw,0x0000,0x3300);
}
}
/****************************************************************************** /******************************************************************************
* Set the mac type member in the hw struct. * Set the mac type member in the hw struct.
* *
...@@ -101,10 +187,19 @@ e1000_set_mac_type(struct e1000_hw *hw) ...@@ -101,10 +187,19 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546EB_FIBER:
hw->mac_type = e1000_82546; hw->mac_type = e1000_82546;
break; break;
case E1000_DEV_ID_82541EI:
case E1000_DEV_ID_82541EP:
hw->mac_type = e1000_82541;
break;
case E1000_DEV_ID_82547EI:
hw->mac_type = e1000_82547;
break;
default: default:
/* Should never have loaded on this device */ /* Should never have loaded on this device */
return -E1000_ERR_MAC_TYPE; return -E1000_ERR_MAC_TYPE;
} }
return E1000_SUCCESS; return E1000_SUCCESS;
} }
/****************************************************************************** /******************************************************************************
...@@ -119,6 +214,7 @@ e1000_reset_hw(struct e1000_hw *hw) ...@@ -119,6 +214,7 @@ e1000_reset_hw(struct e1000_hw *hw)
uint32_t ctrl_ext; uint32_t ctrl_ext;
uint32_t icr; uint32_t icr;
uint32_t manc; uint32_t manc;
uint32_t led_ctrl;
DEBUGFUNC("e1000_reset_hw"); DEBUGFUNC("e1000_reset_hw");
...@@ -156,6 +252,12 @@ e1000_reset_hw(struct e1000_hw *hw) ...@@ -156,6 +252,12 @@ e1000_reset_hw(struct e1000_hw *hw)
DEBUGOUT("Issuing a global reset to MAC\n"); DEBUGOUT("Issuing a global reset to MAC\n");
ctrl = E1000_READ_REG(hw, CTRL); ctrl = E1000_READ_REG(hw, CTRL);
/* Must reset the PHY before resetting the MAC */
if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST));
msec_delay(5);
}
if(hw->mac_type > e1000_82543) if(hw->mac_type > e1000_82543)
E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
else else
...@@ -173,13 +275,25 @@ e1000_reset_hw(struct e1000_hw *hw) ...@@ -173,13 +275,25 @@ e1000_reset_hw(struct e1000_hw *hw)
msec_delay(2); msec_delay(2);
} else { } else {
/* Wait for EEPROM reload (it happens automatically) */ /* Wait for EEPROM reload (it happens automatically) */
msec_delay(4); msec_delay(5);
/* Dissable HW ARPs on ASF enabled adapters */ /* Dissable HW ARPs on ASF enabled adapters */
manc = E1000_READ_REG(hw, MANC); manc = E1000_READ_REG(hw, MANC);
manc &= ~(E1000_MANC_ARP_EN); manc &= ~(E1000_MANC_ARP_EN);
E1000_WRITE_REG(hw, MANC, manc); E1000_WRITE_REG(hw, MANC, manc);
} }
if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
e1000_phy_init_script(hw);
/* Configure activity LED after PHY reset */
led_ctrl = E1000_READ_REG(hw, LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= IGP_ACTIVITY_LED_ENABLE;
if(hw->mac_type == e1000_82547)
led_ctrl |= IGP_LED3_MODE;
E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
}
/* Clear interrupt mask to stop board from generating interrupts */ /* Clear interrupt mask to stop board from generating interrupts */
DEBUGOUT("Masking off all interrupts\n"); DEBUGOUT("Masking off all interrupts\n");
E1000_WRITE_REG(hw, IMC, 0xffffffff); E1000_WRITE_REG(hw, IMC, 0xffffffff);
...@@ -353,7 +467,7 @@ e1000_setup_link(struct e1000_hw *hw) ...@@ -353,7 +467,7 @@ e1000_setup_link(struct e1000_hw *hw)
* control setting, then the variable hw->fc will * control setting, then the variable hw->fc will
* be initialized based on a value in the EEPROM. * be initialized based on a value in the EEPROM.
*/ */
if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, &eeprom_data) < 0) { if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n"); DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM; return -E1000_ERR_EEPROM;
} }
...@@ -574,7 +688,7 @@ e1000_setup_fiber_link(struct e1000_hw *hw) ...@@ -574,7 +688,7 @@ e1000_setup_fiber_link(struct e1000_hw *hw)
static int32_t static int32_t
e1000_setup_copper_link(struct e1000_hw *hw) e1000_setup_copper_link(struct e1000_hw *hw)
{ {
uint32_t ctrl; uint32_t ctrl, led_ctrl;
int32_t ret_val; int32_t ret_val;
uint16_t i; uint16_t i;
uint16_t phy_data; uint16_t phy_data;
...@@ -604,6 +718,72 @@ e1000_setup_copper_link(struct e1000_hw *hw) ...@@ -604,6 +718,72 @@ e1000_setup_copper_link(struct e1000_hw *hw)
} }
DEBUGOUT1("Phy ID = %x \n", hw->phy_id); DEBUGOUT1("Phy ID = %x \n", hw->phy_id);
if (hw->phy_type == e1000_phy_igp) {
ret_val = e1000_phy_reset(hw);
if(ret_val < 0) {
DEBUGOUT("Error Resetting the PHY\n");
return ret_val;
}
/* Wait 10ms for MAC to configure PHY from eeprom settings */
msec_delay(15);
if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) {
DEBUGOUT("PHY Write Error\n");
return -E1000_ERR_PHY;
}
/* Configure activity LED after PHY reset */
led_ctrl = E1000_READ_REG(hw, LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= IGP_ACTIVITY_LED_ENABLE;
if(hw->mac_type == e1000_82547)
led_ctrl |= IGP_LED3_MODE;
E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
/* Disable SmartSpeed */
if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
&phy_data) < 0) {
DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY;
}
phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
phy_data) < 0) {
DEBUGOUT("PHY Write Error\n");
return -E1000_ERR_PHY;
}
/* Set auto Master/Slave resolution process */
if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data) < 0) {
DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY;
}
phy_data &= ~CR_1000T_MS_ENABLE;
if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data) < 0) {
DEBUGOUT("PHY Write Error\n");
return -E1000_ERR_PHY;
}
}
if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) {
DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY;
}
/* Force MDI for IGP PHY */
phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX |
IGP01E1000_PSCR_FORCE_MDI_MDIX);
hw->mdix = 1;
if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) {
DEBUGOUT("PHY Write Error\n");
return -E1000_ERR_PHY;
}
} else {
/* Enable CRS on TX. This must be set for half-duplex operation. */ /* Enable CRS on TX. This must be set for half-duplex operation. */
if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) {
DEBUGOUT("PHY Read Error\n"); DEBUGOUT("PHY Read Error\n");
...@@ -665,7 +845,8 @@ e1000_setup_copper_link(struct e1000_hw *hw) ...@@ -665,7 +845,8 @@ e1000_setup_copper_link(struct e1000_hw *hw)
M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) { if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
phy_data) < 0) {
DEBUGOUT("PHY Write Error\n"); DEBUGOUT("PHY Write Error\n");
return -E1000_ERR_PHY; return -E1000_ERR_PHY;
} }
...@@ -677,6 +858,7 @@ e1000_setup_copper_link(struct e1000_hw *hw) ...@@ -677,6 +858,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
DEBUGOUT("Error Resetting the PHY\n"); DEBUGOUT("Error Resetting the PHY\n");
return ret_val; return ret_val;
} }
}
/* Options: /* Options:
* autoneg = 1 (default) * autoneg = 1 (default)
...@@ -736,6 +918,7 @@ e1000_setup_copper_link(struct e1000_hw *hw) ...@@ -736,6 +918,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
return ret_val; return ret_val;
} }
} }
hw->get_link_status = TRUE;
} else { } else {
DEBUGOUT("Forcing speed and duplex\n"); DEBUGOUT("Forcing speed and duplex\n");
ret_val = e1000_phy_force_speed_duplex(hw); ret_val = e1000_phy_force_speed_duplex(hw);
...@@ -1014,6 +1197,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) ...@@ -1014,6 +1197,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
/* Write the configured values back to the Device Control Reg. */ /* Write the configured values back to the Device Control Reg. */
E1000_WRITE_REG(hw, CTRL, ctrl); E1000_WRITE_REG(hw, CTRL, ctrl);
if (hw->phy_type == e1000_phy_m88) {
if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) {
DEBUGOUT("PHY Read Error\n"); DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY; return -E1000_ERR_PHY;
...@@ -1031,6 +1215,23 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) ...@@ -1031,6 +1215,23 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
/* Need to reset the PHY or these changes will be ignored */ /* Need to reset the PHY or these changes will be ignored */
mii_ctrl_reg |= MII_CR_RESET; mii_ctrl_reg |= MII_CR_RESET;
} else {
/* Clear Auto-Crossover to force MDI manually. IGP requires MDI
* forced whenever speed or duplex are forced.
*/
if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) {
DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY;
}
phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) {
DEBUGOUT("PHY Write Error\n");
return -E1000_ERR_PHY;
}
}
/* Write back the modified PHY MII control register. */ /* Write back the modified PHY MII control register. */
if(e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg) < 0) { if(e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg) < 0) {
...@@ -1094,6 +1295,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) ...@@ -1094,6 +1295,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
} }
} }
if (hw->phy_type == e1000_phy_m88) {
/* Because we reset the PHY above, we need to re-force TX_CLK in the /* Because we reset the PHY above, we need to re-force TX_CLK in the
* Extended PHY Specific Control Register to 25MHz clock. This value * Extended PHY Specific Control Register to 25MHz clock. This value
* defaults back to a 2.5MHz clock when the PHY is reset. * defaults back to a 2.5MHz clock when the PHY is reset.
...@@ -1120,6 +1322,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) ...@@ -1120,6 +1322,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
DEBUGOUT("PHY Write Error\n"); DEBUGOUT("PHY Write Error\n");
return -E1000_ERR_PHY; return -E1000_ERR_PHY;
} }
}
return 0; return 0;
} }
...@@ -1136,6 +1339,8 @@ e1000_config_collision_dist(struct e1000_hw *hw) ...@@ -1136,6 +1339,8 @@ e1000_config_collision_dist(struct e1000_hw *hw)
{ {
uint32_t tctl; uint32_t tctl;
DEBUGFUNC("e1000_config_collision_dist");
tctl = E1000_READ_REG(hw, TCTL); tctl = E1000_READ_REG(hw, TCTL);
tctl &= ~E1000_TCTL_COLD; tctl &= ~E1000_TCTL_COLD;
...@@ -1172,6 +1377,26 @@ e1000_config_mac_to_phy(struct e1000_hw *hw) ...@@ -1172,6 +1377,26 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
/* Set up duplex in the Device Control and Transmit Control /* Set up duplex in the Device Control and Transmit Control
* registers depending on negotiated values. * registers depending on negotiated values.
*/ */
if (hw->phy_type == e1000_phy_igp) {
if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) {
DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY;
}
if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD;
else ctrl &= ~E1000_CTRL_FD;
e1000_config_collision_dist(hw);
/* Set up speed in the Device Control register depending on
* negotiated values.
*/
if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
IGP01E1000_PSSR_SPEED_1000MBPS)
ctrl |= E1000_CTRL_SPD_1000;
else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
IGP01E1000_PSSR_SPEED_100MBPS)
ctrl |= E1000_CTRL_SPD_100;
} else {
if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) {
DEBUGOUT("PHY Read Error\n"); DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY; return -E1000_ERR_PHY;
...@@ -1188,6 +1413,7 @@ e1000_config_mac_to_phy(struct e1000_hw *hw) ...@@ -1188,6 +1413,7 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
ctrl |= E1000_CTRL_SPD_1000; ctrl |= E1000_CTRL_SPD_1000;
else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
ctrl |= E1000_CTRL_SPD_100; ctrl |= E1000_CTRL_SPD_100;
}
/* Write the configured values back to the Device Control Reg. */ /* Write the configured values back to the Device Control Reg. */
E1000_WRITE_REG(hw, CTRL, ctrl); E1000_WRITE_REG(hw, CTRL, ctrl);
return 0; return 0;
...@@ -1519,6 +1745,10 @@ e1000_check_for_link(struct e1000_hw *hw) ...@@ -1519,6 +1745,10 @@ e1000_check_for_link(struct e1000_hw *hw)
if(phy_data & MII_SR_LINK_STATUS) { if(phy_data & MII_SR_LINK_STATUS) {
hw->get_link_status = FALSE; hw->get_link_status = FALSE;
/* Check if there was DownShift, must be checked immediately after
* link-up */
e1000_check_downshift(hw);
} else { } else {
/* No link detected */ /* No link detected */
return 0; return 0;
...@@ -2010,6 +2240,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, ...@@ -2010,6 +2240,7 @@ e1000_write_phy_reg(struct e1000_hw *hw,
e1000_shift_out_mdi_bits(hw, mdic, 32); e1000_shift_out_mdi_bits(hw, mdic, 32);
} }
return 0; return 0;
} }
...@@ -2021,8 +2252,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, ...@@ -2021,8 +2252,7 @@ e1000_write_phy_reg(struct e1000_hw *hw,
void void
e1000_phy_hw_reset(struct e1000_hw *hw) e1000_phy_hw_reset(struct e1000_hw *hw)
{ {
uint32_t ctrl; uint32_t ctrl, ctrl_ext, led_ctrl;
uint32_t ctrl_ext;
DEBUGFUNC("e1000_phy_hw_reset"); DEBUGFUNC("e1000_phy_hw_reset");
...@@ -2053,6 +2283,21 @@ e1000_phy_hw_reset(struct e1000_hw *hw) ...@@ -2053,6 +2283,21 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
E1000_WRITE_FLUSH(hw); E1000_WRITE_FLUSH(hw);
} }
udelay(150); udelay(150);
if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) {
DEBUGOUT("PHY Write Error\n");
return;
}
/* Configure activity LED after PHY reset */
led_ctrl = E1000_READ_REG(hw, LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= IGP_ACTIVITY_LED_ENABLE;
if(hw->mac_type == e1000_82547)
led_ctrl |= IGP_LED3_MODE;
E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
}
} }
/****************************************************************************** /******************************************************************************
...@@ -2079,6 +2324,9 @@ e1000_phy_reset(struct e1000_hw *hw) ...@@ -2079,6 +2324,9 @@ e1000_phy_reset(struct e1000_hw *hw)
return -E1000_ERR_PHY; return -E1000_ERR_PHY;
} }
udelay(1); udelay(1);
if (hw->phy_type == e1000_phy_igp) {
e1000_phy_init_script(hw);
}
return 0; return 0;
} }
...@@ -2092,6 +2340,7 @@ e1000_detect_gig_phy(struct e1000_hw *hw) ...@@ -2092,6 +2340,7 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
{ {
uint16_t phy_id_high, phy_id_low; uint16_t phy_id_high, phy_id_low;
boolean_t match = FALSE; boolean_t match = FALSE;
int32_t phy_init_status;
DEBUGFUNC("e1000_detect_gig_phy"); DEBUGFUNC("e1000_detect_gig_phy");
...@@ -2101,7 +2350,7 @@ e1000_detect_gig_phy(struct e1000_hw *hw) ...@@ -2101,7 +2350,7 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
return -E1000_ERR_PHY; return -E1000_ERR_PHY;
} }
hw->phy_id = (uint32_t) (phy_id_high << 16); hw->phy_id = (uint32_t) (phy_id_high << 16);
udelay(2); udelay(20);
if(e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low) < 0) { if(e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low) < 0) {
DEBUGOUT("PHY Read Error\n"); DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY; return -E1000_ERR_PHY;
...@@ -2121,11 +2370,17 @@ e1000_detect_gig_phy(struct e1000_hw *hw) ...@@ -2121,11 +2370,17 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
case e1000_82546: case e1000_82546:
if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE; if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
break; break;
case e1000_82541:
case e1000_82547:
if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
break;
default: default:
DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type); DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
return -E1000_ERR_CONFIG; return -E1000_ERR_CONFIG;
} }
if(match) { phy_init_status = e1000_set_phy_type(hw);
if ((match) && (phy_init_status == E1000_SUCCESS)) {
DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id); DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id);
return 0; return 0;
} }
...@@ -2156,43 +2411,93 @@ e1000_phy_reset_dsp(struct e1000_hw *hw) ...@@ -2156,43 +2411,93 @@ e1000_phy_reset_dsp(struct e1000_hw *hw)
} }
/****************************************************************************** /******************************************************************************
* Get PHY information from various PHY registers * Get PHY information from various PHY registers for igp PHY only.
* *
* hw - Struct containing variables accessed by shared code * hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure * phy_info - PHY information structure
******************************************************************************/ ******************************************************************************/
int32_t int32_t
e1000_phy_get_info(struct e1000_hw *hw, e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
struct e1000_phy_info *phy_info)
{ {
int32_t ret_val = -E1000_ERR_PHY; uint16_t phy_data, polarity, min_length, max_length, average;
uint16_t phy_data;
DEBUGFUNC("e1000_phy_get_info"); DEBUGFUNC("e1000_phy_igp_get_info");
phy_info->cable_length = e1000_cable_length_undefined; /* The downshift status is checked only once, after link is established,
phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined; * and it stored in the hw->speed_downgraded parameter. */
phy_info->cable_polarity = e1000_rev_polarity_undefined; phy_info->downshift = hw->speed_downgraded;
phy_info->polarity_correction = e1000_polarity_reversal_undefined;
phy_info->mdix_mode = e1000_auto_x_mode_undefined;
phy_info->local_rx = e1000_1000t_rx_status_undefined;
phy_info->remote_rx = e1000_1000t_rx_status_undefined;
if(hw->media_type != e1000_media_type_copper) { /* IGP01E1000 does not need to support it. */
DEBUGOUT("PHY info is only valid for copper media\n"); phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal;
return -E1000_ERR_CONFIG;
}
do { /* IGP01E1000 always correct polarity reversal */
if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) break; phy_info->polarity_correction = e1000_polarity_reversal_enabled;
if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) break;
if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { /* Check polarity status */
DEBUGOUT("PHY info is only valid if link is up\n"); if(e1000_check_polarity(hw, &polarity) < 0)
return -E1000_ERR_CONFIG; return -E1000_ERR_PHY;
phy_info->cable_polarity = polarity;
if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0)
return -E1000_ERR_PHY;
phy_info->mdix_mode = (phy_data & IGP01E1000_PSSR_MDIX) >>
IGP01E1000_PSSR_MDIX_SHIFT;
if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
IGP01E1000_PSSR_SPEED_1000MBPS) {
/* Local/Remote Receiver Information are only valid at 1000 Mbps */
if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0)
return -E1000_ERR_PHY;
phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >>
SR_1000T_LOCAL_RX_STATUS_SHIFT;
phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) >>
SR_1000T_REMOTE_RX_STATUS_SHIFT;
/* Get cable length */
if(e1000_get_cable_length(hw, &min_length, &max_length) < 0)
return -E1000_ERR_PHY;
/* transalte to old method */
average = (max_length + min_length) / 2;
if(average <= e1000_igp_cable_length_50)
phy_info->cable_length = e1000_cable_length_50;
else if(average <= e1000_igp_cable_length_80)
phy_info->cable_length = e1000_cable_length_50_80;
else if(average <= e1000_igp_cable_length_110)
phy_info->cable_length = e1000_cable_length_80_110;
else if(average <= e1000_igp_cable_length_140)
phy_info->cable_length = e1000_cable_length_110_140;
else
phy_info->cable_length = e1000_cable_length_140;
} }
return E1000_SUCCESS;
}
/******************************************************************************
* Get PHY information from various PHY registers fot m88 PHY only.
*
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
int32_t
e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
{
uint16_t phy_data, polarity;
DEBUGFUNC("e1000_phy_m88_get_info");
/* The downshift status is checked only once, after link is established,
* and it stored in the hw->speed_downgraded parameter. */
phy_info->downshift = hw->speed_downgraded;
if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0)
break; return -E1000_ERR_PHY;
phy_info->extended_10bt_distance = phy_info->extended_10bt_distance =
(phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >>
M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT; M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT;
...@@ -2200,30 +2505,83 @@ e1000_phy_get_info(struct e1000_hw *hw, ...@@ -2200,30 +2505,83 @@ e1000_phy_get_info(struct e1000_hw *hw,
(phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >> (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >>
M88E1000_PSCR_POLARITY_REVERSAL_SHIFT; M88E1000_PSCR_POLARITY_REVERSAL_SHIFT;
/* Check polarity status */
if(e1000_check_polarity(hw, &polarity) < 0)
return -E1000_ERR_PHY;
phy_info->cable_polarity = polarity;
if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0)
break; return -E1000_ERR_PHY;
phy_info->cable_polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >>
M88E1000_PSSR_REV_POLARITY_SHIFT;
phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >> phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >>
M88E1000_PSSR_MDIX_SHIFT; M88E1000_PSSR_MDIX_SHIFT;
if(phy_data & M88E1000_PSSR_1000MBS) { if(phy_data & M88E1000_PSSR_1000MBS) {
/* Cable Length Estimation and Local/Remote Receiver Informatoion /* Cable Length Estimation and Local/Remote Receiver Informatoion
* are only valid at 1000 Mbps * are only valid at 1000 Mbps
*/ */
phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
M88E1000_PSSR_CABLE_LENGTH_SHIFT); M88E1000_PSSR_CABLE_LENGTH_SHIFT);
if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0)
break; return -E1000_ERR_PHY;
phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >>
SR_1000T_LOCAL_RX_STATUS_SHIFT; SR_1000T_LOCAL_RX_STATUS_SHIFT;
phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) >> phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) >>
SR_1000T_REMOTE_RX_STATUS_SHIFT; SR_1000T_REMOTE_RX_STATUS_SHIFT;
} }
ret_val = 0;
} while(0);
if(ret_val < 0) DEBUGOUT("PHY Read Error\n"); return E1000_SUCCESS;
return ret_val; }
/******************************************************************************
* Get PHY information from various PHY registers
*
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
int32_t
e1000_phy_get_info(struct e1000_hw *hw,
struct e1000_phy_info *phy_info)
{
uint16_t phy_data;
DEBUGFUNC("e1000_phy_get_info");
phy_info->cable_length = e1000_cable_length_undefined;
phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined;
phy_info->cable_polarity = e1000_rev_polarity_undefined;
phy_info->downshift = e1000_downshift_undefined;
phy_info->polarity_correction = e1000_polarity_reversal_undefined;
phy_info->mdix_mode = e1000_auto_x_mode_undefined;
phy_info->local_rx = e1000_1000t_rx_status_undefined;
phy_info->remote_rx = e1000_1000t_rx_status_undefined;
if(hw->media_type != e1000_media_type_copper) {
DEBUGOUT("PHY info is only valid for copper media\n");
return -E1000_ERR_CONFIG;
}
if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) {
DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY;
}
if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) {
DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY;
}
if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) {
DEBUGOUT("PHY info is only valid if link is up\n");
return -E1000_ERR_CONFIG;
}
if (hw->phy_type == e1000_phy_igp)
return e1000_phy_igp_get_info(hw, phy_info);
else
return e1000_phy_m88_get_info(hw, phy_info);
} }
int32_t int32_t
...@@ -2239,15 +2597,118 @@ e1000_validate_mdi_setting(struct e1000_hw *hw) ...@@ -2239,15 +2597,118 @@ e1000_validate_mdi_setting(struct e1000_hw *hw)
return 0; return 0;
} }
/****************************************************************************** /******************************************************************************
* Raises the EEPROM's clock input. * Sets up eeprom variables in the hw struct. Must be called after mac_type
* is configured.
* *
* hw - Struct containing variables accessed by shared code * hw - Struct containing variables accessed by shared code
* eecd - EECD's current value
*****************************************************************************/ *****************************************************************************/
static void void
e1000_raise_ee_clk(struct e1000_hw *hw, e1000_init_eeprom_params(struct e1000_hw *hw)
uint32_t *eecd) {
struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint32_t eecd = E1000_READ_REG(hw, EECD);
uint16_t eeprom_size;
DEBUGFUNC("e1000_init_eeprom_params");
switch (hw->mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
case e1000_82543:
case e1000_82544:
eeprom->type = e1000_eeprom_microwire;
eeprom->word_size = 64;
eeprom->opcode_bits = 3;
eeprom->address_bits = 6;
eeprom->delay_usec = 50;
break;
case e1000_82540:
case e1000_82545:
case e1000_82546:
eeprom->type = e1000_eeprom_microwire;
eeprom->opcode_bits = 3;
eeprom->delay_usec = 50;
if(eecd & E1000_EECD_SIZE) {
eeprom->word_size = 256;
eeprom->address_bits = 8;
} else {
eeprom->word_size = 64;
eeprom->address_bits = 6;
}
break;
case e1000_82541:
case e1000_82547:
default:
if (eecd & E1000_EECD_TYPE) {
eeprom->type = e1000_eeprom_spi;
eeprom->opcode_bits = 8;
eeprom->delay_usec = 1;
if (eecd & E1000_EECD_ADDR_BITS) {
eeprom->page_size = 32;
eeprom->address_bits = 16;
} else {
eeprom->page_size = 8;
eeprom->address_bits = 8;
}
} else {
eeprom->type = e1000_eeprom_microwire;
eeprom->opcode_bits = 3;
eeprom->delay_usec = 50;
if (eecd & E1000_EECD_ADDR_BITS) {
eeprom->word_size = 256;
eeprom->address_bits = 8;
} else {
eeprom->word_size = 64;
eeprom->address_bits = 6;
}
}
break;
}
if (eeprom->type == e1000_eeprom_spi) {
eeprom->word_size = 64;
if (e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size) == 0) {
eeprom_size &= EEPROM_SIZE_MASK;
switch (eeprom_size) {
case EEPROM_SIZE_16KB:
eeprom->word_size = 8192;
break;
case EEPROM_SIZE_8KB:
eeprom->word_size = 4096;
break;
case EEPROM_SIZE_4KB:
eeprom->word_size = 2048;
break;
case EEPROM_SIZE_2KB:
eeprom->word_size = 1024;
break;
case EEPROM_SIZE_1KB:
eeprom->word_size = 512;
break;
case EEPROM_SIZE_512B:
eeprom->word_size = 256;
break;
case EEPROM_SIZE_128B:
default:
eeprom->word_size = 64;
break;
}
}
}
}
/******************************************************************************
* Raises the EEPROM's clock input.
*
* hw - Struct containing variables accessed by shared code
* eecd - EECD's current value
*****************************************************************************/
static void
e1000_raise_ee_clk(struct e1000_hw *hw,
uint32_t *eecd)
{ {
/* Raise the clock input to the EEPROM (by setting the SK bit), and then /* Raise the clock input to the EEPROM (by setting the SK bit), and then
* wait <delay> microseconds. * wait <delay> microseconds.
...@@ -2255,7 +2716,7 @@ e1000_raise_ee_clk(struct e1000_hw *hw, ...@@ -2255,7 +2716,7 @@ e1000_raise_ee_clk(struct e1000_hw *hw,
*eecd = *eecd | E1000_EECD_SK; *eecd = *eecd | E1000_EECD_SK;
E1000_WRITE_REG(hw, EECD, *eecd); E1000_WRITE_REG(hw, EECD, *eecd);
E1000_WRITE_FLUSH(hw); E1000_WRITE_FLUSH(hw);
udelay(50); udelay(hw->eeprom.delay_usec);
} }
/****************************************************************************** /******************************************************************************
...@@ -2274,7 +2735,7 @@ e1000_lower_ee_clk(struct e1000_hw *hw, ...@@ -2274,7 +2735,7 @@ e1000_lower_ee_clk(struct e1000_hw *hw,
*eecd = *eecd & ~E1000_EECD_SK; *eecd = *eecd & ~E1000_EECD_SK;
E1000_WRITE_REG(hw, EECD, *eecd); E1000_WRITE_REG(hw, EECD, *eecd);
E1000_WRITE_FLUSH(hw); E1000_WRITE_FLUSH(hw);
udelay(50); udelay(hw->eeprom.delay_usec);
} }
/****************************************************************************** /******************************************************************************
...@@ -2289,6 +2750,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw, ...@@ -2289,6 +2750,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
uint16_t data, uint16_t data,
uint16_t count) uint16_t count)
{ {
struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint32_t eecd; uint32_t eecd;
uint32_t mask; uint32_t mask;
...@@ -2298,7 +2760,11 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw, ...@@ -2298,7 +2760,11 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
*/ */
mask = 0x01 << (count - 1); mask = 0x01 << (count - 1);
eecd = E1000_READ_REG(hw, EECD); eecd = E1000_READ_REG(hw, EECD);
eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); if (eeprom->type == e1000_eeprom_microwire) {
eecd &= ~E1000_EECD_DO;
} else if (eeprom->type == e1000_eeprom_spi) {
eecd |= E1000_EECD_DO;
}
do { do {
/* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1", /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
* and then raising and then lowering the clock (the SK bit controls * and then raising and then lowering the clock (the SK bit controls
...@@ -2313,7 +2779,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw, ...@@ -2313,7 +2779,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_REG(hw, EECD, eecd);
E1000_WRITE_FLUSH(hw); E1000_WRITE_FLUSH(hw);
udelay(50); udelay(eeprom->delay_usec);
e1000_raise_ee_clk(hw, &eecd); e1000_raise_ee_clk(hw, &eecd);
e1000_lower_ee_clk(hw, &eecd); e1000_lower_ee_clk(hw, &eecd);
...@@ -2333,7 +2799,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw, ...@@ -2333,7 +2799,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code * hw - Struct containing variables accessed by shared code
*****************************************************************************/ *****************************************************************************/
static uint16_t static uint16_t
e1000_shift_in_ee_bits(struct e1000_hw *hw) e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count)
{ {
uint32_t eecd; uint32_t eecd;
uint32_t i; uint32_t i;
...@@ -2351,7 +2817,7 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw) ...@@ -2351,7 +2817,7 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw)
eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
data = 0; data = 0;
for(i = 0; i < 16; i++) { for(i = 0; i < count; i++) {
data = data << 1; data = data << 1;
e1000_raise_ee_clk(hw, &eecd); e1000_raise_ee_clk(hw, &eecd);
...@@ -2375,20 +2841,53 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw) ...@@ -2375,20 +2841,53 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw)
* Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
* function should be called before issuing a command to the EEPROM. * function should be called before issuing a command to the EEPROM.
*****************************************************************************/ *****************************************************************************/
static void static int32_t
e1000_setup_eeprom(struct e1000_hw *hw) e1000_acquire_eeprom(struct e1000_hw *hw)
{ {
uint32_t eecd; struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint32_t eecd, i=0;
DEBUGFUNC("e1000_acquire_eeprom");
eecd = E1000_READ_REG(hw, EECD); eecd = E1000_READ_REG(hw, EECD);
/* Request EEPROM Access */
if(hw->mac_type > e1000_82544) {
eecd |= E1000_EECD_REQ;
E1000_WRITE_REG(hw, EECD, eecd);
eecd = E1000_READ_REG(hw, EECD);
while((!(eecd & E1000_EECD_GNT)) &&
(i < E1000_EEPROM_GRANT_ATTEMPTS)) {
i++;
udelay(5);
eecd = E1000_READ_REG(hw, EECD);
}
if(!(eecd & E1000_EECD_GNT)) {
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, EECD, eecd);
DEBUGOUT("Could not acquire EEPROM grant\n");
return -E1000_ERR_EEPROM;
}
}
/* Setup EEPROM for Read/Write */
if (eeprom->type == e1000_eeprom_microwire) {
/* Clear SK and DI */ /* Clear SK and DI */
eecd &= ~(E1000_EECD_SK | E1000_EECD_DI); eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_REG(hw, EECD, eecd);
/* Set CS */ /* Set CS */
eecd |= E1000_EECD_CS; eecd |= E1000_EECD_CS;
E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_REG(hw, EECD, eecd);
} else if (eeprom->type == e1000_eeprom_spi) {
/* Clear SK and CS */
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
E1000_WRITE_REG(hw, EECD, eecd);
udelay(1);
}
return E1000_SUCCESS;
} }
/****************************************************************************** /******************************************************************************
...@@ -2399,77 +2898,136 @@ e1000_setup_eeprom(struct e1000_hw *hw) ...@@ -2399,77 +2898,136 @@ e1000_setup_eeprom(struct e1000_hw *hw)
static void static void
e1000_standby_eeprom(struct e1000_hw *hw) e1000_standby_eeprom(struct e1000_hw *hw)
{ {
struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint32_t eecd; uint32_t eecd;
eecd = E1000_READ_REG(hw, EECD); eecd = E1000_READ_REG(hw, EECD);
/* Deselct EEPROM */ if(eeprom->type == e1000_eeprom_microwire) {
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_REG(hw, EECD, eecd);
E1000_WRITE_FLUSH(hw); E1000_WRITE_FLUSH(hw);
udelay(50); udelay(eeprom->delay_usec);
/* Clock high */ /* Clock high */
eecd |= E1000_EECD_SK; eecd |= E1000_EECD_SK;
E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_REG(hw, EECD, eecd);
E1000_WRITE_FLUSH(hw); E1000_WRITE_FLUSH(hw);
udelay(50); udelay(eeprom->delay_usec);
/* Select EEPROM */ /* Select EEPROM */
eecd |= E1000_EECD_CS; eecd |= E1000_EECD_CS;
E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_REG(hw, EECD, eecd);
E1000_WRITE_FLUSH(hw); E1000_WRITE_FLUSH(hw);
udelay(50); udelay(eeprom->delay_usec);
/* Clock low */ /* Clock low */
eecd &= ~E1000_EECD_SK; eecd &= ~E1000_EECD_SK;
E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_REG(hw, EECD, eecd);
E1000_WRITE_FLUSH(hw); E1000_WRITE_FLUSH(hw);
udelay(50); udelay(eeprom->delay_usec);
} else if(eeprom->type == e1000_eeprom_spi) {
/* Toggle CS to flush commands */
eecd |= E1000_EECD_CS;
E1000_WRITE_REG(hw, EECD, eecd);
E1000_WRITE_FLUSH(hw);
udelay(eeprom->delay_usec);
eecd &= ~E1000_EECD_CS;
E1000_WRITE_REG(hw, EECD, eecd);
E1000_WRITE_FLUSH(hw);
udelay(eeprom->delay_usec);
}
} }
/****************************************************************************** /******************************************************************************
* Raises then lowers the EEPROM's clock pin * Terminates a command by inverting the EEPROM's chip select pin
* *
* hw - Struct containing variables accessed by shared code * hw - Struct containing variables accessed by shared code
*****************************************************************************/ *****************************************************************************/
static void static void
e1000_clock_eeprom(struct e1000_hw *hw) e1000_release_eeprom(struct e1000_hw *hw)
{ {
uint32_t eecd; uint32_t eecd;
DEBUGFUNC("e1000_release_eeprom");
eecd = E1000_READ_REG(hw, EECD); eecd = E1000_READ_REG(hw, EECD);
if (hw->eeprom.type == e1000_eeprom_spi) {
eecd |= E1000_EECD_CS; /* Pull CS high */
eecd &= ~E1000_EECD_SK; /* Lower SCK */
E1000_WRITE_REG(hw, EECD, eecd);
udelay(hw->eeprom.delay_usec);
} else if(hw->eeprom.type == e1000_eeprom_microwire) {
/* cleanup eeprom */
/* CS on Microwire is active-high */
eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
E1000_WRITE_REG(hw, EECD, eecd);
/* Rising edge of clock */ /* Rising edge of clock */
eecd |= E1000_EECD_SK; eecd |= E1000_EECD_SK;
E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_REG(hw, EECD, eecd);
E1000_WRITE_FLUSH(hw); E1000_WRITE_FLUSH(hw);
udelay(50); udelay(hw->eeprom.delay_usec);
/* Falling edge of clock */ /* Falling edge of clock */
eecd &= ~E1000_EECD_SK; eecd &= ~E1000_EECD_SK;
E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_REG(hw, EECD, eecd);
E1000_WRITE_FLUSH(hw); E1000_WRITE_FLUSH(hw);
udelay(50); udelay(hw->eeprom.delay_usec);
}
/* Stop requesting EEPROM access */
if(hw->mac_type > e1000_82544) {
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, EECD, eecd);
}
} }
/****************************************************************************** /******************************************************************************
* Terminates a command by lowering the EEPROM's chip select pin * Reads a 16 bit word from the EEPROM.
* *
* hw - Struct containing variables accessed by shared code * hw - Struct containing variables accessed by shared code
*****************************************************************************/ *****************************************************************************/
static void int32_t
e1000_cleanup_eeprom(struct e1000_hw *hw) e1000_spi_eeprom_ready(struct e1000_hw *hw)
{ {
uint32_t eecd; uint16_t retry_count = 0;
uint8_t spi_stat_reg;
eecd = E1000_READ_REG(hw, EECD); DEBUGFUNC("e1000_spi_eeprom_ready");
eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); /* Read "Status Register" repeatedly until the LSB is cleared. The
* EEPROM will signal that the command has been completed by clearing
* bit 0 of the internal status register. If it's not cleared within
* 5 milliseconds, then error out.
*/
retry_count = 0;
do {
e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
hw->eeprom.opcode_bits);
spi_stat_reg = (uint8_t)e1000_shift_in_ee_bits(hw, 8);
if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
break;
E1000_WRITE_REG(hw, EECD, eecd); udelay(5);
retry_count += 5;
e1000_clock_eeprom(hw); } while(retry_count < EEPROM_MAX_RETRY_SPI);
/* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and
* only 0-5mSec on 5V devices)
*/
if(retry_count >= EEPROM_MAX_RETRY_SPI) {
DEBUGOUT("SPI EEPROM Status error\n");
return -E1000_ERR_EEPROM;
}
return E1000_SUCCESS;
} }
/****************************************************************************** /******************************************************************************
...@@ -2478,64 +3036,69 @@ e1000_cleanup_eeprom(struct e1000_hw *hw) ...@@ -2478,64 +3036,69 @@ e1000_cleanup_eeprom(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code * hw - Struct containing variables accessed by shared code
* offset - offset of word in the EEPROM to read * offset - offset of word in the EEPROM to read
* data - word read from the EEPROM * data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/ *****************************************************************************/
int32_t int32_t
e1000_read_eeprom(struct e1000_hw *hw, e1000_read_eeprom(struct e1000_hw *hw,
uint16_t offset, uint16_t offset,
uint16_t words,
uint16_t *data) uint16_t *data)
{ {
uint32_t eecd; struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint32_t i = 0; uint32_t i = 0;
boolean_t large_eeprom = FALSE;
DEBUGFUNC("e1000_read_eeprom"); DEBUGFUNC("e1000_read_eeprom");
/* Request EEPROM Access */ /* A check for invalid values: offset too large, too many words, and not
if(hw->mac_type > e1000_82544) { * enough words.
eecd = E1000_READ_REG(hw, EECD); */
if(eecd & E1000_EECD_SIZE) large_eeprom = TRUE; if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) ||
eecd |= E1000_EECD_REQ; (words == 0)) {
E1000_WRITE_REG(hw, EECD, eecd); DEBUGOUT("\"words\" parameter out of bounds\n");
eecd = E1000_READ_REG(hw, EECD);
while((!(eecd & E1000_EECD_GNT)) && (i < 100)) {
i++;
udelay(5);
eecd = E1000_READ_REG(hw, EECD);
}
if(!(eecd & E1000_EECD_GNT)) {
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, EECD, eecd);
DEBUGOUT("Could not acquire EEPROM grant\n");
return -E1000_ERR_EEPROM; return -E1000_ERR_EEPROM;
} }
}
/* Prepare the EEPROM for reading */ /* Prepare the EEPROM for reading */
e1000_setup_eeprom(hw); if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
return -E1000_ERR_EEPROM;
/* Send the READ command (opcode + addr) */ if(eeprom->type == e1000_eeprom_spi) {
e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE, 3); uint8_t read_opcode = EEPROM_READ_OPCODE_SPI;
if(large_eeprom) {
/* If we have a 256 word EEPROM, there are 8 address bits */
e1000_shift_out_ee_bits(hw, offset, 8);
} else {
/* If we have a 64 word EEPROM, there are 6 address bits */
e1000_shift_out_ee_bits(hw, offset, 6);
}
/* Read the data */ if(e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM;
*data = e1000_shift_in_ee_bits(hw);
/* End this read operation */
e1000_standby_eeprom(hw); e1000_standby_eeprom(hw);
/* Stop requesting EEPROM access */ /* Some SPI eeproms use the 8th address bit embedded in the opcode */
if(hw->mac_type > e1000_82544) { if((eeprom->address_bits == 8) && (offset >= 128))
eecd = E1000_READ_REG(hw, EECD); read_opcode |= EEPROM_A8_OPCODE_SPI;
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, EECD, eecd); /* Send the READ command (opcode + addr) */
e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
e1000_shift_out_ee_bits(hw, (uint16_t)(offset*2), eeprom->address_bits);
}
else if(eeprom->type == e1000_eeprom_microwire) {
/* Send the READ command (opcode + addr) */
e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE,
eeprom->opcode_bits);
e1000_shift_out_ee_bits(hw, offset, eeprom->address_bits);
} }
/* Read the data. The address of the eeprom internally increments with
* each word (microwire) or byte (spi) being read, saving on the overhead
* of eeprom setup and tear-down. The address counter will roll over if
* reading beyond the size of the eeprom, thus allowing the entire memory
* to be read starting from any offset. */
for (i = 0; i < words; i++) {
uint16_t word_in = e1000_shift_in_ee_bits(hw, 16);
if (eeprom->type == e1000_eeprom_spi)
word_in = (word_in >> 8) | (word_in << 8);
data[i] = word_in;
}
/* End this read operation */
e1000_release_eeprom(hw);
return 0; return 0;
} }
...@@ -2557,7 +3120,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw) ...@@ -2557,7 +3120,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
DEBUGFUNC("e1000_validate_eeprom_checksum"); DEBUGFUNC("e1000_validate_eeprom_checksum");
for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
if(e1000_read_eeprom(hw, i, &eeprom_data) < 0) { if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n"); DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM; return -E1000_ERR_EEPROM;
} }
...@@ -2589,14 +3152,14 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw) ...@@ -2589,14 +3152,14 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
DEBUGFUNC("e1000_update_eeprom_checksum"); DEBUGFUNC("e1000_update_eeprom_checksum");
for(i = 0; i < EEPROM_CHECKSUM_REG; i++) { for(i = 0; i < EEPROM_CHECKSUM_REG; i++) {
if(e1000_read_eeprom(hw, i, &eeprom_data) < 0) { if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n"); DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM; return -E1000_ERR_EEPROM;
} }
checksum += eeprom_data; checksum += eeprom_data;
} }
checksum = (uint16_t) EEPROM_SUM - checksum; checksum = (uint16_t) EEPROM_SUM - checksum;
if(e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, checksum) < 0) { if(e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
DEBUGOUT("EEPROM Write Error\n"); DEBUGOUT("EEPROM Write Error\n");
return -E1000_ERR_EEPROM; return -E1000_ERR_EEPROM;
} }
...@@ -2604,11 +3167,12 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw) ...@@ -2604,11 +3167,12 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
} }
/****************************************************************************** /******************************************************************************
* Writes a 16 bit word to a given offset in the EEPROM. * Parent function for writing words to the different EEPROM types.
* *
* hw - Struct containing variables accessed by shared code * hw - Struct containing variables accessed by shared code
* offset - offset within the EEPROM to be written to * offset - offset within the EEPROM to be written to
* data - 16 bit word to be writen to the EEPROM * words - number of words to write
* data - 16 bit word to be written to the EEPROM
* *
* If e1000_update_eeprom_checksum is not called after this function, the * If e1000_update_eeprom_checksum is not called after this function, the
* EEPROM will most likely contain an invalid checksum. * EEPROM will most likely contain an invalid checksum.
...@@ -2616,69 +3180,157 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw) ...@@ -2616,69 +3180,157 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
int32_t int32_t
e1000_write_eeprom(struct e1000_hw *hw, e1000_write_eeprom(struct e1000_hw *hw,
uint16_t offset, uint16_t offset,
uint16_t data) uint16_t words,
uint16_t *data)
{ {
uint32_t eecd; struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint32_t i = 0;
int32_t status = 0; int32_t status = 0;
boolean_t large_eeprom = FALSE;
DEBUGFUNC("e1000_write_eeprom"); DEBUGFUNC("e1000_write_eeprom");
/* Request EEPROM Access */ /* A check for invalid values: offset too large, too many words, and not
if(hw->mac_type > e1000_82544) { * enough words.
eecd = E1000_READ_REG(hw, EECD); */
if(eecd & E1000_EECD_SIZE) large_eeprom = TRUE; if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) ||
eecd |= E1000_EECD_REQ; (words == 0)) {
E1000_WRITE_REG(hw, EECD, eecd); DEBUGOUT("\"words\" parameter out of bounds\n");
eecd = E1000_READ_REG(hw, EECD); return -E1000_ERR_EEPROM;
while((!(eecd & E1000_EECD_GNT)) && (i < 100)) {
i++;
udelay(5);
eecd = E1000_READ_REG(hw, EECD);
} }
if(!(eecd & E1000_EECD_GNT)) {
eecd &= ~E1000_EECD_REQ; /* Prepare the EEPROM for writing */
E1000_WRITE_REG(hw, EECD, eecd); if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
DEBUGOUT("Could not acquire EEPROM grant\n");
return -E1000_ERR_EEPROM; return -E1000_ERR_EEPROM;
if(eeprom->type == e1000_eeprom_microwire)
status = e1000_write_eeprom_microwire(hw, offset, words, data);
else
status = e1000_write_eeprom_spi(hw, offset, words, data);
/* Done with writing */
e1000_release_eeprom(hw);
return status;
}
/******************************************************************************
* Writes a 16 bit word to a given offset in an SPI EEPROM.
*
* hw - Struct containing variables accessed by shared code
* offset - offset within the EEPROM to be written to
* words - number of words to write
* data - pointer to array of 8 bit words to be written to the EEPROM
*
*****************************************************************************/
int32_t
e1000_write_eeprom_spi(struct e1000_hw *hw,
uint16_t offset,
uint16_t words,
uint16_t *data)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint16_t widx = 0;
DEBUGFUNC("e1000_write_eeprom_spi");
while (widx < words) {
uint8_t write_opcode = EEPROM_WRITE_OPCODE_SPI;
if(e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM;
e1000_standby_eeprom(hw);
/* Send the WRITE ENABLE command (8 bit opcode ) */
e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI,
eeprom->opcode_bits);
e1000_standby_eeprom(hw);
/* Some SPI eeproms use the 8th address bit embedded in the opcode */
if((eeprom->address_bits == 8) && (offset >= 128))
write_opcode |= EEPROM_A8_OPCODE_SPI;
/* Send the Write command (8-bit opcode + addr) */
e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits);
e1000_shift_out_ee_bits(hw, (uint16_t)((offset + widx)*2),
eeprom->address_bits);
/* Send the data */
/* Loop to allow for up to whole page write (32 bytes) of eeprom */
while (widx < words) {
uint16_t word_out = data[widx];
word_out = (word_out >> 8) | (word_out << 8);
e1000_shift_out_ee_bits(hw, word_out, 16);
widx++;
/* Some larger eeprom sizes are capable of a 32-byte PAGE WRITE
* operation, while the smaller eeproms are capable of an 8-byte
* PAGE WRITE operation. Break the inner loop to pass new address
*/
if((((offset + widx)*2) % eeprom->page_size) == 0) {
e1000_standby_eeprom(hw);
break;
}
} }
} }
/* Prepare the EEPROM for writing */ return E1000_SUCCESS;
e1000_setup_eeprom(hw); }
/******************************************************************************
* Writes a 16 bit word to a given offset in a Microwire EEPROM.
*
* hw - Struct containing variables accessed by shared code
* offset - offset within the EEPROM to be written to
* words - number of words to write
* data - pointer to array of 16 bit words to be written to the EEPROM
*
*****************************************************************************/
int32_t
e1000_write_eeprom_microwire(struct e1000_hw *hw,
uint16_t offset,
uint16_t words,
uint16_t *data)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint32_t eecd;
uint16_t words_written = 0;
uint16_t i = 0;
/* Send the 9-bit (or 11-bit on large EEPROM) EWEN (write enable) command DEBUGFUNC("e1000_write_eeprom_microwire");
* to the EEPROM (5-bit opcode plus 4/6-bit dummy). This puts the EEPROM
* into write/erase mode. /* Send the write enable command to the EEPROM (3-bit opcode plus
* 6/8-bit dummy address beginning with 11). It's less work to include
* the 11 of the dummy address as part of the opcode than it is to shift
* it over the correct number of bits for the address. This puts the
* EEPROM into write/erase mode.
*/ */
e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE, 5); e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE,
if(large_eeprom) (uint16_t)(eeprom->opcode_bits + 2));
e1000_shift_out_ee_bits(hw, 0, 6);
else e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2));
e1000_shift_out_ee_bits(hw, 0, 4);
/* Prepare the EEPROM */ /* Prepare the EEPROM */
e1000_standby_eeprom(hw); e1000_standby_eeprom(hw);
while (words_written < words) {
/* Send the Write command (3-bit opcode + addr) */ /* Send the Write command (3-bit opcode + addr) */
e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE, 3); e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE,
if(large_eeprom) eeprom->opcode_bits);
/* If we have a 256 word EEPROM, there are 8 address bits */
e1000_shift_out_ee_bits(hw, offset, 8); e1000_shift_out_ee_bits(hw, (uint16_t)(offset + words_written),
else eeprom->address_bits);
/* If we have a 64 word EEPROM, there are 6 address bits */
e1000_shift_out_ee_bits(hw, offset, 6);
/* Send the data */ /* Send the data */
e1000_shift_out_ee_bits(hw, data, 16); e1000_shift_out_ee_bits(hw, data[words_written], 16);
/* Toggle the CS line. This in effect tells to EEPROM to actually execute /* Toggle the CS line. This in effect tells the EEPROM to execute
* the command in question. * the previous command.
*/ */
e1000_standby_eeprom(hw); e1000_standby_eeprom(hw);
/* Now read DO repeatedly until is high (equal to '1'). The EEEPROM will /* Read DO repeatedly until it is high (equal to '1'). The EEPROM will
* signal that the command has been completed by raising the DO signal. * signal that the command has been completed by raising the DO signal.
* If DO does not go high in 10 milliseconds, then error out. * If DO does not go high in 10 milliseconds, then error out.
*/ */
...@@ -2689,33 +3341,27 @@ e1000_write_eeprom(struct e1000_hw *hw, ...@@ -2689,33 +3341,27 @@ e1000_write_eeprom(struct e1000_hw *hw,
} }
if(i == 200) { if(i == 200) {
DEBUGOUT("EEPROM Write did not complete\n"); DEBUGOUT("EEPROM Write did not complete\n");
status = -E1000_ERR_EEPROM; return -E1000_ERR_EEPROM;
} }
/* Recover from write */ /* Recover from write */
e1000_standby_eeprom(hw); e1000_standby_eeprom(hw);
/* Send the 9-bit (or 11-bit on large EEPROM) EWDS (write disable) command words_written++;
* to the EEPROM (5-bit opcode plus 4/6-bit dummy). This takes the EEPROM }
* out of write/erase mode.
*/
e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE, 5);
if(large_eeprom)
e1000_shift_out_ee_bits(hw, 0, 6);
else
e1000_shift_out_ee_bits(hw, 0, 4);
/* Done with writing */ /* Send the write disable command to the EEPROM (3-bit opcode plus
e1000_cleanup_eeprom(hw); * 6/8-bit dummy address beginning with 10). It's less work to include
* the 10 of the dummy address as part of the opcode than it is to shift
* it over the correct number of bits for the address. This takes the
* EEPROM out of write/erase mode.
*/
e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE,
(uint16_t)(eeprom->opcode_bits + 2));
/* Stop requesting EEPROM access */ e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2));
if(hw->mac_type > e1000_82544) {
eecd = E1000_READ_REG(hw, EECD);
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, EECD, eecd);
}
return status; return 0;
} }
/****************************************************************************** /******************************************************************************
...@@ -2734,7 +3380,7 @@ e1000_read_part_num(struct e1000_hw *hw, ...@@ -2734,7 +3380,7 @@ e1000_read_part_num(struct e1000_hw *hw,
DEBUGFUNC("e1000_read_part_num"); DEBUGFUNC("e1000_read_part_num");
/* Get word 0 from EEPROM */ /* Get word 0 from EEPROM */
if(e1000_read_eeprom(hw, offset, &eeprom_data) < 0) { if(e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n"); DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM; return -E1000_ERR_EEPROM;
} }
...@@ -2742,7 +3388,7 @@ e1000_read_part_num(struct e1000_hw *hw, ...@@ -2742,7 +3388,7 @@ e1000_read_part_num(struct e1000_hw *hw,
*part_num = (uint32_t) (eeprom_data << 16); *part_num = (uint32_t) (eeprom_data << 16);
/* Get word 1 from EEPROM */ /* Get word 1 from EEPROM */
if(e1000_read_eeprom(hw, ++offset, &eeprom_data) < 0) { if(e1000_read_eeprom(hw, ++offset, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n"); DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM; return -E1000_ERR_EEPROM;
} }
...@@ -2768,7 +3414,7 @@ e1000_read_mac_addr(struct e1000_hw * hw) ...@@ -2768,7 +3414,7 @@ e1000_read_mac_addr(struct e1000_hw * hw)
for(i = 0; i < NODE_ADDRESS_SIZE; i += 2) { for(i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
offset = i >> 1; offset = i >> 1;
if(e1000_read_eeprom(hw, offset, &eeprom_data) < 0) { if(e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n"); DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM; return -E1000_ERR_EEPROM;
} }
...@@ -3068,7 +3714,7 @@ e1000_id_led_init(struct e1000_hw * hw) ...@@ -3068,7 +3714,7 @@ e1000_id_led_init(struct e1000_hw * hw)
hw->ledctl_mode1 = hw->ledctl_default; hw->ledctl_mode1 = hw->ledctl_default;
hw->ledctl_mode2 = hw->ledctl_default; hw->ledctl_mode2 = hw->ledctl_default;
if(e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, &eeprom_data) < 0) { if(e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n"); DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM; return -E1000_ERR_EEPROM;
} }
...@@ -3155,6 +3801,9 @@ e1000_setup_led(struct e1000_hw *hw) ...@@ -3155,6 +3801,9 @@ e1000_setup_led(struct e1000_hw *hw)
case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82541EI:
case E1000_DEV_ID_82541EP:
case E1000_DEV_ID_82547EI:
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
break; break;
default: default:
...@@ -3193,6 +3842,9 @@ e1000_cleanup_led(struct e1000_hw *hw) ...@@ -3193,6 +3842,9 @@ e1000_cleanup_led(struct e1000_hw *hw)
case E1000_DEV_ID_82545EM_FIBER: case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82541EI:
case E1000_DEV_ID_82541EP:
case E1000_DEV_ID_82547EI:
/* Restore LEDCTL settings */ /* Restore LEDCTL settings */
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default); E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default);
break; break;
...@@ -3244,6 +3896,9 @@ e1000_led_on(struct e1000_hw *hw) ...@@ -3244,6 +3896,9 @@ e1000_led_on(struct e1000_hw *hw)
case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82541EI:
case E1000_DEV_ID_82541EP:
case E1000_DEV_ID_82547EI:
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2);
break; break;
default: default:
...@@ -3294,6 +3949,9 @@ e1000_led_off(struct e1000_hw *hw) ...@@ -3294,6 +3949,9 @@ e1000_led_off(struct e1000_hw *hw)
case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82540EM_LOM:
case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_COPPER:
case E1000_DEV_ID_82541EI:
case E1000_DEV_ID_82541EP:
case E1000_DEV_ID_82547EI:
E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
break; break;
default: default:
...@@ -3608,3 +4266,221 @@ e1000_write_reg_io(struct e1000_hw *hw, ...@@ -3608,3 +4266,221 @@ e1000_write_reg_io(struct e1000_hw *hw,
e1000_io_write(hw, io_data, value); e1000_io_write(hw, io_data, value);
} }
/******************************************************************************
* Estimates the cable length.
*
* hw - Struct containing variables accessed by shared code
* min_length - The estimated minimum length
* max_length - The estimated maximum length
*
* returns: E1000_SUCCESS / -E1000_ERR_XXX
*
* This function always returns a ranged length (minimum & maximum).
* So for M88 phy's, this function interprets the one value returned from the
* register to the minimum and maximum range.
* For IGP phy's, the function calculates the range by the AGC registers.
*****************************************************************************/
int32_t
e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length,
uint16_t *max_length)
{
uint16_t agc_value = 0;
uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
uint16_t i, phy_data;
DEBUGFUNC("e1000_get_cable_length");
*min_length = *max_length = 0;
/* Use old method for Phy older than IGP */
if(hw->phy_type == e1000_phy_m88) {
if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0)
return -E1000_ERR_PHY;
/* Convert the enum value to ranged values */
switch((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
M88E1000_PSSR_CABLE_LENGTH_SHIFT) {
case e1000_cable_length_50:
*min_length = 0;
*max_length = e1000_igp_cable_length_50;
break;
case e1000_cable_length_50_80:
*min_length = e1000_igp_cable_length_50;
*max_length = e1000_igp_cable_length_80;
break;
case e1000_cable_length_80_110:
*min_length = e1000_igp_cable_length_80;
*max_length = e1000_igp_cable_length_110;
break;
case e1000_cable_length_110_140:
*min_length = e1000_igp_cable_length_110;
*max_length = e1000_igp_cable_length_140;
break;
case e1000_cable_length_140:
*min_length = e1000_igp_cable_length_140;
*max_length = e1000_igp_cable_length_170;
break;
default:
return -E1000_ERR_PHY;
break;
}
} else if(hw->phy_type == e1000_phy_igp) { /* For IGP PHY */
uint16_t agc_reg_array[IGP01E1000_PHY_AGC_NUM] = {IGP01E1000_PHY_AGC_A,
IGP01E1000_PHY_AGC_B,
IGP01E1000_PHY_AGC_C,
IGP01E1000_PHY_AGC_D};
/* Read the AGC registers for all channels */
for(i = 0; i < IGP01E1000_PHY_AGC_NUM; i++) {
if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
agc_reg_array[i]) != E1000_SUCCESS)
return -E1000_ERR_PHY;
if(e1000_read_phy_reg(hw, agc_reg_array[i] &
IGP01E1000_PHY_PAGE_SELECT, &phy_data) !=
E1000_SUCCESS)
return -E1000_ERR_PHY;
cur_agc = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT;
/* Array bound check. */
if((cur_agc >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||
(cur_agc == 0))
return -E1000_ERR_PHY;
agc_value += cur_agc;
/* Update minimal AGC value. */
if(min_agc > cur_agc)
min_agc = cur_agc;
}
/* Return to page 0 */
if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0) !=
E1000_SUCCESS)
return -E1000_ERR_PHY;
/* Remove the minimal AGC result for length < 50m */
if(agc_value < IGP01E1000_PHY_AGC_NUM * e1000_igp_cable_length_50) {
agc_value -= min_agc;
/* Get the average length of the remaining 3 channels */
agc_value /= (IGP01E1000_PHY_AGC_NUM - 1);
} else {
/* Get the average length of all the 4 channels. */
agc_value /= IGP01E1000_PHY_AGC_NUM;
}
/* Set the range of the calculated length. */
*min_length = ((e1000_igp_cable_length_table[agc_value] -
IGP01E1000_AGC_RANGE) > 0) ?
(e1000_igp_cable_length_table[agc_value] -
IGP01E1000_AGC_RANGE) : 0;
*max_length = e1000_igp_cable_length_table[agc_value] +
IGP01E1000_AGC_RANGE;
}
return E1000_SUCCESS;
}
/******************************************************************************
* Check the cable polarity
*
* hw - Struct containing variables accessed by shared code
* polarity - output parameter : 0 - Polarity is not reversed
* 1 - Polarity is reversed.
*
* returns: E1000_SUCCESS / -E1000_ERR_XXX
*
* For phy's older then IGP, this function simply reads the polarity bit in the
* Phy Status register. For IGP phy's, this bit is valid only if link speed is
* 10 Mbps. If the link speed is 100 Mbps there is no polarity so this bit will
* return 0. If the link speed is 1000 Mbps the polarity status is in the
* IGP01E1000_PHY_PCS_INIT_REG.
*****************************************************************************/
int32_t
e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity)
{
uint16_t phy_data;
DEBUGFUNC("e1000_check_polarity");
if(hw->phy_type == e1000_phy_m88) {
/* return the Polarity bit in the Status register. */
if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0)
return -E1000_ERR_PHY;
*polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >>
M88E1000_PSSR_REV_POLARITY_SHIFT;
} else if(hw->phy_type == e1000_phy_igp) {
/* Read the Status register to check the speed */
if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0)
return -E1000_ERR_PHY;
/* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to
* find the polarity status */
if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
IGP01E1000_PSSR_SPEED_1000MBPS) {
/* Read the GIG initialization PCS register (0x00B4) */
if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_PHY_PCS_INIT_REG) < 0)
return -E1000_ERR_PHY;
if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG &
IGP01E1000_PHY_PAGE_SELECT, &phy_data) < 0)
return -E1000_ERR_PHY;
/* Return to page 0 */
if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0) !=
E1000_SUCCESS)
return -E1000_ERR_PHY;
/* Check the polarity bits */
*polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ? 1 : 0;
} else {
/* For 10 Mbps, read the polarity bit in the status register. (for
* 100 Mbps this bit is always 0) */
*polarity = phy_data & IGP01E1000_PSSR_POLARITY_REVERSED;
}
}
return E1000_SUCCESS;
}
/******************************************************************************
* Check if Downshift occured
*
* hw - Struct containing variables accessed by shared code
* downshift - output parameter : 0 - No Downshift ocured.
* 1 - Downshift ocured.
*
* returns: E1000_SUCCESS / -E1000_ERR_XXX
*
* For phy's older then IGP, this function reads the Downshift bit in the Phy
* Specific Status register. For IGP phy's, it reads the Downgrade bit in the
* Link Health register. In IGP this bit is latched high, so the driver must
* read it immediately after link is established.
*****************************************************************************/
int32_t
e1000_check_downshift(struct e1000_hw *hw)
{
uint16_t phy_data;
DEBUGFUNC("e1000_check_downshift");
if(hw->phy_type == e1000_phy_igp) {
if(e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, &phy_data) < 0) {
DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY;
}
hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
}
else if(hw->phy_type == e1000_phy_m88) {
if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) {
DEBUGOUT("PHY Read Error\n");
return -E1000_ERR_PHY;
}
hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
M88E1000_PSSR_DOWNSHIFT_SHIFT;
}
return E1000_SUCCESS;
}
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#ifndef _E1000_HW_H_ #ifndef _E1000_HW_H_
#define _E1000_HW_H_ #define _E1000_HW_H_
#include "e1000_osdep.h" #include "e1000_osdep.h"
/* Forward declarations of structures used by the shared code */ /* Forward declarations of structures used by the shared code */
...@@ -50,9 +51,18 @@ typedef enum { ...@@ -50,9 +51,18 @@ typedef enum {
e1000_82540, e1000_82540,
e1000_82545, e1000_82545,
e1000_82546, e1000_82546,
e1000_82541,
e1000_82547,
e1000_num_macs e1000_num_macs
} e1000_mac_type; } e1000_mac_type;
typedef enum {
e1000_eeprom_uninitialized = 0,
e1000_eeprom_spi,
e1000_eeprom_microwire,
e1000_num_eeprom_types
} e1000_eeprom_type;
/* Media Types */ /* Media Types */
typedef enum { typedef enum {
e1000_media_type_copper = 0, e1000_media_type_copper = 0,
...@@ -110,6 +120,27 @@ typedef enum { ...@@ -110,6 +120,27 @@ typedef enum {
e1000_cable_length_undefined = 0xFF e1000_cable_length_undefined = 0xFF
} e1000_cable_length; } e1000_cable_length;
typedef enum {
e1000_igp_cable_length_10 = 10,
e1000_igp_cable_length_20 = 20,
e1000_igp_cable_length_30 = 30,
e1000_igp_cable_length_40 = 40,
e1000_igp_cable_length_50 = 50,
e1000_igp_cable_length_60 = 60,
e1000_igp_cable_length_70 = 70,
e1000_igp_cable_length_80 = 80,
e1000_igp_cable_length_90 = 90,
e1000_igp_cable_length_100 = 100,
e1000_igp_cable_length_110 = 110,
e1000_igp_cable_length_120 = 120,
e1000_igp_cable_length_130 = 130,
e1000_igp_cable_length_140 = 140,
e1000_igp_cable_length_150 = 150,
e1000_igp_cable_length_160 = 160,
e1000_igp_cable_length_170 = 170,
e1000_igp_cable_length_180 = 180
} e1000_igp_cable_length;
typedef enum { typedef enum {
e1000_10bt_ext_dist_enable_normal = 0, e1000_10bt_ext_dist_enable_normal = 0,
e1000_10bt_ext_dist_enable_lower, e1000_10bt_ext_dist_enable_lower,
...@@ -122,6 +153,12 @@ typedef enum { ...@@ -122,6 +153,12 @@ typedef enum {
e1000_rev_polarity_undefined = 0xFF e1000_rev_polarity_undefined = 0xFF
} e1000_rev_polarity; } e1000_rev_polarity;
typedef enum {
e1000_downshift_normal = 0,
e1000_downshift_activated,
e1000_downshift_undefined = 0xFF
} e1000_downshift;
typedef enum { typedef enum {
e1000_polarity_reversal_enabled = 0, e1000_polarity_reversal_enabled = 0,
e1000_polarity_reversal_disabled, e1000_polarity_reversal_disabled,
...@@ -142,10 +179,17 @@ typedef enum { ...@@ -142,10 +179,17 @@ typedef enum {
e1000_1000t_rx_status_undefined = 0xFF e1000_1000t_rx_status_undefined = 0xFF
} e1000_1000t_rx_status; } e1000_1000t_rx_status;
typedef enum {
e1000_phy_m88 = 0,
e1000_phy_igp,
e1000_phy_undefined = 0xFF
} e1000_phy_type;
struct e1000_phy_info { struct e1000_phy_info {
e1000_cable_length cable_length; e1000_cable_length cable_length;
e1000_10bt_ext_dist_enable extended_10bt_distance; e1000_10bt_ext_dist_enable extended_10bt_distance;
e1000_rev_polarity cable_polarity; e1000_rev_polarity cable_polarity;
e1000_downshift downshift;
e1000_polarity_reversal polarity_correction; e1000_polarity_reversal polarity_correction;
e1000_auto_x_mode mdix_mode; e1000_auto_x_mode mdix_mode;
e1000_1000t_rx_status local_rx; e1000_1000t_rx_status local_rx;
...@@ -157,6 +201,15 @@ struct e1000_phy_stats { ...@@ -157,6 +201,15 @@ struct e1000_phy_stats {
uint32_t receive_errors; uint32_t receive_errors;
}; };
struct e1000_eeprom_info {
e1000_eeprom_type type;
uint16_t word_size;
uint16_t opcode_bits;
uint16_t address_bits;
uint16_t delay_usec;
uint16_t page_size;
};
/* Error Codes */ /* Error Codes */
...@@ -166,6 +219,7 @@ struct e1000_phy_stats { ...@@ -166,6 +219,7 @@ struct e1000_phy_stats {
#define E1000_ERR_CONFIG 3 #define E1000_ERR_CONFIG 3
#define E1000_ERR_PARAM 4 #define E1000_ERR_PARAM 4
#define E1000_ERR_MAC_TYPE 5 #define E1000_ERR_MAC_TYPE 5
#define E1000_ERR_PHY_TYPE 6
/* Function prototypes */ /* Function prototypes */
/* Initialization */ /* Initialization */
...@@ -189,13 +243,19 @@ void e1000_phy_hw_reset(struct e1000_hw *hw); ...@@ -189,13 +243,19 @@ void e1000_phy_hw_reset(struct e1000_hw *hw);
int32_t e1000_phy_reset(struct e1000_hw *hw); int32_t e1000_phy_reset(struct e1000_hw *hw);
int32_t e1000_detect_gig_phy(struct e1000_hw *hw); int32_t e1000_detect_gig_phy(struct e1000_hw *hw);
int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
int32_t e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
int32_t e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
int32_t e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, uint16_t *max_length);
int32_t e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity);
int32_t e1000_check_downshift(struct e1000_hw *hw);
int32_t e1000_validate_mdi_setting(struct e1000_hw *hw); int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
/* EEPROM Functions */ /* EEPROM Functions */
int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t *data); void e1000_init_eeprom_params(struct e1000_hw *hw);
int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw); int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw);
int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw); int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw);
int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t data); int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num); int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num);
int32_t e1000_read_mac_addr(struct e1000_hw * hw); int32_t e1000_read_mac_addr(struct e1000_hw * hw);
...@@ -231,6 +291,7 @@ uint32_t e1000_io_read(struct e1000_hw *hw, uint32_t port); ...@@ -231,6 +291,7 @@ uint32_t e1000_io_read(struct e1000_hw *hw, uint32_t port);
uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset); uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset);
void e1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value); void e1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value);
void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value);
#define E1000_READ_REG_IO(a, reg) \ #define E1000_READ_REG_IO(a, reg) \
e1000_read_reg_io((a), E1000_##reg) e1000_read_reg_io((a), E1000_##reg)
#define E1000_WRITE_REG_IO(a, reg, val) \ #define E1000_WRITE_REG_IO(a, reg, val) \
...@@ -253,7 +314,10 @@ void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); ...@@ -253,7 +314,10 @@ void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value);
#define E1000_DEV_ID_82545EM_FIBER 0x1011 #define E1000_DEV_ID_82545EM_FIBER 0x1011
#define E1000_DEV_ID_82546EB_COPPER 0x1010 #define E1000_DEV_ID_82546EB_COPPER 0x1010
#define E1000_DEV_ID_82546EB_FIBER 0x1012 #define E1000_DEV_ID_82546EB_FIBER 0x1012
#define NUM_DEV_IDS 16 #define E1000_DEV_ID_82541EI 0x1013
#define E1000_DEV_ID_82541EP 0x1018
#define E1000_DEV_ID_82547EI 0x1019
#define NUM_DEV_IDS 19
#define NODE_ADDRESS_SIZE 6 #define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6 #define ETH_LENGTH_OF_ADDRESS 6
...@@ -324,7 +388,7 @@ void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); ...@@ -324,7 +388,7 @@ void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value);
* reserve one of these spots for our directed address, allowing us room for * reserve one of these spots for our directed address, allowing us room for
* E1000_RAR_ENTRIES - 1 multicast addresses. * E1000_RAR_ENTRIES - 1 multicast addresses.
*/ */
#define E1000_RAR_ENTRIES 16 #define E1000_RAR_ENTRIES 15
#define MIN_NUMBER_OF_DESCRIPTORS 8 #define MIN_NUMBER_OF_DESCRIPTORS 8
#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8 #define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8
...@@ -537,6 +601,7 @@ struct e1000_ffvt_entry { ...@@ -537,6 +601,7 @@ struct e1000_ffvt_entry {
#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ #define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
#define E1000_EERD 0x00014 /* EEPROM Read - RW */ #define E1000_EERD 0x00014 /* EEPROM Read - RW */
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ #define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
#define E1000_FLA 0x0001C /* Flash Access Register - RW */
#define E1000_MDIC 0x00020 /* MDI Control - RW */ #define E1000_MDIC 0x00020 /* MDI Control - RW */
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
...@@ -569,6 +634,11 @@ struct e1000_ffvt_entry { ...@@ -569,6 +634,11 @@ struct e1000_ffvt_entry {
#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */ #define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */
#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */ #define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */
#define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */ #define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */
#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */
#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */
#define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */
#define E1000_TDFTS 0x03428 /* TX Data FIFO Tail Saved - RW */
#define E1000_TDFPC 0x03430 /* TX Data FIFO Packet Count - RW */
#define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */ #define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */
#define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */ #define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */
#define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */ #define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */
...@@ -664,6 +734,7 @@ struct e1000_ffvt_entry { ...@@ -664,6 +734,7 @@ struct e1000_ffvt_entry {
#define E1000_82542_EECD E1000_EECD #define E1000_82542_EECD E1000_EECD
#define E1000_82542_EERD E1000_EERD #define E1000_82542_EERD E1000_EERD
#define E1000_82542_CTRL_EXT E1000_CTRL_EXT #define E1000_82542_CTRL_EXT E1000_CTRL_EXT
#define E1000_82542_FLA E1000_FLA
#define E1000_82542_MDIC E1000_MDIC #define E1000_82542_MDIC E1000_MDIC
#define E1000_82542_FCAL E1000_FCAL #define E1000_82542_FCAL E1000_FCAL
#define E1000_82542_FCAH E1000_FCAH #define E1000_82542_FCAH E1000_FCAH
...@@ -705,6 +776,9 @@ struct e1000_ffvt_entry { ...@@ -705,6 +776,9 @@ struct e1000_ffvt_entry {
#define E1000_82542_RADV E1000_RADV #define E1000_82542_RADV E1000_RADV
#define E1000_82542_RSRPD E1000_RSRPD #define E1000_82542_RSRPD E1000_RSRPD
#define E1000_82542_TXDMAC E1000_TXDMAC #define E1000_82542_TXDMAC E1000_TXDMAC
#define E1000_82542_TDFHS E1000_TDFHS
#define E1000_82542_TDFTS E1000_TDFTS
#define E1000_82542_TDFPC E1000_TDFPC
#define E1000_82542_TXDCTL E1000_TXDCTL #define E1000_82542_TXDCTL E1000_TXDCTL
#define E1000_82542_TADV E1000_TADV #define E1000_82542_TADV E1000_TADV
#define E1000_82542_TSPMT E1000_TSPMT #define E1000_82542_TSPMT E1000_TSPMT
...@@ -777,6 +851,8 @@ struct e1000_ffvt_entry { ...@@ -777,6 +851,8 @@ struct e1000_ffvt_entry {
#define E1000_82542_WUPL E1000_WUPL #define E1000_82542_WUPL E1000_WUPL
#define E1000_82542_WUPM E1000_WUPM #define E1000_82542_WUPM E1000_WUPM
#define E1000_82542_FFLT E1000_FFLT #define E1000_82542_FFLT E1000_FFLT
#define E1000_82542_TDFH 0x08010
#define E1000_82542_TDFT 0x08018
#define E1000_82542_FFMT E1000_FFMT #define E1000_82542_FFMT E1000_FFMT
#define E1000_82542_FFVT E1000_FFVT #define E1000_82542_FFVT E1000_FFVT
...@@ -846,12 +922,15 @@ struct e1000_hw_stats { ...@@ -846,12 +922,15 @@ struct e1000_hw_stats {
struct e1000_hw { struct e1000_hw {
uint8_t *hw_addr; uint8_t *hw_addr;
e1000_mac_type mac_type; e1000_mac_type mac_type;
e1000_phy_type phy_type;
uint32_t phy_init_script;
e1000_media_type media_type; e1000_media_type media_type;
void *back; void *back;
e1000_fc_type fc; e1000_fc_type fc;
e1000_bus_speed bus_speed; e1000_bus_speed bus_speed;
e1000_bus_width bus_width; e1000_bus_width bus_width;
e1000_bus_type bus_type; e1000_bus_type bus_type;
struct e1000_eeprom_info eeprom;
uint32_t io_base; uint32_t io_base;
uint32_t phy_id; uint32_t phy_id;
uint32_t phy_revision; uint32_t phy_revision;
...@@ -891,6 +970,7 @@ struct e1000_hw { ...@@ -891,6 +970,7 @@ struct e1000_hw {
uint8_t mac_addr[NODE_ADDRESS_SIZE]; uint8_t mac_addr[NODE_ADDRESS_SIZE];
uint8_t perm_mac_addr[NODE_ADDRESS_SIZE]; uint8_t perm_mac_addr[NODE_ADDRESS_SIZE];
boolean_t disable_polarity_correction; boolean_t disable_polarity_correction;
boolean_t speed_downgraded;
boolean_t get_link_status; boolean_t get_link_status;
boolean_t tbi_compatibility_en; boolean_t tbi_compatibility_en;
boolean_t tbi_compatibility_on; boolean_t tbi_compatibility_on;
...@@ -971,10 +1051,16 @@ struct e1000_hw { ...@@ -971,10 +1051,16 @@ struct e1000_hw {
#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */ #define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */
#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */ #define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */
#define E1000_EECD_FWE_SHIFT 4 #define E1000_EECD_FWE_SHIFT 4
#define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */
#define E1000_EECD_REQ 0x00000040 /* EEPROM Access Request */ #define E1000_EECD_REQ 0x00000040 /* EEPROM Access Request */
#define E1000_EECD_GNT 0x00000080 /* EEPROM Access Grant */ #define E1000_EECD_GNT 0x00000080 /* EEPROM Access Grant */
#define E1000_EECD_PRES 0x00000100 /* EEPROM Present */ #define E1000_EECD_PRES 0x00000100 /* EEPROM Present */
#define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */
#define E1000_EECD_ADDR_BITS 0x00000400 /* EEPROM Addressing bits based on type
* (0-small, 1-large) */
#define E1000_EECD_TYPE 0x00002000 /* EEPROM Type (1-SPI, 0-Microwire) */
#ifndef E1000_EEPROM_GRANT_ATTEMPTS
#define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */
#endif
/* EEPROM Read */ /* EEPROM Read */
#define E1000_EERD_START 0x00000001 /* Start Read */ #define E1000_EERD_START 0x00000001 /* Start Read */
...@@ -984,6 +1070,13 @@ struct e1000_hw { ...@@ -984,6 +1070,13 @@ struct e1000_hw {
#define E1000_EERD_DATA_SHIFT 16 #define E1000_EERD_DATA_SHIFT 16
#define E1000_EERD_DATA_MASK 0xFFFF0000 /* Read Data */ #define E1000_EERD_DATA_MASK 0xFFFF0000 /* Read Data */
/* SPI EEPROM Status Register */
#define EEPROM_STATUS_RDY_SPI 0x01
#define EEPROM_STATUS_WEN_SPI 0x02
#define EEPROM_STATUS_BP0_SPI 0x04
#define EEPROM_STATUS_BP1_SPI 0x08
#define EEPROM_STATUS_WPEN_SPI 0x80
/* Extended Device Control */ /* Extended Device Control */
#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */ #define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */
#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */ #define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */
...@@ -1239,6 +1332,7 @@ struct e1000_hw { ...@@ -1239,6 +1332,7 @@ struct e1000_hw {
#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ #define E1000_WUC_PME_EN 0x00000002 /* PME Enable */
#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ #define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ #define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */
#define E1000_WUC_SPM 0x80000000 /* Enable SPM */
/* Wake Up Filter Control */ /* Wake Up Filter Control */
#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ #define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
...@@ -1302,18 +1396,40 @@ struct e1000_hw { ...@@ -1302,18 +1396,40 @@ struct e1000_hw {
#define E1000_MDALIGN 4096 #define E1000_MDALIGN 4096
/* EEPROM Commands */ /* EEPROM Commands - Microwire */
#define EEPROM_READ_OPCODE 0x6 /* EERPOM read opcode */ #define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */
#define EEPROM_WRITE_OPCODE 0x5 /* EERPOM write opcode */ #define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */
#define EEPROM_ERASE_OPCODE 0x7 /* EERPOM erase opcode */ #define EEPROM_ERASE_OPCODE_MICROWIRE 0x7 /* EEPROM erase opcode */
#define EEPROM_EWEN_OPCODE 0x13 /* EERPOM erase/write enable */ #define EEPROM_EWEN_OPCODE_MICROWIRE 0x13 /* EEPROM erase/write enable */
#define EEPROM_EWDS_OPCODE 0x10 /* EERPOM erast/write disable */ #define EEPROM_EWDS_OPCODE_MICROWIRE 0x10 /* EEPROM erast/write disable */
/* EEPROM Commands - SPI */
#define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */
#define EEPROM_READ_OPCODE_SPI 0x3 /* EEPROM read opcode */
#define EEPROM_WRITE_OPCODE_SPI 0x2 /* EEPROM write opcode */
#define EEPROM_A8_OPCODE_SPI 0x8 /* opcode bit-3 = address bit-8 */
#define EEPROM_WREN_OPCODE_SPI 0x6 /* EEPROM set Write Enable latch */
#define EEPROM_WRDI_OPCODE_SPI 0x4 /* EEPROM reset Write Enable latch */
#define EEPROM_RDSR_OPCODE_SPI 0x5 /* EEPROM read Status register */
#define EEPROM_WRSR_OPCODE_SPI 0x1 /* EEPROM write Status register */
/* EEPROM Size definitions */
#define EEPROM_SIZE_16KB 0x1800
#define EEPROM_SIZE_8KB 0x1400
#define EEPROM_SIZE_4KB 0x1000
#define EEPROM_SIZE_2KB 0x0C00
#define EEPROM_SIZE_1KB 0x0800
#define EEPROM_SIZE_512B 0x0400
#define EEPROM_SIZE_128B 0x0000
#define EEPROM_SIZE_MASK 0x1C00
/* EEPROM Word Offsets */ /* EEPROM Word Offsets */
#define EEPROM_COMPAT 0x0003 #define EEPROM_COMPAT 0x0003
#define EEPROM_ID_LED_SETTINGS 0x0004 #define EEPROM_ID_LED_SETTINGS 0x0004
#define EEPROM_INIT_CONTROL1_REG 0x000A #define EEPROM_INIT_CONTROL1_REG 0x000A
#define EEPROM_INIT_CONTROL2_REG 0x000F #define EEPROM_INIT_CONTROL2_REG 0x000F
#define EEPROM_CFG 0x0012
#define EEPROM_FLASH_VERSION 0x0032 #define EEPROM_FLASH_VERSION 0x0032
#define EEPROM_CHECKSUM_REG 0x003F #define EEPROM_CHECKSUM_REG 0x003F
...@@ -1334,9 +1450,10 @@ struct e1000_hw { ...@@ -1334,9 +1450,10 @@ struct e1000_hw {
#define ID_LED_OFF1_ON2 0x8 #define ID_LED_OFF1_ON2 0x8
#define ID_LED_OFF1_OFF2 0x9 #define ID_LED_OFF1_OFF2 0x9
/* Mask bits for fields in Word 0x03 of the EEPROM */ #define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF
#define EEPROM_COMPAT_SERVER 0x0400 #define IGP_ACTIVITY_LED_ENABLE 0x0300
#define EEPROM_COMPAT_CLIENT 0x0200 #define IGP_LED3_MODE 0x07000000
/* Mask bits for fields in Word 0x0a of the EEPROM */ /* Mask bits for fields in Word 0x0a of the EEPROM */
#define EEPROM_WORD0A_ILOS 0x0010 #define EEPROM_WORD0A_ILOS 0x0010
...@@ -1409,7 +1526,9 @@ struct e1000_hw { ...@@ -1409,7 +1526,9 @@ struct e1000_hw {
/* PBA constants */ /* PBA constants */
#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ #define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */
#define E1000_PBA_22K 0x0016
#define E1000_PBA_24K 0x0018 #define E1000_PBA_24K 0x0018
#define E1000_PBA_30K 0x001E
#define E1000_PBA_40K 0x0028 #define E1000_PBA_40K 0x0028
#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */ #define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */
...@@ -1547,6 +1666,29 @@ struct e1000_hw { ...@@ -1547,6 +1666,29 @@ struct e1000_hw {
#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ #define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */
#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ #define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */
/* IGP01E1000 Specific Registers */
#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */
#define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */
#define IGP01E1000_PHY_PORT_CTRL 0x12 /* PHY Specific Control Register */
#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health Register */
#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO Register */
#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality Register */
#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* PHY Page Select Core Register */
/* IGP01E1000 AGC Registers - stores the cable length values*/
#define IGP01E1000_PHY_AGC_A 0x1172
#define IGP01E1000_PHY_AGC_B 0x1272
#define IGP01E1000_PHY_AGC_C 0x1472
#define IGP01E1000_PHY_AGC_D 0x1872
/* Number of AGC registers */
#define IGP01E1000_PHY_AGC_NUM 4
/* IGP01E1000 PCS Initialization register - stores the polarity status when
* speed = 1000 Mbps. */
#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
/* PHY Control Register */ /* PHY Control Register */
...@@ -1608,7 +1750,7 @@ struct e1000_hw { ...@@ -1608,7 +1750,7 @@ struct e1000_hw {
#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */ #define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */
#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */ #define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */
#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */ #define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
#define NWAY_ER_PAR_DETECT_FAULT 0x0100 /* LP is 100TX Full Duplex Capable */ #define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */
/* Next Page TX Register */ /* Next Page TX Register */
#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ #define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
...@@ -1712,6 +1854,7 @@ struct e1000_hw { ...@@ -1712,6 +1854,7 @@ struct e1000_hw {
/* M88E1000 PHY Specific Status Register */ /* M88E1000 PHY Specific Status Register */
#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */ #define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */
#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ #define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */
#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */
#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ #define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */
#define M88E1000_PSSR_CABLE_LENGTH 0x0380 /* 0=<50M;1=50-80M;2=80-110M; #define M88E1000_PSSR_CABLE_LENGTH 0x0380 /* 0=<50M;1=50-80M;2=80-110M;
* 3=110-140M;4=>140M */ * 3=110-140M;4=>140M */
...@@ -1725,6 +1868,7 @@ struct e1000_hw { ...@@ -1725,6 +1868,7 @@ struct e1000_hw {
#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ #define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
#define M88E1000_PSSR_REV_POLARITY_SHIFT 1 #define M88E1000_PSSR_REV_POLARITY_SHIFT 1
#define M88E1000_PSSR_DOWNSHIFT_SHIFT 5
#define M88E1000_PSSR_MDIX_SHIFT 6 #define M88E1000_PSSR_MDIX_SHIFT 6
#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
...@@ -1753,10 +1897,93 @@ struct e1000_hw { ...@@ -1753,10 +1897,93 @@ struct e1000_hw {
#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ #define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ #define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */
/* IGP01E1000 Specific Port Config Register - R/W */
#define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010
#define IGP01E1000_PSCFR_PRE_EN 0x0020
#define IGP01E1000_PSCFR_SMART_SPEED 0x0080
#define IGP01E1000_PSCFR_DISABLE_TPLOOPBACK 0x0100
#define IGP01E1000_PSCFR_DISABLE_JABBER 0x0400
#define IGP01E1000_PSCFR_DISABLE_TRANSMIT 0x2000
/* IGP01E1000 Specific Port Status Register - R/O */
#define IGP01E1000_PSSR_AUTONEG_FAILED 0x0001 /* RO LH SC */
#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002
#define IGP01E1000_PSSR_CABLE_LENGTH 0x007C
#define IGP01E1000_PSSR_FULL_DUPLEX 0x0200
#define IGP01E1000_PSSR_LINK_UP 0x0400
#define IGP01E1000_PSSR_MDIX 0x0800
#define IGP01E1000_PSSR_SPEED_MASK 0xC000 /* speed bits mask */
#define IGP01E1000_PSSR_SPEED_10MBPS 0x4000
#define IGP01E1000_PSSR_SPEED_100MBPS 0x8000
#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000
#define IGP01E1000_PSSR_CABLE_LENGTH_SHIFT 0x0002 /* shift right 2 */
#define IGP01E1000_PSSR_MDIX_SHIFT 0x000B /* shift right 11 */
/* IGP01E1000 Specific Port Control Register - R/W */
#define IGP01E1000_PSCR_TP_LOOPBACK 0x0001
#define IGP01E1000_PSCR_CORRECT_NC_SCMBLR 0x0200
#define IGP01E1000_PSCR_TEN_CRS_SELECT 0x0400
#define IGP01E1000_PSCR_FLIP_CHIP 0x0800
#define IGP01E1000_PSCR_AUTO_MDIX 0x1000
#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0-MDI, 1-MDIX */
/* IGP01E1000 Specific Port Link Health Register */
#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
#define IGP01E1000_PLHR_GIG_SCRAMBLER_ERROR 0x4000
#define IGP01E1000_PLHR_GIG_REM_RCVR_NOK 0x0800 /* LH */
#define IGP01E1000_PLHR_IDLE_ERROR_CNT_OFLOW 0x0400 /* LH */
#define IGP01E1000_PLHR_DATA_ERR_1 0x0200 /* LH */
#define IGP01E1000_PLHR_DATA_ERR_0 0x0100
#define IGP01E1000_PLHR_AUTONEG_FAULT 0x0010
#define IGP01E1000_PLHR_AUTONEG_ACTIVE 0x0008
#define IGP01E1000_PLHR_VALID_CHANNEL_D 0x0004
#define IGP01E1000_PLHR_VALID_CHANNEL_C 0x0002
#define IGP01E1000_PLHR_VALID_CHANNEL_B 0x0001
#define IGP01E1000_PLHR_VALID_CHANNEL_A 0x0000
/* IGP01E1000 Channel Quality Register */
#define IGP01E1000_MSE_CHANNEL_D 0x000F
#define IGP01E1000_MSE_CHANNEL_C 0x00F0
#define IGP01E1000_MSE_CHANNEL_B 0x0F00
#define IGP01E1000_MSE_CHANNEL_A 0xF000
/* IGP01E1000 AGC Registers */
#define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */
/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */
#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128
/* The precision of the length is +/- 10 meters */
#define IGP01E1000_AGC_RANGE 10
/* IGP cable length table */
static const
uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
{ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60,
60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90,
90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120};
/* IGP01E1000 PCS Initialization register */
/* bits 3:6 in the PCS registers stores the channels polarity */
#define IGP01E1000_PHY_POLARITY_MASK 0x0078
/* IGP01E1000 GMII FIFO Register */
#define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed
* on Link-Up */
#define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */
/* Bit definitions for valid PHY IDs. */ /* Bit definitions for valid PHY IDs. */
#define M88E1000_E_PHY_ID 0x01410C50 #define M88E1000_E_PHY_ID 0x01410C50
#define M88E1000_I_PHY_ID 0x01410C30 #define M88E1000_I_PHY_ID 0x01410C30
#define M88E1011_I_PHY_ID 0x01410C20 #define M88E1011_I_PHY_ID 0x01410C20
#define IGP01E1000_I_PHY_ID 0x02A80380
#define M88E1000_12_PHY_ID M88E1000_E_PHY_ID #define M88E1000_12_PHY_ID M88E1000_E_PHY_ID
#define M88E1000_14_PHY_ID M88E1000_E_PHY_ID #define M88E1000_14_PHY_ID M88E1000_E_PHY_ID
#define M88E1011_I_REV_4 0x04 #define M88E1011_I_REV_4 0x04
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -30,7 +30,22 @@ ...@@ -30,7 +30,22 @@
/* Change Log /* Change Log
* *
* 4.4.19 11/27/02 * 5.0.43 3/5/03
* o Feature: Added support for 82541 and 82547 hardware.
* o Feature: Added support for Intel Gigabit PHY (IGP) and a variety of
* eeproms.
* o Feature: Added support for TCP Segmentation Offload (TSO).
* o Feature: Added MII ioctl.
* o Feature: Added support for statistics reporting through ethtool.
* o Cleanup: Removed proprietary hooks for ANS.
* o Cleanup: Miscellaneous code changes to improve CPU utilization.
* - Replaced "%" with conditionals and "+-" operators.
* - Implemented dynamic Interrupt Throttle Rate (ITR).
* - Reduced expensive PCI reads of ICR in interrupt.
* o Bug fix: Request IRQ after descriptor ring setup to avoid panic in
* shared interrupt instances.
*
* 4.4.18 11/27/02
* o Feature: Added user-settable knob for interrupt throttle rate (ITR). * o Feature: Added user-settable knob for interrupt throttle rate (ITR).
* o Cleanup: removed large static array allocations. * o Cleanup: removed large static array allocations.
* o Cleanup: C99 struct initializer format. * o Cleanup: C99 struct initializer format.
...@@ -42,25 +57,12 @@ ...@@ -42,25 +57,12 @@
* o Bug fix: Make ethtool EEPROM acceses work on older versions of ethtool. * o Bug fix: Make ethtool EEPROM acceses work on older versions of ethtool.
* *
* 4.4.12 10/15/02 * 4.4.12 10/15/02
* o Clean up: use members of pci_device rather than direct calls to
* pci_read_config_word.
* o Bug fix: changed default flow control settings.
* o Clean up: ethtool file now has an inclusive list for adapters in the
* Wake-On-LAN capabilities instead of an exclusive list.
* o Bug fix: miscellaneous WoL bug fixes.
* o Added software interrupt for clearing rx ring
* o Bug fix: easier to undo "forcing" of 1000/fd using ethtool.
* o Now setting netdev->mem_end in e1000_probe.
* o Clean up: Moved tx_timeout from interrupt context to process context
* using schedule_task.
*
* 4.3.15 8/9/02
*/ */
char e1000_driver_name[] = "e1000"; char e1000_driver_name[] = "e1000";
char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
char e1000_driver_version[] = "4.4.19-k3"; char e1000_driver_version[] = "5.0.43-k1";
char e1000_copyright[] = "Copyright (c) 1999-2002 Intel Corporation."; char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation.";
/* e1000_pci_tbl - PCI Device ID Table /* e1000_pci_tbl - PCI Device ID Table
* *
...@@ -104,6 +106,8 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = { ...@@ -104,6 +106,8 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = {
{0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
/* required last entry */ /* required last entry */
{0,} {0,}
}; };
...@@ -112,7 +116,7 @@ MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); ...@@ -112,7 +116,7 @@ MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
static char *e1000_strings[] = { static char *e1000_strings[] = {
"Intel(R) PRO/1000 Network Connection", "Intel(R) PRO/1000 Network Connection",
"Compaq Gigabit Ethernet Server Adapter", "HP Gigabit Ethernet Server Adapter",
"IBM Mobile, Desktop & Server Adapters" "IBM Mobile, Desktop & Server Adapters"
}; };
...@@ -121,6 +125,7 @@ static char *e1000_strings[] = { ...@@ -121,6 +125,7 @@ static char *e1000_strings[] = {
int e1000_up(struct e1000_adapter *adapter); int e1000_up(struct e1000_adapter *adapter);
void e1000_down(struct e1000_adapter *adapter); void e1000_down(struct e1000_adapter *adapter);
void e1000_reset(struct e1000_adapter *adapter); void e1000_reset(struct e1000_adapter *adapter);
int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
static int e1000_init_module(void); static int e1000_init_module(void);
static void e1000_exit_module(void); static void e1000_exit_module(void);
...@@ -141,6 +146,7 @@ static void e1000_free_rx_resources(struct e1000_adapter *adapter); ...@@ -141,6 +146,7 @@ static void e1000_free_rx_resources(struct e1000_adapter *adapter);
static void e1000_set_multi(struct net_device *netdev); static void e1000_set_multi(struct net_device *netdev);
static void e1000_update_phy_info(unsigned long data); static void e1000_update_phy_info(unsigned long data);
static void e1000_watchdog(unsigned long data); static void e1000_watchdog(unsigned long data);
static void e1000_82547_tx_fifo_stall(unsigned long data);
static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev); static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
static struct net_device_stats * e1000_get_stats(struct net_device *netdev); static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
static int e1000_change_mtu(struct net_device *netdev, int new_mtu); static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
...@@ -149,14 +155,18 @@ static void e1000_update_stats(struct e1000_adapter *adapter); ...@@ -149,14 +155,18 @@ static void e1000_update_stats(struct e1000_adapter *adapter);
static inline void e1000_irq_disable(struct e1000_adapter *adapter); static inline void e1000_irq_disable(struct e1000_adapter *adapter);
static inline void e1000_irq_enable(struct e1000_adapter *adapter); static inline void e1000_irq_enable(struct e1000_adapter *adapter);
static void e1000_intr(int irq, void *data, struct pt_regs *regs); static void e1000_intr(int irq, void *data, struct pt_regs *regs);
static void e1000_clean_tx_irq(struct e1000_adapter *adapter);
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
static int e1000_poll(struct net_device *netdev, int *budget); static int e1000_clean(struct net_device *netdev, int *budget);
static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
int *work_done, int work_to_do);
#else #else
static void e1000_clean_rx_irq(struct e1000_adapter *adapter); static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter);
#endif #endif
static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter); static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
static inline void e1000_rx_checksum(struct e1000_adapter *adapter, static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
...@@ -164,6 +174,9 @@ static inline void e1000_rx_checksum(struct e1000_adapter *adapter, ...@@ -164,6 +174,9 @@ static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
struct sk_buff *skb); struct sk_buff *skb);
static void e1000_tx_timeout(struct net_device *dev); static void e1000_tx_timeout(struct net_device *dev);
static void e1000_tx_timeout_task(struct net_device *dev); static void e1000_tx_timeout_task(struct net_device *dev);
static void e1000_smartspeed(struct e1000_adapter *adapter);
static inline int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
struct sk_buff *skb);
static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
...@@ -182,6 +195,7 @@ struct notifier_block e1000_notifier_reboot = { ...@@ -182,6 +195,7 @@ struct notifier_block e1000_notifier_reboot = {
.priority = 0 .priority = 0
}; };
/* Exported from other modules */ /* Exported from other modules */
extern void e1000_check_options(struct e1000_adapter *adapter); extern void e1000_check_options(struct e1000_adapter *adapter);
...@@ -249,13 +263,10 @@ e1000_up(struct e1000_adapter *adapter) ...@@ -249,13 +263,10 @@ e1000_up(struct e1000_adapter *adapter)
{ {
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM,
netdev->name, netdev))
return -1;
/* hardware has been reset, we need to reload some things */ /* hardware has been reset, we need to reload some things */
e1000_set_multi(netdev); e1000_set_multi(netdev);
e1000_restore_vlan(adapter); e1000_restore_vlan(adapter);
e1000_configure_tx(adapter); e1000_configure_tx(adapter);
...@@ -263,6 +274,14 @@ e1000_up(struct e1000_adapter *adapter) ...@@ -263,6 +274,14 @@ e1000_up(struct e1000_adapter *adapter)
e1000_configure_rx(adapter); e1000_configure_rx(adapter);
e1000_alloc_rx_buffers(adapter); e1000_alloc_rx_buffers(adapter);
if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM,
netdev->name, netdev)) {
e1000_reset_hw(&adapter->hw);
e1000_free_tx_resources(adapter);
e1000_free_rx_resources(adapter);
return -1;
}
mod_timer(&adapter->watchdog_timer, jiffies); mod_timer(&adapter->watchdog_timer, jiffies);
e1000_irq_enable(adapter); e1000_irq_enable(adapter);
...@@ -276,6 +295,7 @@ e1000_down(struct e1000_adapter *adapter) ...@@ -276,6 +295,7 @@ e1000_down(struct e1000_adapter *adapter)
e1000_irq_disable(adapter); e1000_irq_disable(adapter);
free_irq(netdev->irq, netdev); free_irq(netdev->irq, netdev);
del_timer_sync(&adapter->tx_fifo_stall_timer);
del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_info_timer); del_timer_sync(&adapter->phy_info_timer);
adapter->link_speed = 0; adapter->link_speed = 0;
...@@ -291,14 +311,28 @@ e1000_down(struct e1000_adapter *adapter) ...@@ -291,14 +311,28 @@ e1000_down(struct e1000_adapter *adapter)
void void
e1000_reset(struct e1000_adapter *adapter) e1000_reset(struct e1000_adapter *adapter)
{ {
uint32_t pba;
/* Repartition Pba for greater than 9k mtu /* Repartition Pba for greater than 9k mtu
* To take effect CTRL.RST is required. * To take effect CTRL.RST is required.
*/ */
if(adapter->hw.mac_type < e1000_82547) {
if(adapter->rx_buffer_len > E1000_RXBUFFER_8192)
pba = E1000_PBA_40K;
else
pba = E1000_PBA_48K;
} else {
if(adapter->rx_buffer_len > E1000_RXBUFFER_8192) if(adapter->rx_buffer_len > E1000_RXBUFFER_8192)
E1000_WRITE_REG(&adapter->hw, PBA, E1000_JUMBO_PBA); pba = E1000_PBA_22K;
else else
E1000_WRITE_REG(&adapter->hw, PBA, E1000_DEFAULT_PBA); pba = E1000_PBA_30K;
adapter->tx_fifo_head = 0;
adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
adapter->tx_fifo_size =
(E1000_PBA_40K - pba) << E1000_TX_FIFO_SIZE_SHIFT;
atomic_set(&adapter->tx_fifo_stall, 0);
}
E1000_WRITE_REG(&adapter->hw, PBA, pba);
adapter->hw.fc = adapter->hw.original_fc; adapter->hw.fc = adapter->hw.original_fc;
e1000_reset_hw(&adapter->hw); e1000_reset_hw(&adapter->hw);
...@@ -389,9 +423,9 @@ e1000_probe(struct pci_dev *pdev, ...@@ -389,9 +423,9 @@ e1000_probe(struct pci_dev *pdev,
netdev->change_mtu = &e1000_change_mtu; netdev->change_mtu = &e1000_change_mtu;
netdev->do_ioctl = &e1000_ioctl; netdev->do_ioctl = &e1000_ioctl;
netdev->tx_timeout = &e1000_tx_timeout; netdev->tx_timeout = &e1000_tx_timeout;
netdev->watchdog_timeo = HZ; netdev->watchdog_timeo = 5 * HZ;
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
netdev->poll = &e1000_poll; netdev->poll = &e1000_clean;
netdev->weight = 64; netdev->weight = 64;
#endif #endif
netdev->vlan_rx_register = e1000_vlan_rx_register; netdev->vlan_rx_register = e1000_vlan_rx_register;
...@@ -421,7 +455,8 @@ e1000_probe(struct pci_dev *pdev, ...@@ -421,7 +455,8 @@ e1000_probe(struct pci_dev *pdev,
netdev->features = NETIF_F_SG; netdev->features = NETIF_F_SG;
} }
if(adapter->hw.mac_type >= e1000_82544) if((adapter->hw.mac_type >= e1000_82544) &&
(adapter->hw.mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO; netdev->features |= NETIF_F_TSO;
if(pci_using_dac) if(pci_using_dac)
...@@ -446,13 +481,9 @@ e1000_probe(struct pci_dev *pdev, ...@@ -446,13 +481,9 @@ e1000_probe(struct pci_dev *pdev,
e1000_get_bus_info(&adapter->hw); e1000_get_bus_info(&adapter->hw);
if((adapter->hw.mac_type == e1000_82544) && init_timer(&adapter->tx_fifo_stall_timer);
(adapter->hw.bus_type == e1000_bus_type_pcix)) adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall;
adapter->tx_fifo_stall_timer.data = (unsigned long) adapter;
adapter->max_data_per_txd = 4096;
else
adapter->max_data_per_txd = MAX_JUMBO_FRAME_SIZE;
init_timer(&adapter->watchdog_timer); init_timer(&adapter->watchdog_timer);
adapter->watchdog_timer.function = &e1000_watchdog; adapter->watchdog_timer.function = &e1000_watchdog;
...@@ -482,11 +513,12 @@ e1000_probe(struct pci_dev *pdev, ...@@ -482,11 +513,12 @@ e1000_probe(struct pci_dev *pdev,
* enable the ACPI Magic Packet filter * enable the ACPI Magic Packet filter
*/ */
e1000_read_eeprom(&adapter->hw, EEPROM_INIT_CONTROL2_REG, &eeprom_data); e1000_read_eeprom(&adapter->hw, EEPROM_INIT_CONTROL2_REG,1, &eeprom_data);
if((adapter->hw.mac_type >= e1000_82544) && if((adapter->hw.mac_type >= e1000_82544) &&
(eeprom_data & E1000_EEPROM_APME)) (eeprom_data & E1000_EEPROM_APME))
adapter->wol |= E1000_WUFC_MAG; adapter->wol |= E1000_WUFC_MAG;
/* reset the hardware with the new settings */ /* reset the hardware with the new settings */
e1000_reset(adapter); e1000_reset(adapter);
...@@ -533,6 +565,7 @@ e1000_remove(struct pci_dev *pdev) ...@@ -533,6 +565,7 @@ e1000_remove(struct pci_dev *pdev)
e1000_phy_hw_reset(&adapter->hw); e1000_phy_hw_reset(&adapter->hw);
iounmap(adapter->hw.hw_addr); iounmap(adapter->hw.hw_addr);
pci_release_regions(pdev); pci_release_regions(pdev);
...@@ -578,6 +611,10 @@ e1000_sw_init(struct e1000_adapter *adapter) ...@@ -578,6 +611,10 @@ e1000_sw_init(struct e1000_adapter *adapter)
return -1; return -1;
} }
/* initialize eeprom parameters */
e1000_init_eeprom_params(hw);
/* flow control settings */ /* flow control settings */
hw->fc_high_water = E1000_FC_HIGH_THRESH; hw->fc_high_water = E1000_FC_HIGH_THRESH;
...@@ -585,6 +622,9 @@ e1000_sw_init(struct e1000_adapter *adapter) ...@@ -585,6 +622,9 @@ e1000_sw_init(struct e1000_adapter *adapter)
hw->fc_pause_time = E1000_FC_PAUSE_TIME; hw->fc_pause_time = E1000_FC_PAUSE_TIME;
hw->fc_send_xon = 1; hw->fc_send_xon = 1;
if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547))
hw->phy_init_script = 1;
/* Media type - copper or fiber */ /* Media type - copper or fiber */
if(hw->mac_type >= e1000_82543) { if(hw->mac_type >= e1000_82543) {
...@@ -907,12 +947,9 @@ e1000_configure_rx(struct e1000_adapter *adapter) ...@@ -907,12 +947,9 @@ e1000_configure_rx(struct e1000_adapter *adapter)
if(adapter->hw.mac_type >= e1000_82540) { if(adapter->hw.mac_type >= e1000_82540) {
E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay); E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay);
if(adapter->itr > 1)
/* Set the interrupt throttling rate. Value is calculated E1000_WRITE_REG(&adapter->hw, ITR,
* as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) */ 1000000000 / (adapter->itr * 256));
#define MAX_INTS_PER_SEC 8000
#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256)
E1000_WRITE_REG(&adapter->hw, ITR, DEFAULT_ITR);
} }
/* Setup the Base and Length of the Rx Descriptor Ring */ /* Setup the Base and Length of the Rx Descriptor Ring */
...@@ -1184,9 +1221,9 @@ e1000_set_multi(struct net_device *netdev) ...@@ -1184,9 +1221,9 @@ e1000_set_multi(struct net_device *netdev)
if(hw->mac_type == e1000_82542_rev2_0) if(hw->mac_type == e1000_82542_rev2_0)
e1000_enter_82542_rst(adapter); e1000_enter_82542_rst(adapter);
/* load the first 15 multicast address into the exact filters 1-15 /* load the first 14 multicast address into the exact filters 1-14
* RAR 0 is used for the station MAC adddress * RAR 0 is used for the station MAC adddress
* if there are not 15 addresses, go ahead and clear the filters * if there are not 14 addresses, go ahead and clear the filters
*/ */
mc_ptr = netdev->mc_list; mc_ptr = netdev->mc_list;
...@@ -1216,6 +1253,40 @@ e1000_set_multi(struct net_device *netdev) ...@@ -1216,6 +1253,40 @@ e1000_set_multi(struct net_device *netdev)
e1000_leave_82542_rst(adapter); e1000_leave_82542_rst(adapter);
} }
static void
e1000_tx_flush(struct e1000_adapter *adapter)
{
uint32_t ctrl, tctl, txcw, icr;
e1000_irq_disable(adapter);
if(adapter->hw.mac_type < e1000_82543) {
/* Transmit Unit Reset */
tctl = E1000_READ_REG(&adapter->hw, TCTL);
E1000_WRITE_REG(&adapter->hw, TCTL, tctl | E1000_TCTL_RST);
E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
e1000_clean_tx_ring(adapter);
e1000_configure_tx(adapter);
} else {
txcw = E1000_READ_REG(&adapter->hw, TXCW);
E1000_WRITE_REG(&adapter->hw, TXCW, txcw & ~E1000_TXCW_ANE);
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl | E1000_CTRL_SLU |
E1000_CTRL_ILOS);
mdelay(10);
e1000_clean_tx_irq(adapter);
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
E1000_WRITE_REG(&adapter->hw, TXCW, txcw);
/* clear the link status change interrupts this caused */
icr = E1000_READ_REG(&adapter->hw, ICR);
}
e1000_irq_enable(adapter);
}
/* need to wait a few seconds after link up to get diagnostic information from the phy */ /* need to wait a few seconds after link up to get diagnostic information from the phy */
...@@ -1226,6 +1297,48 @@ e1000_update_phy_info(unsigned long data) ...@@ -1226,6 +1297,48 @@ e1000_update_phy_info(unsigned long data)
e1000_phy_get_info(&adapter->hw, &adapter->phy_info); e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
} }
/**
* e1000_82547_tx_fifo_stall - Timer Call-back
* @data: pointer to adapter cast into an unsigned long
**/
static void
e1000_82547_tx_fifo_stall(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
struct net_device *netdev = adapter->netdev;
uint32_t tctl;
if(atomic_read(&adapter->tx_fifo_stall)) {
if((E1000_READ_REG(&adapter->hw, TDT) ==
E1000_READ_REG(&adapter->hw, TDH)) &&
(E1000_READ_REG(&adapter->hw, TDFT) ==
E1000_READ_REG(&adapter->hw, TDFH)) &&
(E1000_READ_REG(&adapter->hw, TDFTS) ==
E1000_READ_REG(&adapter->hw, TDFHS))) {
tctl = E1000_READ_REG(&adapter->hw, TCTL);
E1000_WRITE_REG(&adapter->hw, TCTL,
tctl & ~E1000_TCTL_EN);
E1000_WRITE_REG(&adapter->hw, TDFT,
adapter->tx_head_addr);
E1000_WRITE_REG(&adapter->hw, TDFH,
adapter->tx_head_addr);
E1000_WRITE_REG(&adapter->hw, TDFTS,
adapter->tx_head_addr);
E1000_WRITE_REG(&adapter->hw, TDFHS,
adapter->tx_head_addr);
E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
E1000_WRITE_FLUSH(&adapter->hw);
adapter->tx_fifo_head = 0;
atomic_set(&adapter->tx_fifo_stall, 0);
netif_wake_queue(netdev);
} else {
mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
}
}
}
/** /**
* e1000_watchdog - Timer Call-back * e1000_watchdog - Timer Call-back
* @data: pointer to netdev cast into an unsigned long * @data: pointer to netdev cast into an unsigned long
...@@ -1256,6 +1369,7 @@ e1000_watchdog(unsigned long data) ...@@ -1256,6 +1369,7 @@ e1000_watchdog(unsigned long data)
netif_carrier_on(netdev); netif_carrier_on(netdev);
netif_wake_queue(netdev); netif_wake_queue(netdev);
mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ); mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
adapter->smartspeed = 0;
} }
} else { } else {
if(netif_carrier_ok(netdev)) { if(netif_carrier_ok(netdev)) {
...@@ -1268,11 +1382,34 @@ e1000_watchdog(unsigned long data) ...@@ -1268,11 +1382,34 @@ e1000_watchdog(unsigned long data)
netif_stop_queue(netdev); netif_stop_queue(netdev);
mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ); mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
} }
e1000_smartspeed(adapter);
} }
e1000_update_stats(adapter); e1000_update_stats(adapter);
e1000_update_adaptive(&adapter->hw); e1000_update_adaptive(&adapter->hw);
if(!netif_carrier_ok(netdev)) {
if(E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
unsigned long flags;
spin_lock_irqsave(&netdev->xmit_lock, flags);
e1000_tx_flush(adapter);
spin_unlock_irqrestore(&netdev->xmit_lock, flags);
}
}
/* Dynamic mode for Interrupt Throttle Rate (ITR) */
if(adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) {
/* Symmetric Tx/Rx gets a reduced ITR=2000; Total
* asymmetrical Tx or Rx gets ITR=8000; everyone
* else is between 2000-8000. */
uint32_t goc = (adapter->gotcl + adapter->gorcl) / 10000;
uint32_t dif = (adapter->gotcl > adapter->gorcl ?
adapter->gotcl - adapter->gorcl :
adapter->gorcl - adapter->gotcl) / 10000;
uint32_t itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (itr * 256));
}
/* Cause software interrupt to ensure rx ring is cleaned */ /* Cause software interrupt to ensure rx ring is cleaned */
E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
...@@ -1335,7 +1472,7 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags) ...@@ -1335,7 +1472,7 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags)
E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP | E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
(skb->len - (hdr_len))); (skb->len - (hdr_len)));
i = (i + 1) % adapter->tx_ring.count; if(++i == adapter->tx_ring.count) i = 0;
adapter->tx_ring.next_to_use = i; adapter->tx_ring.next_to_use = i;
return TRUE; return TRUE;
...@@ -1365,7 +1502,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) ...@@ -1365,7 +1502,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
context_desc->cmd_and_length = context_desc->cmd_and_length =
cpu_to_le32(adapter->txd_cmd | E1000_TXD_CMD_DEXT); cpu_to_le32(adapter->txd_cmd | E1000_TXD_CMD_DEXT);
i = (i + 1) % adapter->tx_ring.count; if(++i == adapter->tx_ring.count) i = 0;
adapter->tx_ring.next_to_use = i; adapter->tx_ring.next_to_use = i;
return TRUE; return TRUE;
...@@ -1374,24 +1511,24 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) ...@@ -1374,24 +1511,24 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
return FALSE; return FALSE;
} }
#define E1000_MAX_TXD_PWR 12
#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
static inline int static inline int
e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb) e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb)
{ {
struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
int len, offset, size, count, i; int len = skb->len, offset = 0, size, count = 0, i;
int tso = skb_shinfo(skb)->tso_size; int tso = skb_shinfo(skb)->tso_size;
int nr_frags = skb_shinfo(skb)->nr_frags; int nr_frags = skb_shinfo(skb)->nr_frags;
int f; int f;
len = skb->len - skb->data_len; len -= skb->data_len;
i = (tx_ring->next_to_use + tx_ring->count - 1) % tx_ring->count;
count = 0;
offset = 0; i = tx_ring->next_to_use;
while(len) { while(len) {
i = (i + 1) % tx_ring->count; size = min(len, E1000_MAX_DATA_PER_TXD);
size = min(len, adapter->max_data_per_txd);
/* Workaround for premature desc write-backs /* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */ * in TSO mode. Append 4-byte sentinel desc */
if(tso && !nr_frags && size == len && size > 4) if(tso && !nr_frags && size == len && size > 4)
...@@ -1407,6 +1544,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb) ...@@ -1407,6 +1544,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb)
len -= size; len -= size;
offset += size; offset += size;
count++; count++;
if(++i == tx_ring->count) i = 0;
} }
for(f = 0; f < nr_frags; f++) { for(f = 0; f < nr_frags; f++) {
...@@ -1417,8 +1555,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb) ...@@ -1417,8 +1555,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb)
offset = 0; offset = 0;
while(len) { while(len) {
i = (i + 1) % tx_ring->count; size = min(len, E1000_MAX_DATA_PER_TXD);
size = min(len, adapter->max_data_per_txd);
/* Workaround for premature desc write-backs /* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */ * in TSO mode. Append 4-byte sentinel desc */
if(tso && f == (nr_frags-1) && size == len && size > 4) if(tso && f == (nr_frags-1) && size == len && size > 4)
...@@ -1435,8 +1572,10 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb) ...@@ -1435,8 +1572,10 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb)
len -= size; len -= size;
offset += size; offset += size;
count++; count++;
if(++i == tx_ring->count) i = 0;
} }
} }
if(--i < 0) i = tx_ring->count - 1;
tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[i].skb = skb;
return count; return count;
...@@ -1477,7 +1616,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) ...@@ -1477,7 +1616,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
tx_desc->lower.data = tx_desc->lower.data =
cpu_to_le32(txd_lower | tx_ring->buffer_info[i].length); cpu_to_le32(txd_lower | tx_ring->buffer_info[i].length);
tx_desc->upper.data = cpu_to_le32(txd_upper); tx_desc->upper.data = cpu_to_le32(txd_upper);
i = (i + 1) % tx_ring->count; if(++i == tx_ring->count) i = 0;
} }
tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP); tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP);
...@@ -1492,33 +1631,73 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) ...@@ -1492,33 +1631,73 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
E1000_WRITE_REG(&adapter->hw, TDT, i); E1000_WRITE_REG(&adapter->hw, TDT, i);
} }
#define TXD_USE_COUNT(S, X) (((S) / (X)) + (((S) % (X)) ? 1 : 0)) /**
* 82547 workaround to avoid controller hang in half-duplex environment.
* The workaround is to avoid queuing a large packet that would span
* the internal Tx FIFO ring boundary by notifying the stack to resend
* the packet at a later time. This gives the Tx FIFO an opportunity to
* flush all packets. When that occurs, we reset the Tx FIFO pointers
* to the beginning of the Tx FIFO.
**/
#define E1000_FIFO_HDR 0x10
#define E1000_82547_PAD_LEN 0x3E0
static inline int
e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
{
uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
uint32_t skb_fifo_len = skb->len + E1000_FIFO_HDR;
E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR);
if(adapter->link_duplex != HALF_DUPLEX)
goto no_fifo_stall_required;
if(atomic_read(&adapter->tx_fifo_stall))
return 1;
if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
atomic_set(&adapter->tx_fifo_stall, 1);
return 1;
}
no_fifo_stall_required:
adapter->tx_fifo_head += skb_fifo_len;
if(adapter->tx_fifo_head >= adapter->tx_fifo_size)
adapter->tx_fifo_head -= adapter->tx_fifo_size;
return 0;
}
/* Tx Descriptors needed, worst case */
#define TXD_USE_COUNT(S) (((S) >> E1000_MAX_TXD_PWR) + \
(((S) & (E1000_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
#define DESC_NEEDED TXD_USE_COUNT(MAX_JUMBO_FRAME_SIZE) + \
MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1
static int static int
e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{ {
struct e1000_adapter *adapter = netdev->priv; struct e1000_adapter *adapter = netdev->priv;
int tx_flags = 0, count; int tx_flags = 0;
int f;
count = TXD_USE_COUNT(skb->len - skb->data_len,
adapter->max_data_per_txd);
if(count == 0) { if(skb->len <= 0) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return 0; return 0;
} }
for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) if(E1000_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED) {
count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size, netif_stop_queue(netdev);
adapter->max_data_per_txd); return 1;
if((skb_shinfo(skb)->tso_size) || (skb->ip_summed == CHECKSUM_HW)) }
count++;
if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) { if(adapter->hw.mac_type == e1000_82547) {
if(e1000_82547_fifo_workaround(adapter, skb)) {
netif_stop_queue(netdev); netif_stop_queue(netdev);
mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
return 1; return 1;
} }
}
if(adapter->vlgrp && vlan_tx_tag_present(skb)) { if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
tx_flags |= E1000_TX_FLAGS_VLAN; tx_flags |= E1000_TX_FLAGS_VLAN;
...@@ -1530,9 +1709,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1530,9 +1709,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
else if(e1000_tx_csum(adapter, skb)) else if(e1000_tx_csum(adapter, skb))
tx_flags |= E1000_TX_FLAGS_CSUM; tx_flags |= E1000_TX_FLAGS_CSUM;
count = e1000_tx_map(adapter, skb); e1000_tx_queue(adapter, e1000_tx_map(adapter, skb), tx_flags);
e1000_tx_queue(adapter, count, tx_flags);
netdev->trans_start = jiffies; netdev->trans_start = jiffies;
...@@ -1653,7 +1830,8 @@ e1000_update_stats(struct e1000_adapter *adapter) ...@@ -1653,7 +1830,8 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS); adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS);
adapter->stats.gprc += E1000_READ_REG(hw, GPRC); adapter->stats.gprc += E1000_READ_REG(hw, GPRC);
adapter->stats.gorcl += E1000_READ_REG(hw, GORCL); adapter->gorcl = E1000_READ_REG(hw, GORCL);
adapter->stats.gorcl += adapter->gorcl;
adapter->stats.gorch += E1000_READ_REG(hw, GORCH); adapter->stats.gorch += E1000_READ_REG(hw, GORCH);
adapter->stats.bprc += E1000_READ_REG(hw, BPRC); adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
adapter->stats.mprc += E1000_READ_REG(hw, MPRC); adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
...@@ -1684,7 +1862,8 @@ e1000_update_stats(struct e1000_adapter *adapter) ...@@ -1684,7 +1862,8 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC); adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC);
adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC); adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC);
adapter->stats.gptc += E1000_READ_REG(hw, GPTC); adapter->stats.gptc += E1000_READ_REG(hw, GPTC);
adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL); adapter->gotcl = E1000_READ_REG(hw, GOTCL);
adapter->stats.gotcl += adapter->gotcl;
adapter->stats.gotch += E1000_READ_REG(hw, GOTCH); adapter->stats.gotch += E1000_READ_REG(hw, GOTCH);
adapter->stats.rnbc += E1000_READ_REG(hw, RNBC); adapter->stats.rnbc += E1000_READ_REG(hw, RNBC);
adapter->stats.ruc += E1000_READ_REG(hw, RUC); adapter->stats.ruc += E1000_READ_REG(hw, RUC);
...@@ -1807,60 +1986,57 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) ...@@ -1807,60 +1986,57 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
{ {
struct net_device *netdev = data; struct net_device *netdev = data;
struct e1000_adapter *adapter = netdev->priv; struct e1000_adapter *adapter = netdev->priv;
uint32_t icr = E1000_READ_REG(&adapter->hw, ICR);
#ifndef CONFIG_E1000_NAPI
int i;
#endif
#ifdef CONFIG_E1000_NAPI if(!icr)
if (netif_rx_schedule_prep(netdev)) { return; /* Not our interrupt */
/* Disable interrupts and enable polling */
atomic_inc(&adapter->irq_sem);
E1000_WRITE_REG(&adapter->hw, IMC, ~0);
E1000_WRITE_FLUSH(&adapter->hw);
__netif_rx_schedule(netdev);
}
#else
uint32_t icr;
int i = E1000_MAX_INTR;
while(i && (icr = E1000_READ_REG(&adapter->hw, ICR))) {
if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
adapter->hw.get_link_status = 1; adapter->hw.get_link_status = 1;
mod_timer(&adapter->watchdog_timer, jiffies); mod_timer(&adapter->watchdog_timer, jiffies);
} }
e1000_clean_rx_irq(adapter); #ifdef CONFIG_E1000_NAPI
e1000_clean_tx_irq(adapter); /* Don't disable interrupts - rely on h/w interrupt
i--; * moderation to keep interrupts low. netif_rx_schedule
* is NOP if already polling. */
} netif_rx_schedule(netdev);
#else
for(i = 0; i < E1000_MAX_INTR; i++)
if(!e1000_clean_rx_irq(adapter) &&
!e1000_clean_tx_irq(adapter))
break;
#endif #endif
} }
#ifdef CONFIG_E1000_NAPI #ifdef CONFIG_E1000_NAPI
/**
* e1000_clean - NAPI Rx polling callback
* @adapter: board private structure
**/
static int static int
e1000_process_intr(struct net_device *netdev) e1000_clean(struct net_device *netdev, int *budget)
{ {
struct e1000_adapter *adapter = netdev->priv; struct e1000_adapter *adapter = netdev->priv;
uint32_t icr; int work_to_do = min(*budget, netdev->quota);
int i = E1000_MAX_INTR; int work_done = 0;
int hasReceived = 0;
while(i && (icr = E1000_READ_REG(&adapter->hw, ICR))) { while(work_done < work_to_do)
if (icr & E1000_ICR_RXT0) if(!e1000_clean_rx_irq(adapter, &work_done, work_to_do) &&
hasReceived = 1; !e1000_clean_tx_irq(adapter))
if (!(icr & ~(E1000_ICR_RXT0)))
break; break;
if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { *budget -= work_done;
adapter->hw.get_link_status = 1; netdev->quota -= work_done;
mod_timer(&adapter->watchdog_timer, jiffies);
}
e1000_clean_tx_irq(adapter); if(work_done < work_to_do)
i--; netif_rx_complete(netdev);
}
return hasReceived; return (work_done >= work_to_do);
} }
#endif #endif
...@@ -1869,20 +2045,22 @@ e1000_process_intr(struct net_device *netdev) ...@@ -1869,20 +2045,22 @@ e1000_process_intr(struct net_device *netdev)
* @adapter: board private structure * @adapter: board private structure
**/ **/
static void static boolean_t
e1000_clean_tx_irq(struct e1000_adapter *adapter) e1000_clean_tx_irq(struct e1000_adapter *adapter)
{ {
struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev; struct pci_dev *pdev = adapter->pdev;
struct e1000_tx_desc *tx_desc; struct e1000_tx_desc *tx_desc;
int i; int i, cleaned = FALSE;
i = tx_ring->next_to_clean; i = tx_ring->next_to_clean;
tx_desc = E1000_TX_DESC(*tx_ring, i); tx_desc = E1000_TX_DESC(*tx_ring, i);
while(tx_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { while(tx_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
cleaned = TRUE;
if(tx_ring->buffer_info[i].dma) { if(tx_ring->buffer_info[i].dma) {
pci_unmap_page(pdev, pci_unmap_page(pdev,
...@@ -1900,158 +2078,34 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) ...@@ -1900,158 +2078,34 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
tx_ring->buffer_info[i].skb = NULL; tx_ring->buffer_info[i].skb = NULL;
} }
tx_desc->buffer_addr = 0;
tx_desc->lower.data = 0;
tx_desc->upper.data = 0; tx_desc->upper.data = 0;
i = (i + 1) % tx_ring->count; if(++i == tx_ring->count) i = 0;
tx_desc = E1000_TX_DESC(*tx_ring, i); tx_desc = E1000_TX_DESC(*tx_ring, i);
} }
tx_ring->next_to_clean = i; tx_ring->next_to_clean = i;
if(netif_queue_stopped(netdev) && netif_carrier_ok(netdev) && if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
(E1000_DESC_UNUSED(tx_ring) > E1000_TX_QUEUE_WAKE)) {
netif_wake_queue(netdev); netif_wake_queue(netdev);
}
}
#ifdef CONFIG_E1000_NAPI
static int
e1000_poll(struct net_device *netdev, int *budget)
{
struct e1000_adapter *adapter = netdev->priv;
struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc;
struct sk_buff *skb;
unsigned long flags;
uint32_t length;
uint8_t last_byte;
int i;
int received = 0;
int rx_work_limit = *budget;
if(rx_work_limit > netdev->quota)
rx_work_limit = netdev->quota;
e1000_process_intr(netdev);
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC(*rx_ring, i);
while(rx_desc->status & E1000_RXD_STAT_DD) {
if(--rx_work_limit < 0)
goto not_done;
pci_unmap_single(pdev,
rx_ring->buffer_info[i].dma,
rx_ring->buffer_info[i].length,
PCI_DMA_FROMDEVICE);
skb = rx_ring->buffer_info[i].skb;
length = le16_to_cpu(rx_desc->length);
if(!(rx_desc->status & E1000_RXD_STAT_EOP)) { return cleaned;
/* All receives must fit into a single buffer */
E1000_DBG("Receive packet consumed multiple buffers\n");
dev_kfree_skb_irq(skb);
rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = E1000_RX_DESC(*rx_ring, i);
continue;
}
if(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
last_byte = *(skb->data + length - 1);
if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
rx_desc->errors, length, last_byte)) {
spin_lock_irqsave(&adapter->stats_lock, flags);
e1000_tbi_adjust_stats(&adapter->hw,
&adapter->stats,
length, skb->data);
spin_unlock_irqrestore(&adapter->stats_lock,
flags);
length--;
} else {
dev_kfree_skb_irq(skb);
rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = E1000_RX_DESC(*rx_ring, i);
continue;
}
}
/* Good Receive */
skb_put(skb, length - ETHERNET_FCS_SIZE);
/* Receive Checksum Offload */
e1000_rx_checksum(adapter, rx_desc, skb);
skb->protocol = eth_type_trans(skb, netdev);
if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
(rx_desc->special & E1000_RXD_SPC_VLAN_MASK));
} else {
netif_receive_skb(skb);
}
netdev->last_rx = jiffies;
rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = E1000_RX_DESC(*rx_ring, i);
received++;
}
if(!received)
received = 1;
e1000_alloc_rx_buffers(adapter);
rx_ring->next_to_clean = i;
netdev->quota -= received;
*budget -= received;
netif_rx_complete(netdev);
e1000_irq_enable(adapter);
return 0;
not_done:
e1000_alloc_rx_buffers(adapter);
rx_ring->next_to_clean = i;
netdev->quota -= received;
*budget -= received;
return 1;
} }
#else
/** /**
* e1000_clean_rx_irq - Send received data up the network stack, * e1000_clean_rx_irq - Send received data up the network stack,
* @adapter: board private structure * @adapter: board private structure
**/ **/
static void static boolean_t
#ifdef CONFIG_E1000_NAPI
e1000_clean_rx_irq(struct e1000_adapter *adapter, int *work_done,
int work_to_do)
#else
e1000_clean_rx_irq(struct e1000_adapter *adapter) e1000_clean_rx_irq(struct e1000_adapter *adapter)
#endif
{ {
struct e1000_desc_ring *rx_ring = &adapter->rx_ring; struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
...@@ -2061,13 +2115,22 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) ...@@ -2061,13 +2115,22 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
unsigned long flags; unsigned long flags;
uint32_t length; uint32_t length;
uint8_t last_byte; uint8_t last_byte;
int i; int i, cleaned = FALSE;
i = rx_ring->next_to_clean; i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc = E1000_RX_DESC(*rx_ring, i);
while(rx_desc->status & E1000_RXD_STAT_DD) { while(rx_desc->status & E1000_RXD_STAT_DD) {
#ifdef CONFIG_E1000_NAPI
if(*work_done >= work_to_do)
break;
(*work_done)++;
#endif
cleaned = TRUE;
pci_unmap_single(pdev, pci_unmap_single(pdev,
rx_ring->buffer_info[i].dma, rx_ring->buffer_info[i].dma,
rx_ring->buffer_info[i].length, rx_ring->buffer_info[i].length,
...@@ -2086,7 +2149,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) ...@@ -2086,7 +2149,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
rx_desc->status = 0; rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL; rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count; if(++i == rx_ring->count) i = 0;
rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc = E1000_RX_DESC(*rx_ring, i);
continue; continue;
...@@ -2114,7 +2177,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) ...@@ -2114,7 +2177,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
rx_desc->status = 0; rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL; rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count; if(++i == rx_ring->count) i = 0;
rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc = E1000_RX_DESC(*rx_ring, i);
continue; continue;
...@@ -2128,18 +2191,28 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) ...@@ -2128,18 +2191,28 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
e1000_rx_checksum(adapter, rx_desc, skb); e1000_rx_checksum(adapter, rx_desc, skb);
skb->protocol = eth_type_trans(skb, netdev); skb->protocol = eth_type_trans(skb, netdev);
#ifdef CONFIG_E1000_NAPI
if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
(rx_desc->special & E1000_RXD_SPC_VLAN_MASK));
} else {
netif_receive_skb(skb);
}
#else /* CONFIG_E1000_NAPI */
if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_hwaccel_rx(skb, adapter->vlgrp,
(rx_desc->special & E1000_RXD_SPC_VLAN_MASK)); (rx_desc->special & E1000_RXD_SPC_VLAN_MASK));
} else { } else {
netif_rx(skb); netif_rx(skb);
} }
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies; netdev->last_rx = jiffies;
rx_desc->status = 0; rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL; rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count; if(++i == rx_ring->count) i = 0;
rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc = E1000_RX_DESC(*rx_ring, i);
} }
...@@ -2147,8 +2220,9 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) ...@@ -2147,8 +2220,9 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
rx_ring->next_to_clean = i; rx_ring->next_to_clean = i;
e1000_alloc_rx_buffers(adapter); e1000_alloc_rx_buffers(adapter);
return cleaned;
} }
#endif
/** /**
* e1000_alloc_rx_buffers - Replace used receive buffers * e1000_alloc_rx_buffers - Replace used receive buffers
...@@ -2163,11 +2237,9 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) ...@@ -2163,11 +2237,9 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
struct pci_dev *pdev = adapter->pdev; struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc; struct e1000_rx_desc *rx_desc;
struct sk_buff *skb; struct sk_buff *skb;
int reserve_len; int reserve_len = 2;
int i; int i;
reserve_len = 2;
i = rx_ring->next_to_use; i = rx_ring->next_to_use;
while(!rx_ring->buffer_info[i].skb) { while(!rx_ring->buffer_info[i].skb) {
...@@ -2198,7 +2270,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) ...@@ -2198,7 +2270,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma); rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma);
if(!(i % E1000_RX_BUFFER_WRITE)) { if((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i) {
/* Force memory writes to complete before letting h/w /* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only * know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs, * applicable for weak-ordered memory model archs,
...@@ -2208,12 +2280,67 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) ...@@ -2208,12 +2280,67 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, RDT, i); E1000_WRITE_REG(&adapter->hw, RDT, i);
} }
i = (i + 1) % rx_ring->count; if(++i == rx_ring->count) i = 0;
} }
rx_ring->next_to_use = i; rx_ring->next_to_use = i;
} }
/**
* e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers.
* @adapter:
**/
static void
e1000_smartspeed(struct e1000_adapter *adapter)
{
uint16_t phy_status;
uint16_t phy_ctrl;
if((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
!(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))
return;
if(adapter->smartspeed == 0) {
/* If Master/Slave config fault is asserted twice,
* we assume back-to-back */
e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
if(phy_ctrl & CR_1000T_MS_ENABLE) {
phy_ctrl &= ~CR_1000T_MS_ENABLE;
e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL,
phy_ctrl);
adapter->smartspeed++;
if(!e1000_phy_setup_autoneg(&adapter->hw) &&
!e1000_read_phy_reg(&adapter->hw, PHY_CTRL,
&phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
MII_CR_RESTART_AUTO_NEG);
e1000_write_phy_reg(&adapter->hw, PHY_CTRL,
phy_ctrl);
}
}
return;
} else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
/* If still no link, perhaps using 2/3 pair cable */
e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
phy_ctrl |= CR_1000T_MS_ENABLE;
e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl);
if(!e1000_phy_setup_autoneg(&adapter->hw) &&
!e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
MII_CR_RESTART_AUTO_NEG);
e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl);
}
}
/* Restart process after E1000_SMARTSPEED_MAX iterations */
if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
adapter->smartspeed = 0;
}
/** /**
* e1000_ioctl - * e1000_ioctl -
* @netdev: * @netdev:
...@@ -2225,6 +2352,10 @@ static int ...@@ -2225,6 +2352,10 @@ static int
e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{ {
switch (cmd) { switch (cmd) {
case SIOCGMIIPHY:
case SIOCGMIIREG:
case SIOCSMIIREG:
return e1000_mii_ioctl(netdev, ifr, cmd);
case SIOCETHTOOL: case SIOCETHTOOL:
return e1000_ethtool_ioctl(netdev, ifr); return e1000_ethtool_ioctl(netdev, ifr);
default: default:
...@@ -2232,6 +2363,86 @@ e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ...@@ -2232,6 +2363,86 @@ e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
} }
} }
/**
* e1000_mii_ioctl -
* @netdev:
* @ifreq:
* @cmd:
**/
static int
e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
struct e1000_adapter *adapter = netdev->priv;
struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;
int retval;
uint16_t mii_reg;
uint16_t spddplx;
if(adapter->hw.media_type == e1000_media_type_fiber)
return -EOPNOTSUPP;
switch (cmd) {
case SIOCGMIIPHY:
data->phy_id = adapter->hw.phy_addr;
break;
case SIOCGMIIREG:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
&data->val_out))
return -EIO;
break;
case SIOCSMIIREG:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (data->reg_num & ~(0x1F))
return -EFAULT;
mii_reg = data->val_in;
if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
data->val_in))
return -EIO;
if (adapter->hw.phy_type == e1000_phy_m88) {
switch (data->reg_num) {
case PHY_CTRL:
if(data->val_in & MII_CR_AUTO_NEG_EN) {
adapter->hw.autoneg = 1;
adapter->hw.autoneg_advertised = 0x2F;
} else {
if (data->val_in & 0x40)
spddplx = SPEED_1000;
else if (data->val_in & 0x2000)
spddplx = SPEED_100;
else
spddplx = SPEED_10;
spddplx += (data->val_in & 0x100)
? FULL_DUPLEX :
HALF_DUPLEX;
retval = e1000_set_spd_dplx(adapter,
spddplx);
if(retval)
return retval;
}
if(netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
e1000_reset(adapter);
break;
case M88E1000_PHY_SPEC_CTRL:
case M88E1000_EXT_PHY_SPEC_CTRL:
if (e1000_phy_reset(&adapter->hw))
return -EIO;
break;
}
}
break;
default:
return -EOPNOTSUPP;
}
return E1000_SUCCESS;
}
/** /**
* e1000_rx_checksum - Receive Checksum Offload for 82543 * e1000_rx_checksum - Receive Checksum Offload for 82543
* @adapter: board private structure * @adapter: board private structure
...@@ -2402,6 +2613,35 @@ e1000_restore_vlan(struct e1000_adapter *adapter) ...@@ -2402,6 +2613,35 @@ e1000_restore_vlan(struct e1000_adapter *adapter)
} }
} }
int
e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
{
adapter->hw.autoneg = 0;
switch(spddplx) {
case SPEED_10 + DUPLEX_HALF:
adapter->hw.forced_speed_duplex = e1000_10_half;
break;
case SPEED_10 + DUPLEX_FULL:
adapter->hw.forced_speed_duplex = e1000_10_full;
break;
case SPEED_100 + DUPLEX_HALF:
adapter->hw.forced_speed_duplex = e1000_100_half;
break;
case SPEED_100 + DUPLEX_FULL:
adapter->hw.forced_speed_duplex = e1000_100_full;
break;
case SPEED_1000 + DUPLEX_FULL:
adapter->hw.autoneg = 1;
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
break;
case SPEED_1000 + DUPLEX_HALF: /* not supported */
default:
return -EINVAL;
}
return 0;
}
static int static int
e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
{ {
...@@ -2419,6 +2659,7 @@ e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) ...@@ -2419,6 +2659,7 @@ e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static int static int
e1000_suspend(struct pci_dev *pdev, uint32_t state) e1000_suspend(struct pci_dev *pdev, uint32_t state)
{ {
...@@ -2483,7 +2724,8 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state) ...@@ -2483,7 +2724,8 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state)
if(manc & E1000_MANC_SMBUS_EN) { if(manc & E1000_MANC_SMBUS_EN) {
manc |= E1000_MANC_ARP_EN; manc |= E1000_MANC_ARP_EN;
E1000_WRITE_REG(&adapter->hw, MANC, manc); E1000_WRITE_REG(&adapter->hw, MANC, manc);
state = 0; pci_enable_wake(pdev, 3, 1);
pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
} }
} }
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -77,24 +77,22 @@ typedef enum { ...@@ -77,24 +77,22 @@ typedef enum {
#define E1000_WRITE_REG(a, reg, value) ( \ #define E1000_WRITE_REG(a, reg, value) ( \
((a)->mac_type >= e1000_82543) ? \ writel((value), ((a)->hw_addr + \
(writel((value), ((a)->hw_addr + E1000_##reg))) : \ (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg))))
(writel((value), ((a)->hw_addr + E1000_82542_##reg))))
#define E1000_READ_REG(a, reg) ( \ #define E1000_READ_REG(a, reg) ( \
((a)->mac_type >= e1000_82543) ? \ readl((a)->hw_addr + \
readl((a)->hw_addr + E1000_##reg) : \ (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)))
readl((a)->hw_addr + E1000_82542_##reg))
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \ #define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
((a)->mac_type >= e1000_82543) ? \ writel((value), ((a)->hw_addr + \
writel((value), ((a)->hw_addr + E1000_##reg + ((offset) << 2))) : \ (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
writel((value), ((a)->hw_addr + E1000_82542_##reg + ((offset) << 2)))) ((offset) << 2))))
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ #define E1000_READ_REG_ARRAY(a, reg, offset) ( \
((a)->mac_type >= e1000_82543) ? \ readl((a)->hw_addr + \
readl((a)->hw_addr + E1000_##reg + ((offset) << 2)) : \ (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
readl((a)->hw_addr + E1000_82542_##reg + ((offset) << 2))) ((offset) << 2)))
#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS) #define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
......
/******************************************************************************* /*******************************************************************************
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
...@@ -169,7 +169,7 @@ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); ...@@ -169,7 +169,7 @@ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
* *
* Valid Range: 0-65535 * Valid Range: 0-65535
* *
* Default Value: 0/128 * Default Value: 0
*/ */
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
...@@ -183,6 +183,15 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); ...@@ -183,6 +183,15 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
/* Interrupt Throttle Rate (interrupts/sec)
*
* Valid Range: 100-100000 (0=off, 1=dynamic)
*
* Default Value: 1
*/
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
#define AUTONEG_ADV_DEFAULT 0x2F #define AUTONEG_ADV_DEFAULT 0x2F
#define AUTONEG_ADV_MASK 0x2F #define AUTONEG_ADV_MASK 0x2F
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL #define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
...@@ -213,6 +222,10 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); ...@@ -213,6 +222,10 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
#define MAX_TXABSDELAY 0xFFFF #define MAX_TXABSDELAY 0xFFFF
#define MIN_TXABSDELAY 0 #define MIN_TXABSDELAY 0
#define DEFAULT_ITR 1
#define MAX_ITR 100000
#define MIN_ITR 100
struct e1000_option { struct e1000_option {
enum { enable_option, range_option, list_option } type; enum { enable_option, range_option, list_option } type;
char *name; char *name;
...@@ -309,7 +322,7 @@ e1000_check_options(struct e1000_adapter *adapter) ...@@ -309,7 +322,7 @@ e1000_check_options(struct e1000_adapter *adapter)
.name = "Transmit Descriptors", .name = "Transmit Descriptors",
.err = "using default of " __MODULE_STRING(DEFAULT_TXD), .err = "using default of " __MODULE_STRING(DEFAULT_TXD),
.def = DEFAULT_TXD, .def = DEFAULT_TXD,
.arg = { .r = { .min = MIN_TXD }} .arg = { .r { .min = MIN_TXD }}
}; };
struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
e1000_mac_type mac_type = adapter->hw.mac_type; e1000_mac_type mac_type = adapter->hw.mac_type;
...@@ -362,7 +375,8 @@ e1000_check_options(struct e1000_adapter *adapter) ...@@ -362,7 +375,8 @@ e1000_check_options(struct e1000_adapter *adapter)
.name = "Flow Control", .name = "Flow Control",
.err = "reading default settings from EEPROM", .err = "reading default settings from EEPROM",
.def = e1000_fc_default, .def = e1000_fc_default,
.arg = { .l = { .nr = ARRAY_SIZE(fc_list), .p = fc_list }} .arg = { .l = { .nr = ARRAY_SIZE(fc_list),
.p = fc_list }}
}; };
int fc = FlowControl[bd]; int fc = FlowControl[bd];
...@@ -370,57 +384,77 @@ e1000_check_options(struct e1000_adapter *adapter) ...@@ -370,57 +384,77 @@ e1000_check_options(struct e1000_adapter *adapter)
adapter->hw.fc = adapter->hw.original_fc = fc; adapter->hw.fc = adapter->hw.original_fc = fc;
} }
{ /* Transmit Interrupt Delay */ { /* Transmit Interrupt Delay */
char *tidv = "using default of " __MODULE_STRING(DEFAULT_TIDV);
struct e1000_option opt = { struct e1000_option opt = {
.type = range_option, .type = range_option,
.name = "Transmit Interrupt Delay", .name = "Transmit Interrupt Delay",
.arg = { .r = { .min = MIN_TXDELAY, .max = MAX_TXDELAY }} .err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
.def = DEFAULT_TIDV,
.arg = { .r = { .min = MIN_TXDELAY,
.max = MAX_TXDELAY }}
}; };
opt.def = DEFAULT_TIDV;
opt.err = tidv;
adapter->tx_int_delay = TxIntDelay[bd]; adapter->tx_int_delay = TxIntDelay[bd];
e1000_validate_option(&adapter->tx_int_delay, &opt); e1000_validate_option(&adapter->tx_int_delay, &opt);
} }
{ /* Transmit Absolute Interrupt Delay */ { /* Transmit Absolute Interrupt Delay */
char *tadv = "using default of " __MODULE_STRING(DEFAULT_TADV);
struct e1000_option opt = { struct e1000_option opt = {
.type = range_option, .type = range_option,
.name = "Transmit Absolute Interrupt Delay", .name = "Transmit Absolute Interrupt Delay",
.arg = { .r = { .min = MIN_TXABSDELAY, .max = MAX_TXABSDELAY }} .err = "using default of " __MODULE_STRING(DEFAULT_TADV),
.def = DEFAULT_TADV,
.arg = { .r = { .min = MIN_TXABSDELAY,
.max = MAX_TXABSDELAY }}
}; };
opt.def = DEFAULT_TADV;
opt.err = tadv;
adapter->tx_abs_int_delay = TxAbsIntDelay[bd]; adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
e1000_validate_option(&adapter->tx_abs_int_delay, &opt); e1000_validate_option(&adapter->tx_abs_int_delay, &opt);
} }
{ /* Receive Interrupt Delay */ { /* Receive Interrupt Delay */
char *rdtr = "using default of " __MODULE_STRING(DEFAULT_RDTR);
struct e1000_option opt = { struct e1000_option opt = {
.type = range_option, .type = range_option,
.name = "Receive Interrupt Delay", .name = "Receive Interrupt Delay",
.arg = { .r = { .min = MIN_RXDELAY, .max = MAX_RXDELAY }} .err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
.def = DEFAULT_RDTR,
.arg = { .r = { .min = MIN_RXDELAY,
.max = MAX_RXDELAY }}
}; };
opt.def = DEFAULT_RDTR;
opt.err = rdtr;
adapter->rx_int_delay = RxIntDelay[bd]; adapter->rx_int_delay = RxIntDelay[bd];
e1000_validate_option(&adapter->rx_int_delay, &opt); e1000_validate_option(&adapter->rx_int_delay, &opt);
} }
{ /* Receive Absolute Interrupt Delay */ { /* Receive Absolute Interrupt Delay */
char *radv = "using default of " __MODULE_STRING(DEFAULT_RADV);
struct e1000_option opt = { struct e1000_option opt = {
.type = range_option, .type = range_option,
.name = "Receive Absolute Interrupt Delay", .name = "Receive Absolute Interrupt Delay",
.arg = { .r = { .min = MIN_RXABSDELAY, .max = MAX_RXABSDELAY }} .err = "using default of " __MODULE_STRING(DEFAULT_RADV),
.def = DEFAULT_RADV,
.arg = { .r = { .min = MIN_RXABSDELAY,
.max = MAX_RXABSDELAY }}
}; };
opt.def = DEFAULT_RADV;
opt.err = radv;
adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
e1000_validate_option(&adapter->rx_abs_int_delay, &opt); e1000_validate_option(&adapter->rx_abs_int_delay, &opt);
} }
{ /* Interrupt Throttling Rate */
struct e1000_option opt = {
.type = range_option,
.name = "Interrupt Throttling Rate (ints/sec)",
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
.def = DEFAULT_ITR,
.arg = { .r = { .min = MIN_ITR,
.max = MAX_ITR }}
};
adapter->itr = InterruptThrottleRate[bd];
if(adapter->itr == 0) {
printk(KERN_INFO "%s turned off\n", opt.name);
} else if(adapter->itr == 1 || adapter->itr == -1) {
/* Dynamic mode */
adapter->itr = 1;
} else {
e1000_validate_option(&adapter->itr, &opt);
}
}
switch(adapter->hw.media_type) { switch(adapter->hw.media_type) {
case e1000_media_type_fiber: case e1000_media_type_fiber:
...@@ -486,7 +520,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter) ...@@ -486,7 +520,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
.name = "Speed", .name = "Speed",
.err = "parameter ignored", .err = "parameter ignored",
.def = 0, .def = 0,
.arg = { .l = { .nr = ARRAY_SIZE(speed_list), .p = speed_list }} .arg = { .l = { .nr = ARRAY_SIZE(speed_list),
.p = speed_list }}
}; };
speed = Speed[bd]; speed = Speed[bd];
...@@ -502,7 +537,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter) ...@@ -502,7 +537,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
.name = "Duplex", .name = "Duplex",
.err = "parameter ignored", .err = "parameter ignored",
.def = 0, .def = 0,
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list), .p = dplx_list }} .arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
.p = dplx_list }}
}; };
dplx = Duplex[bd]; dplx = Duplex[bd];
...@@ -554,7 +590,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter) ...@@ -554,7 +590,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
.name = "AutoNeg", .name = "AutoNeg",
.err = "parameter ignored", .err = "parameter ignored",
.def = AUTONEG_ADV_DEFAULT, .def = AUTONEG_ADV_DEFAULT,
.arg = { .l = { .nr = ARRAY_SIZE(an_list), .p = an_list }} .arg = { .l = { .nr = ARRAY_SIZE(an_list),
.p = an_list }}
}; };
int an = AutoNeg[bd]; int an = AutoNeg[bd];
......
/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
/*
Written 1992-94 by Donald Becker.
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
This driver should work with many programmed-I/O 8390-based ethernet
boards. Currently it supports the NE1000, NE2000, many clones,
and some Cabletron products.
Changelog:
Paul Gortmaker : use ENISR_RDC to monitor Tx PIO uploads, made
sanity checks and bad clone support optional.
Paul Gortmaker : new reset code, reset card after probe at boot.
Paul Gortmaker : multiple card support for module users.
Paul Gortmaker : Support for PCI ne2k clones, similar to lance.c
Paul Gortmaker : Allow users with bad cards to avoid full probe.
Paul Gortmaker : PCI probe changes, more PCI cards supported.
rjohnson@analogic.com : Changed init order so an interrupt will only
occur after memory is allocated for dev->priv. Deallocated memory
last in cleanup_modue()
Richard Guenther : Added support for ISAPnP cards
Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead.
Osamu Tomita : Separate driver for NEC PC-9800.
*/
/* Routines for the NatSemi-based designs (NE[12]000). */
static const char version1[] =
"ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)\n";
static const char version2[] =
"Last modified Nov 1, 2000 by Paul Gortmaker\n";
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/isapnp.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <asm/system.h>
#include <asm/io.h>
#include "8390.h"
/* Some defines that people can play with if so inclined. */
/* Do we support clones that don't adhere to 14,15 of the SAprom ? */
#define SUPPORT_NE_BAD_CLONES
/* Do we perform extra sanity checks on stuff ? */
/* #define NE_SANITY_CHECK */
/* Do we implement the read before write bugfix ? */
/* #define NE_RW_BUGFIX */
/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
/* #define PACKETBUF_MEMSIZE 0x40 */
#ifdef SUPPORT_NE_BAD_CLONES
/* A list of bad clones that we none-the-less recognize. */
static struct { const char *name8, *name16; unsigned char SAprefix[4];}
bad_clone_list[] __initdata = {
{"LA/T-98?", "LA/T-98", {0x00, 0xa0, 0xb0}}, /* I/O Data */
{"EGY-98?", "EGY-98", {0x00, 0x40, 0x26}}, /* Melco EGY98 */
{"ICM?", "ICM-27xx-ET", {0x00, 0x80, 0xc8}}, /* ICM IF-27xx-ET */
{"CNET-98/EL?", "CNET(98)E/L", {0x00, 0x80, 0x4C}}, /* Contec CNET-98/EL */
{0,}
};
#endif
/* ---- No user-serviceable parts below ---- */
#define NE_BASE (dev->base_addr)
#define NE_CMD EI_SHIFT(0x00)
#define NE_DATAPORT EI_SHIFT(0x10) /* NatSemi-defined port window offset. */
#define NE_RESET EI_SHIFT(0x1f) /* Issue a read to reset, a write to clear. */
#define NE_IO_EXTENT 0x20
#define NE1SM_START_PG 0x20 /* First page of TX buffer */
#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
#define NESM_START_PG 0x40 /* First page of TX buffer */
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
#include "ne2k_cbus.h"
int ne_probe(struct net_device *dev);
static int ne_probe1(struct net_device *dev, int ioaddr);
static int ne_open(struct net_device *dev);
static int ne_close(struct net_device *dev);
static void ne_reset_8390(struct net_device *dev);
static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
static void ne_block_input(struct net_device *dev, int count,
struct sk_buff *skb, int ring_offset);
static void ne_block_output(struct net_device *dev, const int count,
const unsigned char *buf, const int start_page);
/* Probe for various non-shared-memory ethercards.
NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
buffer memory space. NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
the SAPROM, while other supposed NE2000 clones must be detected by their
SA prefix.
Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
mode results in doubled values, which can be detected and compensated for.
The probe is also responsible for initializing the card and filling
in the 'dev' and 'ei_status' structures.
We use the minimum memory size for some ethercard product lines, iff we can't
distinguish models. You can increase the packet buffer size by setting
PACKETBUF_MEMSIZE. Reported Cabletron packet buffer locations are:
E1010 starts at 0x100 and ends at 0x2000.
E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
E2010 starts at 0x100 and ends at 0x4000.
E2010-x starts at 0x100 and ends at 0xffff. */
int __init ne_probe(struct net_device *dev)
{
unsigned int base_addr = dev->base_addr;
SET_MODULE_OWNER(dev);
if (ei_debug > 2)
printk(KERN_DEBUG "ne_probe(): entered.\n");
/* If CONFIG_NET_CBUS,
we need dev->priv->reg_offset BEFORE to probe */
if (ne2k_cbus_init(dev) != 0)
return -ENOMEM;
/* First check any supplied i/o locations. User knows best. <cough> */
if (base_addr > 0) {
int result;
const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
if (ei_debug > 2)
printk(KERN_DEBUG "ne_probe(): call ne_probe_cbus(base_addr=0x%x)\n", base_addr);
result = ne_probe_cbus(dev, hw, base_addr);
if (result != 0)
ne2k_cbus_destroy(dev);
return result;
}
if (ei_debug > 2)
printk(KERN_DEBUG "ne_probe(): base_addr is not specified.\n");
#ifndef MODULE
/* Last resort. The semi-risky C-Bus auto-probe. */
if (ei_debug > 2)
printk(KERN_DEBUG "ne_probe(): auto-probe start.\n");
{
const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
if (hw && hw->hwtype) {
const unsigned short *plist;
for (plist = hw->portlist; *plist; plist++)
if (ne_probe_cbus(dev, hw, *plist) == 0)
return 0;
} else {
for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) {
const unsigned short *plist;
for (plist = hw->portlist; *plist; plist++)
if (ne_probe_cbus(dev, hw, *plist) == 0)
return 0;
}
}
}
#endif
ne2k_cbus_destroy(dev);
return -ENODEV;
}
static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr)
{
if (ei_debug > 2)
printk(KERN_DEBUG "ne_probe_cbus(): entered. (called from %p)\n",
__builtin_return_address(0));
if (hw && hw->hwtype) {
ne2k_cbus_set_hwtype(dev, hw, ioaddr);
return ne_probe1(dev, ioaddr);
} else {
/* auto detect */
printk(KERN_DEBUG "ne_probe_cbus(): try to determine hardware types.\n");
for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) {
ne2k_cbus_set_hwtype(dev, hw, ioaddr);
if (ne_probe1(dev, ioaddr) == 0)
return 0;
}
}
return -ENODEV;
}
static int __init ne_probe1(struct net_device *dev, int ioaddr)
{
int i;
unsigned char SA_prom[32];
int wordlength = 2;
const char *name = NULL;
int start_page, stop_page;
int neX000, bad_card;
int reg0, ret;
static unsigned version_printed;
const struct ne2k_cbus_region *rlist;
const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
struct ei_device *ei_local = (struct ei_device *)(dev->priv);
#ifdef CONFIG_NE2K_CBUS_CNET98EL
if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) {
outb_p(0, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE);
/* udelay(5000); */
outb_p(1, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE);
/* udelay(5000); */
outb_p((ioaddr & 0xf000) >> 8 | 0x08 | 0x01, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE + 2);
/* udelay(5000); */
}
#endif
for (rlist = hw->regionlist; rlist->range; rlist++)
if (!request_region(ioaddr + rlist->start,
rlist->range, dev->name)) {
ret = -EBUSY;
goto err_out;
}
reg0 = inb_p(ioaddr + EI_SHIFT(0));
if (reg0 == 0xFF) {
ret = -ENODEV;
goto err_out;
}
/* Do a preliminary verification that we have a 8390. */
#ifdef CONFIG_NE2K_CBUS_CNET98EL
if (hw->hwtype != NE2K_CBUS_HARDWARE_TYPE_CNET98EL)
#endif
{
int regd;
outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
regd = inb_p(ioaddr + EI_SHIFT(0x0d));
outb_p(0xff, ioaddr + EI_SHIFT(0x0d));
outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
outb_p(reg0, ioaddr);
outb_p(regd, ioaddr + EI_SHIFT(0x0d)); /* Restore the old values. */
ret = -ENODEV;
goto err_out;
}
}
if (ei_debug && version_printed++ == 0)
printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr);
/* A user with a poor card that fails to ack the reset, or that
does not have a valid 0x57,0x57 signature can still use this
without having to recompile. Specifying an i/o address along
with an otherwise unused dev->mem_end value of "0xBAD" will
cause the driver to skip these parts of the probe. */
bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
/* Reset card. Who knows what dain-bramaged state it was left in. */
{
unsigned long reset_start_time = jiffies;
/* derived from CNET98EL-patch for bad clones */
outb_p(E8390_NODMA | E8390_STOP, ioaddr + E8390_CMD);
/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
if (jiffies - reset_start_time > 2*HZ/100) {
if (bad_card) {
printk(" (warning: no reset ack)");
break;
} else {
printk(" not found (no reset ack).\n");
ret = -ENODEV;
goto err_out;
}
}
outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */
}
#ifdef CONFIG_NE2K_CBUS_CNET98EL
if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) {
static const char pat[32] ="AbcdeFghijKlmnoPqrstUvwxyZ789012";
char buf[32];
int maxwait = 200;
if (ei_debug > 2)
printk(" [CNET98EL-specific initialize...");
outb_p(E8390_NODMA | E8390_STOP, ioaddr + E8390_CMD); /* 0x20|0x1 */
i = inb(ioaddr);
if ((i & ~0x2) != (0x20 | 0x01))
return -ENODEV;
if ((inb(ioaddr + 0x7) & 0x80) != 0x80)
return -ENODEV;
outb_p(E8390_RXOFF, ioaddr + EN0_RXCR); /* out(ioaddr+0xc, 0x20) */
/* outb_p(ENDCFG_WTS|ENDCFG_FT1|ENDCFG_LS, ioaddr+EN0_DCFG); */
outb_p(ENDCFG_WTS | 0x48, ioaddr + EN0_DCFG); /* 0x49 */
outb_p(CNET98EL_START_PG, ioaddr + EN0_STARTPG);
outb_p(CNET98EL_STOP_PG, ioaddr + EN0_STOPPG);
if (ei_debug > 2)
printk("memory check");
for (i = 0; i < 65536; i += 1024) {
if (ei_debug > 2)
printk(" %04x", i);
ne2k_cbus_writemem(dev, ioaddr, i, pat, 32);
while (((inb(ioaddr + EN0_ISR) & ENISR_RDC) != ENISR_RDC) && --maxwait)
;
ne2k_cbus_readmem(dev, ioaddr, i, buf, 32);
if (memcmp(pat, buf, 32)) {
if (ei_debug > 2)
printk(" failed.");
break;
}
}
if (i != 16384) {
if (ei_debug > 2)
printk("] ");
printk("memory failure at %x\n", i);
return -ENODEV;
}
if (ei_debug > 2)
printk(" good...");
if (!dev->irq) {
if (ei_debug > 2)
printk("] ");
printk("IRQ must be specified for C-NET(98)E/L. probe failed.\n");
return -ENODEV;
}
outb((dev->irq > 5) ? (dev->irq & 4):(dev->irq >> 1), ioaddr + (0x2 | 0x400));
outb(0x7e, ioaddr + (0x4 | 0x400));
ne2k_cbus_readmem(dev, ioaddr, 16384, SA_prom, 32);
outb(0xff, ioaddr + EN0_ISR);
if (ei_debug > 2)
printk("done]");
} else
#endif /* CONFIG_NE2K_CBUS_CNET98EL */
/* Read the 16 bytes of station address PROM.
We must first initialize registers, similar to NS8390_init(eifdev, 0).
We can't reliably read the SAPROM address without this.
(I learned the hard way!). */
{
struct {unsigned char value; unsigned short offset;} program_seq[] =
{
{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
/* NEC PC-9800: some board can only handle word-wide access? */
{0x48 | ENDCFG_WTS, EN0_DCFG}, /* Set word-wide (0x48) access. */
{16384 / 256, EN0_STARTPG},
{32768 / 256, EN0_STOPPG},
{0x00, EN0_RCNTLO}, /* Clear the count regs. */
{0x00, EN0_RCNTHI},
{0x00, EN0_IMR}, /* Mask completion irq. */
{0xFF, EN0_ISR},
{E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
{E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
{32, EN0_RCNTLO},
{0x00, EN0_RCNTHI},
{0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
{0x00, EN0_RSARHI},
{E8390_RREAD+E8390_START, E8390_CMD},
};
for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
insw(ioaddr + NE_DATAPORT, SA_prom, 32 >> 1);
}
if (wordlength == 2)
{
for (i = 0; i < 16; i++)
SA_prom[i] = SA_prom[i+i];
start_page = NESM_START_PG;
stop_page = NESM_STOP_PG;
#ifdef CONFIG_NE2K_CBUS_CNET98EL
if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) {
start_page = CNET98EL_START_PG;
stop_page = CNET98EL_STOP_PG;
}
#endif
} else {
start_page = NE1SM_START_PG;
stop_page = NE1SM_STOP_PG;
}
neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
if (neX000) {
name = "C-Bus-NE2K-compat";
}
else
{
#ifdef SUPPORT_NE_BAD_CLONES
/* Ack! Well, there might be a *bad* NE*000 clone there.
Check for total bogus addresses. */
for (i = 0; bad_clone_list[i].name8; i++)
{
if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
SA_prom[2] == bad_clone_list[i].SAprefix[2])
{
if (wordlength == 2)
{
name = bad_clone_list[i].name16;
} else {
name = bad_clone_list[i].name8;
}
break;
}
}
if (bad_clone_list[i].name8 == NULL)
{
printk(" not found (invalid signature %2.2x %2.2x).\n",
SA_prom[14], SA_prom[15]);
ret = -ENXIO;
goto err_out;
}
#else
printk(" not found.\n");
ret = -ENXIO;
goto err_out;
#endif
}
if (dev->irq < 2)
{
unsigned long cookie = probe_irq_on();
outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */
outb_p(0x00, ioaddr + EN0_RCNTLO);
outb_p(0x00, ioaddr + EN0_RCNTHI);
outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
mdelay(10); /* wait 10ms for interrupt to propagate */
outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */
dev->irq = probe_irq_off(cookie);
if (ei_debug > 2)
printk(" autoirq is %d\n", dev->irq);
} else if (dev->irq == 7)
/* Fixup for users that don't know that IRQ 7 is really IRQ 11,
or don't know which one to set. */
dev->irq = 11;
if (! dev->irq) {
printk(" failed to detect IRQ line.\n");
ret = -EAGAIN;
goto err_out;
}
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev))
{
printk (" unable to get memory for dev->priv.\n");
ret = -ENOMEM;
goto err_out;
}
/* Snarf the interrupt now. There's no point in waiting since we cannot
share and the board will usually be enabled. */
ret = request_irq(dev->irq, ei_interrupt, 0, name, dev);
if (ret) {
printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
goto err_out_kfree;
}
dev->base_addr = ioaddr;
for(i = 0; i < ETHER_ADDR_LEN; i++) {
printk(" %2.2x", SA_prom[i]);
dev->dev_addr[i] = SA_prom[i];
}
printk("\n%s: %s found at %#x, hardware type %d(%s), using IRQ %d.\n",
dev->name, name, ioaddr, hw->hwtype, hw->hwident, dev->irq);
ei_status.name = name;
ei_status.tx_start_page = start_page;
ei_status.stop_page = stop_page;
ei_status.word16 = (wordlength == 2);
ei_status.rx_start_page = start_page + TX_PAGES;
#ifdef PACKETBUF_MEMSIZE
/* Allow the packet buffer size to be overridden by know-it-alls. */
ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
#endif
ei_status.reset_8390 = &ne_reset_8390;
ei_status.block_input = &ne_block_input;
ei_status.block_output = &ne_block_output;
ei_status.get_8390_hdr = &ne_get_8390_hdr;
ei_status.priv = 0;
dev->open = &ne_open;
dev->stop = &ne_close;
NS8390_init(dev, 0);
return 0;
err_out_kfree:
ne2k_cbus_destroy(dev);
err_out:
while (rlist > hw->regionlist) {
rlist --;
release_region(ioaddr + rlist->start, rlist->range);
}
return ret;
}
static int ne_open(struct net_device *dev)
{
ei_open(dev);
return 0;
}
static int ne_close(struct net_device *dev)
{
if (ei_debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
ei_close(dev);
return 0;
}
/* Hard reset the card. This used to pause for the same period that a
8390 reset command required, but that shouldn't be necessary. */
static void ne_reset_8390(struct net_device *dev)
{
unsigned long reset_start_time = jiffies;
struct ei_device *ei_local = (struct ei_device *)(dev->priv);
if (ei_debug > 1)
printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
/* derived from CNET98EL-patch for bad clones... */
outb_p(E8390_NODMA | E8390_STOP, NE_BASE + E8390_CMD); /* 0x20 | 0x1 */
/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
ei_status.txing = 0;
ei_status.dmaing = 0;
/* This check _should_not_ be necessary, omit eventually. */
while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
if (jiffies - reset_start_time > 2*HZ/100) {
printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
break;
}
outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
}
/* Grab the 8390 specific header. Similar to the block_input routine, but
we don't need to be concerned with ring wrap as the header will be at
the start of a page, so we optimize accordingly. */
static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{
int nic_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *)(dev->priv);
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing)
{
printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
"[DMAstat:%d][irqlock:%d].\n",
dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}
ei_status.dmaing |= 0x01;
outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
outb_p(0, nic_base + EN0_RCNTHI);
outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
outb_p(ring_page, nic_base + EN0_RSARHI);
outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
if (ei_status.word16)
insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
else
insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
ei_status.dmaing &= ~0x01;
le16_to_cpus(&hdr->count);
}
/* Block input and output, similar to the Crynwr packet driver. If you
are porting to a new ethercard, look at the packet driver source for hints.
The NEx000 doesn't share the on-board packet memory -- you have to put
the packet out through the "remote DMA" dataport using outb. */
static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
{
#ifdef NE_SANITY_CHECK
int xfer_count = count;
#endif
int nic_base = dev->base_addr;
char *buf = skb->data;
struct ei_device *ei_local = (struct ei_device *)(dev->priv);
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing)
{
printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
"[DMAstat:%d][irqlock:%d].\n",
dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}
ei_status.dmaing |= 0x01;
/* round up count to a word (derived from ICM-patch) */
count = (count + 1) & ~1;
outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
outb_p(count & 0xff, nic_base + EN0_RCNTLO);
outb_p(count >> 8, nic_base + EN0_RCNTHI);
outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
if (ei_status.word16)
{
insw(NE_BASE + NE_DATAPORT,buf,count>>1);
if (count & 0x01)
{
buf[count-1] = inb(NE_BASE + NE_DATAPORT);
#ifdef NE_SANITY_CHECK
xfer_count++;
#endif
}
} else {
insb(NE_BASE + NE_DATAPORT, buf, count);
}
#ifdef NE_SANITY_CHECK
/* This was for the ALPHA version only, but enough people have
been encountering problems so it is still here. If you see
this message you either 1) have a slightly incompatible clone
or 2) have noise/speed problems with your bus. */
if (ei_debug > 1)
{
/* DMA termination address check... */
int addr, tries = 20;
do {
/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
-- it's broken for Rx on some cards! */
int high = inb_p(nic_base + EN0_RSARHI);
int low = inb_p(nic_base + EN0_RSARLO);
addr = (high << 8) + low;
if (((ring_offset + xfer_count) & 0xff) == low)
break;
} while (--tries > 0);
if (tries <= 0)
printk(KERN_WARNING "%s: RX transfer address mismatch,"
"%#4.4x (expected) vs. %#4.4x (actual).\n",
dev->name, ring_offset + xfer_count, addr);
}
#endif
outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
ei_status.dmaing &= ~0x01;
}
static void ne_block_output(struct net_device *dev, int count,
const unsigned char *buf, const int start_page)
{
int nic_base = NE_BASE;
unsigned long dma_start;
#ifdef NE_SANITY_CHECK
int retries = 0;
#endif
struct ei_device *ei_local = (struct ei_device *)(dev->priv);
/* Round the count up for word writes. Do we need to do this?
What effect will an odd byte count have on the 8390?
I should check someday. */
if (ei_status.word16 && (count & 0x01))
count++;
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing)
{
printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
"[DMAstat:%d][irqlock:%d]\n",
dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}
ei_status.dmaing |= 0x01;
/* We should already be in page 0, but to be safe... */
outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
#ifdef NE_SANITY_CHECK
retry:
#endif
#ifdef NE8390_RW_BUGFIX
/* Handle the read-before-write bug the same way as the
Crynwr packet driver -- the NatSemi method doesn't work.
Actually this doesn't always work either, but if you have
problems with your NEx000 this is better than nothing! */
outb_p(0x42, nic_base + EN0_RCNTLO);
outb_p(0x00, nic_base + EN0_RCNTHI);
outb_p(0x42, nic_base + EN0_RSARLO);
outb_p(0x00, nic_base + EN0_RSARHI);
outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
/* Make certain that the dummy read has occurred. */
udelay(6);
#endif
outb_p(ENISR_RDC, nic_base + EN0_ISR);
/* Now the normal output. */
outb_p(count & 0xff, nic_base + EN0_RCNTLO);
outb_p(count >> 8, nic_base + EN0_RCNTHI);
outb_p(0x00, nic_base + EN0_RSARLO);
outb_p(start_page, nic_base + EN0_RSARHI);
outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
if (ei_status.word16) {
outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
} else {
outsb(NE_BASE + NE_DATAPORT, buf, count);
}
dma_start = jiffies;
#ifdef NE_SANITY_CHECK
/* This was for the ALPHA version only, but enough people have
been encountering problems so it is still here. */
if (ei_debug > 1)
{
/* DMA termination address check... */
int addr, tries = 20;
do {
int high = inb_p(nic_base + EN0_RSARHI);
int low = inb_p(nic_base + EN0_RSARLO);
addr = (high << 8) + low;
if ((start_page << 8) + count == addr)
break;
} while (--tries > 0);
if (tries <= 0)
{
printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
"%#4.4x (expected) vs. %#4.4x (actual).\n",
dev->name, (start_page << 8) + count, addr);
if (retries++ == 0)
goto retry;
}
}
#endif
while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
ne_reset_8390(dev);
NS8390_init(dev,1);
break;
}
outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
ei_status.dmaing &= ~0x01;
return;
}
#ifdef MODULE
#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
static struct net_device dev_ne[MAX_NE_CARDS];
static int io[MAX_NE_CARDS];
static int irq[MAX_NE_CARDS];
static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
static int hwtype[MAX_NE_CARDS] = { 0, }; /* board type */
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
MODULE_PARM(hwtype, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
MODULE_PARM_DESC(io, "I/O base address(es),required");
MODULE_PARM_DESC(irq, "IRQ number(s)");
MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
MODULE_PARM_DESC(hwtype, "Board type of PC-9800 C-Bus NIC");
MODULE_DESCRIPTION("NE1000/NE2000 PC-9800 C-bus Ethernet driver");
MODULE_LICENSE("GPL");
/* This is set up so that no ISA autoprobe takes place. We can't guarantee
that the ne2k probe is the last 8390 based probe to take place (as it
is at boot) and so the probe will get confused by any other 8390 cards.
ISA device autoprobes on a running machine are not recommended anyway. */
int init_module(void)
{
int this_dev, found = 0;
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
struct net_device *dev = &dev_ne[this_dev];
dev->irq = irq[this_dev];
dev->mem_end = bad[this_dev];
dev->base_addr = io[this_dev];
dev->mem_start = hwtype[this_dev];
dev->init = ne_probe;
if (register_netdev(dev) == 0) {
found++;
continue;
}
if (found != 0) { /* Got at least one. */
return 0;
}
if (io[this_dev] != 0)
printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
else
printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for C-Bus cards.\n");
return -ENXIO;
}
return 0;
}
void cleanup_module(void)
{
int this_dev;
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
struct net_device *dev = &dev_ne[this_dev];
if (dev->priv != NULL) {
const struct ne2k_cbus_region *rlist;
const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
free_irq(dev->irq, dev);
for (rlist = hw->regionlist; rlist->range; rlist++) {
release_region(dev->base_addr + rlist->start,
rlist->range);
}
unregister_netdev(dev);
ne2k_cbus_destroy(dev);
}
}
}
#endif /* MODULE */
/*
* Local variables:
* compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c ne.c"
* version-control: t
* kept-new-versions: 5
* End:
*/
/* ne2k_cbus.h:
vender-specific information definition for NEC PC-9800
C-bus Ethernet Cards
Used in ne.c
(C)1998,1999 KITAGWA Takurou & Linux/98 project
*/
#include <linux/config.h>
#undef NE_RESET
#define NE_RESET EI_SHIFT(0x11) /* Issue a read to reset, a write to clear. */
#ifdef CONFIG_NE2K_CBUS_CNET98EL
#ifndef CONFIG_NE2K_CBUS_CNET98EL_IO_BASE
#warning CONFIG_NE2K_CBUS_CNET98EL_IO_BASE is not defined(config error?)
#warning use 0xaaed as default
#define CONFIG_NE2K_CBUS_CNET98EL_IO_BASE 0xaaed /* or 0x55ed */
#endif
#define CNET98EL_START_PG 0x00
#define CNET98EL_STOP_PG 0x40
#endif
/* Hardware type definition (derived from *BSD) */
#define NE2K_CBUS_HARDWARE_TYPE_MASK 0xff
/* 0: reserved for auto-detect */
/* 1: (not tested)
Allied Telesis CentreCom LA-98-T */
#define NE2K_CBUS_HARDWARE_TYPE_ATLA98 1
/* 2: (not tested)
ELECOM Laneed
LD-BDN[123]A
PLANET SMART COM 98 EN-2298-C
MACNICA ME98 */
#define NE2K_CBUS_HARDWARE_TYPE_BDN 2
/* 3:
Melco EGY-98
Contec C-NET(98)E*A/L*A,C-NET(98)P */
#define NE2K_CBUS_HARDWARE_TYPE_EGY98 3
/* 4:
Melco LGY-98,IND-SP,IND-SS
MACNICA NE2098 */
#define NE2K_CBUS_HARDWARE_TYPE_LGY98 4
/* 5:
ICM DT-ET-25,DT-ET-T5,IF-2766ET,IF-2771ET
PLANET SMART COM 98 EN-2298-T,EN-2298P-T
D-Link DE-298PT,DE-298PCAT
ELECOM Laneed LD-98P */
#define NE2K_CBUS_HARDWARE_TYPE_ICM 5
/* 6: (reserved for SIC-98, which is not supported in this driver.) */
/* 7: (unused in *BSD?)
<Original NE2000 compatible>
<for PCI/PCMCIA cards>
*/
#define NE2K_CBUS_HARDWARE_TYPE_NE2K 7
/* 8:
NEC PC-9801-108 */
#define NE2K_CBUS_HARDWARE_TYPE_NEC108 8
/* 9:
I-O DATA LA-98,LA/T-98 */
#define NE2K_CBUS_HARDWARE_TYPE_IOLA98 9
/* 10: (reserved for C-NET(98), which is not supported in this driver.) */
/* 11:
Contec C-NET(98)E,L */
#define NE2K_CBUS_HARDWARE_TYPE_CNET98EL 11
#define NE2K_CBUS_HARDWARE_TYPE_MAX 11
/* HARDWARE TYPE ID 12-31: reserved */
struct ne2k_cbus_offsetinfo {
unsigned short skip;
unsigned short offset8; /* +0x8 - +0xf */
unsigned short offset10; /* +0x10 */
unsigned short offset1f; /* +0x1f */
};
struct ne2k_cbus_region {
unsigned short start;
short range;
};
struct ne2k_cbus_hwinfo {
const unsigned short hwtype;
const unsigned char *hwident;
#ifndef MODULE
const unsigned short *portlist;
#endif
const struct ne2k_cbus_offsetinfo *offsetinfo;
const struct ne2k_cbus_region *regionlist;
};
#ifdef CONFIG_NE2K_CBUS_ATLA98
#ifndef MODULE
static unsigned short atla98_portlist[] __initdata = {
0xd0,
0
};
#endif
#define atla98_offsetinfo ne2k_offsetinfo
#define atla98_regionlist ne2k_regionlist
#endif /* CONFIG_NE2K_CBUS_ATLA98 */
#ifdef CONFIG_NE2K_CBUS_BDN
#ifndef MODULE
static unsigned short bdn_portlist[] __initdata = {
0xd0,
0
};
#endif
static struct ne2k_cbus_offsetinfo bdn_offsetinfo __initdata = {
#if 0
/* comes from FreeBSD(98) ed98.h */
0x1000, 0x8000, 0x100, 0xc200 /* ??? */
#else
/* comes from NetBSD/pc98 if_ne_isa.c */
0x1000, 0x8000, 0x100, 0x7f00 /* ??? */
#endif
};
static struct ne2k_cbus_region bdn_regionlist[] __initdata = {
{0x0, 1}, {0x1000, 1}, {0x2000, 1}, {0x3000,1},
{0x4000, 1}, {0x5000, 1}, {0x6000, 1}, {0x7000, 1},
{0x8000, 1}, {0x9000, 1}, {0xa000, 1}, {0xb000, 1},
{0xc000, 1}, {0xd000, 1}, {0xe000, 1}, {0xf000, 1},
{0x100, 1}, {0x7f00, 1},
{0x0, 0}
};
#endif /* CONFIG_NE2K_CBUS_BDN */
#ifdef CONFIG_NE2K_CBUS_EGY98
#ifndef MODULE
static unsigned short egy98_portlist[] __initdata = {
0xd0,
0
};
#endif
static struct ne2k_cbus_offsetinfo egy98_offsetinfo __initdata = {
0x02, 0x100, 0x200, 0x300
};
static struct ne2k_cbus_region egy98_regionlist[] __initdata = {
{0x0, 1}, {0x2, 1}, {0x4, 1}, {0x6, 1},
{0x8, 1}, {0xa, 1}, {0xc, 1}, {0xe, 1},
{0x100, 1}, {0x102, 1}, {0x104, 1}, {0x106, 1},
{0x108, 1}, {0x10a, 1}, {0x10c, 1}, {0x10e, 1},
{0x200, 1}, {0x300, 1},
{0x0, 0}
};
#endif /* CONFIG_NE2K_CBUS_EGY98 */
#ifdef CONFIG_NE2K_CBUS_LGY98
#ifndef MODULE
static unsigned short lgy98_portlist[] __initdata = {
0xd0, 0x10d0, 0x20d0, 0x30d0, 0x40d0, 0x50d0, 0x60d0, 0x70d0,
0
};
#endif
static struct ne2k_cbus_offsetinfo lgy98_offsetinfo __initdata = {
0x01, 0x08, 0x200, 0x300
};
static struct ne2k_cbus_region lgy98_regionlist[] __initdata = {
{0x0, 16}, {0x200, 1}, {0x300, 1},
{0x0, 0}
};
#endif /* CONFIG_NE2K_CBUS_LGY98 */
#ifdef CONFIG_NE2K_CBUS_ICM
#ifndef MODULE
static unsigned short icm_portlist[] __initdata = {
/* ICM */
0x56d0,
/* LD-98PT */
0x46d0, 0x66d0, 0x76d0, 0x86d0, 0x96d0, 0xa6d0, 0xb6d0, 0xc6d0,
0
};
#endif
static struct ne2k_cbus_offsetinfo icm_offsetinfo __initdata = {
0x01, 0x08, 0x100, 0x10f
};
static struct ne2k_cbus_region icm_regionlist[] __initdata = {
{0x0, 16}, {0x100, 16},
{0x0, 0}
};
#endif /* CONFIG_NE2K_CBUS_ICM */
#if defined(CONFIG_NE2K_CBUS_NE2K) && !defined(MODULE)
static unsigned short ne2k_portlist[] __initdata = {
0xd0, 0x300, 0x280, 0x320, 0x340, 0x360, 0x380,
0
};
#endif
#if defined(CONFIG_NE2K_CBUS_NE2K) || defined(CONFIG_NE2K_CBUS_ATLA98)
static struct ne2k_cbus_offsetinfo ne2k_offsetinfo __initdata = {
0x01, 0x08, 0x10, 0x1f
};
static struct ne2k_cbus_region ne2k_regionlist[] __initdata = {
{0x0, 32},
{0x0, 0}
};
#endif
#ifdef CONFIG_NE2K_CBUS_NEC108
#ifndef MODULE
static unsigned short nec108_portlist[] __initdata = {
0x770, 0x2770, 0x4770, 0x6770,
0
};
#endif
static struct ne2k_cbus_offsetinfo nec108_offsetinfo __initdata = {
0x02, 0x1000, 0x888, 0x88a
};
static struct ne2k_cbus_region nec108_regionlist[] __initdata = {
{0x0, 1}, {0x2, 1}, {0x4, 1}, {0x6, 1},
{0x8, 1}, {0xa, 1}, {0xc, 1}, {0xe, 1},
{0x1000, 1}, {0x1002, 1}, {0x1004, 1}, {0x1006, 1},
{0x1008, 1}, {0x100a, 1}, {0x100c, 1}, {0x100e, 1},
{0x888, 1}, {0x88a, 1}, {0x88c, 1}, {0x88e, 1},
{0x0, 0}
};
#endif
#ifdef CONFIG_NE2K_CBUS_IOLA98
#ifndef MODULE
static unsigned short iola98_portlist[] __initdata = {
0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
0
};
#endif
static struct ne2k_cbus_offsetinfo iola98_offsetinfo __initdata = {
0x1000, 0x8000, 0x100, 0xf100
};
static struct ne2k_cbus_region iola98_regionlist[] __initdata = {
{0x0, 1}, {0x1000, 1}, {0x2000, 1}, {0x3000, 1},
{0x4000, 1}, {0x5000, 1}, {0x6000, 1}, {0x7000, 1},
{0x8000, 1}, {0x9000, 1}, {0xa000, 1}, {0xb000, 1},
{0xc000, 1}, {0xd000, 1}, {0xe000, 1}, {0xf000, 1},
{0x100, 1}, {0xf100, 1},
{0x0,0}
};
#endif /* CONFIG_NE2K_CBUS_IOLA98 */
#ifdef CONFIG_NE2K_CBUS_CNET98EL
#ifndef MODULE
static unsigned short cnet98el_portlist[] __initdata = {
0x3d0, 0x13d0, 0x23d0, 0x33d0, 0x43d0, 0x53d0, 0x60d0, 0x70d0,
0
};
#endif
static struct ne2k_cbus_offsetinfo cnet98el_offsetinfo __initdata = {
0x01, 0x08, 0x40e, 0x400
};
static struct ne2k_cbus_region cnet98el_regionlist[] __initdata = {
{0x0, 16}, {0x400, 16},
{0x0, 0}
};
#endif
/* port information table (for ne.c initialize/probe process) */
static struct ne2k_cbus_hwinfo ne2k_cbus_hwinfo_list[] __initdata = {
#ifdef CONFIG_NE2K_CBUS_ATLA98
/* NOT TESTED */
{
NE2K_CBUS_HARDWARE_TYPE_ATLA98,
"LA-98-T",
#ifndef MODULE
atla98_portlist,
#endif
&atla98_offsetinfo, atla98_regionlist
},
#endif
#ifdef CONFIG_NE2K_CBUS_BDN
/* NOT TESTED */
{
NE2K_CBUS_HARDWARE_TYPE_BDN,
"LD-BDN[123]A",
#ifndef MODULE
bdn_portlist,
#endif
&bdn_offsetinfo, bdn_regionlist
},
#endif
#ifdef CONFIG_NE2K_CBUS_ICM
{
NE2K_CBUS_HARDWARE_TYPE_ICM,
"IF-27xxET",
#ifndef MODULE
icm_portlist,
#endif
&icm_offsetinfo, icm_regionlist
},
#endif
#ifdef CONFIG_NE2K_CBUS_NE2K
{
NE2K_CBUS_HARDWARE_TYPE_NE2K,
"NE2000 compat.",
#ifndef MODULE
ne2k_portlist,
#endif
&ne2k_offsetinfo, ne2k_regionlist
},
#endif
#ifdef CONFIG_NE2K_CBUS_NEC108
{
NE2K_CBUS_HARDWARE_TYPE_NEC108,
"PC-9801-108",
#ifndef MODULE
nec108_portlist,
#endif
&nec108_offsetinfo, nec108_regionlist
},
#endif
#ifdef CONFIG_NE2K_CBUS_IOLA98
{
NE2K_CBUS_HARDWARE_TYPE_IOLA98,
"LA-98",
#ifndef MODULE
iola98_portlist,
#endif
&iola98_offsetinfo, iola98_regionlist
},
#endif
#ifdef CONFIG_NE2K_CBUS_CNET98EL
{
NE2K_CBUS_HARDWARE_TYPE_CNET98EL,
"C-NET(98)E/L",
#ifndef MODULE
cnet98el_portlist,
#endif
&cnet98el_offsetinfo, cnet98el_regionlist
},
#endif
/* NOTE: LGY98 must be probed before EGY98, or system stalled!? */
#ifdef CONFIG_NE2K_CBUS_LGY98
{
NE2K_CBUS_HARDWARE_TYPE_LGY98,
"LGY-98",
#ifndef MODULE
lgy98_portlist,
#endif
&lgy98_offsetinfo, lgy98_regionlist
},
#endif
#ifdef CONFIG_NE2K_CBUS_EGY98
{
NE2K_CBUS_HARDWARE_TYPE_EGY98,
"EGY-98",
#ifndef MODULE
egy98_portlist,
#endif
&egy98_offsetinfo, egy98_regionlist
},
#endif
{
0,
"unsupported hardware",
#ifndef MODULE
NULL,
#endif
NULL, NULL
}
};
static int __init ne2k_cbus_init(struct net_device *dev)
{
struct ei_device *ei_local;
if (dev->priv == NULL) {
ei_local = kmalloc(sizeof(struct ei_device), GFP_KERNEL);
if (ei_local == NULL)
return -ENOMEM;
memset(ei_local, 0, sizeof(struct ei_device));
ei_local->reg_offset = kmalloc(sizeof(typeof(*ei_local->reg_offset))*18, GFP_KERNEL);
if (ei_local->reg_offset == NULL) {
kfree(ei_local);
return -ENOMEM;
}
spin_lock_init(&ei_local->page_lock);
dev->priv = ei_local;
}
return 0;
}
static void ne2k_cbus_destroy(struct net_device *dev)
{
struct ei_device *ei_local = (struct ei_device *)(dev->priv);
if (ei_local != NULL) {
if (ei_local->reg_offset)
kfree(ei_local->reg_offset);
kfree(dev->priv);
dev->priv = NULL;
}
}
static const struct ne2k_cbus_hwinfo * __init ne2k_cbus_get_hwinfo(int hwtype)
{
const struct ne2k_cbus_hwinfo *hw;
for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) {
if (hw->hwtype == hwtype) break;
}
return hw;
}
static void __init ne2k_cbus_set_hwtype(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr)
{
struct ei_device *ei_local = (struct ei_device *)(dev->priv);
int i;
int hwtype_old = dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK;
if (!ei_local)
panic("Gieee! ei_local == NULL!! (from %p)",
__builtin_return_address(0));
dev->mem_start &= ~NE2K_CBUS_HARDWARE_TYPE_MASK;
dev->mem_start |= hw->hwtype & NE2K_CBUS_HARDWARE_TYPE_MASK;
if (ei_debug > 2) {
printk(KERN_DEBUG "hwtype changed: %d -> %d\n",hwtype_old,(int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
}
if (hw->offsetinfo) {
for (i = 0; i < 8; i++) {
ei_local->reg_offset[i] = hw->offsetinfo->skip * i;
}
for (i = 8; i < 16; i++) {
ei_local->reg_offset[i] =
hw->offsetinfo->skip*(i-8) + hw->offsetinfo->offset8;
}
#ifdef CONFIG_NE2K_CBUS_NEC108
if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_NEC108) {
int adj = (ioaddr & 0xf000) /2;
ei_local->reg_offset[16] =
(hw->offsetinfo->offset10 | adj) - ioaddr;
ei_local->reg_offset[17] =
(hw->offsetinfo->offset1f | adj) - ioaddr;
} else {
#endif /* CONFIG_NE2K_CBUS_NEC108 */
ei_local->reg_offset[16] = hw->offsetinfo->offset10;
ei_local->reg_offset[17] = hw->offsetinfo->offset1f;
#ifdef CONFIG_NE2K_CBUS_NEC108
}
#endif
} else {
/* make dummmy offset list */
for (i = 0; i < 16; i++) {
ei_local->reg_offset[i] = i;
}
ei_local->reg_offset[16] = 0x10;
ei_local->reg_offset[17] = 0x1f;
}
}
#if defined(CONFIG_NE2K_CBUS_ICM) || defined(CONFIG_NE2K_CBUS_CNET98EL)
static void __init ne2k_cbus_readmem(struct net_device *dev, int ioaddr, unsigned short memaddr, char *buf, unsigned short len)
{
struct ei_device *ei_local = (struct ei_device *)(dev->priv);
outb_p(E8390_NODMA | E8390_START, ioaddr+E8390_CMD);
outb_p(len & 0xff, ioaddr+EN0_RCNTLO);
outb_p(len >> 8, ioaddr+EN0_RCNTHI);
outb_p(memaddr & 0xff, ioaddr+EN0_RSARLO);
outb_p(memaddr >> 8, ioaddr+EN0_RSARHI);
outb_p(E8390_RREAD | E8390_START, ioaddr+E8390_CMD);
insw(ioaddr+NE_DATAPORT, buf, len >> 1);
}
static void __init ne2k_cbus_writemem(struct net_device *dev, int ioaddr, unsigned short memaddr, const char *buf, unsigned short len)
{
struct ei_device *ei_local = (struct ei_device *)(dev->priv);
outb_p(E8390_NODMA | E8390_START, ioaddr+E8390_CMD);
outb_p(ENISR_RDC, ioaddr+EN0_ISR);
outb_p(len & 0xff, ioaddr+EN0_RCNTLO);
outb_p(len >> 8, ioaddr+EN0_RCNTHI);
outb_p(memaddr & 0xff, ioaddr+EN0_RSARLO);
outb_p(memaddr >> 8, ioaddr+EN0_RSARHI);
outb_p(E8390_RWRITE | E8390_START, ioaddr+E8390_CMD);
outsw(ioaddr+NE_DATAPORT, buf, len >> 1);
}
#endif
static int ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr);
/* End of ne2k_cbus.h */
...@@ -55,8 +55,8 @@ ...@@ -55,8 +55,8 @@
#define DRV_MODULE_NAME "tg3" #define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "1.4c" #define DRV_MODULE_VERSION "1.5"
#define DRV_MODULE_RELDATE "Feb 18, 2003" #define DRV_MODULE_RELDATE "March 21, 2003"
#define TG3_DEF_MAC_MODE 0 #define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0 #define TG3_DEF_RX_MODE 0
...@@ -6581,11 +6581,11 @@ static int __devinit tg3_test_dma(struct tg3 *tp) ...@@ -6581,11 +6581,11 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
ret = 0;
if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
return 0; goto out;
ret = 0;
while (1) { while (1) {
u32 *p, i; u32 *p, i;
......
...@@ -371,6 +371,10 @@ struct tss_struct { ...@@ -371,6 +371,10 @@ struct tss_struct {
* pads the TSS to be cacheline-aligned (size is 0x100) * pads the TSS to be cacheline-aligned (size is 0x100)
*/ */
unsigned long __cacheline_filler[5]; unsigned long __cacheline_filler[5];
/*
* .. and then another 0x100 bytes for emergency kernel stack
*/
unsigned long stack[64];
}; };
struct thread_struct { struct thread_struct {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment