Warning!

Notice: the grml team is migrating from Mercurial to Git.
Please visit git.grml.org instead!

Add README, patches from gentoo, debian, renames,...
authorMichael Prokop <mika@grml.org>
Sat Oct 13 11:57:46 2007 +0200 (13 months ago)
changeset 6073e329a784c4
manifest73e329a784c4
parent 591a0502ab515f
child 61890461c51fd4
Add README, patches from gentoo, debian, renames,...

Notice: uvesafb/fbcondecor needs heavy testing....
2.6.23/0000_README
2.6.23/2405_hostap-netdev-type.patch
2.6.23/2525_usb-storage-nikon-d200-quirk.patch
2.6.23/4000_ipw2200-1.1.4-inject.patch
2.6.23/4010_e1000e-20070806.patch
2.6.23/4011_e1000e-fixes.patch
2.6.23/4020_v7-iwlwifi-add-iwlwifi-wireless-drivers.patch
2.6.23/4030_sierra_umts_MC8775.diff
2.6.23/4105_dm-bbr.patch
2.6.23/4200_fbcondecor-0.9.4-2.6.23-rc7.patch
2.6.23/4200_ipw2200-1.1.4-inject.patch
2.6.23/4205_uvesafb-0.1-rc3-2.6.23-rc3.patch
2.6.23/4220_sierra_umts_MC8775.diff
2.6.23/4300_squashfs-3.2-r2.patch
2.6.23/4301_squashfs-fix-for-2.6.23.patch
2.6.23/4310_e1000e-20070806.patch
2.6.23/4310_fs-asfs.patch
2.6.23/4311_e1000e-fixes.patch
2.6.23/4320_fs-asfs.patch
2.6.23/4320_v7-iwlwifi-add-iwlwifi-wireless-drivers.patch
2.6.23/amd64/5000_grml-kernelversion.patch
2.6.23/amd64/5002_grml-kernelversion.patch
2.6.23/x86/5000_grml-kernelversion.patch
2.6.23/x86/5002_grml-kernelversion.patch
--- a/2.6.23/4300_squashfs-3.2-r2.patch Sat Oct 13 11:17:55 2007 +0200
+++ b/2.6.23/4300_squashfs-3.2-r2.patch Sat Oct 13 11:57:46 2007 +0200
@@ -13,7 +13,7 @@
--- a/fs/Kconfig
+++ b/fs/Kconfig
-@@ -1367,6 +1367,71 @@ config CRAMFS
+@@ -1364,6 +1364,71 @@ config CRAMFS
If unsure, say N.
@@ -107,7 +107,7 @@
+squashfs-y += squashfs2_0.o
--- /dev/null
+++ b/fs/squashfs/inode.c
-@@ -0,0 +1,2327 @@
+@@ -0,0 +1,2329 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
@@ -134,6 +134,7 @@
+#include <linux/squashfs_fs.h>
+#include <linux/module.h>
+#include <linux/zlib.h>
++#include <linux/exportfs.h>
+#include <linux/fs.h>
+#include <linux/squashfs_fs_sb.h>
+#include <linux/squashfs_fs_i.h>
@@ -141,6 +142,7 @@
+#include <linux/vfs.h>
+#include <linux/vmalloc.h>
+#include <linux/smp_lock.h>
++#include <linux/sched.h>
+
+#include "squashfs.h"
+
@@ -2417,7 +2419,7 @@
+ squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
+ sizeof(struct squashfs_inode_info),
+ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
-+ init_once, NULL);
++ init_once);
+ if (squashfs_inode_cachep == NULL)
+ return -ENOMEM;
+ return 0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/2.6.23/0000_README Sat Oct 13 11:57:46 2007 +0200
@@ -0,0 +1,106 @@
+--------------------------------------------------------------------------
+Latest change: Sam Okt 13 11:56:39 CEST 2007 [mika]
+--------------------------------------------------------------------------
+
+README
+--------------------------------------------------------------------------
+This patchset is for the latest linux kernel provided by grml.org.
+It is based on genpatches, ubuntu-2.6.git, debian patches and work by the
+grml-team.
+
+Patchset Numbering Scheme
+--------------------------------------------------------------------------
+
+FIXES
+1000-1400 linux-stable
+1400-1500 linux-stable queue
+1500-1700 security
+1700-1800 architecture-related
+1800-1900 mm/scheduling/misc
+1900-2000 filesystems
+2000-2100 networking core
+2100-2200 storage core
+2200-2300 power management (ACPI, APM)
+2300-2400 bus (USB, IEEE1394, PCI, PCMCIA, ...)
+2400-2500 network drivers
+2500-2600 storage drivers
+2600-2700 input
+2700-2900 media (graphics, sound, tv)
+2900-3000 other
+3000-4000 reserved
+
+FEATURES
+4000-4100 network
+4100-4200 storage
+4200-4300 graphics
+4300-4400 filesystem
+4400-4500 other
+
+GRML
+5000-5100 grml-specific
+
+
+Individual Patch Descriptions:
+--------------------------------------------------------------------------
+
+Patch: 2405_hostap-netdev-type.patch
+From: http://dev.gentoo.org/~dsd/genpatches/trunk/2.6.23/
+Desc: Fix hostap AP interface type to prevent udev confusion
+
+Patch: 2525_usb-storage-nikon-d200-quirk.patch
+From: http://dev.gentoo.org/~dsd/genpatches/trunk/2.6.23/
+Desc: usb-storage capacity quirk for Nikon D200 camera
+
+Patch: 4000_ipw2200-1.1.4-inject.patch
+From: /usr/share/doc/aircrack-ng/injection-patches/ipw2200-1.1.4-inject.patch
+Desc: injection patch for ipw2200 driver
+
+Patch: 4010_e1000e-20070806.patch
+From: svn://svn.debian.org/kernel/dists/trunk/linux-2.6/debian/patches/features/all
+Desc: Support for new ICH9 intel boards (E1000E)
+
+Patch: 4011_e1000e-fixes.patch
+From: svn://svn.debian.org/kernel/dists/trunk/linux-2.6/debian/patches/features/all
+Desc: e1000e: Remove unused or empty labels
+
+Patch: 4020_v7-iwlwifi-add-iwlwifi-wireless-drivers.patch
+From: svn://svn.debian.org/kernel/dists/trunk/linux-2.6/debian/patches/features/all
+Desc: Support for iwlwifi
+
+Patch: 4030_sierra_umts_MC8775.diff
+From: http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-gutsy.git;a=commit;h=6a7024949b3c26ce3027995218159d49b151ff67
+Desc: Enable Sierra Wireless MC8775 0x6813
+
+Patch: 4105_dm-bbr.patch
+From: EVMS 2.5.2
+Desc: Bad block relocation support for LiveCD users
+
+Patch: 4200_fbcondecor-0.9.4-2.6.23-rc7.patch
+From: http://dev.gentoo.org/~spock
+Desc: Bootsplash successor by Michal Januszewski
+
+Patch: 4205_uvesafb-0.1-rc3-2.6.23-rc3.patch
+From: http://dev.gentoo.org/~spock/projects/uvesafb/
+Desc: Successor of vesafb-tng
+
+Patch: 4210_cx88-cinergy-1400-support.patch
+From: http://www2.kernel.org/git/?p=linux%2Fkernel%2Fgit%2Fmchehab%2Fv4l-dvb.git;a=commitdiff_plain;h=6c12898641b46dc3f84ecc61eb1e532f12bff018
+Desc: Cx88: Add support for svideo/composite input of the Terratec Cinergy 1400 DVB-T
+
+Patch: 4300_squashfs-3.2-r2.patch
+From: http://squashfs.sourceforge.net/
+Desc: driver to support squashfs filesystems.
+
+Patch: 4310_fs-asfs.patch
+From: http://svn.debian.org/wsvn/kernel/dists/trunk/linux-2.6/debian/patches/
+Desc: support for the Amiga SmartFileSystem
+
+Patch: 5000_grml-version.patch
+From: http://hg.grml.org/grml-kernel/
+Desc: adjust kernel version for the grml-system (add -grml)
+
+Patch: 5001_grml_logo.patch
+From: http://dufo.tugraz.at/~prokop/grml-kernel/
+Desc: grml-logo in framebuffer
+
+##############################################################################################
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/2.6.23/2405_hostap-netdev-type.patch Sat Oct 13 11:57:46 2007 +0200
@@ -0,0 +1,106 @@
+From: Daniel Drake <dsd@gentoo.org>
+Date: Wed, 26 Sep 2007 20:45:24 +0000 (+0100)
+Subject: [PATCH] hostap: set netdev type before registering AP interface
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Flinville%2Fwireless-2.6.git;a=commitdiff_plain;h=d4a248f175f60fa278d792727ca11b6376f2d4e5
+
+[PATCH] hostap: set netdev type before registering AP interface
+
+As detailed at https://bugs.gentoo.org/159646 hostap with hostapd confuses
+udev by presenting 2 interfaces with the same MAC address. Also, at the time
+of detection, the 'type' attribute is 1, identical to other hostap interfaces.
+
+The AP interface is supposed to have type ARPHRD_IEEE80211 (801), but this is
+not set until after registration.
+
+Setting it before register_netdev() is called allows us to avoid this
+confusion. We can do this by propogating the HOSTAP_INTERFACE type through
+to hostap_setup_dev().
+
+Signed-off-by: Daniel Drake <dsd@gentoo.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+---
+
+Index: linux-2.6.23-gentoo/drivers/net/wireless/hostap/hostap.h
+===================================================================
+--- linux-2.6.23-gentoo.orig/drivers/net/wireless/hostap/hostap.h
++++ linux-2.6.23-gentoo/drivers/net/wireless/hostap/hostap.h
+@@ -35,7 +35,7 @@ int hostap_80211_prism_header_parse(stru
+ int hostap_80211_get_hdrlen(u16 fc);
+ struct net_device_stats *hostap_get_stats(struct net_device *dev);
+ void hostap_setup_dev(struct net_device *dev, local_info_t *local,
+- int main_dev);
++ int type);
+ void hostap_set_multicast_list_queue(struct work_struct *work);
+ int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked);
+ int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked);
+Index: linux-2.6.23-gentoo/drivers/net/wireless/hostap/hostap_hw.c
+===================================================================
+--- linux-2.6.23-gentoo.orig/drivers/net/wireless/hostap/hostap_hw.c
++++ linux-2.6.23-gentoo/drivers/net/wireless/hostap/hostap_hw.c
+@@ -3254,7 +3254,7 @@ while (0)
+
+ INIT_LIST_HEAD(&local->bss_list);
+
+- hostap_setup_dev(dev, local, 1);
++ hostap_setup_dev(dev, local, HOSTAP_INTERFACE_MASTER);
+ local->saved_eth_header_parse = dev->hard_header_parse;
+
+ dev->hard_start_xmit = hostap_master_start_xmit;
+Index: linux-2.6.23-gentoo/drivers/net/wireless/hostap/hostap_main.c
+===================================================================
+--- linux-2.6.23-gentoo.orig/drivers/net/wireless/hostap/hostap_main.c
++++ linux-2.6.23-gentoo/drivers/net/wireless/hostap/hostap_main.c
+@@ -72,7 +72,7 @@ struct net_device * hostap_add_interface
+ dev->mem_start = mdev->mem_start;
+ dev->mem_end = mdev->mem_end;
+
+- hostap_setup_dev(dev, local, 0);
++ hostap_setup_dev(dev, local, type);
+ dev->destructor = free_netdev;
+
+ sprintf(dev->name, "%s%s", prefix, name);
+@@ -838,7 +838,7 @@ static void prism2_tx_timeout(struct net
+
+
+ void hostap_setup_dev(struct net_device *dev, local_info_t *local,
+- int main_dev)
++ int type)
+ {
+ struct hostap_interface *iface;
+
+@@ -858,15 +858,22 @@ void hostap_setup_dev(struct net_device
+ dev->do_ioctl = hostap_ioctl;
+ dev->open = prism2_open;
+ dev->stop = prism2_close;
+- dev->hard_start_xmit = hostap_data_start_xmit;
+ dev->set_mac_address = prism2_set_mac_address;
+ dev->set_multicast_list = hostap_set_multicast_list;
+ dev->change_mtu = prism2_change_mtu;
+ dev->tx_timeout = prism2_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
++ if (type == HOSTAP_INTERFACE_AP) {
++ dev->hard_start_xmit = hostap_mgmt_start_xmit;
++ dev->type = ARPHRD_IEEE80211;
++ dev->hard_header_parse = hostap_80211_header_parse;
++ } else {
++ dev->hard_start_xmit = hostap_data_start_xmit;
++ }
++
+ dev->mtu = local->mtu;
+- if (!main_dev) {
++ if (type != HOSTAP_INTERFACE_MASTER) {
+ /* use main radio device queue */
+ dev->tx_queue_len = 0;
+ }
+@@ -892,10 +899,6 @@ static int hostap_enable_hostapd(local_i
+ if (local->apdev == NULL)
+ return -ENOMEM;
+
+- local->apdev->hard_start_xmit = hostap_mgmt_start_xmit;
+- local->apdev->type = ARPHRD_IEEE80211;
+- local->apdev->hard_header_parse = hostap_80211_header_parse;
+-
+ return 0;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/2.6.23/2525_usb-storage-nikon-d200-quirk.patch Sat Oct 13 11:57:46 2007 +0200
@@ -0,0 +1,36 @@
+From phil@ipom.com Sat Sep 22 20:58:28 2007
+From: Phil Dibowitz <phil@ipom.com>
+Date: Sat, 22 Sep 2007 20:58:12 -0700
+Subject: USB: unusual_devs modification for Nikon D200
+To: Mike <mpagano-kernel@mpagano.com>
+Cc: stern@rowland.harvard.edu, linux-usb-devel@lists.sourceforge.net, Greg KH <greg@kroah.com>
+Message-ID: <46F5E454.40903@ipom.com>
+
+
+Upgrade the unusual_devs.h file to support the Nikon D200
+
+Signed-off-by: Mike Pagano <mpagano-kernel@mpagano.com>
+Signed-off-by: Phil Dibowitz <phil@ipom.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/storage/unusual_devs.h | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -341,6 +341,13 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
++/* Reported by Graber and Mike Pagano <mpagano-kernel@mpagano.com> */
++UNUSUAL_DEV( 0x04b0, 0x040f, 0x0200, 0x0200,
++ "NIKON",
++ "NIKON DSC D200",
++ US_SC_DEVICE, US_PR_DEVICE, NULL,
++ US_FL_FIX_CAPACITY),
++
+ /* Reported by Emil Larsson <emil@swip.net> */
+ UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101,
+ "NIKON",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/2.6.23/4000_ipw2200-1.1.4-inject.patch Sat Oct 13 11:57:46 2007 +0200
@@ -0,0 +1,77 @@
+--- a/drivers/net/wireless/ipw2200.c 2007-02-04 19:44:54.000000000 +0100
++++ b/drivers/net/wireless/ipw2200.c 2007-05-03 19:01:14.272961391 +0200
+@@ -1847,6 +1847,66 @@
+ static DEVICE_ATTR(net_stats, S_IWUSR | S_IRUGO,
+ show_net_stats, store_net_stats);
+
++static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, int pri);
++
++/* SYSFS INJECT */
++static ssize_t store_inject(struct device *d,
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12)
++ struct device_attribute *attr,
++#endif
++ const char *buf, size_t count)
++{
++ struct ipw_priv *priv = (struct ipw_priv *)d->driver_data;
++ struct ieee80211_device *ieee = priv->ieee;
++ struct ieee80211_txb * txb;
++ struct sk_buff *skb_frag;
++ unsigned char * newbuf;
++ unsigned long flags;
++
++ // should test (ieee->is_queue_full)
++
++ // Fw only accepts data, so avoid accidental fw errors.
++ if ( (buf[0]&0x0c) != '\x08') {
++ //printk("ipw2200: inject: discarding non-data frame (type=%02X)\n",(int)(unsigned char)buf[0]);
++ return count;
++ }
++
++ if (count>1500) {
++ count=1500;
++ printk("ipw2200: inject: cutting down frame to 1500 bytes\n");
++ }
++
++ spin_lock_irqsave(&priv->lock, flags);
++
++ // Create a txb with one skb
++ txb = kmalloc(sizeof(struct ieee80211_txb) + sizeof(u8 *), GFP_ATOMIC);
++ if (!txb)
++ goto nosepuede;
++ txb->nr_frags=1;
++ txb->frag_size = ieee->tx_headroom;
++ txb->fragments[0]=__dev_alloc_skb(count + ieee->tx_headroom, GFP_ATOMIC);
++ if (!txb->fragments[0]) {
++ kfree(txb);
++ goto nosepuede;
++ }
++ skb_reserve(txb->fragments[0], ieee->tx_headroom);
++ txb->encrypted=0;
++ txb->payload_size=count;
++ skb_frag = txb->fragments[0];
++ newbuf=skb_put(skb_frag, count);
++
++ // copy data into txb->skb and send it
++ memcpy(newbuf, buf, count);
++
++ ipw_tx_skb(priv, txb, 0);
++
++nosepuede:
++ spin_unlock_irqrestore(&priv->lock, flags);
++ return count;
++}
++
++static DEVICE_ATTR(inject, S_IWUSR, NULL, store_inject);
++
+ static void notify_wx_assoc_event(struct ipw_priv *priv)
+ {
+ union iwreq_data wrqu;
+@@ -11386,6 +11446,7 @@
+ #ifdef CONFIG_IPW2200_PROMISCUOUS
+ &dev_attr_rtap_iface.attr,
+ &dev_attr_rtap_filter.attr,
++ &dev_attr_inject.attr,
+ #endif
+ NULL
+ };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/2.6.23/4010_e1000e-20070806.patch Sat Oct 13 11:57:46 2007 +0200
@@ -0,0 +1,18164 @@
+From b0d321c026f3c3f2b53df13e1d9bc1fe21ce129a Mon Sep 17 00:00:00 2001
+From: Auke Kok <auke-jan.h.kok@intel.com>
+Date: Mon, 6 Aug 2007 14:14:44 -0700
+Subject: [PATCH] e1000e: New pci-express e1000 driver (currently for ICH9 devices only)
+
+This driver implements support for the ICH9 on-board LAN ethernet
+device. The device is similar to ICH8.
+
+The driver encompasses code to support 82571/2/3, es2lan and ICH8
+devices as well, but those device IDs are disabled and will be
+"lifted" from the e1000 driver over one at a time once this driver
+receives some more live time.
+
+Changes to the last snapshot posted are exclusively in the internal
+hardware API organization. Many thanks to Jeff Garzik for jumping in
+and getting this organized with a keen eye on the future layout.
+
+Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
+---
+ drivers/net/Kconfig | 23 +
+ drivers/net/Makefile | 1 +
+ drivers/net/e1000e/82571.c | 1382 +++++++++++++
+ drivers/net/e1000e/Makefile | 37 +
+ drivers/net/e1000e/defines.h | 738 +++++++
+ drivers/net/e1000e/e1000.h | 518 +++++
+ drivers/net/e1000e/es2lan.c | 1255 ++++++++++++
+ drivers/net/e1000e/ethtool.c | 1763 +++++++++++++++++
+ drivers/net/e1000e/hw.h | 862 +++++++++
+ drivers/net/e1000e/ich8lan.c | 2297 ++++++++++++++++++++++
+ drivers/net/e1000e/lib.c | 2528 ++++++++++++++++++++++++
+ drivers/net/e1000e/netdev.c | 4413 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/net/e1000e/param.c | 382 ++++
+ drivers/net/e1000e/phy.c | 1821 +++++++++++++++++
+ 14 files changed, 18020 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/net/e1000e/82571.c
+ create mode 100644 drivers/net/e1000e/Makefile
+ create mode 100644 drivers/net/e1000e/defines.h
+ create mode 100644 drivers/net/e1000e/e1000.h
+ create mode 100644 drivers/net/e1000e/es2lan.c
+ create mode 100644 drivers/net/e1000e/ethtool.c
+ create mode 100644 drivers/net/e1000e/hw.h
+ create mode 100644 drivers/net/e1000e/ich8lan.c
+ create mode 100644 drivers/net/e1000e/lib.c
+ create mode 100644 drivers/net/e1000e/netdev.c
+ create mode 100644 drivers/net/e1000e/param.c
+ create mode 100644 drivers/net/e1000e/phy.c
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 81ef81c..e5f2f02 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -2059,6 +2059,29 @@ config E1000_DISABLE_PACKET_SPLIT
+
+ If in doubt, say N.
+
++config E1000E
++ tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
++ depends on PCI
++ ---help---
++ This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
++ ethernet family of adapters. For PCI or PCI-X e1000 adapters,
++ use the regular e1000 driver For more information on how to
++ identify your adapter, go to the Adapter & Driver ID Guide at:
++
++ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
++
++ For general information and support, go to the Intel support
++ website at:
++
++ <http://support.intel.com>
++
++ More specific information on configuring the driver is in
++ <file:Documentation/networking/e1000e.txt>.
++
++ To compile this driver as a module, choose M here and read
++ <file:Documentation/networking/net-modules.txt>. The module
++ will be called e1000e.
++
+ source "drivers/net/ixp2000/Kconfig"
+
+ config MYRI_SBUS
+diff --git a/drivers/net/Makefile b/drivers/net/Makefile
+index e684212..4140a0c 100644
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -3,6 +3,7 @@
+ #
+
+ obj-$(CONFIG_E1000) += e1000/
++obj-$(CONFIG_E1000E) += e1000e/
+ obj-$(CONFIG_IBM_EMAC) += ibm_emac/
+ obj-$(CONFIG_IXGB) += ixgb/
+ obj-$(CONFIG_CHELSIO_T1) += chelsio/
+diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
+new file mode 100644
+index 0000000..a1b9d16
+--- /dev/null
++++ b/drivers/net/e1000e/82571.c
+@@ -0,0 +1,1382 @@
++/*******************************************************************************
++
++ Intel PRO/1000 Linux driver
++ Copyright(c) 1999 - 2007 Intel Corporation.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms and conditions of the GNU General Public License,
++ version 2, as published by the Free Software Foundation.
++
++ This program is distributed in the hope 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.,
++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++
++ The full GNU General Public License is included in this distribution in
++ the file called "COPYING".
++
++ Contact Information:
++ Linux NICS <linux.nics@intel.com>
++ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++
++*******************************************************************************/
++
++/*
++ * 82571EB Gigabit Ethernet Controller
++ * 82571EB Gigabit Ethernet Controller (Fiber)
++ * 82572EI Gigabit Ethernet Controller (Copper)
++ * 82572EI Gigabit Ethernet Controller (Fiber)
++ * 82572EI Gigabit Ethernet Controller
++ * 82573V Gigabit Ethernet Controller (Copper)
++ * 82573E Gigabit Ethernet Controller (Copper)
++ * 82573L Gigabit Ethernet Controller
++ */
++
++#include "e1000.h"
++
++#define ID_LED_RESERVED_F746 0xF746
++#define ID_LED_DEFAULT_82573 ((ID_LED_DEF1_DEF2 << 12) | \
++ (ID_LED_OFF1_ON2 << 8) | \
++ (ID_LED_DEF1_DEF2 << 4) | \
++ (ID_LED_DEF1_DEF2))
++
++#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
++
++static s32 e1000_get_phy_id_82571(struct e1000_hw *hw);
++static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw);
++static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw);
++static s32 e1000_get_phy_id_82571(struct e1000_hw *hw);
++static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
++ u16 words, u16 *data);
++static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw);
++static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw);
++static s32 e1000_setup_link_82571(struct e1000_hw *hw);
++static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
++
++/**
++ * e1000_init_phy_params_82571 - Init PHY func ptrs.
++ * @hw: pointer to the HW structure
++ *
++ * This is a function pointer entry point called by the api module.
++ **/
++static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
++{
++ struct e1000_phy_info *phy = &hw->phy;
++ s32 ret_val = E1000_SUCCESS;
++
++ if (hw->media_type != e1000_media_type_copper) {
++ phy->type = e1000_phy_none;
++ goto out;
++ }
++
++ phy->addr = 1;
++ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
++ phy->reset_delay_us = 100;
++
++ switch (hw->mac.type) {
++ case e1000_82571:
++ case e1000_82572:
++ phy->type = e1000_phy_igp_2;
++ break;
++ case e1000_82573:
++ phy->type = e1000_phy_m88;
++ break;
++ default:
++ ret_val = -E1000_ERR_PHY;
++ goto out;
++ break;
++ }
++
++ /* This can only be done after all function pointers are setup. */
++ ret_val = e1000_get_phy_id_82571(hw);
++
++ /* Verify phy id */
++ switch (hw->mac.type) {
++ case e1000_82571:
++ case e1000_82572:
++ if (phy->id != IGP01E1000_I_PHY_ID) {
++ ret_val = -E1000_ERR_PHY;
++ goto out;
++ }
++ break;
++ case e1000_82573:
++ if (phy->id != M88E1111_I_PHY_ID) {
++ ret_val = -E1000_ERR_PHY;
++ goto out;
++ }
++ break;
++ default:
++ ret_val = -E1000_ERR_PHY;
++ goto out;
++ break;
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_init_nvm_params_82571 - Init NVM func ptrs.
++ * @hw: pointer to the HW structure
++ *
++ * This is a function pointer entry point called by the api module.
++ **/
++static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
++{
++ struct e1000_nvm_info *nvm = &hw->nvm;
++ u32 eecd = er32(EECD);
++ u16 size;
++
++ nvm->opcode_bits = 8;
++ nvm->delay_usec = 1;
++ switch (nvm->override) {
++ case e1000_nvm_override_spi_large:
++ nvm->page_size = 32;
++ nvm->address_bits = 16;
++ break;
++ case e1000_nvm_override_spi_small:
++ nvm->page_size = 8;
++ nvm->address_bits = 8;
++ break;
++ default:
++ nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
++ nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
++ break;
++ }
++
++ switch (hw->mac.type) {
++ case e1000_82573:
++ if (((eecd >> 15) & 0x3) == 0x3) {
++ nvm->type = e1000_nvm_flash_hw;
++ nvm->word_size = 2048;
++ /* Autonomous Flash update bit must be cleared due
++ * to Flash update issue.
++ */
++ eecd &= ~E1000_EECD_AUPDEN;
++ ew32(EECD, eecd);
++ break;
++ }
++ /* Fall Through */
++ default:
++ nvm->type = e1000_nvm_eeprom_spi;
++ size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
++ E1000_EECD_SIZE_EX_SHIFT);
++ /* Added to a constant, "size" becomes the left-shift value
++ * for setting word_size.
++ */
++ size += NVM_WORD_SIZE_BASE_SHIFT;
++ nvm->word_size = 1 << size;
++ break;
++ }
++
++ return E1000_SUCCESS;
++}
++
++/**
++ * e1000_init_mac_params_82571 - Init MAC func ptrs.
++ * @hw: pointer to the HW structure
++ *
++ * This is a function pointer entry point called by the api module.
++ **/
++static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct e1000_mac_info *mac = &hw->mac;
++ struct e1000_mac_operations *func = &mac->ops;
++ s32 ret_val = E1000_SUCCESS;
++
++ /* Set media type */
++ switch (adapter->pdev->device) {
++ case E1000_DEV_ID_82571EB_FIBER:
++ case E1000_DEV_ID_82572EI_FIBER:
++ case E1000_DEV_ID_82571EB_QUAD_FIBER:
++ hw->media_type = e1000_media_type_fiber;
++ break;
++ case E1000_DEV_ID_82571EB_SERDES:
++ case E1000_DEV_ID_82572EI_SERDES:
++ hw->media_type = e1000_media_type_internal_serdes;
++ break;
++ default:
++ hw->media_type = e1000_media_type_copper;
++ break;
++ }
++
++ /* Set mta register count */
++ mac->mta_reg_count = 128;
++ /* Set rar entry count */
++ mac->rar_entry_count = E1000_RAR_ENTRIES;
++ /* Set if manageability features are enabled. */
++ mac->arc_subsystem_valid =
++ (er32(FWSM) & E1000_FWSM_MODE_MASK) ? 1 : 0;
++
++ /* check for link */
++ switch (hw->media_type) {
++ case e1000_media_type_copper:
++ func->setup_physical_interface = e1000_setup_copper_link_82571;
++ func->check_for_link = e1000_check_for_copper_link;
++ func->get_link_up_info = e1000_get_speed_and_duplex_copper;
++ break;
++ case e1000_media_type_fiber:
++ func->setup_physical_interface = e1000_setup_fiber_serdes_link_82571;
++ func->check_for_link = e1000_check_for_fiber_link;
++ func->get_link_up_info = e1000_get_speed_and_duplex_fiber_serdes;
++ break;
++ case e1000_media_type_internal_serdes:
++ func->setup_physical_interface = e1000_setup_fiber_serdes_link_82571;
++ func->check_for_link = e1000_check_for_serdes_link;
++ func->get_link_up_info = e1000_get_speed_and_duplex_fiber_serdes;
++ break;
++ default:
++ ret_val = -E1000_ERR_CONFIG;
++ goto out;
++ break;
++ }
++
++out:
++ return ret_val;
++}
++
++static s32 e1000_get_invariants_82571(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ static int global_quad_port_a; /* global port a indication */
++ struct pci_dev *pdev = adapter->pdev;
++ u16 eeprom_data = 0;
++ int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1;
++ s32 rc;
++
++ rc = e1000_init_mac_params_82571(adapter);
++ if (rc)
++ return rc;
++
++ rc = e1000_init_nvm_params_82571(hw);
++ if (rc)
++ return rc;
++
++ rc = e1000_init_phy_params_82571(hw);
++ if (rc)
++ return rc;
++
++ /* tag quad port adapters first, it's used below */
++ switch (pdev->device) {
++ case E1000_DEV_ID_82571EB_QUAD_COPPER:
++ case E1000_DEV_ID_82571EB_QUAD_FIBER:
++ case E1000_DEV_ID_82571EB_QUAD_COPPER_LP:
++ adapter->flags |= FLAG_IS_QUAD_PORT;
++ /* mark the first port */
++ if (global_quad_port_a == 0)
++ adapter->flags |= FLAG_IS_QUAD_PORT_A;
++ /* Reset for multiple quad port adapters */
++ global_quad_port_a++;
++ if (global_quad_port_a == 4)
++ global_quad_port_a = 0;
++ break;
++ default:
++ break;
++ }
++
++ switch (adapter->hw.mac.type) {
++ case e1000_82571:
++ /* these dual ports don't have WoL on port B at all */
++ if (((pdev->device == E1000_DEV_ID_82571EB_FIBER) ||
++ (pdev->device == E1000_DEV_ID_82571EB_SERDES) ||
++ (pdev->device == E1000_DEV_ID_82571EB_COPPER)) &&
++ (is_port_b))
++ adapter->flags &= ~FLAG_HAS_WOL;
++ /* quad ports only support WoL on port A */
++ if (adapter->flags & FLAG_IS_QUAD_PORT &&
++ (!adapter->flags & FLAG_IS_QUAD_PORT_A))
++ adapter->flags &= ~FLAG_HAS_WOL;
++ break;
++
++ case e1000_82573:
++ if (pdev->device == E1000_DEV_ID_82573L) {
++ e1000_read_nvm(&adapter->hw, NVM_INIT_3GIO_3, 1,
++ &eeprom_data);
++ if (eeprom_data & NVM_WORD1A_ASPM_MASK)
++ adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES;
++ }
++ break;
++ default:
++ break;
++ }
++
++ return E1000_SUCCESS;
++}
++
++/**
++ * e1000_get_phy_id_82571 - Retrieve the PHY ID and revision
++ * @hw: pointer to the HW structure
++ *
++ * Reads the PHY registers and stores the PHY ID and possibly the PHY
++ * revision in the hardware structure.
++ **/
++static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
++{
++ struct e1000_phy_info *phy = &hw->phy;
++ s32 ret_val = E1000_SUCCESS;
++
++ switch (hw->mac.type) {
++ case e1000_82571:
++ case e1000_82572:
++ /* The 82571 firmware may still be configuring the PHY.
++ * In this case, we cannot access the PHY until the
++ * configuration is done. So we explicitly set the
++ * PHY ID. */
++ phy->id = IGP01E1000_I_PHY_ID;
++ break;
++ case e1000_82573:
++ ret_val = e1000_get_phy_id(hw);
++ break;
++ default:
++ ret_val = -E1000_ERR_PHY;
++ break;
++ }
++
++ return ret_val;
++}
++
++/**
++ * e1000_get_hw_semaphore_82571 - Acquire hardware semaphore
++ * @hw: pointer to the HW structure
++ *
++ * Acquire the HW semaphore to access the PHY or NVM
++ **/
++static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
++{
++ u32 swsm;
++ s32 ret_val = E1000_SUCCESS;
++ s32 timeout = hw->nvm.word_size + 1;
++ s32 i = 0;
++
++ /* Get the FW semaphore. */
++ for (i = 0; i < timeout; i++) {
++ swsm = er32(SWSM);
++ ew32(SWSM, swsm | E1000_SWSM_SWESMBI);
++
++ /* Semaphore acquired if bit latched */
++ if (er32(SWSM) & E1000_SWSM_SWESMBI)
++ break;
++
++ udelay(50);
++ }
++
++ if (i == timeout) {
++ /* Release semaphores */
++ e1000_put_hw_semaphore(hw);
++ hw_dbg(hw, "Driver can't access the NVM\n");
++ ret_val = -E1000_ERR_NVM;
++ goto out;
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_put_hw_semaphore_82571 - Release hardware semaphore
++ * @hw: pointer to the HW structure
++ *
++ * Release hardware semaphore used to access the PHY or NVM
++ **/
++static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
++{
++ u32 swsm;
++
++ swsm = er32(SWSM);
++
++ swsm &= ~E1000_SWSM_SWESMBI;
++
++ ew32(SWSM, swsm);
++}
++
++/**
++ * e1000_acquire_nvm_82571 - Request for access to the EEPROM
++ * @hw: pointer to the HW structure
++ *
++ * To gain access to the EEPROM, first we must obtain a hardware semaphore.
++ * Then for non-82573 hardware, set the EEPROM access request bit and wait
++ * for EEPROM access grant bit. If the access grant bit is not set, release
++ * hardware semaphore.
++ **/
++static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
++{
++ s32 ret_val;
++
++ ret_val = e1000_get_hw_semaphore_82571(hw);
++ if (ret_val)
++ goto out;
++
++ if (hw->mac.type != e1000_82573)
++ ret_val = e1000_acquire_nvm(hw);
++
++ if (ret_val)
++ e1000_put_hw_semaphore_82571(hw);
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_release_nvm_82571 - Release exclusive access to EEPROM
++ * @hw: pointer to the HW structure
++ *
++ * Stop any current commands to the EEPROM and clear the EEPROM request bit.
++ **/
++static void e1000_release_nvm_82571(struct e1000_hw *hw)
++{
++ e1000_release_nvm(hw);
++ e1000_put_hw_semaphore_82571(hw);
++}
++
++/**
++ * e1000_write_nvm_82571 - Write to EEPROM using appropriate interface
++ * @hw: pointer to the HW structure
++ * @offset: offset within the EEPROM to be written to
++ * @words: number of words to write
++ * @data: 16 bit word(s) to be written to the EEPROM
++ *
++ * For non-82573 silicon, write data to EEPROM at offset using SPI interface.
++ *
++ * If e1000_update_nvm_checksum is not called after this function, the
++ * EEPROM will most likley contain an invalid checksum.
++ **/
++static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words,
++ u16 *data)
++{
++ s32 ret_val = E1000_SUCCESS;
++
++ switch (hw->mac.type) {
++ case e1000_82573:
++ ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data);
++ break;
++ case e1000_82571:
++ case e1000_82572:
++ ret_val = e1000_write_nvm_spi(hw, offset, words, data);
++ break;
++ default:
++ ret_val = -E1000_ERR_NVM;
++ break;
++ }
++
++ return ret_val;
++}
++
++/**
++ * e1000_update_nvm_checksum_82571 - Update EEPROM checksum
++ * @hw: pointer to the HW structure
++ *
++ * Updates the EEPROM checksum by reading/adding each word of the EEPROM
++ * up to the checksum. Then calculates the EEPROM checksum and writes the
++ * value to the EEPROM.
++ **/
++static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
++{
++ u32 eecd;
++ s32 ret_val;
++ u16 i;
++
++ ret_val = e1000_update_nvm_checksum_generic(hw);
++ if (ret_val)
++ goto out;
++
++ /* If our nvm is an EEPROM, then we're done
++ * otherwise, commit the checksum to the flash NVM. */
++ if (hw->nvm.type != e1000_nvm_flash_hw)
++ goto out;
++
++ /* Check for pending operations. */
++ for (i = 0; i < E1000_FLASH_UPDATES; i++) {
++ msleep(1);
++ if ((er32(EECD) & E1000_EECD_FLUPD) == 0)
++ break;
++ }
++
++ if (i == E1000_FLASH_UPDATES) {
++ ret_val = -E1000_ERR_NVM;
++ goto out;
++ }
++
++ /* Reset the firmware if using STM opcode. */
++ if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) {
++ /* The enabling of and the actual reset must be done
++ * in two write cycles.
++ */
++ ew32(HICR, E1000_HICR_FW_RESET_ENABLE);
++ e1e_flush();
++ ew32(HICR, E1000_HICR_FW_RESET);
++ }
++
++ /* Commit the write to flash */
++ eecd = er32(EECD) | E1000_EECD_FLUPD;
++ ew32(EECD, eecd);
++
++ for (i = 0; i < E1000_FLASH_UPDATES; i++) {
++ msleep(1);
++ if ((er32(EECD) & E1000_EECD_FLUPD) == 0)
++ break;
++ }
++
++ if (i == E1000_FLASH_UPDATES) {
++ ret_val = -E1000_ERR_NVM;
++ goto out;
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_validate_nvm_checksum_82571 - Validate EEPROM checksum
++ * @hw: pointer to the HW structure
++ *
++ * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
++ * and then verifies that the sum of the EEPROM is equal to 0xBABA.
++ **/
++static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw)
++{
++ if (hw->nvm.type == e1000_nvm_flash_hw)
++ e1000_fix_nvm_checksum_82571(hw);
++
++ return e1000_validate_nvm_checksum_generic(hw);
++}
++
++/**
++ * e1000_write_nvm_eewr_82571 - Write to EEPROM for 82573 silicon
++ * @hw: pointer to the HW structure
++ * @offset: offset within the EEPROM to be written to
++ * @words: number of words to write
++ * @data: 16 bit word(s) to be written to the EEPROM
++ *
++ * After checking for invalid values, poll the EEPROM to ensure the previous
++ * command has completed before trying to write the next word. After write
++ * poll for completion.
++ *
++ * If e1000_update_nvm_checksum is not called after this function, the
++ * EEPROM will most likley contain an invalid checksum.
++ **/
++static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
++ u16 words, u16 *data)
++{
++ struct e1000_nvm_info *nvm = &hw->nvm;
++ u32 i;
++ u32 eewr = 0;
++ s32 ret_val = 0;
++
++ /* A check for invalid values: offset too large, too many words,
++ * and not enough words. */
++ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
++ (words == 0)) {
++ hw_dbg(hw, "nvm parameter(s) out of bounds\n");
++ ret_val = -E1000_ERR_NVM;
++ goto out;
++ }
++
++ for (i = 0; i < words; i++) {
++ eewr = (data[i] << E1000_NVM_RW_REG_DATA) |
++ ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
++ E1000_NVM_RW_REG_START;
++
++ ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE);
++ if (ret_val)
++ break;
++
++ ew32(EEWR, eewr);
++
++ ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE);
++ if (ret_val)
++ break;
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_get_cfg_done_82571 - Poll for configuration done
++ * @hw: pointer to the HW structure
++ *
++ * Reads the management control register for the config done bit to be set.
++ **/
++static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw)
++{
++ s32 timeout = PHY_CFG_TIMEOUT;
++ s32 ret_val = E1000_SUCCESS;
++
++ while (timeout) {
++ if (er32(EEMNGCTL) &
++ E1000_NVM_CFG_DONE_PORT_0)
++ break;
++ msleep(1);
++ timeout--;
++ }
++ if (!timeout) {
++ hw_dbg(hw, "MNG configuration cycle has not completed.\n");
++ ret_val = -E1000_ERR_RESET;
++ goto out;
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_set_d0_lplu_state_82571 - Set Low Power Linkup D0 state
++ * @hw: pointer to the HW structure
++ * @active: TRUE to enable LPLU, FALSE to disable
++ *
++ * Sets the LPLU D0 state according to the active flag. When activating LPLU
++ * this function also disables smart speed and vice versa. LPLU will not be
++ * activated unless the device autonegotiation advertisement meets standards
++ * of either 10 or 10/100 or 10/100/1000 at all duplexes. This is a function
++ * pointer entry point only called by PHY setup routines.
++ **/
++static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
++{
++ struct e1000_phy_info *phy = &hw->phy;
++ s32 ret_val;
++ u16 data;
++
++ ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data);
++ if (ret_val)
++ goto out;
++
++ if (active) {
++ data |= IGP02E1000_PM_D0_LPLU;
++ ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
++ if (ret_val)
++ goto out;
++
++ /* When LPLU is enabled, we should disable SmartSpeed */
++ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data);
++ data &= ~IGP01E1000_PSCFR_SMART_SPEED;
++ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data);
++ if (ret_val)
++ goto out;
++ } else {
++ data &= ~IGP02E1000_PM_D0_LPLU;
++ ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
++ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
++ * during Dx states where the power conservation is most
++ * important. During driver activity we should enable
++ * SmartSpeed, so performance is maintained. */
++ if (phy->smart_speed == e1000_smart_speed_on) {
++ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++ &data);
++ if (ret_val)
++ goto out;
++
++ data |= IGP01E1000_PSCFR_SMART_SPEED;
++ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++ data);
++ if (ret_val)
++ goto out;
++ } else if (phy->smart_speed == e1000_smart_speed_off) {
++ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++ &data);
++ if (ret_val)
++ goto out;
++
++ data &= ~IGP01E1000_PSCFR_SMART_SPEED;
++ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++ data);
++ if (ret_val)
++ goto out;
++ }
++ }
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_reset_hw_82571 - Reset hardware
++ * @hw: pointer to the HW structure
++ *
++ * This resets the hardware into a known state. This is a
++ * function pointer entry point called by the api module.
++ **/
++static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
++{
++ u32 ctrl;
++ u32 extcnf_ctrl;
++ u32 ctrl_ext;
++ u32 icr;
++ s32 ret_val;
++ u16 i = 0;
++
++ /* Prevent the PCI-E bus from sticking if there is no TLP connection
++ * on the last TLP read/write transaction when MAC is reset.
++ */
++ ret_val = e1000_disable_pcie_master(hw);
++ if (ret_val)
++ hw_dbg(hw, "PCI-E Master disable polling has failed.\n");
++
++ hw_dbg(hw, "Masking off all interrupts\n");
++ ew32(IMC, 0xffffffff);
++
++ ew32(RCTL, 0);
++ ew32(TCTL, E1000_TCTL_PSP);
++ e1e_flush();
++
++ msleep(10);
++
++ /* Must acquire the MDIO ownership before MAC reset.
++ * Ownership defaults to firmware after a reset. */
++ if (hw->mac.type == e1000_82573) {
++ extcnf_ctrl = er32(EXTCNF_CTRL);
++ extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
++
++ do {
++ ew32(EXTCNF_CTRL, extcnf_ctrl);
++ extcnf_ctrl = er32(EXTCNF_CTRL);
++
++ if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
++ break;
++
++ extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
++
++ msleep(2);
++ i++;
++ } while (i < MDIO_OWNERSHIP_TIMEOUT);
++ }
++
++ ctrl = er32(CTRL);
++
++ hw_dbg(hw, "Issuing a global reset to MAC\n");
++ ew32(CTRL, ctrl | E1000_CTRL_RST);
++
++ if (hw->nvm.type == e1000_nvm_flash_hw) {
++ udelay(10);
++ ctrl_ext = er32(CTRL_EXT);
++ ctrl_ext |= E1000_CTRL_EXT_EE_RST;
++ ew32(CTRL_EXT, ctrl_ext);
++ e1e_flush();
++ }
++
++ ret_val = e1000_get_auto_rd_done(hw);
++ if (ret_val)
++ /* We don't want to continue accessing MAC registers. */
++ goto out;
++
++ /* Phy configuration from NVM just starts after EECD_AUTO_RD is set.
++ * Need to wait for Phy configuration completion before accessing
++ * NVM and Phy.
++ */
++ if (hw->mac.type == e1000_82573)
++ msleep(25);
++
++ /* Clear any pending interrupt events. */
++ ew32(IMC, 0xffffffff);
++ icr = er32(ICR);
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_init_hw_82571 - Initialize hardware
++ * @hw: pointer to the HW structure
++ *
++ * This inits the hardware readying it for operation.
++ **/
++static s32 e1000_init_hw_82571(struct e1000_hw *hw)
++{
++ struct e1000_mac_info *mac = &hw->mac;
++ u32 reg_data;
++ s32 ret_val;
++ u16 i;
++ u16 rar_count = mac->rar_entry_count;
++
++ e1000_initialize_hw_bits_82571(hw);
++
++ /* Initialize identification LED */
++ ret_val = e1000_id_led_init(hw);
++ if (ret_val) {
++ hw_dbg(hw, "Error initializing identification LED\n");
++ goto out;
++ }
++
++ /* Disabling VLAN filtering */
++ hw_dbg(hw, "Initializing the IEEE VLAN\n");
++ e1000_clear_vfta(hw);
++
++ /* Setup the receive address. */
++ /* If, however, a locally administered address was assigned to the
++ * 82571, we must reserve a RAR for it to work around an issue where
++ * resetting one port will reload the MAC on the other port.
++ */
++ if (e1000_get_laa_state_82571(hw))
++ rar_count--;
++ e1000_init_rx_addrs(hw, rar_count);
++
++ /* Zero out the Multicast HASH table */
++ hw_dbg(hw, "Zeroing the MTA\n");
++ for (i = 0; i < mac->mta_reg_count; i++)
++ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
++
++ /* Setup link and flow control */
++ ret_val = e1000_setup_link_82571(hw);
++
++ /* Set the transmit descriptor write-back policy */
++ reg_data = er32(TXDCTL);
++ reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
++ E1000_TXDCTL_FULL_TX_DESC_WB |
++ E1000_TXDCTL_COUNT_DESC;
++ ew32(TXDCTL, reg_data);
++
++ /* ...for both queues. */
++ if (mac->type != e1000_82573) {
++ reg_data = er32(TXDCTL1);
++ reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
++ E1000_TXDCTL_FULL_TX_DESC_WB |
++ E1000_TXDCTL_COUNT_DESC;
++ ew32(TXDCTL1, reg_data);
++ } else {
++ e1000_enable_tx_pkt_filtering(hw);
++ reg_data = er32(GCR);
++ reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
++ ew32(GCR, reg_data);
++ }
++
++ /* Clear all of the statistics registers (clear on read). It is
++ * important that we do this after we have tried to establish link
++ * because the symbol error count will increment wildly if there
++ * is no link.
++ */
++ e1000_clear_hw_cntrs_82571(hw);
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_initialize_hw_bits_82571 - Initialize hardware-dependent bits
++ * @hw: pointer to the HW structure
++ *
++ * Initializes required hardware-dependent bits needed for normal operation.
++ **/
++static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
++{
++ u32 reg;
++
++ /* Transmit Descriptor Control 0 */
++ reg = er32(TXDCTL);
++ reg |= (1 << 22);
++ ew32(TXDCTL, reg);
++
++ /* Transmit Descriptor Control 1 */
++ reg = er32(TXDCTL1);
++ reg |= (1 << 22);
++ ew32(TXDCTL1, reg);
++
++ /* Transmit Arbitration Control 0 */
++ reg = er32(TARC0);
++ reg &= ~(0xF << 27); /* 30:27 */
++ switch (hw->mac.type) {
++ case e1000_82571:
++ case e1000_82572:
++ reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26);
++ break;
++ default:
++ break;
++ }
++ ew32(TARC0, reg);
++
++ /* Transmit Arbitration Control 1 */
++ reg = er32(TARC1);
++ switch (hw->mac.type) {
++ case e1000_82571:
++ case e1000_82572:
++ reg &= ~((1 << 29) | (1 << 30));
++ reg |= (1 << 22) | (1 << 24) | (1 << 25) | (1 << 26);
++ if (er32(TCTL) & E1000_TCTL_MULR)
++ reg &= ~(1 << 28);
++ else
++ reg |= (1 << 28);
++ ew32(TARC1, reg);
++ break;
++ default:
++ break;
++ }
++
++ /* Device Control */
++ if (hw->mac.type == e1000_82573) {
++ reg = er32(CTRL);
++ reg &= ~(1 << 29);
++ ew32(CTRL, reg);
++ }
++
++ /* Extended Device Control */
++ if (hw->mac.type == e1000_82573) {
++ reg = er32(CTRL_EXT);
++ reg &= ~(1 << 23);
++ reg |= (1 << 22);
++ ew32(CTRL_EXT, reg);
++ }
++}
++
++/**
++ * e1000_clear_vfta - Clear VLAN filter table
++ * @hw: pointer to the HW structure
++ *
++ * Clears the register array which contains the VLAN filter table by
++ * setting all the values to 0.
++ **/
++void e1000_clear_vfta(struct e1000_hw *hw)
++{
++ u32 offset;
++ u32 vfta_value = 0;
++ u32 vfta_offset = 0;
++ u32 vfta_bit_in_reg = 0;
++
++ if (hw->mac.type == e1000_82573) {
++ if (hw->mng_cookie.vlan_id != 0) {
++ /* The VFTA is a 4096b bit-field, each identifying
++ * a single VLAN ID. The following operations
++ * determine which 32b entry (i.e. offset) into the
++ * array we want to set the VLAN ID (i.e. bit) of
++ * the manageability unit.
++ */
++ vfta_offset = (hw->mng_cookie.vlan_id >>
++ E1000_VFTA_ENTRY_SHIFT) &
++ E1000_VFTA_ENTRY_MASK;
++ vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id &
++ E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
++ }
++ }
++ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
++ /* If the offset we want to clear is the same offset of the
++ * manageability VLAN ID, then clear all bits except that of
++ * the manageability unit.
++ */
++ vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
++ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, vfta_value);
++ e1e_flush();
++ }
++}
++
++/**
++ * e1000_mc_addr_list_update_82571 - Update Multicast addresses
++ * @hw: pointer to the HW structure
++ * @mc_addr_list: array of multicast addresses to program
++ * @mc_addr_count: number of multicast addresses to program
++ * @rar_used_count: the first RAR register free to program
++ * @rar_count: total number of supported Receive Address Registers
++ *
++ * Updates the Receive Address Registers and Multicast Table Array.
++ * The caller must have a packed mc_addr_list of multicast addresses.
++ * The parameter rar_count will usually be hw->mac.rar_entry_count
++ * unless there are workarounds that change this.
++ **/
++static void e1000_mc_addr_list_update_82571(struct e1000_hw *hw,
++ u8 *mc_addr_list,
++ u32 mc_addr_count,
++ u32 rar_used_count,
++ u32 rar_count)
++{
++ if (e1000_get_laa_state_82571(hw))
++ rar_count--;
++
++ e1000_mc_addr_list_update_generic(hw, mc_addr_list, mc_addr_count,
++ rar_used_count, rar_count);
++}
++
++/**
++ * e1000_setup_link_82571 - Setup flow control and link settings
++ * @hw: pointer to the HW structure
++ *
++ * Determines which flow control settings to use, then configures flow
++ * control. Calls the appropriate media-specific link configuration
++ * function. Assuming the adapter has a valid link partner, a valid link
++ * should be established. Assumes the hardware has previously been reset
++ * and the transmitter and receiver are not enabled.
++ **/
++static s32 e1000_setup_link_82571(struct e1000_hw *hw)
++{
++ /* 82573 does not have a word in the NVM to determine
++ * the default flow control setting, so we explicitly
++ * set it to full.
++ */
++ if (hw->mac.type == e1000_82573)
++ hw->mac.fc = e1000_fc_full;
++
++ return e1000_setup_link(hw);
++}
++
++/**
++ * e1000_setup_copper_link_82571 - Configure copper link settings
++ * @hw: pointer to the HW structure
++ *
++ * Configures the link for auto-neg or forced speed and duplex. Then we check
++ * for link, once link is established calls to configure collision distance
++ * and flow control are called.
++ **/
++static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)
++{
++ u32 ctrl;
++ u32 led_ctrl;
++ s32 ret_val;
++
++ ctrl = er32(CTRL);
++ ctrl |= E1000_CTRL_SLU;
++ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
++ ew32(CTRL, ctrl);
++
++ switch (hw->phy.type) {
++ case e1000_phy_m88:
++ ret_val = e1000_copper_link_setup_m88(hw);
++ break;
++ case e1000_phy_igp_2:
++ ret_val = e1000_copper_link_setup_igp(hw);
++ /* Setup activity LED */
++ led_ctrl = er32(LEDCTL);
++ led_ctrl &= IGP_ACTIVITY_LED_MASK;
++ led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
++ ew32(LEDCTL, led_ctrl);
++ break;
++ default:
++ ret_val = -E1000_ERR_PHY;
++ break;
++ }
++
++ if (ret_val)
++ goto out;
++
++ ret_val = e1000_setup_copper_link(hw);
++
++out:
++ return ret_val;
++}
++
++/**
++ * e1000_setup_fiber_serdes_link_82571 - Setup link for fiber/serdes
++ * @hw: pointer to the HW structure
++ *
++ * Configures collision distance and flow control for fiber and serdes links.
++ * Upon successful setup, poll for link.
++ **/
++static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
++{
++ switch (hw->mac.type) {
++ case e1000_82571:
++ case e1000_82572:
++ /* If SerDes loopback mode is entered, there is no form
++ * of reset to take the adapter out of that mode. So we
++ * have to explicitly take the adapter out of loopback
++ * mode. This prevents drivers from twidling their thumbs
++ * if another tool failed to take it out of loopback mode.
++ */
++ ew32(SCTL,
++ E1000_SCTL_DISABLE_SERDES_LOOPBACK);
++ break;
++ default:
++ break;
++ }
++
++ return e1000_setup_fiber_serdes_link(hw);
++}
++
++/**
++ * e1000_valid_led_default_82571 - Verify a valid default LED config
++