get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/965/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 965,
    "url": "http://patchwork.ozlabs.org/api/patches/965/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/200809222152.m8MLqTnO031997@imap1.linux-foundation.org/",
    "project": {
        "id": 7,
        "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api",
        "name": "Linux network development",
        "link_name": "netdev",
        "list_id": "netdev.vger.kernel.org",
        "list_email": "netdev@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<200809222152.m8MLqTnO031997@imap1.linux-foundation.org>",
    "list_archive_url": null,
    "date": "2008-09-22T21:52:28",
    "name": "[20/21] atl2: add atl2 driver",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "57f2bef8a63e0505d6e95cd9407ac5ffddf57448",
    "submitter": {
        "id": 107,
        "url": "http://patchwork.ozlabs.org/api/people/107/?format=api",
        "name": "Andrew Morton",
        "email": "akpm@linux-foundation.org"
    },
    "delegate": {
        "id": 36,
        "url": "http://patchwork.ozlabs.org/api/users/36/?format=api",
        "username": "jgarzik",
        "first_name": "Jeff",
        "last_name": "Garzik",
        "email": "jgarzik@pobox.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/200809222152.m8MLqTnO031997@imap1.linux-foundation.org/mbox/",
    "series": [],
    "comments": "http://patchwork.ozlabs.org/api/patches/965/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/965/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<netdev-owner@vger.kernel.org>",
        "X-Original-To": "patchwork-incoming@ozlabs.org",
        "Delivered-To": "patchwork-incoming@ozlabs.org",
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.176.167])\n\tby ozlabs.org (Postfix) with ESMTP id 02D7FDDF26\n\tfor <patchwork-incoming@ozlabs.org>;\n\tTue, 23 Sep 2008 07:55:14 +1000 (EST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1753736AbYIVVzH (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tMon, 22 Sep 2008 17:55:07 -0400",
            "(majordomo@vger.kernel.org) by vger.kernel.org id S1753272AbYIVVzH\n\t(ORCPT <rfc822; netdev-outgoing>); Mon, 22 Sep 2008 17:55:07 -0400",
            "from smtp1.linux-foundation.org ([140.211.169.13]:51926 \"EHLO\n\tsmtp1.linux-foundation.org\" rhost-flags-OK-OK-OK-OK)\n\tby vger.kernel.org with ESMTP id S1753347AbYIVVy7 (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Mon, 22 Sep 2008 17:54:59 -0400",
            "from imap1.linux-foundation.org (imap1.linux-foundation.org\n\t[140.211.169.55])\n\tby smtp1.linux-foundation.org (8.14.2/8.13.5/Debian-3ubuntu1.1) with\n\tESMTP id m8MLqTX3018388\n\t(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO);\n\tMon, 22 Sep 2008 14:52:30 -0700",
            "from localhost.localdomain (localhost [127.0.0.1])\n\tby imap1.linux-foundation.org\n\t(8.13.5.20060308/8.13.5/Debian-3ubuntu1.1) with ESMTP id\n\tm8MLqTnO031997; Mon, 22 Sep 2008 14:52:29 -0700"
        ],
        "Message-Id": "<200809222152.m8MLqTnO031997@imap1.linux-foundation.org>",
        "Subject": "[patch 20/21] atl2: add atl2 driver",
        "To": "jeff@garzik.org",
        "Cc": "netdev@vger.kernel.org, akpm@linux-foundation.org,\n\tcsnook@redhat.com, jacliburn@bellsouth.net",
        "From": "akpm@linux-foundation.org",
        "Date": "Mon, 22 Sep 2008 14:52:28 -0700",
        "X-Spam-Status": "No, hits=-3.359 required=5 tests=AWL, BAYES_00,\n\tOSDL_HEADER_SUBJECT_BRACKETED",
        "X-Spam-Checker-Version": "SpamAssassin 3.2.4-osdl_revision__1.47__",
        "X-MIMEDefang-Filter": "lf$Revision: 1.188 $",
        "X-Scanned-By": "MIMEDefang 2.63 on 140.211.169.13",
        "Sender": "netdev-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<netdev.vger.kernel.org>",
        "X-Mailing-List": "netdev@vger.kernel.org"
    },
    "content": "From: Chris Snook <csnook@redhat.com>\n\nDriver for Atheros L2 10/100 network device. Includes necessary\nchanges for Kconfig, Makefile, and pci_ids.h.\n\nSigned-off-by: Chris Snook <csnook@redhat.com>\nSigned-off-by: Jay Cliburn <jacliburn@bellsouth.net>\nSigned-off-by: Andrew Morton <akpm@linux-foundation.org>\n---\n\n drivers/net/Kconfig       |   11 \n drivers/net/Makefile      |    1 \n drivers/net/atlx/Makefile |    2 \n drivers/net/atlx/atl2.c   | 3127 ++++++++++++++++++++++++++++++++++++\n drivers/net/atlx/atl2.h   |  530 ++++++\n include/linux/pci_ids.h   |    1 \n 6 files changed, 3672 insertions(+)",
    "diff": "diff -puN drivers/net/Kconfig~atl2-add-atl2-driver drivers/net/Kconfig\n--- a/drivers/net/Kconfig~atl2-add-atl2-driver\n+++ a/drivers/net/Kconfig\n@@ -1827,6 +1827,17 @@ config NE_H8300\n \t  Say Y here if you want to use the NE2000 compatible\n \t  controller on the Renesas H8/300 processor.\n \n+config ATL2\n+\ttristate \"Atheros L2 Fast Ethernet support\"\n+\tdepends on PCI\n+\tselect CRC32\n+\tselect MII\n+\thelp\n+\t  This driver supports the Atheros L2 fast ethernet adapter.\n+\n+\t  To compile this driver as a module, choose M here.  The module\n+\t  will be called atl2.\n+\n source \"drivers/net/fs_enet/Kconfig\"\n \n endif # NET_ETHERNET\ndiff -puN drivers/net/Makefile~atl2-add-atl2-driver drivers/net/Makefile\n--- a/drivers/net/Makefile~atl2-add-atl2-driver\n+++ a/drivers/net/Makefile\n@@ -15,6 +15,7 @@ obj-$(CONFIG_EHEA) += ehea/\n obj-$(CONFIG_CAN) += can/\n obj-$(CONFIG_BONDING) += bonding/\n obj-$(CONFIG_ATL1) += atlx/\n+obj-$(CONFIG_ATL2) += atlx/\n obj-$(CONFIG_ATL1E) += atl1e/\n obj-$(CONFIG_GIANFAR) += gianfar_driver.o\n obj-$(CONFIG_TEHUTI) += tehuti.o\ndiff -puN drivers/net/atlx/Makefile~atl2-add-atl2-driver drivers/net/atlx/Makefile\n--- a/drivers/net/atlx/Makefile~atl2-add-atl2-driver\n+++ a/drivers/net/atlx/Makefile\n@@ -1 +1,3 @@\n obj-$(CONFIG_ATL1)\t+= atl1.o\n+obj-$(CONFIG_ATL2)\t+= atl2.o\n+\ndiff -puN /dev/null drivers/net/atlx/atl2.c\n--- /dev/null\n+++ a/drivers/net/atlx/atl2.c\n@@ -0,0 +1,3127 @@\n+/*\n+ * Copyright(c) 2006 - 2007 Atheros Corporation. All rights reserved.\n+ * Copyright(c) 2007 - 2008 Chris Snook <csnook@redhat.com>\n+ *\n+ * Derived from Intel e1000 driver\n+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.\n+ *\n+ * This program is free software; you can redistribute it and/or modify it\n+ * under the terms of the GNU General Public License as published by the Free\n+ * Software Foundation; either version 2 of the License, or (at your option)\n+ * any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful, but WITHOUT\n+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\n+ * more details.\n+ *\n+ * You should have received a copy of the GNU General Public License along with\n+ * this program; if not, write to the Free Software Foundation, Inc., 59\n+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n+ */\n+\n+#include <asm/atomic.h>\n+#include <linux/crc32.h>\n+#include <linux/dma-mapping.h>\n+#include <linux/etherdevice.h>\n+#include <linux/ethtool.h>\n+#include <linux/hardirq.h>\n+#include <linux/if_vlan.h>\n+#include <linux/in.h>\n+#include <linux/interrupt.h>\n+#include <linux/ip.h>\n+#include <linux/irqflags.h>\n+#include <linux/irqreturn.h>\n+#include <linux/mii.h>\n+#include <linux/net.h>\n+#include <linux/netdevice.h>\n+#include <linux/pci.h>\n+#include <linux/pci_ids.h>\n+#include <linux/pm.h>\n+#include <linux/skbuff.h>\n+#include <linux/spinlock.h>\n+#include <linux/string.h>\n+#include <linux/tcp.h>\n+#include <linux/timer.h>\n+#include <linux/types.h>\n+#include <linux/workqueue.h>\n+\n+#include \"atl2.h\"\n+\n+#define ATL2_DRV_VERSION \"2.2.3\"\n+\n+static char atl2_driver_name[] = \"atl2\";\n+static const char atl2_driver_string[] = \"Atheros(R) L2 Ethernet Driver\";\n+static char atl2_copyright[] = \"Copyright (c) 2007 Atheros Corporation.\";\n+static char atl2_driver_version[] = ATL2_DRV_VERSION;\n+\n+MODULE_AUTHOR(\"Atheros Corporation <xiong.huang@atheros.com>, Chris Snook <csnook@redhat.com>\");\n+MODULE_DESCRIPTION(\"Atheros Fast Ethernet Network Driver\");\n+MODULE_LICENSE(\"GPL\");\n+MODULE_VERSION(ATL2_DRV_VERSION);\n+\n+/*\n+ * atl2_pci_tbl - PCI Device ID Table\n+ */\n+static struct pci_device_id atl2_pci_tbl[] = {\n+\t{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2)},\n+\t/* required last entry */\n+\t{0,}\n+};\n+MODULE_DEVICE_TABLE(pci, atl2_pci_tbl);\n+\n+static void atl2_set_ethtool_ops(struct net_device *netdev);\n+\n+static void atl2_check_options(struct atl2_adapter *adapter);\n+\n+/*\n+ * atl2_sw_init - Initialize general software structures (struct atl2_adapter)\n+ * @adapter: board private structure to initialize\n+ *\n+ * atl2_sw_init initializes the Adapter private data structure.\n+ * Fields are initialized based on PCI device information and\n+ * OS network device settings (MTU size).\n+ */\n+static int __devinit atl2_sw_init(struct atl2_adapter *adapter)\n+{\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\tstruct pci_dev *pdev = adapter->pdev;\n+\n+\t/* PCI config space info */\n+\thw->vendor_id = pdev->vendor;\n+\thw->device_id = pdev->device;\n+\thw->subsystem_vendor_id = pdev->subsystem_vendor;\n+\thw->subsystem_id = pdev->subsystem_device;\n+\n+\tpci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);\n+\tpci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);\n+\n+\tadapter->wol = 0;\n+\tadapter->ict = 50000;  /* ~100ms */\n+\tadapter->link_speed = SPEED_0;   /* hardware init */\n+\tadapter->link_duplex = FULL_DUPLEX;\n+\n+\thw->phy_configured = false;\n+\thw->preamble_len = 7;\n+\thw->ipgt = 0x60;\n+\thw->min_ifg = 0x50;\n+\thw->ipgr1 = 0x40;\n+\thw->ipgr2 = 0x60;\n+\thw->retry_buf = 2;\n+\thw->max_retry = 0xf;\n+\thw->lcol = 0x37;\n+\thw->jam_ipg = 7;\n+\thw->fc_rxd_hi = 0;\n+\thw->fc_rxd_lo = 0;\n+\thw->max_frame_size = adapter->netdev->mtu;\n+\n+\tspin_lock_init(&adapter->stats_lock);\n+\tspin_lock_init(&adapter->tx_lock);\n+\n+\tset_bit(__ATL2_DOWN, &adapter->flags);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * atl2_set_multi - Multicast and Promiscuous mode set\n+ * @netdev: network interface device structure\n+ *\n+ * The set_multi entry point is called whenever the multicast address\n+ * list or the network interface flags are updated.  This routine is\n+ * responsible for configuring the hardware for proper multicast,\n+ * promiscuous mode, and all-multi behavior.\n+ */\n+static void atl2_set_multi(struct net_device *netdev)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\tstruct dev_mc_list *mc_ptr;\n+\tu32 rctl;\n+\tu32 hash_value;\n+\n+\t/* Check for Promiscuous and All Multicast modes */\n+\trctl = ATL2_READ_REG(hw, REG_MAC_CTRL);\n+\n+\tif (netdev->flags & IFF_PROMISC) {\n+\t\trctl |= MAC_CTRL_PROMIS_EN;\n+\t} else if (netdev->flags & IFF_ALLMULTI) {\n+\t\trctl |= MAC_CTRL_MC_ALL_EN;\n+\t\trctl &= ~MAC_CTRL_PROMIS_EN;\n+\t} else\n+\t\trctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);\n+\n+\tATL2_WRITE_REG(hw, REG_MAC_CTRL, rctl);\n+\n+\t/* clear the old settings from the multicast hash table */\n+\tATL2_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);\n+\tATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);\n+\n+\t/* comoute mc addresses' hash value ,and put it into hash table */\n+\tfor (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {\n+\t\thash_value = atl2_hash_mc_addr(hw, mc_ptr->dmi_addr);\n+\t\tatl2_hash_set(hw, hash_value);\n+\t}\n+}\n+\n+static void init_ring_ptrs(struct atl2_adapter *adapter)\n+{\n+\t/* Read / Write Ptr Initialize: */\n+\tadapter->txd_write_ptr = 0;\n+\tatomic_set(&adapter->txd_read_ptr, 0);\n+\n+\tadapter->rxd_read_ptr = 0;\n+\tadapter->rxd_write_ptr = 0;\n+\n+\tatomic_set(&adapter->txs_write_ptr, 0);\n+\tadapter->txs_next_clear = 0;\n+}\n+\n+/*\n+ * atl2_configure - Configure Transmit&Receive Unit after Reset\n+ * @adapter: board private structure\n+ *\n+ * Configure the Tx /Rx unit of the MAC after a reset.\n+ */\n+static int atl2_configure(struct atl2_adapter *adapter)\n+{\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\tu32 value;\n+\n+\t/* clear interrupt status */\n+\tATL2_WRITE_REG(&adapter->hw, REG_ISR, 0xffffffff);\n+\n+\t/* set MAC Address */\n+\tvalue = (((u32)hw->mac_addr[2]) << 24) |\n+\t\t(((u32)hw->mac_addr[3]) << 16) |\n+\t\t(((u32)hw->mac_addr[4]) << 8) |\n+\t\t(((u32)hw->mac_addr[5]));\n+\tATL2_WRITE_REG(hw, REG_MAC_STA_ADDR, value);\n+\tvalue = (((u32)hw->mac_addr[0]) << 8) |\n+\t\t(((u32)hw->mac_addr[1]));\n+\tATL2_WRITE_REG(hw, (REG_MAC_STA_ADDR+4), value);\n+\n+\t/* HI base address */\n+\tATL2_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI,\n+\t\t(u32)((adapter->ring_dma & 0xffffffff00000000ULL) >> 32));\n+\n+\t/* LO base address */\n+\tATL2_WRITE_REG(hw, REG_TXD_BASE_ADDR_LO,\n+\t\t(u32)(adapter->txd_dma & 0x00000000ffffffffULL));\n+\tATL2_WRITE_REG(hw, REG_TXS_BASE_ADDR_LO,\n+\t\t(u32)(adapter->txs_dma & 0x00000000ffffffffULL));\n+\tATL2_WRITE_REG(hw, REG_RXD_BASE_ADDR_LO,\n+\t\t(u32)(adapter->rxd_dma & 0x00000000ffffffffULL));\n+\n+\t/* element count */\n+\tATL2_WRITE_REGW(hw, REG_TXD_MEM_SIZE, (u16)(adapter->txd_ring_size/4));\n+\tATL2_WRITE_REGW(hw, REG_TXS_MEM_SIZE, (u16)adapter->txs_ring_size);\n+\tATL2_WRITE_REGW(hw, REG_RXD_BUF_NUM,  (u16)adapter->rxd_ring_size);\n+\n+\t/* config Internal SRAM */\n+/*\n+    ATL2_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_tx_end);\n+    ATL2_WRITE_REGW(hw, REG_SRAM_TXRAM_END, sram_rx_end);\n+*/\n+\n+\t/* config IPG/IFG */\n+\tvalue = (((u32)hw->ipgt & MAC_IPG_IFG_IPGT_MASK) <<\n+\t\tMAC_IPG_IFG_IPGT_SHIFT) |\n+\t\t(((u32)hw->min_ifg & MAC_IPG_IFG_MIFG_MASK) <<\n+\t\tMAC_IPG_IFG_MIFG_SHIFT) |\n+\t\t(((u32)hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK) <<\n+\t\tMAC_IPG_IFG_IPGR1_SHIFT)|\n+\t\t(((u32)hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK) <<\n+\t\tMAC_IPG_IFG_IPGR2_SHIFT);\n+\tATL2_WRITE_REG(hw, REG_MAC_IPG_IFG, value);\n+\n+\t/* config  Half-Duplex Control */\n+\tvalue = ((u32)hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |\n+\t\t(((u32)hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK) <<\n+\t\tMAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |\n+\t\tMAC_HALF_DUPLX_CTRL_EXC_DEF_EN |\n+\t\t(0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |\n+\t\t(((u32)hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK) <<\n+\t\tMAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);\n+\tATL2_WRITE_REG(hw, REG_MAC_HALF_DUPLX_CTRL, value);\n+\n+\t/* set Interrupt Moderator Timer */\n+\tATL2_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, adapter->imt);\n+\tATL2_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_ITIMER_EN);\n+\n+\t/* set Interrupt Clear Timer */\n+\tATL2_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, adapter->ict);\n+\n+\t/* set MTU */\n+\tATL2_WRITE_REG(hw, REG_MTU, adapter->netdev->mtu +\n+\t\tENET_HEADER_SIZE + VLAN_SIZE + ETHERNET_FCS_SIZE);\n+\n+\t/* 1590 */\n+\tATL2_WRITE_REG(hw, REG_TX_CUT_THRESH, 0x177);\n+\n+\t/* flow control */\n+\tATL2_WRITE_REGW(hw, REG_PAUSE_ON_TH, hw->fc_rxd_hi);\n+\tATL2_WRITE_REGW(hw, REG_PAUSE_OFF_TH, hw->fc_rxd_lo);\n+\n+\t/* Init mailbox */\n+\tATL2_WRITE_REGW(hw, REG_MB_TXD_WR_IDX, (u16)adapter->txd_write_ptr);\n+\tATL2_WRITE_REGW(hw, REG_MB_RXD_RD_IDX, (u16)adapter->rxd_read_ptr);\n+\n+\t/* enable DMA read/write */\n+\tATL2_WRITE_REGB(hw, REG_DMAR, DMAR_EN);\n+\tATL2_WRITE_REGB(hw, REG_DMAW, DMAW_EN);\n+\n+\tvalue = ATL2_READ_REG(&adapter->hw, REG_ISR);\n+\tif ((value & ISR_PHY_LINKDOWN) != 0)\n+\t\tvalue = 1; /* config failed */\n+\telse\n+\t\tvalue = 0;\n+\n+\t/* clear all interrupt status */\n+\tATL2_WRITE_REG(&adapter->hw, REG_ISR, 0x3fffffff);\n+\tATL2_WRITE_REG(&adapter->hw, REG_ISR, 0);\n+\treturn value;\n+}\n+\n+/*\n+ * atl2_setup_ring_resources - allocate Tx / RX descriptor resources\n+ * @adapter: board private structure\n+ *\n+ * Return 0 on success, negative on failure\n+ */\n+static s32 atl2_setup_ring_resources(struct atl2_adapter *adapter)\n+{\n+\tstruct pci_dev *pdev = adapter->pdev;\n+\tint size;\n+\tu8 offset = 0;\n+\n+\t/* real ring DMA buffer */\n+\tadapter->ring_size = size =\n+\t\tadapter->txd_ring_size * 1 + 7 +\t/* dword align */\n+\t\tadapter->txs_ring_size * 4 + 7 +\t/* dword align */\n+\t\tadapter->rxd_ring_size * 1536 + 127;\t/* 128bytes align */\n+\n+\tadapter->ring_vir_addr = pci_alloc_consistent(pdev, size,\n+\t\t&adapter->ring_dma);\n+\tif (!adapter->ring_vir_addr)\n+\t\treturn -ENOMEM;\n+\tmemset(adapter->ring_vir_addr, 0, adapter->ring_size);\n+\n+\t/* Init TXD Ring */\n+\tadapter->txd_dma = adapter->ring_dma ;\n+\toffset = (adapter->txd_dma & 0x7) ? (8 - (adapter->txd_dma & 0x7)) : 0;\n+\tadapter->txd_dma += offset;\n+\tadapter->txd_ring = (struct tx_pkt_header *) (adapter->ring_vir_addr +\n+\t\toffset);\n+\n+\t/* Init TXS Ring */\n+\tadapter->txs_dma = adapter->txd_dma + adapter->txd_ring_size;\n+\toffset = (adapter->txs_dma & 0x7) ? (8 - (adapter->txs_dma & 0x7)) : 0;\n+\tadapter->txs_dma += offset;\n+\tadapter->txs_ring = (struct tx_pkt_status *)\n+\t\t(((u8 *)adapter->txd_ring) + (adapter->txd_ring_size + offset));\n+\n+\t/* Init RXD Ring */\n+\tadapter->rxd_dma = adapter->txs_dma + adapter->txs_ring_size * 4;\n+\toffset = (adapter->rxd_dma & 127) ?\n+\t\t(128 - (adapter->rxd_dma & 127)) : 0;\n+\tif (offset > 7)\n+\t\toffset -= 8;\n+\telse\n+\t\toffset += (128 - 8);\n+\n+\tadapter->rxd_dma += offset;\n+\tadapter->rxd_ring = (struct rx_desc *) (((u8 *)adapter->txs_ring) +\n+\t\t(adapter->txs_ring_size * 4 + offset));\n+\n+/*\n+ * Read / Write Ptr Initialize:\n+ *      init_ring_ptrs(adapter);\n+ */\n+\treturn 0;\n+}\n+\n+/*\n+ * atl2_irq_enable - Enable default interrupt generation settings\n+ * @adapter: board private structure\n+ */\n+static inline void atl2_irq_enable(struct atl2_adapter *adapter)\n+{\n+\tATL2_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);\n+\tATL2_WRITE_FLUSH(&adapter->hw);\n+}\n+\n+/*\n+ * atl2_irq_disable - Mask off interrupt generation on the NIC\n+ * @adapter: board private structure\n+ */\n+static inline void atl2_irq_disable(struct atl2_adapter *adapter)\n+{\n+    ATL2_WRITE_REG(&adapter->hw, REG_IMR, 0);\n+    ATL2_WRITE_FLUSH(&adapter->hw);\n+    synchronize_irq(adapter->pdev->irq);\n+}\n+\n+#ifdef NETIF_F_HW_VLAN_TX\n+static void atl2_vlan_rx_register(struct net_device *netdev,\n+\tstruct vlan_group *grp)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tu32 ctrl;\n+\n+\tatl2_irq_disable(adapter);\n+\tadapter->vlgrp = grp;\n+\n+\tif (grp) {\n+\t\t/* enable VLAN tag insert/strip */\n+\t\tctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL);\n+\t\tctrl |= MAC_CTRL_RMV_VLAN;\n+\t\tATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl);\n+\t} else {\n+\t\t/* disable VLAN tag insert/strip */\n+\t\tctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL);\n+\t\tctrl &= ~MAC_CTRL_RMV_VLAN;\n+\t\tATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl);\n+\t}\n+\n+\tatl2_irq_enable(adapter);\n+}\n+\n+static void atl2_restore_vlan(struct atl2_adapter *adapter)\n+{\n+\tatl2_vlan_rx_register(adapter->netdev, adapter->vlgrp);\n+}\n+#endif\n+\n+static void atl2_intr_rx(struct atl2_adapter *adapter)\n+{\n+\tstruct net_device *netdev = adapter->netdev;\n+\tstruct rx_desc *rxd;\n+\tstruct sk_buff *skb;\n+\n+\tdo {\n+\t\trxd = adapter->rxd_ring+adapter->rxd_write_ptr;\n+\t\tif (!rxd->status.update)\n+\t\t\tbreak; /* end of tx */\n+\n+\t\t/* clear this flag at once */\n+\t\trxd->status.update = 0;\n+\n+\t\tif (rxd->status.ok && rxd->status.pkt_size >= 60) {\n+\t\t\tint rx_size = (int)(rxd->status.pkt_size - 4);\n+\t\t\t/* alloc new buffer */\n+\t\t\tskb = netdev_alloc_skb(netdev, rx_size + NET_IP_ALIGN);\n+\t\t\tif (NULL == skb) {\n+\t\t\t\tprintk(KERN_WARNING\n+\t\t\t\t\t\"%s: Mem squeeze, deferring packet.\\n\",\n+\t\t\t\t\tnetdev->name);\n+\t\t\t\t/*\n+\t\t\t\t * Check that some rx space is free. If not,\n+\t\t\t\t * free one and mark stats->rx_dropped++.\n+\t\t\t\t */\n+\t\t\t\tadapter->net_stats.rx_dropped++;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tskb_reserve(skb, NET_IP_ALIGN);\n+\t\t\tskb->dev = netdev;\n+\t\t\tmemcpy(skb->data, rxd->packet, rx_size);\n+\t\t\tskb_put(skb, rx_size);\n+\t\t\tskb->protocol = eth_type_trans(skb, netdev);\n+#ifdef NETIF_F_HW_VLAN_TX\n+\t\t\tif (adapter->vlgrp && (rxd->status.vlan)) {\n+\t\t\t\tu16 vlan_tag = (rxd->status.vtag>>4) |\n+\t\t\t\t\t((rxd->status.vtag&7) << 13) |\n+\t\t\t\t\t((rxd->status.vtag&8) << 9);\n+\t\t\t\tvlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);\n+\t\t\t} else\n+#endif\n+\t\t\tnetif_rx(skb);\n+\t\t\tadapter->net_stats.rx_bytes += rx_size;\n+\t\t\tadapter->net_stats.rx_packets++;\n+\t\t\tnetdev->last_rx = jiffies;\n+\t\t} else {\n+\t\t\tadapter->net_stats.rx_errors++;\n+\n+\t\t\tif (rxd->status.ok && rxd->status.pkt_size <= 60)\n+\t\t\t\tadapter->net_stats.rx_length_errors++;\n+\t\t\tif (rxd->status.mcast)\n+\t\t\t\tadapter->net_stats.multicast++;\n+\t\t\tif (rxd->status.crc)\n+\t\t\t\tadapter->net_stats.rx_crc_errors++;\n+\t\t\tif (rxd->status.align)\n+\t\t\t\tadapter->net_stats.rx_frame_errors++;\n+\t\t}\n+\n+\t\t/* advance write ptr */\n+\t\tif (++adapter->rxd_write_ptr == adapter->rxd_ring_size)\n+\t\t\tadapter->rxd_write_ptr = 0;\n+\t} while (1);\n+\n+\t/* update mailbox? */\n+\tadapter->rxd_read_ptr = adapter->rxd_write_ptr;\n+\tATL2_WRITE_REGW(&adapter->hw, REG_MB_RXD_RD_IDX, adapter->rxd_read_ptr);\n+}\n+\n+static void atl2_intr_tx(struct atl2_adapter *adapter)\n+{\n+\tu32 txd_read_ptr;\n+\tu32 txs_write_ptr;\n+\tstruct tx_pkt_status *txs;\n+\tstruct tx_pkt_header *txph;\n+\tint free_hole = 0;\n+\n+\tdo {\n+\t\ttxs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr);\n+\t\ttxs = adapter->txs_ring + txs_write_ptr;\n+\t\tif (!txs->update)\n+\t\t\tbreak; /* tx stop here */\n+\n+\t\tfree_hole = 1;\n+\t\ttxs->update = 0;\n+\n+\t\tif (++txs_write_ptr == adapter->txs_ring_size)\n+\t\t\ttxs_write_ptr = 0;\n+\t\tatomic_set(&adapter->txs_write_ptr, (int)txs_write_ptr);\n+\n+\t\ttxd_read_ptr = (u32) atomic_read(&adapter->txd_read_ptr);\n+\t\ttxph = (struct tx_pkt_header *)\n+\t\t\t(((u8 *)adapter->txd_ring) + txd_read_ptr);\n+\n+\t\tif (txph->pkt_size != txs->pkt_size) {\n+\t\t\tstruct tx_pkt_status *old_txs = txs;\n+\t\t\tprintk(KERN_WARNING\n+\t\t\t\t\"%s: txs packet size not consistent with txd\"\n+\t\t\t\t\" txd_:0x%08x, txs_:0x%08x!\\n\",\n+\t\t\t\tadapter->netdev->name,\n+\t\t\t\t*(u32 *)txph, *(u32 *)txs);\n+\t\t\tprintk(KERN_WARNING\n+\t\t\t\t\"txd read ptr: 0x%x\\n\",\n+\t\t\t\ttxd_read_ptr);\n+\t\t\ttxs = adapter->txs_ring + txs_write_ptr;\n+\t\t\tprintk(KERN_WARNING\n+\t\t\t\t\"txs-behind:0x%08x\\n\",\n+\t\t\t\t*(u32 *)txs);\n+\t\t\tif (txs_write_ptr < 2) {\n+\t\t\t\ttxs = adapter->txs_ring +\n+\t\t\t\t\t(adapter->txs_ring_size +\n+\t\t\t\t\ttxs_write_ptr - 2);\n+\t\t\t} else {\n+\t\t\t\ttxs = adapter->txs_ring + (txs_write_ptr - 2);\n+\t\t\t}\n+\t\t\tprintk(KERN_WARNING\n+\t\t\t\t\"txs-before:0x%08x\\n\",\n+\t\t\t\t*(u32 *)txs);\n+\t\t\ttxs = old_txs;\n+\t\t}\n+\n+\t\t /* 4for TPH */\n+\t\ttxd_read_ptr += (((u32)(txph->pkt_size) + 7) & ~3);\n+\t\tif (txd_read_ptr >= adapter->txd_ring_size)\n+\t\t\ttxd_read_ptr -= adapter->txd_ring_size;\n+\n+\t\tatomic_set(&adapter->txd_read_ptr, (int)txd_read_ptr);\n+\n+\t\t/* tx statistics: */\n+\t\tif (txs->ok)\n+\t\t\tadapter->net_stats.tx_packets++;\n+\t\telse\n+\t\t\tadapter->net_stats.tx_errors++;\n+\n+\t\tif (txs->defer)\n+\t\t\tadapter->net_stats.collisions++;\n+\t\tif (txs->abort_col)\n+\t\t\tadapter->net_stats.tx_aborted_errors++;\n+\t\tif (txs->late_col)\n+\t\t\tadapter->net_stats.tx_window_errors++;\n+\t\tif (txs->underun)\n+\t\t\tadapter->net_stats.tx_fifo_errors++;\n+\t} while (1);\n+\n+\tif (free_hole) {\n+\t\tif (netif_queue_stopped(adapter->netdev) &&\n+\t\t\tnetif_carrier_ok(adapter->netdev))\n+\t\t\tnetif_wake_queue(adapter->netdev);\n+\t}\n+}\n+\n+static void atl2_check_for_link(struct atl2_adapter *adapter)\n+{\n+\tstruct net_device *netdev = adapter->netdev;\n+\tu16 phy_data = 0;\n+\n+\tspin_lock(&adapter->stats_lock);\n+\tatl2_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);\n+\tatl2_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);\n+\tspin_unlock(&adapter->stats_lock);\n+\n+\t/* notify upper layer link down ASAP */\n+\tif (!(phy_data & BMSR_LSTATUS)) { /* Link Down */\n+\t\tif (netif_carrier_ok(netdev)) { /* old link state: Up */\n+\t\tprintk(KERN_INFO \"%s: %s NIC Link is Down\\n\",\n+\t\t\tatl2_driver_name, netdev->name);\n+\t\tadapter->link_speed = SPEED_0;\n+\t\tnetif_carrier_off(netdev);\n+\t\tnetif_stop_queue(netdev);\n+\t\t}\n+\t}\n+\tschedule_work(&adapter->link_chg_task);\n+}\n+\n+static inline void atl2_clear_phy_int(struct atl2_adapter *adapter)\n+{\n+\tu16 phy_data;\n+\tspin_lock(&adapter->stats_lock);\n+\tatl2_read_phy_reg(&adapter->hw, 19, &phy_data);\n+\tspin_unlock(&adapter->stats_lock);\n+}\n+\n+/*\n+ * atl2_intr - Interrupt Handler\n+ * @irq: interrupt number\n+ * @data: pointer to a network interface device structure\n+ * @pt_regs: CPU registers structure\n+ */\n+static irqreturn_t atl2_intr(int irq, void *data)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(data);\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\tu32 status;\n+\n+\tstatus = ATL2_READ_REG(hw, REG_ISR);\n+\tif (0 == status)\n+\t\treturn IRQ_NONE;\n+\n+\t/* link event */\n+\tif (status & ISR_PHY)\n+\t\tatl2_clear_phy_int(adapter);\n+\n+\t/* clear ISR status, and Enable CMB DMA/Disable Interrupt */\n+\tATL2_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);\n+\n+\t/* check if PCIE PHY Link down */\n+\tif (status & ISR_PHY_LINKDOWN) {\n+\t\tif (netif_running(adapter->netdev)) { /* reset MAC */\n+\t\t\tATL2_WRITE_REG(hw, REG_ISR, 0);\n+\t\t\tATL2_WRITE_REG(hw, REG_IMR, 0);\n+\t\t\tATL2_WRITE_FLUSH(hw);\n+\t\t\tschedule_work(&adapter->reset_task);\n+\t\t\treturn IRQ_HANDLED;\n+\t\t}\n+\t}\n+\n+\t/* check if DMA read/write error? */\n+\tif (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {\n+\t\tATL2_WRITE_REG(hw, REG_ISR, 0);\n+\t\tATL2_WRITE_REG(hw, REG_IMR, 0);\n+\t\tATL2_WRITE_FLUSH(hw);\n+\t\tschedule_work(&adapter->reset_task);\n+\t\treturn IRQ_HANDLED;\n+\t}\n+\n+\t/* link event */\n+\tif (status & (ISR_PHY | ISR_MANUAL)) {\n+\t\tadapter->net_stats.tx_carrier_errors++;\n+\t\tatl2_check_for_link(adapter);\n+\t}\n+\n+\t/* transmit event */\n+\tif (status & ISR_TX_EVENT)\n+\t\tatl2_intr_tx(adapter);\n+\n+\t/* rx exception */\n+\tif (status & ISR_RX_EVENT)\n+\t\tatl2_intr_rx(adapter);\n+\n+\t/* re-enable Interrupt */\n+\tATL2_WRITE_REG(&adapter->hw, REG_ISR, 0);\n+\treturn IRQ_HANDLED;\n+}\n+\n+static int atl2_request_irq(struct atl2_adapter *adapter)\n+{\n+\tstruct net_device *netdev = adapter->netdev;\n+\tint flags, err = 0;\n+\n+\tflags = IRQF_SHARED;\n+#ifdef CONFIG_PCI_MSI\n+\tadapter->have_msi = true;\n+\terr = pci_enable_msi(adapter->pdev);\n+\tif (err)\n+\t\tadapter->have_msi = false;\n+\n+\tif (adapter->have_msi)\n+\t\tflags &= ~IRQF_SHARED;\n+#endif\n+\n+\treturn request_irq(adapter->pdev->irq, &atl2_intr, flags, netdev->name,\n+\t\tnetdev);\n+}\n+\n+/*\n+ * atl2_free_ring_resources - Free Tx / RX descriptor Resources\n+ * @adapter: board private structure\n+ *\n+ * Free all transmit software resources\n+ */\n+static void atl2_free_ring_resources(struct atl2_adapter *adapter)\n+{\n+\tstruct pci_dev *pdev = adapter->pdev;\n+\tpci_free_consistent(pdev, adapter->ring_size, adapter->ring_vir_addr,\n+\t\tadapter->ring_dma);\n+}\n+\n+/*\n+ * atl2_open - Called when a network interface is made active\n+ * @netdev: network interface device structure\n+ *\n+ * Returns 0 on success, negative value on failure\n+ *\n+ * The open entry point is called when a network interface is made\n+ * active by the system (IFF_UP).  At this point all resources needed\n+ * for transmit and receive operations are allocated, the interrupt\n+ * handler is registered with the OS, the watchdog timer is started,\n+ * and the stack is notified that the interface is ready.\n+ */\n+static int atl2_open(struct net_device *netdev)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tint err;\n+\tu32 val;\n+\n+\t/* disallow open during test */\n+\tif (test_bit(__ATL2_TESTING, &adapter->flags))\n+\t\treturn -EBUSY;\n+\n+\t/* allocate transmit descriptors */\n+\terr = atl2_setup_ring_resources(adapter);\n+\tif (err)\n+\t\treturn err;\n+\n+\terr = atl2_init_hw(&adapter->hw);\n+\tif (err) {\n+\t\terr = -EIO;\n+\t\tgoto err_init_hw;\n+\t}\n+\n+\t/* hardware has been reset, we need to reload some things */\n+\tatl2_set_multi(netdev);\n+\tinit_ring_ptrs(adapter);\n+\n+#ifdef NETIF_F_HW_VLAN_TX\n+\tatl2_restore_vlan(adapter);\n+#endif\n+\n+\tif (atl2_configure(adapter)) {\n+\t\terr = -EIO;\n+\t\tgoto err_config;\n+\t}\n+\n+\terr = atl2_request_irq(adapter);\n+\tif (err)\n+\t\tgoto err_req_irq;\n+\n+\tclear_bit(__ATL2_DOWN, &adapter->flags);\n+\n+\tmod_timer(&adapter->watchdog_timer, jiffies + 4*HZ);\n+\n+\tval = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL);\n+\tATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL,\n+\t\tval | MASTER_CTRL_MANUAL_INT);\n+\n+\tatl2_irq_enable(adapter);\n+\n+\treturn 0;\n+\n+err_init_hw:\n+err_req_irq:\n+err_config:\n+\tatl2_free_ring_resources(adapter);\n+\tatl2_reset_hw(&adapter->hw);\n+\n+\treturn err;\n+}\n+\n+static void atl2_down(struct atl2_adapter *adapter)\n+{\n+\tstruct net_device *netdev = adapter->netdev;\n+\n+\t/* signal that we're down so the interrupt handler does not\n+\t * reschedule our watchdog timer */\n+\tset_bit(__ATL2_DOWN, &adapter->flags);\n+\n+#ifdef NETIF_F_LLTX\n+\tnetif_stop_queue(netdev);\n+#else\n+\tnetif_tx_disable(netdev);\n+#endif\n+\n+\t/* reset MAC to disable all RX/TX */\n+\tatl2_reset_hw(&adapter->hw);\n+\tmsleep(1);\n+\n+\tatl2_irq_disable(adapter);\n+\n+\tdel_timer_sync(&adapter->watchdog_timer);\n+\tdel_timer_sync(&adapter->phy_config_timer);\n+\tclear_bit(0, &adapter->cfg_phy);\n+\n+\tnetif_carrier_off(netdev);\n+\tadapter->link_speed = SPEED_0;\n+\tadapter->link_duplex = -1;\n+}\n+\n+static void atl2_free_irq(struct atl2_adapter *adapter)\n+{\n+\tstruct net_device *netdev = adapter->netdev;\n+\n+\tfree_irq(adapter->pdev->irq, netdev);\n+\n+#ifdef CONFIG_PCI_MSI\n+\tif (adapter->have_msi)\n+\t\tpci_disable_msi(adapter->pdev);\n+#endif\n+}\n+\n+/*\n+ * atl2_close - Disables a network interface\n+ * @netdev: network interface device structure\n+ *\n+ * Returns 0, this is not allowed to fail\n+ *\n+ * The close entry point is called when an interface is de-activated\n+ * by the OS.  The hardware is still under the drivers control, but\n+ * needs to be disabled.  A global MAC reset is issued to stop the\n+ * hardware, and all transmit and receive resources are freed.\n+ */\n+static int atl2_close(struct net_device *netdev)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\n+\tWARN_ON(test_bit(__ATL2_RESETTING, &adapter->flags));\n+\n+\tatl2_down(adapter);\n+\tatl2_free_irq(adapter);\n+\tatl2_free_ring_resources(adapter);\n+\n+\treturn 0;\n+}\n+\n+static inline int TxsFreeUnit(struct atl2_adapter *adapter)\n+{\n+\tu32 txs_write_ptr = (u32) atomic_read(&adapter->txs_write_ptr);\n+\n+\treturn (adapter->txs_next_clear >= txs_write_ptr) ?\n+\t\t(int) (adapter->txs_ring_size - adapter->txs_next_clear +\n+\t\ttxs_write_ptr - 1) :\n+\t\t(int) (txs_write_ptr - adapter->txs_next_clear - 1);\n+}\n+\n+static inline int TxdFreeBytes(struct atl2_adapter *adapter)\n+{\n+\tu32 txd_read_ptr = (u32)atomic_read(&adapter->txd_read_ptr);\n+\n+\treturn (adapter->txd_write_ptr >= txd_read_ptr) ?\n+\t\t(int) (adapter->txd_ring_size - adapter->txd_write_ptr +\n+\t\ttxd_read_ptr - 1) :\n+\t\t(int) (txd_read_ptr - adapter->txd_write_ptr - 1);\n+}\n+\n+static int atl2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tunsigned long flags;\n+\tstruct tx_pkt_header *txph;\n+\tu32 offset, copy_len;\n+\tint txs_unused;\n+\tint txbuf_unused;\n+\n+\tif (test_bit(__ATL2_DOWN, &adapter->flags)) {\n+\t\tdev_kfree_skb_any(skb);\n+\t\treturn NETDEV_TX_OK;\n+\t}\n+\n+\tif (unlikely(skb->len <= 0)) {\n+\t\tdev_kfree_skb_any(skb);\n+\t\treturn NETDEV_TX_OK;\n+\t}\n+\n+#ifdef NETIF_F_LLTX\n+\tlocal_irq_save(flags);\n+\tif (!spin_trylock(&adapter->tx_lock)) {\n+\t\t/* Collision - tell upper layer to requeue */\n+\t\tlocal_irq_restore(flags);\n+\t\treturn NETDEV_TX_LOCKED;\n+\t}\n+#else\n+\tspin_lock_irqsave(&adapter->tx_lock, flags);\n+#endif\n+\ttxs_unused = TxsFreeUnit(adapter);\n+\ttxbuf_unused = TxdFreeBytes(adapter);\n+\n+\tif (skb->len + sizeof(struct tx_pkt_header) + 4  > txbuf_unused ||\n+\t\ttxs_unused < 1) {\n+\t\t/* not enough resources */\n+\t\tnetif_stop_queue(netdev);\n+\t\tspin_unlock_irqrestore(&adapter->tx_lock, flags);\n+\t\treturn NETDEV_TX_BUSY;\n+\t}\n+\n+\toffset = adapter->txd_write_ptr;\n+\n+\ttxph = (struct tx_pkt_header *) (((u8 *)adapter->txd_ring) + offset);\n+\n+\t*(u32 *)txph = 0;\n+\ttxph->pkt_size = skb->len;\n+\n+\toffset += 4;\n+\tif (offset >= adapter->txd_ring_size)\n+\t\toffset -= adapter->txd_ring_size;\n+\tcopy_len = adapter->txd_ring_size - offset;\n+\tif (copy_len >= skb->len) {\n+\t\tmemcpy(((u8 *)adapter->txd_ring) + offset, skb->data, skb->len);\n+\t\toffset += ((u32)(skb->len + 3) & ~3);\n+\t} else {\n+\t\tmemcpy(((u8 *)adapter->txd_ring)+offset, skb->data, copy_len);\n+\t\tmemcpy((u8 *)adapter->txd_ring, skb->data+copy_len,\n+\t\t\tskb->len-copy_len);\n+\t\toffset = ((u32)(skb->len-copy_len + 3) & ~3);\n+\t}\n+#ifdef NETIF_F_HW_VLAN_TX\n+\tif (adapter->vlgrp && vlan_tx_tag_present(skb)) {\n+\t\tu16 vlan_tag = vlan_tx_tag_get(skb);\n+\t\tvlan_tag = (vlan_tag << 4) |\n+\t\t\t(vlan_tag >> 13) |\n+\t\t\t((vlan_tag >> 9) & 0x8);\n+\t\ttxph->ins_vlan = 1;\n+\t\ttxph->vlan = vlan_tag;\n+\t}\n+#endif\n+\tif (offset >= adapter->txd_ring_size)\n+\t\toffset -= adapter->txd_ring_size;\n+\tadapter->txd_write_ptr = offset;\n+\n+\t/* clear txs before send */\n+\tadapter->txs_ring[adapter->txs_next_clear].update = 0;\n+\tif (++adapter->txs_next_clear == adapter->txs_ring_size)\n+\t\tadapter->txs_next_clear = 0;\n+\n+\tATL2_WRITE_REGW(&adapter->hw, REG_MB_TXD_WR_IDX,\n+\t\t(adapter->txd_write_ptr >> 2));\n+\n+\tspin_unlock_irqrestore(&adapter->tx_lock, flags);\n+\n+\tnetdev->trans_start = jiffies;\n+\tdev_kfree_skb_any(skb);\n+\treturn NETDEV_TX_OK;\n+}\n+\n+/*\n+ * atl2_get_stats - Get System Network Statistics\n+ * @netdev: network interface device structure\n+ *\n+ * Returns the address of the device statistics structure.\n+ * The statistics are actually updated from the timer callback.\n+ */\n+static struct net_device_stats *atl2_get_stats(struct net_device *netdev)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\treturn &adapter->net_stats;\n+}\n+\n+/*\n+ * atl2_change_mtu - Change the Maximum Transfer Unit\n+ * @netdev: network interface device structure\n+ * @new_mtu: new value for maximum frame size\n+ *\n+ * Returns 0 on success, negative on failure\n+ */\n+static int atl2_change_mtu(struct net_device *netdev, int new_mtu)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\n+\tif ((new_mtu < 40) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE)))\n+\t\treturn -EINVAL;\n+\n+\t/* set MTU */\n+\tif (hw->max_frame_size != new_mtu) {\n+\t\tnetdev->mtu = new_mtu;\n+\t\tATL2_WRITE_REG(hw, REG_MTU, new_mtu + ENET_HEADER_SIZE +\n+\t\t\tVLAN_SIZE + ETHERNET_FCS_SIZE);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * atl2_set_mac - Change the Ethernet Address of the NIC\n+ * @netdev: network interface device structure\n+ * @p: pointer to an address structure\n+ *\n+ * Returns 0 on success, negative on failure\n+ */\n+static int atl2_set_mac(struct net_device *netdev, void *p)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tstruct sockaddr *addr = p;\n+\n+\tif (!is_valid_ether_addr(addr->sa_data))\n+\t\treturn -EADDRNOTAVAIL;\n+\n+\tif (netif_running(netdev))\n+\t\treturn -EBUSY;\n+\n+\tmemcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);\n+\tmemcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);\n+\n+\tatl2_set_mac_addr(&adapter->hw);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * atl2_mii_ioctl -\n+ * @netdev:\n+ * @ifreq:\n+ * @cmd:\n+ */\n+static int atl2_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tstruct mii_ioctl_data *data = if_mii(ifr);\n+\tunsigned long flags;\n+\n+\tswitch (cmd) {\n+\tcase SIOCGMIIPHY:\n+\t\tdata->phy_id = 0;\n+\t\tbreak;\n+\tcase SIOCGMIIREG:\n+\t\tif (!capable(CAP_NET_ADMIN))\n+\t\t\treturn -EPERM;\n+\t\tspin_lock_irqsave(&adapter->stats_lock, flags);\n+\t\tif (atl2_read_phy_reg(&adapter->hw,\n+\t\t\tdata->reg_num & 0x1F, &data->val_out)) {\n+\t\t\tspin_unlock_irqrestore(&adapter->stats_lock, flags);\n+\t\t\treturn -EIO;\n+\t\t}\n+\t\tspin_unlock_irqrestore(&adapter->stats_lock, flags);\n+\t\tbreak;\n+\tcase SIOCSMIIREG:\n+\t\tif (!capable(CAP_NET_ADMIN))\n+\t\t\treturn -EPERM;\n+\t\tif (data->reg_num & ~(0x1F))\n+\t\t\treturn -EFAULT;\n+\t\tspin_lock_irqsave(&adapter->stats_lock, flags);\n+\t\tif (atl2_write_phy_reg(&adapter->hw, data->reg_num,\n+\t\t\tdata->val_in)) {\n+\t\t\tspin_unlock_irqrestore(&adapter->stats_lock, flags);\n+\t\t\treturn -EIO;\n+\t\t}\n+\t\tspin_unlock_irqrestore(&adapter->stats_lock, flags);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\treturn 0;\n+}\n+\n+/*\n+ * atl2_ioctl -\n+ * @netdev:\n+ * @ifreq:\n+ * @cmd:\n+ */\n+static int atl2_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)\n+{\n+\tswitch (cmd) {\n+\tcase SIOCGMIIPHY:\n+\tcase SIOCGMIIREG:\n+\tcase SIOCSMIIREG:\n+\t\treturn atl2_mii_ioctl(netdev, ifr, cmd);\n+#ifdef ETHTOOL_OPS_COMPAT\n+\tcase SIOCETHTOOL:\n+\t\treturn ethtool_ioctl(ifr);\n+#endif\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+}\n+\n+/*\n+ * atl2_tx_timeout - Respond to a Tx Hang\n+ * @netdev: network interface device structure\n+ */\n+static void atl2_tx_timeout(struct net_device *netdev)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\n+\t/* Do the reset outside of interrupt context */\n+\tschedule_work(&adapter->reset_task);\n+}\n+\n+/*\n+ * atl2_watchdog - Timer Call-back\n+ * @data: pointer to netdev cast into an unsigned long\n+ */\n+static void atl2_watchdog(unsigned long data)\n+{\n+\tstruct atl2_adapter *adapter = (struct atl2_adapter *) data;\n+\tu32 drop_rxd, drop_rxs;\n+\tunsigned long flags;\n+\n+\tif (!test_bit(__ATL2_DOWN, &adapter->flags)) {\n+\t\tspin_lock_irqsave(&adapter->stats_lock, flags);\n+\t\tdrop_rxd = ATL2_READ_REG(&adapter->hw, REG_STS_RXD_OV);\n+\t\tdrop_rxs = ATL2_READ_REG(&adapter->hw, REG_STS_RXS_OV);\n+\t\tadapter->net_stats.rx_over_errors += (drop_rxd+drop_rxs);\n+\t\tspin_unlock_irqrestore(&adapter->stats_lock, flags);\n+\n+\t\t/* Reset the timer */\n+\t\tmod_timer(&adapter->watchdog_timer, jiffies + 4 * HZ);\n+\t}\n+}\n+\n+/*\n+ * atl2_phy_config - Timer Call-back\n+ * @data: pointer to netdev cast into an unsigned long\n+ */\n+static void atl2_phy_config(unsigned long data)\n+{\n+\tstruct atl2_adapter *adapter = (struct atl2_adapter *) data;\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\tunsigned long flags;\n+\n+\tspin_lock_irqsave(&adapter->stats_lock, flags);\n+\tatl2_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);\n+\tatl2_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN |\n+\t\tMII_CR_RESTART_AUTO_NEG);\n+\tspin_unlock_irqrestore(&adapter->stats_lock, flags);\n+\tclear_bit(0, &adapter->cfg_phy);\n+}\n+\n+static int atl2_up(struct atl2_adapter *adapter)\n+{\n+\tstruct net_device *netdev = adapter->netdev;\n+\tint err = 0;\n+\tu32 val;\n+\n+\t/* hardware has been reset, we need to reload some things */\n+\n+\terr = atl2_init_hw(&adapter->hw);\n+\tif (err) {\n+\t\terr = -EIO;\n+\t\treturn err;\n+\t}\n+\n+\tatl2_set_multi(netdev);\n+\tinit_ring_ptrs(adapter);\n+\n+#ifdef NETIF_F_HW_VLAN_TX\n+\tatl2_restore_vlan(adapter);\n+#endif\n+\n+\tif (atl2_configure(adapter)) {\n+\t\terr = -EIO;\n+\t\tgoto err_up;\n+\t}\n+\n+\tclear_bit(__ATL2_DOWN, &adapter->flags);\n+\n+\tval = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL);\n+\tATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, val |\n+\t\tMASTER_CTRL_MANUAL_INT);\n+\n+\tatl2_irq_enable(adapter);\n+\n+err_up:\n+\treturn err;\n+}\n+\n+static void atl2_reinit_locked(struct atl2_adapter *adapter)\n+{\n+\tWARN_ON(in_interrupt());\n+\twhile (test_and_set_bit(__ATL2_RESETTING, &adapter->flags))\n+\t\tmsleep(1);\n+\tatl2_down(adapter);\n+\tatl2_up(adapter);\n+\tclear_bit(__ATL2_RESETTING, &adapter->flags);\n+}\n+\n+static void atl2_reset_task(struct work_struct *work)\n+{\n+\tstruct atl2_adapter *adapter;\n+\tadapter = container_of(work, struct atl2_adapter, reset_task);\n+\n+\tatl2_reinit_locked(adapter);\n+}\n+\n+static void atl2_setup_mac_ctrl(struct atl2_adapter *adapter)\n+{\n+\tu32 value;\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\tstruct net_device *netdev = adapter->netdev;\n+\n+\t/* Config MAC CTRL Register */\n+\tvalue = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN | MAC_CTRL_MACLP_CLK_PHY;\n+\n+\t/* duplex */\n+\tif (FULL_DUPLEX == adapter->link_duplex)\n+\t\tvalue |= MAC_CTRL_DUPLX;\n+\n+\t/* flow control */\n+\tvalue |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);\n+\n+\t/* PAD & CRC */\n+\tvalue |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);\n+\n+\t/* preamble length */\n+\tvalue |= (((u32)adapter->hw.preamble_len & MAC_CTRL_PRMLEN_MASK) <<\n+\t\tMAC_CTRL_PRMLEN_SHIFT);\n+\n+\t/* vlan */\n+\tif (adapter->vlgrp)\n+\t\tvalue |= MAC_CTRL_RMV_VLAN;\n+\n+\t/* filter mode */\n+\tvalue |= MAC_CTRL_BC_EN;\n+\tif (netdev->flags & IFF_PROMISC)\n+\t\tvalue |= MAC_CTRL_PROMIS_EN;\n+\telse if (netdev->flags & IFF_ALLMULTI)\n+\t\tvalue |= MAC_CTRL_MC_ALL_EN;\n+\n+\t/* half retry buffer */\n+\tvalue |= (((u32)(adapter->hw.retry_buf &\n+\t\tMAC_CTRL_HALF_LEFT_BUF_MASK)) << MAC_CTRL_HALF_LEFT_BUF_SHIFT);\n+\n+\tATL2_WRITE_REG(hw, REG_MAC_CTRL, value);\n+}\n+\n+static int atl2_check_link(struct atl2_adapter *adapter)\n+{\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\tstruct net_device *netdev = adapter->netdev;\n+\tint ret_val;\n+\tu16 speed, duplex, phy_data;\n+\tint reconfig = 0;\n+\n+\t/* MII_BMSR must read twise */\n+\tatl2_read_phy_reg(hw, MII_BMSR, &phy_data);\n+\tatl2_read_phy_reg(hw, MII_BMSR, &phy_data);\n+\tif (!(phy_data&BMSR_LSTATUS)) { /* link down */\n+\t\tif (netif_carrier_ok(netdev)) { /* old link state: Up */\n+\t\t\tu32 value;\n+\t\t\t/* disable rx */\n+\t\t\tvalue = ATL2_READ_REG(hw, REG_MAC_CTRL);\n+\t\t\tvalue &= ~MAC_CTRL_RX_EN;\n+\t\t\tATL2_WRITE_REG(hw, REG_MAC_CTRL, value);\n+\t\t\tadapter->link_speed = SPEED_0;\n+\t\t\tnetif_carrier_off(netdev);\n+\t\t\tnetif_stop_queue(netdev);\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\n+\t/* Link Up */\n+\tret_val = atl2_get_speed_and_duplex(hw, &speed, &duplex);\n+\tif (ret_val)\n+\t\treturn ret_val;\n+\tswitch (hw->MediaType) {\n+\tcase MEDIA_TYPE_100M_FULL:\n+\t\tif (speed  != SPEED_100 || duplex != FULL_DUPLEX)\n+\t\t\treconfig = 1;\n+\t\tbreak;\n+\tcase MEDIA_TYPE_100M_HALF:\n+\t\tif (speed  != SPEED_100 || duplex != HALF_DUPLEX)\n+\t\t\treconfig = 1;\n+\t\tbreak;\n+\tcase MEDIA_TYPE_10M_FULL:\n+\t\tif (speed != SPEED_10 || duplex != FULL_DUPLEX)\n+\t\t\treconfig = 1;\n+\t\tbreak;\n+\tcase MEDIA_TYPE_10M_HALF:\n+\t\tif (speed  != SPEED_10 || duplex != HALF_DUPLEX)\n+\t\t\treconfig = 1;\n+\t\tbreak;\n+\t}\n+\t/* link result is our setting */\n+\tif (reconfig == 0) {\n+\t\tif (adapter->link_speed != speed ||\n+\t\t\tadapter->link_duplex != duplex) {\n+\t\t\tadapter->link_speed = speed;\n+\t\t\tadapter->link_duplex = duplex;\n+\t\t\tatl2_setup_mac_ctrl(adapter);\n+\t\t\tprintk(KERN_INFO \"%s: %s NIC Link is Up<%d Mbps %s>\\n\",\n+\t\t\t\tatl2_driver_name, netdev->name,\n+\t\t\t\tadapter->link_speed,\n+\t\t\t\tadapter->link_duplex == FULL_DUPLEX ?\n+\t\t\t\t\t\"Full Duplex\" : \"Half Duplex\");\n+\t\t}\n+\n+\t\tif (!netif_carrier_ok(netdev)) { /* Link down -> Up */\n+\t\t\tnetif_carrier_on(netdev);\n+\t\t\tnetif_wake_queue(netdev);\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\n+\t/* change original link status */\n+\tif (netif_carrier_ok(netdev)) {\n+\t\tu32 value;\n+\t\t/* disable rx */\n+\t\tvalue = ATL2_READ_REG(hw, REG_MAC_CTRL);\n+\t\tvalue &= ~MAC_CTRL_RX_EN;\n+\t\tATL2_WRITE_REG(hw, REG_MAC_CTRL, value);\n+\n+\t\tadapter->link_speed = SPEED_0;\n+\t\tnetif_carrier_off(netdev);\n+\t\tnetif_stop_queue(netdev);\n+\t}\n+\n+\t/* auto-neg, insert timer to re-config phy\n+\t * (if interval smaller than 5 seconds, something strange) */\n+\tif (!test_bit(__ATL2_DOWN, &adapter->flags)) {\n+\t\tif (!test_and_set_bit(0, &adapter->cfg_phy))\n+\t\t\tmod_timer(&adapter->phy_config_timer, jiffies + 5 * HZ);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * atl2_link_chg_task - deal with link change event Out of interrupt context\n+ * @netdev: network interface device structure\n+ */\n+static void atl2_link_chg_task(struct work_struct *work)\n+{\n+\tstruct atl2_adapter *adapter;\n+\tunsigned long flags;\n+\n+\tadapter = container_of(work, struct atl2_adapter, link_chg_task);\n+\n+\tspin_lock_irqsave(&adapter->stats_lock, flags);\n+\tatl2_check_link(adapter);\n+\tspin_unlock_irqrestore(&adapter->stats_lock, flags);\n+}\n+\n+static void atl2_setup_pcicmd(struct pci_dev *pdev)\n+{\n+\tu16 cmd;\n+\n+\tpci_read_config_word(pdev, PCI_COMMAND, &cmd);\n+\n+\tif (cmd & PCI_COMMAND_INTX_DISABLE)\n+\t\tcmd &= ~PCI_COMMAND_INTX_DISABLE;\n+\tif (cmd & PCI_COMMAND_IO)\n+\t\tcmd &= ~PCI_COMMAND_IO;\n+\tif (0 == (cmd & PCI_COMMAND_MEMORY))\n+\t\tcmd |= PCI_COMMAND_MEMORY;\n+\tif (0 == (cmd & PCI_COMMAND_MASTER))\n+\t\tcmd |= PCI_COMMAND_MASTER;\n+\tpci_write_config_word(pdev, PCI_COMMAND, cmd);\n+\n+\t/*\n+\t * some motherboards BIOS(PXE/EFI) driver may set PME\n+\t * while they transfer control to OS (Windows/Linux)\n+\t * so we should clear this bit before NIC work normally\n+\t */\n+\tpci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0);\n+}\n+\n+/*\n+ * atl2_probe - Device Initialization Routine\n+ * @pdev: PCI device information struct\n+ * @ent: entry in atl2_pci_tbl\n+ *\n+ * Returns 0 on success, negative on failure\n+ *\n+ * atl2_probe initializes an adapter identified by a pci_dev structure.\n+ * The OS initialization, configuring of the adapter private structure,\n+ * and a hardware reset occur.\n+ */\n+static int __devinit atl2_probe(struct pci_dev *pdev,\n+\tconst struct pci_device_id *ent)\n+{\n+\tstruct net_device *netdev;\n+\tstruct atl2_adapter *adapter;\n+\tstatic int cards_found;\n+\tunsigned long mmio_start;\n+\tint mmio_len;\n+\tint err;\n+\n+\tcards_found = 0;\n+\n+\terr = pci_enable_device(pdev);\n+\tif (err)\n+\t\treturn err;\n+\n+\t/*\n+\t * atl2 is a shared-high-32-bit device, so we're stuck with 32-bit DMA\n+\t * until the kernel has the proper infrastructure to support 64-bit DMA\n+\t * on these devices.\n+\t */\n+\tif (pci_set_dma_mask(pdev, DMA_32BIT_MASK) &&\n+\t\tpci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {\n+\t\tprintk(KERN_ERR \"atl2: No usable DMA configuration, aborting\\n\");\n+\t\tgoto err_dma;\n+\t}\n+\n+\t/* Mark all PCI regions associated with PCI device\n+\t * pdev as being reserved by owner atl2_driver_name */\n+\terr = pci_request_regions(pdev, atl2_driver_name);\n+\tif (err)\n+\t\tgoto err_pci_reg;\n+\n+\t/* Enables bus-mastering on the device and calls\n+\t * pcibios_set_master to do the needed arch specific settings */\n+\tpci_set_master(pdev);\n+\n+\terr = -ENOMEM;\n+\tnetdev = alloc_etherdev(sizeof(struct atl2_adapter));\n+\tif (!netdev)\n+\t\tgoto err_alloc_etherdev;\n+\n+\tSET_NETDEV_DEV(netdev, &pdev->dev);\n+\n+\tpci_set_drvdata(pdev, netdev);\n+\tadapter = netdev_priv(netdev);\n+\tadapter->netdev = netdev;\n+\tadapter->pdev = pdev;\n+\tadapter->hw.back = adapter;\n+\n+\tmmio_start = pci_resource_start(pdev, 0x0);\n+\tmmio_len = pci_resource_len(pdev, 0x0);\n+\n+\tadapter->hw.mem_rang = (u32)mmio_len;\n+\tadapter->hw.hw_addr = ioremap(mmio_start, mmio_len);\n+\tif (!adapter->hw.hw_addr) {\n+\t\terr = -EIO;\n+\t\tgoto err_ioremap;\n+\t}\n+\n+\tatl2_setup_pcicmd(pdev);\n+\n+\tnetdev->open = &atl2_open;\n+\tnetdev->stop = &atl2_close;\n+\tnetdev->hard_start_xmit = &atl2_xmit_frame;\n+\tnetdev->get_stats = &atl2_get_stats;\n+\tnetdev->set_multicast_list = &atl2_set_multi;\n+\tnetdev->set_mac_address = &atl2_set_mac;\n+\tnetdev->change_mtu = &atl2_change_mtu;\n+\tnetdev->do_ioctl = &atl2_ioctl;\n+\tatl2_set_ethtool_ops(netdev);\n+\n+#ifdef HAVE_TX_TIMEOUT\n+\tnetdev->tx_timeout = &atl2_tx_timeout;\n+\tnetdev->watchdog_timeo = 5 * HZ;\n+#endif\n+#ifdef NETIF_F_HW_VLAN_TX\n+\tnetdev->vlan_rx_register = atl2_vlan_rx_register;\n+#endif\n+\tstrncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);\n+\n+\tnetdev->mem_start = mmio_start;\n+\tnetdev->mem_end = mmio_start + mmio_len;\n+\tadapter->bd_number = cards_found;\n+\tadapter->pci_using_64 = false;\n+\n+\t/* setup the private structure */\n+\terr = atl2_sw_init(adapter);\n+\tif (err)\n+\t\tgoto err_sw_init;\n+\n+\terr = -EIO;\n+\n+#ifdef NETIF_F_HW_VLAN_TX\n+\tnetdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);\n+#endif\n+\n+#ifdef NETIF_F_LLTX\n+\tnetdev->features |= NETIF_F_LLTX;\n+#endif\n+\n+\t/* Init PHY as early as possible due to power saving issue  */\n+\tatl2_phy_init(&adapter->hw);\n+\n+\t/* reset the controller to\n+\t * put the device in a known good starting state */\n+\n+\tif (atl2_reset_hw(&adapter->hw)) {\n+\t\terr = -EIO;\n+\t\tgoto err_reset;\n+\t}\n+\n+\t/* copy the MAC address out of the EEPROM */\n+\tatl2_read_mac_addr(&adapter->hw);\n+\tmemcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);\n+/* FIXME: do we still need this? */\n+#ifdef ETHTOOL_GPERMADDR\n+\tmemcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);\n+\n+\tif (!is_valid_ether_addr(netdev->perm_addr)) {\n+#else\n+\tif (!is_valid_ether_addr(netdev->dev_addr)) {\n+#endif\n+\t\terr = -EIO;\n+\t\tgoto err_eeprom;\n+\t}\n+\n+\tatl2_check_options(adapter);\n+\n+\tinit_timer(&adapter->watchdog_timer);\n+\tadapter->watchdog_timer.function = &atl2_watchdog;\n+\tadapter->watchdog_timer.data = (unsigned long) adapter;\n+\n+\tinit_timer(&adapter->phy_config_timer);\n+\tadapter->phy_config_timer.function = &atl2_phy_config;\n+\tadapter->phy_config_timer.data = (unsigned long) adapter;\n+\n+\tINIT_WORK(&adapter->reset_task, atl2_reset_task);\n+\tINIT_WORK(&adapter->link_chg_task, atl2_link_chg_task);\n+\n+\tstrcpy(netdev->name, \"eth%d\"); /* ?? */\n+\terr = register_netdev(netdev);\n+\tif (err)\n+\t\tgoto err_register;\n+\n+\t/* assume we have no link for now */\n+\tnetif_carrier_off(netdev);\n+\tnetif_stop_queue(netdev);\n+\n+\tcards_found++;\n+\n+\treturn 0;\n+\n+err_reset:\n+err_register:\n+err_sw_init:\n+err_eeprom:\n+\tiounmap(adapter->hw.hw_addr);\n+err_ioremap:\n+\tfree_netdev(netdev);\n+err_alloc_etherdev:\n+\tpci_release_regions(pdev);\n+err_pci_reg:\n+err_dma:\n+\tpci_disable_device(pdev);\n+\treturn err;\n+}\n+\n+/*\n+ * atl2_remove - Device Removal Routine\n+ * @pdev: PCI device information struct\n+ *\n+ * atl2_remove is called by the PCI subsystem to alert the driver\n+ * that it should release a PCI device.  The could be caused by a\n+ * Hot-Plug event, or because the driver is going to be removed from\n+ * memory.\n+ */\n+/* FIXME: write the original MAC address back in case it was changed from a\n+ * BIOS-set value, as in atl1 -- CHS */\n+static void __devexit atl2_remove(struct pci_dev *pdev)\n+{\n+\tstruct net_device *netdev = pci_get_drvdata(pdev);\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\n+\t/* flush_scheduled work may reschedule our watchdog task, so\n+\t * explicitly disable watchdog tasks from being rescheduled  */\n+\tset_bit(__ATL2_DOWN, &adapter->flags);\n+\n+\tdel_timer_sync(&adapter->watchdog_timer);\n+\tdel_timer_sync(&adapter->phy_config_timer);\n+\n+\tflush_scheduled_work();\n+\n+\tunregister_netdev(netdev);\n+\n+\tatl2_force_ps(&adapter->hw);\n+\n+\tiounmap(adapter->hw.hw_addr);\n+\tpci_release_regions(pdev);\n+\n+\tfree_netdev(netdev);\n+\n+\tpci_disable_device(pdev);\n+}\n+\n+static int atl2_suspend(struct pci_dev *pdev, pm_message_t state)\n+{\n+\tstruct net_device *netdev = pci_get_drvdata(pdev);\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\tu16 speed, duplex;\n+\tu32 ctrl = 0;\n+\tu32 wufc = adapter->wol;\n+\n+#ifdef CONFIG_PM\n+\tint retval = 0;\n+#endif\n+\n+\tnetif_device_detach(netdev);\n+\n+\tif (netif_running(netdev)) {\n+\t\tWARN_ON(test_bit(__ATL2_RESETTING, &adapter->flags));\n+\t\tatl2_down(adapter);\n+\t}\n+\n+#ifdef CONFIG_PM\n+\tretval = pci_save_state(pdev);\n+\tif (retval)\n+\t\treturn retval;\n+#endif\n+\n+\tatl2_read_phy_reg(hw, MII_BMSR, (u16 *)&ctrl);\n+\tatl2_read_phy_reg(hw, MII_BMSR, (u16 *)&ctrl);\n+\tif (ctrl & BMSR_LSTATUS)\n+\t\twufc &= ~ATLX_WUFC_LNKC;\n+\n+\tif (0 != (ctrl & BMSR_LSTATUS) && 0 != wufc) {\n+\t\tu32 ret_val;\n+\t\t/* get current link speed & duplex */\n+\t\tret_val = atl2_get_speed_and_duplex(hw, &speed, &duplex);\n+\t\tif (ret_val) {\n+\t\t\tprintk(KERN_DEBUG\n+\t\t\t\t\"%s: get speed&duplex error while suspend\\n\",\n+\t\t\t\tatl2_driver_name);\n+\t\t\tgoto wol_dis;\n+\t\t}\n+\n+\t\tctrl = 0;\n+\n+\t\t/* turn on magic packet wol */\n+\t\tif (wufc & ATLX_WUFC_MAG)\n+\t\t\tctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN);\n+\n+\t\t/* ignore Link Chg event when Link is up */\n+\t\tATL2_WRITE_REG(hw, REG_WOL_CTRL, ctrl);\n+\n+\t\t/* Config MAC CTRL Register */\n+\t\tctrl = MAC_CTRL_RX_EN | MAC_CTRL_MACLP_CLK_PHY;\n+\t\tif (FULL_DUPLEX == adapter->link_duplex)\n+\t\t\tctrl |= MAC_CTRL_DUPLX;\n+\t\tctrl |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);\n+\t\tctrl |= (((u32)adapter->hw.preamble_len &\n+\t\t\tMAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);\n+\t\tctrl |= (((u32)(adapter->hw.retry_buf &\n+\t\t\tMAC_CTRL_HALF_LEFT_BUF_MASK)) <<\n+\t\t\tMAC_CTRL_HALF_LEFT_BUF_SHIFT);\n+\t\tif (wufc & ATLX_WUFC_MAG) {\n+\t\t\t/* magic packet maybe Broadcast&multicast&Unicast */\n+\t\t\tctrl |= MAC_CTRL_BC_EN;\n+\t\t}\n+\n+\t\tATL2_WRITE_REG(hw, REG_MAC_CTRL, ctrl);\n+\n+\t\t/* pcie patch */\n+\t\tctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC);\n+\t\tctrl |= PCIE_PHYMISC_FORCE_RCV_DET;\n+\t\tATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);\n+\t\tctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1);\n+\t\tctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK;\n+\t\tATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl);\n+\n+\t\tpci_enable_wake(pdev, pci_choose_state(pdev, state), 1);\n+\t\tgoto suspend_exit;\n+\t}\n+\n+\tif (0 == (ctrl&BMSR_LSTATUS) && 0 != (wufc&ATLX_WUFC_LNKC)) {\n+\t\t/* link is down, so only LINK CHG WOL event enable */\n+\t\tctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);\n+\t\tATL2_WRITE_REG(hw, REG_WOL_CTRL, ctrl);\n+\t\tATL2_WRITE_REG(hw, REG_MAC_CTRL, 0);\n+\n+\t\t/* pcie patch */\n+\t\tctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC);\n+\t\tctrl |= PCIE_PHYMISC_FORCE_RCV_DET;\n+\t\tATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);\n+\t\tctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1);\n+\t\tctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK;\n+\t\tATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl);\n+\n+\t\thw->phy_configured = false; /* re-init PHY when resume */\n+\n+\t\tpci_enable_wake(pdev, pci_choose_state(pdev, state), 1);\n+\n+\t\tgoto suspend_exit;\n+\t}\n+\n+wol_dis:\n+\t/* WOL disabled */\n+\tATL2_WRITE_REG(hw, REG_WOL_CTRL, 0);\n+\n+\t/* pcie patch */\n+\tctrl = ATL2_READ_REG(hw, REG_PCIE_PHYMISC);\n+\tctrl |= PCIE_PHYMISC_FORCE_RCV_DET;\n+\tATL2_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);\n+\tctrl = ATL2_READ_REG(hw, REG_PCIE_DLL_TX_CTRL1);\n+\tctrl |= PCIE_DLL_TX_CTRL1_SEL_NOR_CLK;\n+\tATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, ctrl);\n+\n+\tatl2_force_ps(hw);\n+\thw->phy_configured = false; /* re-init PHY when resume */\n+\n+\tpci_enable_wake(pdev, pci_choose_state(pdev, state), 0);\n+\n+suspend_exit:\n+\tif (netif_running(netdev))\n+\t\tatl2_free_irq(adapter);\n+\n+\tpci_disable_device(pdev);\n+\n+\tpci_set_power_state(pdev, pci_choose_state(pdev, state));\n+\n+\treturn 0;\n+}\n+\n+#ifdef CONFIG_PM\n+static int atl2_resume(struct pci_dev *pdev)\n+{\n+\tstruct net_device *netdev = pci_get_drvdata(pdev);\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tu32 err;\n+\n+\tpci_set_power_state(pdev, PCI_D0);\n+\tpci_restore_state(pdev);\n+\n+\terr = pci_enable_device(pdev);\n+\tif (err) {\n+\t\tprintk(KERN_ERR\n+\t\t\t\"atl2: Cannot enable PCI device from suspend\\n\");\n+\t\treturn err;\n+\t}\n+\n+\tpci_set_master(pdev);\n+\n+\tATL2_READ_REG(&adapter->hw, REG_WOL_CTRL); /* clear WOL status */\n+\n+\tpci_enable_wake(pdev, PCI_D3hot, 0);\n+\tpci_enable_wake(pdev, PCI_D3cold, 0);\n+\n+\tATL2_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);\n+\n+\terr = atl2_request_irq(adapter);\n+\tif (netif_running(netdev) && err)\n+\t\treturn err;\n+\n+\tatl2_reset_hw(&adapter->hw);\n+\n+\tif (netif_running(netdev))\n+\t\tatl2_up(adapter);\n+\n+\tnetif_device_attach(netdev);\n+\n+\treturn 0;\n+}\n+#endif\n+\n+static void atl2_shutdown(struct pci_dev *pdev)\n+{\n+\tatl2_suspend(pdev, PMSG_SUSPEND);\n+}\n+\n+static struct pci_driver atl2_driver = {\n+\t.name     = atl2_driver_name,\n+\t.id_table = atl2_pci_tbl,\n+\t.probe    = atl2_probe,\n+\t.remove   = __devexit_p(atl2_remove),\n+\t/* Power Managment Hooks */\n+\t.suspend  = atl2_suspend,\n+#ifdef CONFIG_PM\n+\t.resume   = atl2_resume,\n+#endif\n+\t.shutdown = atl2_shutdown,\n+};\n+\n+/*\n+ * atl2_init_module - Driver Registration Routine\n+ *\n+ * atl2_init_module is the first routine called when the driver is\n+ * loaded. All it does is register with the PCI subsystem.\n+ */\n+static int __init atl2_init_module(void)\n+{\n+\tprintk(KERN_INFO \"%s - version %s\\n\", atl2_driver_string,\n+\t\tatl2_driver_version);\n+\tprintk(KERN_INFO \"%s\\n\", atl2_copyright);\n+\treturn pci_register_driver(&atl2_driver);\n+}\n+module_init(atl2_init_module);\n+\n+/*\n+ * atl2_exit_module - Driver Exit Cleanup Routine\n+ *\n+ * atl2_exit_module is called just before the driver is removed\n+ * from memory.\n+ */\n+static void __exit atl2_exit_module(void)\n+{\n+\tpci_unregister_driver(&atl2_driver);\n+}\n+module_exit(atl2_exit_module);\n+\n+static void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value)\n+{\n+\tstruct atl2_adapter *adapter = hw->back;\n+\tpci_read_config_word(adapter->pdev, reg, value);\n+}\n+\n+static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value)\n+{\n+\tstruct atl2_adapter *adapter = hw->back;\n+\tpci_write_config_word(adapter->pdev, reg, *value);\n+}\n+\n+static int atl2_get_settings(struct net_device *netdev,\n+\tstruct ethtool_cmd *ecmd)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\n+\tecmd->supported = (SUPPORTED_10baseT_Half |\n+\t\tSUPPORTED_10baseT_Full |\n+\t\tSUPPORTED_100baseT_Half |\n+\t\tSUPPORTED_100baseT_Full |\n+\t\tSUPPORTED_Autoneg |\n+\t\tSUPPORTED_TP);\n+\tecmd->advertising = ADVERTISED_TP;\n+\n+\tecmd->advertising |= ADVERTISED_Autoneg;\n+\tecmd->advertising |= hw->autoneg_advertised;\n+\n+\tecmd->port = PORT_TP;\n+\tecmd->phy_address = 0;\n+\tecmd->transceiver = XCVR_INTERNAL;\n+\n+\tif (adapter->link_speed != SPEED_0) {\n+\t\tecmd->speed = adapter->link_speed;\n+\t\tif (adapter->link_duplex == FULL_DUPLEX)\n+\t\t\tecmd->duplex = DUPLEX_FULL;\n+\t\telse\n+\t\t\tecmd->duplex = DUPLEX_HALF;\n+\t} else {\n+\t\tecmd->speed = -1;\n+\t\tecmd->duplex = -1;\n+\t}\n+\n+\tecmd->autoneg = AUTONEG_ENABLE;\n+\treturn 0;\n+}\n+\n+static int atl2_set_settings(struct net_device *netdev,\n+\tstruct ethtool_cmd *ecmd)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\n+\twhile (test_and_set_bit(__ATL2_RESETTING, &adapter->flags))\n+\t\tmsleep(1);\n+\n+\tif (ecmd->autoneg == AUTONEG_ENABLE) {\n+#define MY_ADV_MASK\t(ADVERTISE_10_HALF | \\\n+\t\t\t ADVERTISE_10_FULL | \\\n+\t\t\t ADVERTISE_100_HALF| \\\n+\t\t\t ADVERTISE_100_FULL)\n+\n+\t\tif ((ecmd->advertising & MY_ADV_MASK) == MY_ADV_MASK) {\n+\t\t\thw->MediaType = MEDIA_TYPE_AUTO_SENSOR;\n+\t\t\thw->autoneg_advertised =  MY_ADV_MASK;\n+\t\t} else if ((ecmd->advertising & MY_ADV_MASK) ==\n+\t\t\t\tADVERTISE_100_FULL) {\n+\t\t\thw->MediaType = MEDIA_TYPE_100M_FULL;\n+\t\t\thw->autoneg_advertised = ADVERTISE_100_FULL;\n+\t\t} else if ((ecmd->advertising & MY_ADV_MASK) ==\n+\t\t\t\tADVERTISE_100_HALF) {\n+\t\t\thw->MediaType = MEDIA_TYPE_100M_HALF;\n+\t\t\thw->autoneg_advertised = ADVERTISE_100_HALF;\n+\t\t} else if ((ecmd->advertising & MY_ADV_MASK) ==\n+\t\t\t\tADVERTISE_10_FULL) {\n+\t\t\thw->MediaType = MEDIA_TYPE_10M_FULL;\n+\t\t\thw->autoneg_advertised = ADVERTISE_10_FULL;\n+\t\t}  else if ((ecmd->advertising & MY_ADV_MASK) ==\n+\t\t\t\tADVERTISE_10_HALF) {\n+\t\t\thw->MediaType = MEDIA_TYPE_10M_HALF;\n+\t\t\thw->autoneg_advertised = ADVERTISE_10_HALF;\n+\t\t} else {\n+\t\t\tclear_bit(__ATL2_RESETTING, &adapter->flags);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tecmd->advertising = hw->autoneg_advertised |\n+\t\t\tADVERTISED_TP | ADVERTISED_Autoneg;\n+\t} else {\n+\t\tclear_bit(__ATL2_RESETTING, &adapter->flags);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* reset the link */\n+\tif (netif_running(adapter->netdev)) {\n+\t\tatl2_down(adapter);\n+\t\tatl2_up(adapter);\n+\t} else\n+\t\tatl2_reset_hw(&adapter->hw);\n+\n+\tclear_bit(__ATL2_RESETTING, &adapter->flags);\n+\treturn 0;\n+}\n+\n+static u32 atl2_get_tx_csum(struct net_device *netdev)\n+{\n+\treturn (netdev->features & NETIF_F_HW_CSUM) != 0;\n+}\n+\n+static u32 atl2_get_msglevel(struct net_device *netdev)\n+{\n+\treturn 0;\n+}\n+\n+/*\n+ * It's sane for this to be empty, but we might want to take advantage of this.\n+ */\n+static void atl2_set_msglevel(struct net_device *netdev, u32 data)\n+{\n+}\n+\n+static int atl2_get_regs_len(struct net_device *netdev)\n+{\n+#define ATL2_REGS_LEN 42\n+\treturn sizeof(u32) * ATL2_REGS_LEN;\n+}\n+\n+static void atl2_get_regs(struct net_device *netdev,\n+\tstruct ethtool_regs *regs, void *p)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\tu32 *regs_buff = p;\n+\tu16 phy_data;\n+\n+\tmemset(p, 0, sizeof(u32) * ATL2_REGS_LEN);\n+\n+\tregs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;\n+\n+\tregs_buff[0]  = ATL2_READ_REG(hw, REG_VPD_CAP);\n+\tregs_buff[1]  = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL);\n+\tregs_buff[2]  = ATL2_READ_REG(hw, REG_SPI_FLASH_CONFIG);\n+\tregs_buff[3]  = ATL2_READ_REG(hw, REG_TWSI_CTRL);\n+\tregs_buff[4]  = ATL2_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL);\n+\tregs_buff[5]  = ATL2_READ_REG(hw, REG_MASTER_CTRL);\n+\tregs_buff[6]  = ATL2_READ_REG(hw, REG_MANUAL_TIMER_INIT);\n+\tregs_buff[7]  = ATL2_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT);\n+\tregs_buff[8]  = ATL2_READ_REG(hw, REG_PHY_ENABLE);\n+\tregs_buff[9]  = ATL2_READ_REG(hw, REG_CMBDISDMA_TIMER);\n+\tregs_buff[10] = ATL2_READ_REG(hw, REG_IDLE_STATUS);\n+\tregs_buff[11] = ATL2_READ_REG(hw, REG_MDIO_CTRL);\n+\tregs_buff[12] = ATL2_READ_REG(hw, REG_SERDES_LOCK);\n+\tregs_buff[13] = ATL2_READ_REG(hw, REG_MAC_CTRL);\n+\tregs_buff[14] = ATL2_READ_REG(hw, REG_MAC_IPG_IFG);\n+\tregs_buff[15] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR);\n+\tregs_buff[16] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR+4);\n+\tregs_buff[17] = ATL2_READ_REG(hw, REG_RX_HASH_TABLE);\n+\tregs_buff[18] = ATL2_READ_REG(hw, REG_RX_HASH_TABLE+4);\n+\tregs_buff[19] = ATL2_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL);\n+\tregs_buff[20] = ATL2_READ_REG(hw, REG_MTU);\n+\tregs_buff[21] = ATL2_READ_REG(hw, REG_WOL_CTRL);\n+\tregs_buff[22] = ATL2_READ_REG(hw, REG_SRAM_TXRAM_END);\n+\tregs_buff[23] = ATL2_READ_REG(hw, REG_DESC_BASE_ADDR_HI);\n+\tregs_buff[24] = ATL2_READ_REG(hw, REG_TXD_BASE_ADDR_LO);\n+\tregs_buff[25] = ATL2_READ_REG(hw, REG_TXD_MEM_SIZE);\n+\tregs_buff[26] = ATL2_READ_REG(hw, REG_TXS_BASE_ADDR_LO);\n+\tregs_buff[27] = ATL2_READ_REG(hw, REG_TXS_MEM_SIZE);\n+\tregs_buff[28] = ATL2_READ_REG(hw, REG_RXD_BASE_ADDR_LO);\n+\tregs_buff[29] = ATL2_READ_REG(hw, REG_RXD_BUF_NUM);\n+\tregs_buff[30] = ATL2_READ_REG(hw, REG_DMAR);\n+\tregs_buff[31] = ATL2_READ_REG(hw, REG_TX_CUT_THRESH);\n+\tregs_buff[32] = ATL2_READ_REG(hw, REG_DMAW);\n+\tregs_buff[33] = ATL2_READ_REG(hw, REG_PAUSE_ON_TH);\n+\tregs_buff[34] = ATL2_READ_REG(hw, REG_PAUSE_OFF_TH);\n+\tregs_buff[35] = ATL2_READ_REG(hw, REG_MB_TXD_WR_IDX);\n+\tregs_buff[36] = ATL2_READ_REG(hw, REG_MB_RXD_RD_IDX);\n+\tregs_buff[38] = ATL2_READ_REG(hw, REG_ISR);\n+\tregs_buff[39] = ATL2_READ_REG(hw, REG_IMR);\n+\n+\tatl2_read_phy_reg(hw, MII_BMCR, &phy_data);\n+\tregs_buff[40] = (u32)phy_data;\n+\tatl2_read_phy_reg(hw, MII_BMSR, &phy_data);\n+\tregs_buff[41] = (u32)phy_data;\n+}\n+\n+static int atl2_get_eeprom_len(struct net_device *netdev)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\n+\tif (!atl2_check_eeprom_exist(&adapter->hw))\n+\t\treturn 512;\n+\telse\n+\t\treturn 0;\n+}\n+\n+static int atl2_get_eeprom(struct net_device *netdev,\n+\tstruct ethtool_eeprom *eeprom, u8 *bytes)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\tu32 *eeprom_buff;\n+\tint first_dword, last_dword;\n+\tint ret_val = 0;\n+\tint i;\n+\n+\tif (eeprom->len == 0)\n+\t\treturn -EINVAL;\n+\n+\tif (atl2_check_eeprom_exist(hw))\n+\t\treturn -EINVAL;\n+\n+\teeprom->magic = hw->vendor_id | (hw->device_id << 16);\n+\n+\tfirst_dword = eeprom->offset >> 2;\n+\tlast_dword = (eeprom->offset + eeprom->len - 1) >> 2;\n+\n+\teeprom_buff = kmalloc(sizeof(u32) * (last_dword - first_dword + 1),\n+\t\tGFP_KERNEL);\n+\tif (!eeprom_buff)\n+\t\treturn -ENOMEM;\n+\n+\tfor (i = first_dword; i < last_dword; i++) {\n+\t\tif (!atl2_read_eeprom(hw, i*4, &(eeprom_buff[i-first_dword])))\n+\t\t\treturn -EIO;\n+\t}\n+\n+\tmemcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),\n+\t\teeprom->len);\n+\tkfree(eeprom_buff);\n+\n+\treturn ret_val;\n+}\n+\n+static int atl2_set_eeprom(struct net_device *netdev,\n+\tstruct ethtool_eeprom *eeprom, u8 *bytes)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tstruct atl2_hw *hw = &adapter->hw;\n+\tu32 *eeprom_buff;\n+\tu32 *ptr;\n+\tint max_len, first_dword, last_dword, ret_val = 0;\n+\tint i;\n+\n+\tif (eeprom->len == 0)\n+\t\treturn -EOPNOTSUPP;\n+\n+\tif (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))\n+\t\treturn -EFAULT;\n+\n+\tmax_len = 512;\n+\n+\tfirst_dword = eeprom->offset >> 2;\n+\tlast_dword = (eeprom->offset + eeprom->len - 1) >> 2;\n+\teeprom_buff = kmalloc(max_len, GFP_KERNEL);\n+\tif (!eeprom_buff)\n+\t\treturn -ENOMEM;\n+\n+\tptr = (u32 *)eeprom_buff;\n+\n+\tif (eeprom->offset & 3) {\n+\t\t/* need read/modify/write of first changed EEPROM word */\n+\t\t/* only the second byte of the word is being modified */\n+\t\tif (!atl2_read_eeprom(hw, first_dword*4, &(eeprom_buff[0])))\n+\t\t\treturn -EIO;\n+\t\tptr++;\n+\t}\n+\tif (((eeprom->offset + eeprom->len) & 3)) {\n+\t\t/*\n+\t\t * need read/modify/write of last changed EEPROM word\n+\t\t * only the first byte of the word is being modified\n+\t\t */\n+\t\tif (!atl2_read_eeprom(hw, last_dword * 4,\n+\t\t\t&(eeprom_buff[last_dword - first_dword])))\n+\t\t\treturn -EIO;\n+\t}\n+\n+\t/* Device's eeprom is always little-endian, word addressable */\n+\tmemcpy(ptr, bytes, eeprom->len);\n+\n+\tfor (i = 0; i < last_dword - first_dword + 1; i++) {\n+\t\tif (!atl2_write_eeprom(hw, ((first_dword+i)*4), eeprom_buff[i]))\n+\t\t\treturn -EIO;\n+\t}\n+\n+\tkfree(eeprom_buff);\n+\treturn ret_val;\n+}\n+\n+static void atl2_get_drvinfo(struct net_device *netdev,\n+\tstruct ethtool_drvinfo *drvinfo)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\n+\tstrncpy(drvinfo->driver,  atl2_driver_name, 32);\n+\tstrncpy(drvinfo->version, atl2_driver_version, 32);\n+\tstrncpy(drvinfo->fw_version, \"L2\", 32);\n+\tstrncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);\n+\tdrvinfo->n_stats = 0;\n+\tdrvinfo->testinfo_len = 0;\n+\tdrvinfo->regdump_len = atl2_get_regs_len(netdev);\n+\tdrvinfo->eedump_len = atl2_get_eeprom_len(netdev);\n+}\n+\n+static void atl2_get_wol(struct net_device *netdev,\n+\tstruct ethtool_wolinfo *wol)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\n+\twol->supported = WAKE_MAGIC;\n+\twol->wolopts = 0;\n+\n+\tif (adapter->wol & ATLX_WUFC_EX)\n+\t\twol->wolopts |= WAKE_UCAST;\n+\tif (adapter->wol & ATLX_WUFC_MC)\n+\t\twol->wolopts |= WAKE_MCAST;\n+\tif (adapter->wol & ATLX_WUFC_BC)\n+\t\twol->wolopts |= WAKE_BCAST;\n+\tif (adapter->wol & ATLX_WUFC_MAG)\n+\t\twol->wolopts |= WAKE_MAGIC;\n+\tif (adapter->wol & ATLX_WUFC_LNKC)\n+\t\twol->wolopts |= WAKE_PHY;\n+}\n+\n+static int atl2_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\n+\tif (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))\n+\t\treturn -EOPNOTSUPP;\n+\n+\tif (wol->wolopts & (WAKE_MCAST|WAKE_BCAST|WAKE_MCAST))\n+\t\treturn -EOPNOTSUPP;\n+\n+\t/* these settings will always override what we currently have */\n+\tadapter->wol = 0;\n+\n+\tif (wol->wolopts & WAKE_MAGIC)\n+\t\tadapter->wol |= ATLX_WUFC_MAG;\n+\tif (wol->wolopts & WAKE_PHY)\n+\t\tadapter->wol |= ATLX_WUFC_LNKC;\n+\n+\treturn 0;\n+}\n+\n+static int atl2_nway_reset(struct net_device *netdev)\n+{\n+\tstruct atl2_adapter *adapter = netdev_priv(netdev);\n+\tif (netif_running(netdev))\n+\t\tatl2_reinit_locked(adapter);\n+\treturn 0;\n+}\n+\n+static struct ethtool_ops atl2_ethtool_ops = {\n+\t.get_settings\t\t= atl2_get_settings,\n+\t.set_settings\t\t= atl2_set_settings,\n+\t.get_drvinfo\t\t= atl2_get_drvinfo,\n+\t.get_regs_len\t\t= atl2_get_regs_len,\n+\t.get_regs\t\t= atl2_get_regs,\n+\t.get_wol\t\t= atl2_get_wol,\n+\t.set_wol\t\t= atl2_set_wol,\n+\t.get_msglevel\t\t= atl2_get_msglevel,\n+\t.set_msglevel\t\t= atl2_set_msglevel,\n+\t.nway_reset\t\t= atl2_nway_reset,\n+\t.get_link\t\t= ethtool_op_get_link,\n+\t.get_eeprom_len\t\t= atl2_get_eeprom_len,\n+\t.get_eeprom\t\t= atl2_get_eeprom,\n+\t.set_eeprom\t\t= atl2_set_eeprom,\n+\t.get_tx_csum\t\t= atl2_get_tx_csum,\n+\t.get_sg\t\t\t= ethtool_op_get_sg,\n+\t.set_sg\t\t\t= ethtool_op_set_sg,\n+#ifdef NETIF_F_TSO\n+\t.get_tso\t\t= ethtool_op_get_tso,\n+#endif\n+};\n+\n+static void atl2_set_ethtool_ops(struct net_device *netdev)\n+{\n+\tSET_ETHTOOL_OPS(netdev, &atl2_ethtool_ops);\n+}\n+\n+#define LBYTESWAP(a)  ((((a) & 0x00ff00ff) << 8) | \\\n+\t(((a) & 0xff00ff00) >> 8))\n+#define LONGSWAP(a)   ((LBYTESWAP(a) << 16) | (LBYTESWAP(a) >> 16))\n+#define SHORTSWAP(a)  (((a) << 8) | ((a) >> 8))\n+\n+/*\n+ * Reset the transmit and receive units; mask and clear all interrupts.\n+ *\n+ * hw - Struct containing variables accessed by shared code\n+ * return : 0  or  idle status (if error)\n+ */\n+static s32 atl2_reset_hw(struct atl2_hw *hw)\n+{\n+\tu32 icr;\n+\tu16 pci_cfg_cmd_word;\n+\tint i;\n+\n+\t/* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */\n+\tatl2_read_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word);\n+\tif ((pci_cfg_cmd_word &\n+\t\t(CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) !=\n+\t\t(CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER)) {\n+\t\tpci_cfg_cmd_word |=\n+\t\t\t(CMD_IO_SPACE|CMD_MEMORY_SPACE|CMD_BUS_MASTER);\n+\t\tatl2_write_pci_cfg(hw, PCI_REG_COMMAND, &pci_cfg_cmd_word);\n+\t}\n+\n+\t/* Clear Interrupt mask to stop board from generating\n+\t * interrupts & Clear any pending interrupt events\n+\t */\n+\t/* FIXME */\n+\t/* ATL2_WRITE_REG(hw, REG_IMR, 0); */\n+\t/* ATL2_WRITE_REG(hw, REG_ISR, 0xffffffff); */\n+\n+\t/* Issue Soft Reset to the MAC.  This will reset the chip's\n+\t * transmit, receive, DMA.  It will not effect\n+\t * the current PCI configuration.  The global reset bit is self-\n+\t * clearing, and should clear within a microsecond.\n+\t */\n+\tATL2_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST);\n+\twmb();\n+\tmsleep(1); /* delay about 1ms */\n+\n+\t/* Wait at least 10ms for All module to be Idle */\n+\tfor (i = 0; i < 10; i++) {\n+\t\ticr = ATL2_READ_REG(hw, REG_IDLE_STATUS);\n+\t\tif (!icr)\n+\t\t\tbreak;\n+\t\tmsleep(1); /* delay 1 ms */\n+\t\tcpu_relax();\n+\t}\n+\n+\tif (icr)\n+\t\treturn icr;\n+\n+\treturn 0;\n+}\n+\n+#define CUSTOM_SPI_CS_SETUP        2\n+#define CUSTOM_SPI_CLK_HI          2\n+#define CUSTOM_SPI_CLK_LO          2\n+#define CUSTOM_SPI_CS_HOLD         2\n+#define CUSTOM_SPI_CS_HI           3\n+\n+static struct atl2_spi_flash_dev flash_table[] =\n+{\n+/* MFR    WRSR  READ  PROGRAM WREN  WRDI  RDSR  RDID  SECTOR_ERASE CHIP_ERASE */\n+{\"Atmel\", 0x0,  0x03, 0x02,   0x06, 0x04, 0x05, 0x15, 0x52,        0x62 },\n+{\"SST\",   0x01, 0x03, 0x02,   0x06, 0x04, 0x05, 0x90, 0x20,        0x60 },\n+{\"ST\",    0x01, 0x03, 0x02,   0x06, 0x04, 0x05, 0xAB, 0xD8,        0xC7 },\n+};\n+\n+static bool atl2_spi_read(struct atl2_hw *hw, u32 addr, u32 *buf)\n+{\n+\tint i;\n+\tu32 value;\n+\n+\tATL2_WRITE_REG(hw, REG_SPI_DATA, 0);\n+\tATL2_WRITE_REG(hw, REG_SPI_ADDR, addr);\n+\n+\tvalue = SPI_FLASH_CTRL_WAIT_READY |\n+\t\t(CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<\n+\t\t\tSPI_FLASH_CTRL_CS_SETUP_SHIFT |\n+\t\t(CUSTOM_SPI_CLK_HI & SPI_FLASH_CTRL_CLK_HI_MASK) <<\n+\t\t\tSPI_FLASH_CTRL_CLK_HI_SHIFT |\n+\t\t(CUSTOM_SPI_CLK_LO & SPI_FLASH_CTRL_CLK_LO_MASK) <<\n+\t\t\tSPI_FLASH_CTRL_CLK_LO_SHIFT |\n+\t\t(CUSTOM_SPI_CS_HOLD & SPI_FLASH_CTRL_CS_HOLD_MASK) <<\n+\t\t\tSPI_FLASH_CTRL_CS_HOLD_SHIFT |\n+\t\t(CUSTOM_SPI_CS_HI & SPI_FLASH_CTRL_CS_HI_MASK) <<\n+\t\t\tSPI_FLASH_CTRL_CS_HI_SHIFT |\n+\t\t(0x1 & SPI_FLASH_CTRL_INS_MASK) << SPI_FLASH_CTRL_INS_SHIFT;\n+\n+\tATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);\n+\n+\tvalue |= SPI_FLASH_CTRL_START;\n+\n+\tATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);\n+\n+\tfor (i = 0; i < 10; i++) {\n+\t\tmsleep(1);\n+\t\tvalue = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL);\n+\t\tif (!(value & SPI_FLASH_CTRL_START))\n+\t\t\tbreak;\n+\t}\n+\n+\tif (value & SPI_FLASH_CTRL_START)\n+\t\treturn false;\n+\n+\t*buf = ATL2_READ_REG(hw, REG_SPI_DATA);\n+\n+\treturn true;\n+}\n+\n+/*\n+ * get_permanent_address\n+ * return 0 if get valid mac address,\n+ */\n+static int get_permanent_address(struct atl2_hw *hw)\n+{\n+\tu32 Addr[2];\n+\tu32 i, Control;\n+\tu16 Register;\n+\tu8  EthAddr[NODE_ADDRESS_SIZE];\n+\tbool KeyValid;\n+\n+\tif (is_valid_ether_addr(hw->perm_mac_addr))\n+\t\treturn 0;\n+\n+\tAddr[0] = 0;\n+\tAddr[1] = 0;\n+\n+\tif (!atl2_check_eeprom_exist(hw)) { /* eeprom exists */\n+\t\tRegister = 0;\n+\t\tKeyValid = false;\n+\n+\t\t/* Read out all EEPROM content */\n+\t\ti = 0;\n+\t\twhile (1) {\n+\t\t\tif (atl2_read_eeprom(hw, i + 0x100, &Control)) {\n+\t\t\t\tif (KeyValid) {\n+\t\t\t\t\tif (Register == REG_MAC_STA_ADDR)\n+\t\t\t\t\t\tAddr[0] = Control;\n+\t\t\t\t\telse if (Register ==\n+\t\t\t\t\t\t(REG_MAC_STA_ADDR + 4))\n+\t\t\t\t\t\tAddr[1] = Control;\n+\t\t\t\t\tKeyValid = false;\n+\t\t\t\t} else if ((Control & 0xff) == 0x5A) {\n+\t\t\t\t\tKeyValid = true;\n+\t\t\t\t\tRegister = (u16) (Control >> 16);\n+\t\t\t\t} else {\n+\t\t\t/* assume data end while encount an invalid KEYWORD */\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tbreak; /* read error */\n+\t\t\t}\n+\t\t\ti += 4;\n+\t\t}\n+\n+\t\t*(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]);\n+\t\t*(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *) &Addr[1]);\n+\n+\t\tif (is_valid_ether_addr(EthAddr)) {\n+\t\t\tmemcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE);\n+\t\t\treturn 0;\n+\t\t}\n+\t\treturn 1;\n+\t}\n+\n+\t/* see if SPI flash exists? */\n+\tAddr[0] = 0;\n+\tAddr[1] = 0;\n+\tRegister = 0;\n+\tKeyValid = false;\n+\ti = 0;\n+\twhile (1) {\n+\t\tif (atl2_spi_read(hw, i + 0x1f000, &Control)) {\n+\t\t\tif (KeyValid) {\n+\t\t\t\tif (Register == REG_MAC_STA_ADDR)\n+\t\t\t\t\tAddr[0] = Control;\n+\t\t\t\telse if (Register == (REG_MAC_STA_ADDR + 4))\n+\t\t\t\t\tAddr[1] = Control;\n+\t\t\t\tKeyValid = false;\n+\t\t\t} else if ((Control & 0xff) == 0x5A) {\n+\t\t\t\tKeyValid = true;\n+\t\t\t\tRegister = (u16) (Control >> 16);\n+\t\t\t} else {\n+\t\t\t\tbreak; /* data end */\n+\t\t\t}\n+\t\t} else {\n+\t\t\tbreak; /* read error */\n+\t\t}\n+\t\ti += 4;\n+\t}\n+\n+\t*(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]);\n+\t*(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *)&Addr[1]);\n+\tif (is_valid_ether_addr(EthAddr)) {\n+\t\tmemcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE);\n+\t\treturn 0;\n+\t}\n+\t/* maybe MAC-address is from BIOS */\n+\tAddr[0] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR);\n+\tAddr[1] = ATL2_READ_REG(hw, REG_MAC_STA_ADDR + 4);\n+\t*(u32 *) &EthAddr[2] = LONGSWAP(Addr[0]);\n+\t*(u16 *) &EthAddr[0] = SHORTSWAP(*(u16 *) &Addr[1]);\n+\n+\tif (is_valid_ether_addr(EthAddr)) {\n+\t\tmemcpy(hw->perm_mac_addr, EthAddr, NODE_ADDRESS_SIZE);\n+\t\treturn 0;\n+\t}\n+\n+\treturn 1;\n+}\n+\n+/*\n+ * Reads the adapter's MAC address from the EEPROM\n+ *\n+ * hw - Struct containing variables accessed by shared code\n+ */\n+static s32 atl2_read_mac_addr(struct atl2_hw *hw)\n+{\n+\tu16 i;\n+\n+\tif (get_permanent_address(hw)) {\n+\t\t/* for test */\n+\t\t/* FIXME: shouldn't we use random_ether_addr() here? */\n+\t\thw->perm_mac_addr[0] = 0x00;\n+\t\thw->perm_mac_addr[1] = 0x13;\n+\t\thw->perm_mac_addr[2] = 0x74;\n+\t\thw->perm_mac_addr[3] = 0x00;\n+\t\thw->perm_mac_addr[4] = 0x5c;\n+\t\thw->perm_mac_addr[5] = 0x38;\n+\t}\n+\n+\tfor (i = 0; i < NODE_ADDRESS_SIZE; i++)\n+\t\thw->mac_addr[i] = hw->perm_mac_addr[i];\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Hashes an address to determine its location in the multicast table\n+ *\n+ * hw - Struct containing variables accessed by shared code\n+ * mc_addr - the multicast address to hash\n+ *\n+ * atl2_hash_mc_addr\n+ *  purpose\n+ *      set hash value for a multicast address\n+ *      hash calcu processing :\n+ *          1. calcu 32bit CRC for multicast address\n+ *          2. reverse crc with MSB to LSB\n+ */\n+static u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr)\n+{\n+\tu32 crc32, value;\n+\tint i;\n+\n+\tvalue = 0;\n+\tcrc32 = ether_crc_le(6, mc_addr);\n+\n+\tfor (i = 0; i < 32; i++)\n+\t\tvalue |= (((crc32 >> i) & 1) << (31 - i));\n+\n+\treturn value;\n+}\n+\n+/*\n+ * Sets the bit in the multicast table corresponding to the hash value.\n+ *\n+ * hw - Struct containing variables accessed by shared code\n+ * hash_value - Multicast address hash value\n+ */\n+static void atl2_hash_set(struct atl2_hw *hw, u32 hash_value)\n+{\n+\tu32 hash_bit, hash_reg;\n+\tu32 mta;\n+\n+\t/* The HASH Table  is a register array of 2 32-bit registers.\n+\t * It is treated like an array of 64 bits.  We want to set\n+\t * bit BitArray[hash_value]. So we figure out what register\n+\t * the bit is in, read it, OR in the new bit, then write\n+\t * back the new value.  The register is determined by the\n+\t * upper 7 bits of the hash value and the bit within that\n+\t * register are determined by the lower 5 bits of the value.\n+\t */\n+\thash_reg = (hash_value >> 31) & 0x1;\n+\thash_bit = (hash_value >> 26) & 0x1F;\n+\n+\tmta = ATL2_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);\n+\n+\tmta |= (1 << hash_bit);\n+\n+\tATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);\n+}\n+\n+/*\n+ * atl2_init_pcie - init PCIE module\n+ */\n+static void atl2_init_pcie(struct atl2_hw *hw)\n+{\n+    u32 value;\n+    value = LTSSM_TEST_MODE_DEF;\n+    ATL2_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);\n+\n+    value = PCIE_DLL_TX_CTRL1_DEF;\n+    ATL2_WRITE_REG(hw, REG_PCIE_DLL_TX_CTRL1, value);\n+}\n+\n+static void atl2_init_flash_opcode(struct atl2_hw *hw)\n+{\n+\tif (hw->flash_vendor >= ARRAY_SIZE(flash_table))\n+\t\thw->flash_vendor = 0; /* ATMEL */\n+\n+\t/* Init OP table */\n+\tATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_PROGRAM,\n+\t\tflash_table[hw->flash_vendor].cmdPROGRAM);\n+\tATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_SC_ERASE,\n+\t\tflash_table[hw->flash_vendor].cmdSECTOR_ERASE);\n+\tATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_CHIP_ERASE,\n+\t\tflash_table[hw->flash_vendor].cmdCHIP_ERASE);\n+\tATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDID,\n+\t\tflash_table[hw->flash_vendor].cmdRDID);\n+\tATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_WREN,\n+\t\tflash_table[hw->flash_vendor].cmdWREN);\n+\tATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_RDSR,\n+\t\tflash_table[hw->flash_vendor].cmdRDSR);\n+\tATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_WRSR,\n+\t\tflash_table[hw->flash_vendor].cmdWRSR);\n+\tATL2_WRITE_REGB(hw, REG_SPI_FLASH_OP_READ,\n+\t\tflash_table[hw->flash_vendor].cmdREAD);\n+}\n+\n+/********************************************************************\n+* Performs basic configuration of the adapter.\n+*\n+* hw - Struct containing variables accessed by shared code\n+* Assumes that the controller has previously been reset and is in a\n+* post-reset uninitialized state. Initializes multicast table,\n+* and  Calls routines to setup link\n+* Leaves the transmit and receive units disabled and uninitialized.\n+********************************************************************/\n+static s32 atl2_init_hw(struct atl2_hw *hw)\n+{\n+\tu32 ret_val = 0;\n+\n+\tatl2_init_pcie(hw);\n+\n+\t/* Zero out the Multicast HASH table */\n+\t/* clear the old settings from the multicast hash table */\n+\tATL2_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);\n+\tATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);\n+\n+\tatl2_init_flash_opcode(hw);\n+\n+\tret_val = atl2_phy_init(hw);\n+\n+\treturn ret_val;\n+}\n+\n+/*\n+ * Detects the current speed and duplex settings of the hardware.\n+ *\n+ * hw - Struct containing variables accessed by shared code\n+ * speed - Speed of the connection\n+ * duplex - Duplex setting of the connection\n+ */\n+static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed,\n+\tu16 *duplex)\n+{\n+\ts32 ret_val;\n+\tu16 phy_data;\n+\n+\t/* Read PHY Specific Status Register (17) */\n+\tret_val = atl2_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data);\n+\tif (ret_val)\n+\t\treturn ret_val;\n+\n+\tif (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED))\n+\t\treturn ATLX_ERR_PHY_RES;\n+\n+\tswitch (phy_data & MII_ATLX_PSSR_SPEED) {\n+\tcase MII_ATLX_PSSR_100MBS:\n+\t\t*speed = SPEED_100;\n+\t\tbreak;\n+\tcase MII_ATLX_PSSR_10MBS:\n+\t\t*speed = SPEED_10;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn ATLX_ERR_PHY_SPEED;\n+\t\tbreak;\n+\t}\n+\n+\tif (phy_data & MII_ATLX_PSSR_DPLX)\n+\t\t*duplex = FULL_DUPLEX;\n+\telse\n+\t\t*duplex = HALF_DUPLEX;\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Reads the value from a PHY register\n+ * hw - Struct containing variables accessed by shared code\n+ * reg_addr - address of the PHY register to read\n+ */\n+static s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data)\n+{\n+\tu32 val;\n+\tint i;\n+\n+\tval = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |\n+\t\tMDIO_START |\n+\t\tMDIO_SUP_PREAMBLE |\n+\t\tMDIO_RW |\n+\t\tMDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;\n+\tATL2_WRITE_REG(hw, REG_MDIO_CTRL, val);\n+\n+\twmb();\n+\n+\tfor (i = 0; i < MDIO_WAIT_TIMES; i++) {\n+\t\tudelay(2);\n+\t\tval = ATL2_READ_REG(hw, REG_MDIO_CTRL);\n+\t\tif (!(val & (MDIO_START | MDIO_BUSY)))\n+\t\t\tbreak;\n+\t\twmb();\n+\t}\n+\tif (!(val & (MDIO_START | MDIO_BUSY))) {\n+\t\t*phy_data = (u16)val;\n+\t\treturn 0;\n+\t}\n+\n+\treturn ATLX_ERR_PHY;\n+}\n+\n+/*\n+ * Writes a value to a PHY register\n+ * hw - Struct containing variables accessed by shared code\n+ * reg_addr - address of the PHY register to write\n+ * data - data to write to the PHY\n+ */\n+static s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data)\n+{\n+\tint i;\n+\tu32 val;\n+\n+\tval = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |\n+\t\t(reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |\n+\t\tMDIO_SUP_PREAMBLE |\n+\t\tMDIO_START |\n+\t\tMDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;\n+\tATL2_WRITE_REG(hw, REG_MDIO_CTRL, val);\n+\n+\twmb();\n+\n+\tfor (i = 0; i < MDIO_WAIT_TIMES; i++) {\n+\t\tudelay(2);\n+\t\tval = ATL2_READ_REG(hw, REG_MDIO_CTRL);\n+\t\tif (!(val & (MDIO_START | MDIO_BUSY)))\n+\t\t\tbreak;\n+\n+\t\twmb();\n+\t}\n+\n+\tif (!(val & (MDIO_START | MDIO_BUSY)))\n+\t\treturn 0;\n+\n+\treturn ATLX_ERR_PHY;\n+}\n+\n+/*\n+ * Configures PHY autoneg and flow control advertisement settings\n+ *\n+ * hw - Struct containing variables accessed by shared code\n+ */\n+static s32 atl2_phy_setup_autoneg_adv(struct atl2_hw *hw)\n+{\n+\ts32 ret_val;\n+\ts16 mii_autoneg_adv_reg;\n+\n+\t/* Read the MII Auto-Neg Advertisement Register (Address 4). */\n+\tmii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;\n+\n+\t/* Need to parse autoneg_advertised  and set up\n+\t * the appropriate PHY registers.  First we will parse for\n+\t * autoneg_advertised software override.  Since we can advertise\n+\t * a plethora of combinations, we need to check each bit\n+\t * individually.\n+\t */\n+\n+\t/* First we clear all the 10/100 mb speed bits in the Auto-Neg\n+\t * Advertisement Register (Address 4) and the 1000 mb speed bits in\n+\t * the  1000Base-T Control Register (Address 9). */\n+\tmii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;\n+\n+\t/* Need to parse MediaType and setup the\n+\t * appropriate PHY registers. */\n+\tswitch (hw->MediaType) {\n+\tcase MEDIA_TYPE_AUTO_SENSOR:\n+\t\tmii_autoneg_adv_reg |=\n+\t\t\t(MII_AR_10T_HD_CAPS |\n+\t\t\tMII_AR_10T_FD_CAPS  |\n+\t\t\tMII_AR_100TX_HD_CAPS|\n+\t\t\tMII_AR_100TX_FD_CAPS);\n+\t\thw->autoneg_advertised =\n+\t\t\tADVERTISE_10_HALF |\n+\t\t\tADVERTISE_10_FULL |\n+\t\t\tADVERTISE_100_HALF|\n+\t\t\tADVERTISE_100_FULL;\n+\t\tbreak;\n+\tcase MEDIA_TYPE_100M_FULL:\n+\t\tmii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;\n+\t\thw->autoneg_advertised = ADVERTISE_100_FULL;\n+\t\tbreak;\n+\tcase MEDIA_TYPE_100M_HALF:\n+\t\tmii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;\n+\t\thw->autoneg_advertised = ADVERTISE_100_HALF;\n+\t\tbreak;\n+\tcase MEDIA_TYPE_10M_FULL:\n+\t\tmii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;\n+\t\thw->autoneg_advertised = ADVERTISE_10_FULL;\n+\t\tbreak;\n+\tdefault:\n+\t\tmii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;\n+\t\thw->autoneg_advertised = ADVERTISE_10_HALF;\n+\t\tbreak;\n+\t}\n+\n+\t/* flow control fixed to enable all */\n+\tmii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);\n+\n+\thw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;\n+\n+\tret_val = atl2_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);\n+\n+\tif (ret_val)\n+\t\treturn ret_val;\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Resets the PHY and make all config validate\n+ *\n+ * hw - Struct containing variables accessed by shared code\n+ *\n+ * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)\n+ */\n+static s32 atl2_phy_commit(struct atl2_hw *hw)\n+{\n+\ts32 ret_val;\n+\tu16 phy_data;\n+\n+\tphy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG;\n+\tret_val = atl2_write_phy_reg(hw, MII_BMCR, phy_data);\n+\tif (ret_val) {\n+\t\tu32 val;\n+\t\tint i;\n+\t\t/* pcie serdes link may be down ! */\n+\t\tfor (i = 0; i < 25; i++) {\n+\t\t\tmsleep(1);\n+\t\t\tval = ATL2_READ_REG(hw, REG_MDIO_CTRL);\n+\t\t\tif (!(val & (MDIO_START | MDIO_BUSY)))\n+\t\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (0 != (val & (MDIO_START | MDIO_BUSY))) {\n+\t\t\tprintk(KERN_ERR \"atl2: PCIe link down for at least 25ms !\\n\");\n+\t\t\treturn ret_val;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static s32 atl2_phy_init(struct atl2_hw *hw)\n+{\n+\ts32 ret_val;\n+\tu16 phy_val;\n+\n+\tif (hw->phy_configured)\n+\t\treturn 0;\n+\n+\t/* Enable PHY */\n+\tATL2_WRITE_REGW(hw, REG_PHY_ENABLE, 1);\n+\tATL2_WRITE_FLUSH(hw);\n+\tmsleep(1);\n+\n+\t/* check if the PHY is in powersaving mode */\n+\tatl2_write_phy_reg(hw, MII_DBG_ADDR, 0);\n+\tatl2_read_phy_reg(hw, MII_DBG_DATA, &phy_val);\n+\n+\t/* 024E / 124E 0r 0274 / 1274 ? */\n+\tif (phy_val & 0x1000) {\n+\t\tphy_val &= ~0x1000;\n+\t\tatl2_write_phy_reg(hw, MII_DBG_DATA, phy_val);\n+\t}\n+\n+\tmsleep(1);\n+\n+\t/*Enable PHY LinkChange Interrupt */\n+\tret_val = atl2_write_phy_reg(hw, 18, 0xC00);\n+\tif (ret_val)\n+\t\treturn ret_val;\n+\n+\t/* setup AutoNeg parameters */\n+\tret_val = atl2_phy_setup_autoneg_adv(hw);\n+\tif (ret_val)\n+\t\treturn ret_val;\n+\n+\t/* SW.Reset & En-Auto-Neg to restart Auto-Neg */\n+\tret_val = atl2_phy_commit(hw);\n+\tif (ret_val)\n+\t\treturn ret_val;\n+\n+\thw->phy_configured = true;\n+\n+\treturn ret_val;\n+}\n+\n+static void atl2_set_mac_addr(struct atl2_hw *hw)\n+{\n+\tu32 value;\n+\t/* 00-0B-6A-F6-00-DC\n+\t * 0:  6AF600DC   1: 000B\n+\t * low dword */\n+\tvalue = (((u32)hw->mac_addr[2]) << 24) |\n+\t\t(((u32)hw->mac_addr[3]) << 16) |\n+\t\t(((u32)hw->mac_addr[4]) << 8)  |\n+\t\t(((u32)hw->mac_addr[5]));\n+\tATL2_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);\n+\t/* hight dword */\n+\tvalue = (((u32)hw->mac_addr[0]) << 8) |\n+\t\t(((u32)hw->mac_addr[1]));\n+\tATL2_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);\n+}\n+\n+/*\n+ * check_eeprom_exist\n+ * return 0 if eeprom exist\n+ */\n+static int atl2_check_eeprom_exist(struct atl2_hw *hw)\n+{\n+\tu32 value;\n+\n+\tvalue = ATL2_READ_REG(hw, REG_SPI_FLASH_CTRL);\n+\tif (value & SPI_FLASH_CTRL_EN_VPD) {\n+\t\tvalue &= ~SPI_FLASH_CTRL_EN_VPD;\n+\t\tATL2_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);\n+\t}\n+\tvalue = ATL2_READ_REGW(hw, REG_PCIE_CAP_LIST);\n+\treturn ((value & 0xFF00) == 0x6C00) ? 0 : 1;\n+}\n+\n+/* FIXME: This doesn't look right. -- CHS */\n+static bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value)\n+{\n+\treturn true;\n+}\n+\n+static bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue)\n+{\n+\tint i;\n+\tu32    Control;\n+\n+\tif (Offset & 0x3)\n+\t\treturn false; /* address do not align */\n+\n+\tATL2_WRITE_REG(hw, REG_VPD_DATA, 0);\n+\tControl = (Offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;\n+\tATL2_WRITE_REG(hw, REG_VPD_CAP, Control);\n+\n+\tfor (i = 0; i < 10; i++) {\n+\t\tmsleep(2);\n+\t\tControl = ATL2_READ_REG(hw, REG_VPD_CAP);\n+\t\tif (Control & VPD_CAP_VPD_FLAG)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (Control & VPD_CAP_VPD_FLAG) {\n+\t\t*pValue = ATL2_READ_REG(hw, REG_VPD_DATA);\n+\t\treturn true;\n+\t}\n+\treturn false; /* timeout */\n+}\n+\n+static void atl2_force_ps(struct atl2_hw *hw)\n+{\n+\tu16 phy_val;\n+\n+\tatl2_write_phy_reg(hw, MII_DBG_ADDR, 0);\n+\tatl2_read_phy_reg(hw, MII_DBG_DATA, &phy_val);\n+\tatl2_write_phy_reg(hw, MII_DBG_DATA, phy_val | 0x1000);\n+\n+\tatl2_write_phy_reg(hw, MII_DBG_ADDR, 2);\n+\tatl2_write_phy_reg(hw, MII_DBG_DATA, 0x3000);\n+\tatl2_write_phy_reg(hw, MII_DBG_ADDR, 3);\n+\tatl2_write_phy_reg(hw, MII_DBG_DATA, 0);\n+}\n+\n+/* This is the only thing that needs to be changed to adjust the\n+ * maximum number of ports that the driver can manage.\n+ */\n+#define ATL2_MAX_NIC 4\n+\n+#define OPTION_UNSET    -1\n+#define OPTION_DISABLED 0\n+#define OPTION_ENABLED  1\n+\n+/* All parameters are treated the same, as an integer array of values.\n+ * This macro just reduces the need to repeat the same declaration code\n+ * over and over (plus this helps to avoid typo bugs).\n+ */\n+#define ATL2_PARAM_INIT {[0 ... ATL2_MAX_NIC] = OPTION_UNSET}\n+#ifndef module_param_array\n+/* Module Parameters are always initialized to -1, so that the driver\n+ * can tell the difference between no user specified value or the\n+ * user asking for the default value.\n+ * The true default values are loaded in when atl2_check_options is called.\n+ *\n+ * This is a GCC extension to ANSI C.\n+ * See the item \"Labeled Elements in Initializers\" in the section\n+ * \"Extensions to the C Language Family\" of the GCC documentation.\n+ */\n+\n+#define ATL2_PARAM(X, desc) \\\n+    static const int __devinitdata X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \\\n+    MODULE_PARM(X, \"1-\" __MODULE_STRING(ATL2_MAX_NIC) \"i\"); \\\n+    MODULE_PARM_DESC(X, desc);\n+#else\n+#define ATL2_PARAM(X, desc) \\\n+    static int __devinitdata X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \\\n+    static int num_##X = 0; \\\n+    module_param_array_named(X, X, int, &num_##X, 0); \\\n+    MODULE_PARM_DESC(X, desc);\n+#endif\n+\n+/*\n+ * Transmit Memory Size\n+ * Valid Range: 64-2048\n+ * Default Value: 128\n+ */\n+#define ATL2_MIN_TX_MEMSIZE\t\t4\t/* 4KB */\n+#define ATL2_MAX_TX_MEMSIZE\t\t64\t/* 64KB */\n+#define ATL2_DEFAULT_TX_MEMSIZE\t\t8\t/* 8KB */\n+ATL2_PARAM(TxMemSize, \"Bytes of Transmit Memory\");\n+\n+/*\n+ * Receive Memory Block Count\n+ * Valid Range: 16-512\n+ * Default Value: 128\n+ */\n+#define ATL2_MIN_RXD_COUNT\t\t16\n+#define ATL2_MAX_RXD_COUNT\t\t512\n+#define ATL2_DEFAULT_RXD_COUNT\t\t64\n+ATL2_PARAM(RxMemBlock, \"Number of receive memory block\");\n+\n+/*\n+ * User Specified MediaType Override\n+ *\n+ * Valid Range: 0-5\n+ *  - 0    - auto-negotiate at all supported speeds\n+ *  - 1    - only link at 1000Mbps Full Duplex\n+ *  - 2    - only link at 100Mbps Full Duplex\n+ *  - 3    - only link at 100Mbps Half Duplex\n+ *  - 4    - only link at 10Mbps Full Duplex\n+ *  - 5    - only link at 10Mbps Half Duplex\n+ * Default Value: 0\n+ */\n+ATL2_PARAM(MediaType, \"MediaType Select\");\n+\n+/*\n+ * Interrupt Moderate Timer in units of 2048 ns (~2 us)\n+ * Valid Range: 10-65535\n+ * Default Value: 45000(90ms)\n+ */\n+#define INT_MOD_DEFAULT_CNT\t100 /* 200us */\n+#define INT_MOD_MAX_CNT\t\t65000\n+#define INT_MOD_MIN_CNT\t\t50\n+ATL2_PARAM(IntModTimer, \"Interrupt Moderator Timer\");\n+\n+/*\n+ * FlashVendor\n+ * Valid Range: 0-2\n+ * 0 - Atmel\n+ * 1 - SST\n+ * 2 - ST\n+ */\n+ATL2_PARAM(FlashVendor, \"SPI Flash Vendor\");\n+\n+#define AUTONEG_ADV_DEFAULT\t0x2F\n+#define AUTONEG_ADV_MASK\t0x2F\n+#define FLOW_CONTROL_DEFAULT\tFLOW_CONTROL_FULL\n+\n+#define FLASH_VENDOR_DEFAULT\t0\n+#define FLASH_VENDOR_MIN\t0\n+#define FLASH_VENDOR_MAX\t2\n+\n+struct atl2_option {\n+\tenum { enable_option, range_option, list_option } type;\n+\tchar *name;\n+\tchar *err;\n+\tint  def;\n+\tunion {\n+\t\tstruct { /* range_option info */\n+\t\t\tint min;\n+\t\t\tint max;\n+\t\t} r;\n+\t\tstruct { /* list_option info */\n+\t\t\tint nr;\n+\t\t\tstruct atl2_opt_list { int i; char *str; } *p;\n+\t\t} l;\n+\t} arg;\n+};\n+\n+static int __devinit atl2_validate_option(int *value, struct atl2_option *opt)\n+{\n+\tint i;\n+\tstruct atl2_opt_list *ent;\n+\n+\tif (*value == OPTION_UNSET) {\n+\t\t*value = opt->def;\n+\t\treturn 0;\n+\t}\n+\n+\tswitch (opt->type) {\n+\tcase enable_option:\n+\t\tswitch (*value) {\n+\t\tcase OPTION_ENABLED:\n+\t\t\tprintk(KERN_INFO \"%s Enabled\\n\", opt->name);\n+\t\t\treturn 0;\n+\t\t\tbreak;\n+\t\tcase OPTION_DISABLED:\n+\t\t\tprintk(KERN_INFO \"%s Disabled\\n\", opt->name);\n+\t\t\treturn 0;\n+\t\t\tbreak;\n+\t\t}\n+\t\tbreak;\n+\tcase range_option:\n+\t\tif (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {\n+\t\t\tprintk(KERN_INFO \"%s set to %i\\n\", opt->name, *value);\n+\t\t\treturn 0;\n+\t\t}\n+\t\tbreak;\n+\tcase list_option:\n+\t\tfor (i = 0; i < opt->arg.l.nr; i++) {\n+\t\t\tent = &opt->arg.l.p[i];\n+\t\t\tif (*value == ent->i) {\n+\t\t\t\tif (ent->str[0] != '\\0')\n+\t\t\t\t\tprintk(KERN_INFO \"%s\\n\", ent->str);\n+\t\t\treturn 0;\n+\t\t\t}\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tBUG();\n+\t}\n+\n+\tprintk(KERN_INFO \"Invalid %s specified (%i) %s\\n\",\n+\t\topt->name, *value, opt->err);\n+\t*value = opt->def;\n+\treturn -1;\n+}\n+\n+/*\n+ * atl2_check_options - Range Checking for Command Line Parameters\n+ * @adapter: board private structure\n+ *\n+ * This routine checks all command line parameters for valid user\n+ * input.  If an invalid value is given, or if no user specified\n+ * value exists, a default value is used.  The final value is stored\n+ * in a variable in the adapter structure.\n+ */\n+static void __devinit atl2_check_options(struct atl2_adapter *adapter)\n+{\n+\tint val;\n+\tstruct atl2_option opt;\n+\tint bd = adapter->bd_number;\n+\tif (bd >= ATL2_MAX_NIC) {\n+\t\tprintk(KERN_NOTICE \"Warning: no configuration for board #%i\\n\",\n+\t\t\tbd);\n+\t\tprintk(KERN_NOTICE \"Using defaults for all values\\n\");\n+#ifndef module_param_array\n+\t\tbd = ATL2_MAX_NIC;\n+#endif\n+\t}\n+\n+\t/* Bytes of Transmit Memory */\n+\topt.type = range_option;\n+\topt.name = \"Bytes of Transmit Memory\";\n+\topt.err = \"using default of \" __MODULE_STRING(ATL2_DEFAULT_TX_MEMSIZE);\n+\topt.def = ATL2_DEFAULT_TX_MEMSIZE;\n+\topt.arg.r.min = ATL2_MIN_TX_MEMSIZE;\n+\topt.arg.r.max = ATL2_MAX_TX_MEMSIZE;\n+#ifdef module_param_array\n+\tif (num_TxMemSize > bd) {\n+#endif\n+\t\tval = TxMemSize[bd];\n+\t\tatl2_validate_option(&val, &opt);\n+\t\tadapter->txd_ring_size = ((u32) val) * 1024;\n+#ifdef module_param_array\n+\t} else\n+\t\tadapter->txd_ring_size = ((u32)opt.def) * 1024;\n+#endif\n+\t/* txs ring size: */\n+\tadapter->txs_ring_size = adapter->txd_ring_size / 128;\n+\tif (adapter->txs_ring_size > 160)\n+\t\tadapter->txs_ring_size = 160;\n+\n+\t/* Receive Memory Block Count */\n+\topt.type = range_option;\n+\topt.name = \"Number of receive memory block\";\n+\topt.err = \"using default of \" __MODULE_STRING(ATL2_DEFAULT_RXD_COUNT);\n+\topt.def = ATL2_DEFAULT_RXD_COUNT;\n+\topt.arg.r.min = ATL2_MIN_RXD_COUNT;\n+\topt.arg.r.max = ATL2_MAX_RXD_COUNT;\n+#ifdef module_param_array\n+\tif (num_RxMemBlock > bd) {\n+#endif\n+\t\tval = RxMemBlock[bd];\n+\t\tatl2_validate_option(&val, &opt);\n+\t\tadapter->rxd_ring_size = (u32)val;\n+\t\t/* FIXME */\n+\t\t/* ((u16)val)&~1; */\t/* even number */\n+#ifdef module_param_array\n+\t} else\n+\t\tadapter->rxd_ring_size = (u32)opt.def;\n+#endif\n+\t/* init RXD Flow control value */\n+\tadapter->hw.fc_rxd_hi = (adapter->rxd_ring_size / 8) * 7;\n+\tadapter->hw.fc_rxd_lo = (ATL2_MIN_RXD_COUNT / 8) >\n+\t\t(adapter->rxd_ring_size / 12) ? (ATL2_MIN_RXD_COUNT / 8) :\n+\t\t(adapter->rxd_ring_size / 12);\n+\n+\t/* Interrupt Moderate Timer */\n+\topt.type = range_option;\n+\topt.name = \"Interrupt Moderate Timer\";\n+\topt.err = \"using default of \" __MODULE_STRING(INT_MOD_DEFAULT_CNT);\n+\topt.def = INT_MOD_DEFAULT_CNT;\n+\topt.arg.r.min = INT_MOD_MIN_CNT;\n+\topt.arg.r.max = INT_MOD_MAX_CNT;\n+#ifdef module_param_array\n+\tif (num_IntModTimer > bd) {\n+#endif\n+\t\tval = IntModTimer[bd];\n+\t\tatl2_validate_option(&val, &opt);\n+\t\tadapter->imt = (u16) val;\n+#ifdef module_param_array\n+\t} else\n+\t\tadapter->imt = (u16)(opt.def);\n+#endif\n+\t/* Flash Vendor */\n+\topt.type = range_option;\n+\topt.name = \"SPI Flash Vendor\";\n+\topt.err = \"using default of \" __MODULE_STRING(FLASH_VENDOR_DEFAULT);\n+\topt.def = FLASH_VENDOR_DEFAULT;\n+\topt.arg.r.min = FLASH_VENDOR_MIN;\n+\topt.arg.r.max = FLASH_VENDOR_MAX;\n+#ifdef module_param_array\n+\tif (num_FlashVendor > bd) {\n+#endif\n+\t\tval = FlashVendor[bd];\n+\t\tatl2_validate_option(&val, &opt);\n+\t\tadapter->hw.flash_vendor = (u8) val;\n+#ifdef module_param_array\n+\t} else\n+\t\tadapter->hw.flash_vendor = (u8)(opt.def);\n+#endif\n+\t/* MediaType */\n+\topt.type = range_option;\n+\topt.name = \"Speed/Duplex Selection\";\n+\topt.err = \"using default of \" __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR);\n+\topt.def = MEDIA_TYPE_AUTO_SENSOR;\n+\topt.arg.r.min = MEDIA_TYPE_AUTO_SENSOR;\n+\topt.arg.r.max = MEDIA_TYPE_10M_HALF;\n+#ifdef module_param_array\n+\tif (num_MediaType > bd) {\n+#endif\n+\t\tval = MediaType[bd];\n+\t\tatl2_validate_option(&val, &opt);\n+\t\tadapter->hw.MediaType = (u16) val;\n+#ifdef module_param_array\n+\t} else\n+\t\tadapter->hw.MediaType = (u16)(opt.def);\n+#endif\n+}\ndiff -puN /dev/null drivers/net/atlx/atl2.h\n--- /dev/null\n+++ a/drivers/net/atlx/atl2.h\n@@ -0,0 +1,530 @@\n+/* atl2.h -- atl2 driver definitions\n+ *\n+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.\n+ * Copyright(c) 2006 xiong huang <xiong.huang@atheros.com>\n+ * Copyright(c) 2007 Chris Snook <csnook@redhat.com>\n+ *\n+ * Derived from Intel e1000 driver\n+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.\n+ *\n+ * This program is free software; you can redistribute it and/or modify it\n+ * under the terms of the GNU General Public License as published by the Free\n+ * Software Foundation; either version 2 of the License, or (at your option)\n+ * any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful, but WITHOUT\n+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\n+ * more details.\n+ *\n+ * You should have received a copy of the GNU General Public License along with\n+ * this program; if not, write to the Free Software Foundation, Inc., 59\n+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n+ */\n+\n+#ifndef _ATL2_H_\n+#define _ATL2_H_\n+\n+#include <asm/atomic.h>\n+#include <linux/netdevice.h>\n+\n+#ifndef _ATL2_HW_H_\n+#define _ATL2_HW_H_\n+\n+#ifndef _ATL2_OSDEP_H_\n+#define _ATL2_OSDEP_H_\n+\n+#include <linux/pci.h>\n+#include <linux/delay.h>\n+#include <linux/interrupt.h>\n+#include <linux/if_ether.h>\n+\n+#include \"atlx.h\"\n+\n+#ifdef ETHTOOL_OPS_COMPAT\n+extern int ethtool_ioctl(struct ifreq *ifr);\n+#endif\n+\n+#define PCI_COMMAND_REGISTER\tPCI_COMMAND\n+#define CMD_MEM_WRT_INVALIDATE\tPCI_COMMAND_INVALIDATE\n+#define ETH_ADDR_LEN\t\tETH_ALEN\n+\n+#define ATL2_WRITE_REG(a, reg, value) (iowrite32((value), \\\n+\t((a)->hw_addr + (reg))))\n+\n+#define ATL2_WRITE_FLUSH(a) (ioread32((a)->hw_addr))\n+\n+#define ATL2_READ_REG(a, reg) (ioread32((a)->hw_addr + (reg)))\n+\n+#define ATL2_WRITE_REGB(a, reg, value) (iowrite8((value), \\\n+\t((a)->hw_addr + (reg))))\n+\n+#define ATL2_READ_REGB(a, reg) (ioread8((a)->hw_addr + (reg)))\n+\n+#define ATL2_WRITE_REGW(a, reg, value) (iowrite16((value), \\\n+\t((a)->hw_addr + (reg))))\n+\n+#define ATL2_READ_REGW(a, reg) (ioread16((a)->hw_addr + (reg)))\n+\n+#define ATL2_WRITE_REG_ARRAY(a, reg, offset, value) \\\n+\t(iowrite32((value), (((a)->hw_addr + (reg)) + ((offset) << 2))))\n+\n+#define ATL2_READ_REG_ARRAY(a, reg, offset) \\\n+\t(ioread32(((a)->hw_addr + (reg)) + ((offset) << 2)))\n+\n+#endif /* _ATL2_OSDEP_H_ */\n+\n+struct atl2_adapter;\n+struct atl2_hw;\n+\n+/* function prototype */\n+static s32 atl2_reset_hw(struct atl2_hw *hw);\n+static s32 atl2_read_mac_addr(struct atl2_hw *hw);\n+static s32 atl2_init_hw(struct atl2_hw *hw);\n+static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed,\n+\tu16 *duplex);\n+static u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr);\n+static void atl2_hash_set(struct atl2_hw *hw, u32 hash_value);\n+static s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data);\n+static s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data);\n+static void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value);\n+static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value);\n+static void atl2_set_mac_addr(struct atl2_hw *hw);\n+static bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue);\n+static bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value);\n+static s32 atl2_phy_init(struct atl2_hw *hw);\n+static int atl2_check_eeprom_exist(struct atl2_hw *hw);\n+static void atl2_force_ps(struct atl2_hw *hw);\n+\n+/* register definition */\n+\n+/* Block IDLE Status Register */\n+#define IDLE_STATUS_RXMAC\t1\t/* 1: RXMAC is non-IDLE */\n+#define IDLE_STATUS_TXMAC\t2\t/* 1: TXMAC is non-IDLE */\n+#define IDLE_STATUS_DMAR\t8\t/* 1: DMAR is non-IDLE */\n+#define IDLE_STATUS_DMAW\t4\t/* 1: DMAW is non-IDLE */\n+\n+/* MDIO Control Register */\n+#define MDIO_WAIT_TIMES\t\t10\n+\n+/* MAC Control Register */\n+#define MAC_CTRL_DBG_TX_BKPRESURE\t0x100000\t/* 1: TX max backoff */\n+#define MAC_CTRL_MACLP_CLK_PHY\t\t0x8000000\t/* 1: 25MHz from phy */\n+#define MAC_CTRL_HALF_LEFT_BUF_SHIFT\t28\n+#define MAC_CTRL_HALF_LEFT_BUF_MASK\t0xF\t\t/* MAC retry buf x32B */\n+\n+/* Internal SRAM Partition Register */\n+#define REG_SRAM_TXRAM_END\t0x1500\t/* Internal tail address of TXRAM\n+\t\t\t\t\t * default: 2byte*1024 */\n+#define REG_SRAM_RXRAM_END\t0x1502\t/* Internal tail address of RXRAM\n+\t\t\t\t\t * default: 2byte*1024 */\n+\n+/* Descriptor Control register */\n+#define REG_TXD_BASE_ADDR_LO\t0x1544\t/* The base address of the Transmit\n+\t\t\t\t\t * Data Mem low 32-bit(dword align) */\n+#define REG_TXD_MEM_SIZE\t0x1548\t/* Transmit Data Memory size(by\n+\t\t\t\t\t * double word , max 256KB) */\n+#define REG_TXS_BASE_ADDR_LO\t0x154C\t/* The base address of the Transmit\n+\t\t\t\t\t * Status Memory low 32-bit(dword word\n+\t\t\t\t\t * align) */\n+#define REG_TXS_MEM_SIZE\t0x1550\t/* double word unit, max 4*2047\n+\t\t\t\t\t * bytes. */\n+#define REG_RXD_BASE_ADDR_LO\t0x1554\t/* The base address of the Transmit\n+\t\t\t\t\t * Status Memory low 32-bit(unit 8\n+\t\t\t\t\t * bytes) */\n+#define REG_RXD_BUF_NUM\t\t0x1558\t/* Receive Data & Status Memory buffer\n+\t\t\t\t\t * number (unit 1536bytes, max\n+\t\t\t\t\t * 1536*2047) */\n+\n+/* DMAR Control Register */\n+#define REG_DMAR\t0x1580\n+#define     DMAR_EN\t0x1\t/* 1: Enable DMAR */\n+\n+/* TX Cur-Through (early tx threshold) Control Register */\n+#define REG_TX_CUT_THRESH\t0x1590\t/* TxMac begin transmit packet\n+\t\t\t\t\t * threshold(unit word) */\n+\n+/* DMAW Control Register */\n+#define REG_DMAW\t0x15A0\n+#define     DMAW_EN\t0x1\n+\n+/* Flow control register */\n+#define REG_PAUSE_ON_TH\t\t0x15A8\t/* RXD high watermark of overflow\n+\t\t\t\t\t * threshold configuration register */\n+#define REG_PAUSE_OFF_TH\t0x15AA\t/* RXD lower watermark of overflow\n+\t\t\t\t\t * threshold configuration register */\n+\n+/* Mailbox Register */\n+#define REG_MB_TXD_WR_IDX\t0x15f0\t/* double word align */\n+#define REG_MB_RXD_RD_IDX\t0x15F4\t/* RXD Read index (unit: 1536byets) */\n+\n+/* Interrupt Status Register */\n+#define ISR_TIMER\t1\t/* Interrupt when Timer counts down to zero */\n+#define ISR_MANUAL\t2\t/* Software manual interrupt, for debug. Set\n+\t\t\t\t * when SW_MAN_INT_EN is set in Table 51\n+\t\t\t\t * Selene Master Control Register\n+\t\t\t\t * (Offset 0x1400). */\n+#define ISR_RXF_OV\t4\t/* RXF overflow interrupt */\n+#define ISR_TXF_UR\t8\t/* TXF underrun interrupt */\n+#define ISR_TXS_OV\t0x10\t/* Internal transmit status buffer full\n+\t\t\t\t * interrupt */\n+#define ISR_RXS_OV\t0x20\t/* Internal receive status buffer full\n+\t\t\t\t * interrupt */\n+#define ISR_LINK_CHG\t0x40\t/* Link Status Change Interrupt */\n+#define ISR_HOST_TXD_UR\t0x80\n+#define ISR_HOST_RXD_OV\t0x100\t/* Host rx data memory full , one pulse */\n+#define ISR_DMAR_TO_RST\t0x200\t/* DMAR op timeout interrupt. SW should\n+\t\t\t\t * do Reset */\n+#define ISR_DMAW_TO_RST\t0x400\n+#define ISR_PHY\t\t0x800\t/* phy interrupt */\n+#define ISR_TS_UPDATE\t0x10000\t/* interrupt after new tx pkt status written\n+\t\t\t\t * to host */\n+#define ISR_RS_UPDATE\t0x20000\t/* interrupt ater new rx pkt status written\n+\t\t\t\t * to host. */\n+#define ISR_TX_EARLY\t0x40000\t/* interrupt when txmac begin transmit one\n+\t\t\t\t * packet */\n+\n+#define ISR_TX_EVENT (ISR_TXF_UR | ISR_TXS_OV | ISR_HOST_TXD_UR |\\\n+\tISR_TS_UPDATE | ISR_TX_EARLY)\n+#define ISR_RX_EVENT (ISR_RXF_OV | ISR_RXS_OV | ISR_HOST_RXD_OV |\\\n+\t ISR_RS_UPDATE)\n+\n+#define IMR_NORMAL_MASK\t\t(\\\n+\t/*ISR_LINK_CHG\t\t|*/\\\n+\tISR_MANUAL\t\t|\\\n+\tISR_DMAR_TO_RST\t\t|\\\n+\tISR_DMAW_TO_RST\t\t|\\\n+\tISR_PHY\t\t\t|\\\n+\tISR_PHY_LINKDOWN\t|\\\n+\tISR_TS_UPDATE\t\t|\\\n+\tISR_RS_UPDATE)\n+\n+/* Receive MAC Statistics Registers */\n+#define REG_STS_RX_PAUSE\t0x1700\t/* Num pause packets received */\n+#define REG_STS_RXD_OV\t\t0x1704\t/* Num frames dropped due to RX\n+\t\t\t\t\t * FIFO overflow */\n+#define REG_STS_RXS_OV\t\t0x1708\t/* Num frames dropped due to RX\n+\t\t\t\t\t * Status Buffer Overflow */\n+#define REG_STS_RX_FILTER\t0x170C\t/* Num packets dropped due to\n+\t\t\t\t\t * address filtering */\n+\n+/* MII definitions */\n+\n+/* PHY Common Register */\n+#define MII_SMARTSPEED\t0x14\n+#define MII_DBG_ADDR\t0x1D\n+#define MII_DBG_DATA\t0x1E\n+\n+/* PCI Command Register Bit Definitions */\n+#define PCI_REG_COMMAND\t\t0x04\n+#define CMD_IO_SPACE\t\t0x0001\n+#define CMD_MEMORY_SPACE\t0x0002\n+#define CMD_BUS_MASTER\t\t0x0004\n+\n+#define MEDIA_TYPE_100M_FULL\t1\n+#define MEDIA_TYPE_100M_HALF\t2\n+#define MEDIA_TYPE_10M_FULL\t3\n+#define MEDIA_TYPE_10M_HALF\t4\n+\n+#define AUTONEG_ADVERTISE_SPEED_DEFAULT\t0x000F\t/* Everything */\n+\n+/* The size (in bytes) of a ethernet packet */\n+#define ENET_HEADER_SIZE\t\t14\n+#define MAXIMUM_ETHERNET_FRAME_SIZE\t1518\t/* with FCS */\n+#define MINIMUM_ETHERNET_FRAME_SIZE\t64\t/* with FCS */\n+#define ETHERNET_FCS_SIZE\t\t4\n+#define MAX_JUMBO_FRAME_SIZE\t\t0x2000\n+#define VLAN_SIZE                                               4\n+\n+struct tx_pkt_header {\n+\tunsigned pkt_size:11;\n+\tunsigned:4;\t\t\t/* reserved */\n+\tunsigned ins_vlan:1;\t\t/* txmac should insert vlan */\n+\tunsigned short vlan;\t\t/* vlan tag */\n+};\n+/* FIXME: replace above bitfields with MASK/SHIFT defines below */\n+#define TX_PKT_HEADER_SIZE_MASK\t\t0x7FF\n+#define TX_PKT_HEADER_SIZE_SHIFT\t0\n+#define TX_PKT_HEADER_INS_VLAN_MASK\t0x1\n+#define TX_PKT_HEADER_INS_VLAN_SHIFT\t15\n+#define TX_PKT_HEADER_VLAN_TAG_MASK\t0xFFFF\n+#define TX_PKT_HEADER_VLAN_TAG_SHIFT\t16\n+\n+struct tx_pkt_status {\n+\tunsigned pkt_size:11;\n+\tunsigned:5;\t\t/* reserved */\n+\tunsigned ok:1;\t\t/* current packet transmitted without error */\n+\tunsigned bcast:1;\t/* broadcast packet */\n+\tunsigned mcast:1;\t/* multicast packet */\n+\tunsigned pause:1;\t/* transmiited a pause frame */\n+\tunsigned ctrl:1;\n+\tunsigned defer:1;    \t/* current packet is xmitted with defer */\n+\tunsigned exc_defer:1;\n+\tunsigned single_col:1;\n+\tunsigned multi_col:1;\n+\tunsigned late_col:1;\n+\tunsigned abort_col:1;\n+\tunsigned underun:1;\t/* current packet is aborted\n+\t\t\t\t * due to txram underrun */\n+\tunsigned:3;\t\t/* reserved */\n+\tunsigned update:1;\t/* always 1'b1 in tx_status_buf */\n+};\n+/* FIXME: replace above bitfields with MASK/SHIFT defines below */\n+#define TX_PKT_STATUS_SIZE_MASK\t\t0x7FF\n+#define TX_PKT_STATUS_SIZE_SHIFT\t0\n+#define TX_PKT_STATUS_OK_MASK\t\t0x1\n+#define TX_PKT_STATUS_OK_SHIFT\t\t16\n+#define TX_PKT_STATUS_BCAST_MASK\t0x1\n+#define TX_PKT_STATUS_BCAST_SHIFT\t17\n+#define TX_PKT_STATUS_MCAST_MASK\t0x1\n+#define TX_PKT_STATUS_MCAST_SHIFT\t18\n+#define TX_PKT_STATUS_PAUSE_MASK\t0x1\n+#define TX_PKT_STATUS_PAUSE_SHIFT\t19\n+#define TX_PKT_STATUS_CTRL_MASK\t\t0x1\n+#define TX_PKT_STATUS_CTRL_SHIFT\t20\n+#define TX_PKT_STATUS_DEFER_MASK\t0x1\n+#define TX_PKT_STATUS_DEFER_SHIFT\t21\n+#define TX_PKT_STATUS_EXC_DEFER_MASK\t0x1\n+#define TX_PKT_STATUS_EXC_DEFER_SHIFT\t22\n+#define TX_PKT_STATUS_SINGLE_COL_MASK\t0x1\n+#define TX_PKT_STATUS_SINGLE_COL_SHIFT\t23\n+#define TX_PKT_STATUS_MULTI_COL_MASK\t0x1\n+#define TX_PKT_STATUS_MULTI_COL_SHIFT\t24\n+#define TX_PKT_STATUS_LATE_COL_MASK\t0x1\n+#define TX_PKT_STATUS_LATE_COL_SHIFT\t25\n+#define TX_PKT_STATUS_ABORT_COL_MASK\t0x1\n+#define TX_PKT_STATUS_ABORT_COL_SHIFT\t26\n+#define TX_PKT_STATUS_UNDERRUN_MASK\t0x1\n+#define TX_PKT_STATUS_UNDERRUN_SHIFT\t27\n+#define TX_PKT_STATUS_UPDATE_MASK\t0x1\n+#define TX_PKT_STATUS_UPDATE_SHIFT\t31\n+\n+struct rx_pkt_status {\n+\tunsigned pkt_size:11;\t/* packet size, max 2047 bytes */\n+\tunsigned:5;\t\t/* reserved */\n+\tunsigned ok:1;\t\t/* current packet received ok without error */\n+\tunsigned bcast:1;\t/* current packet is broadcast */\n+\tunsigned mcast:1;\t/* current packet is multicast */\n+\tunsigned pause:1;\n+\tunsigned ctrl:1;\n+\tunsigned crc:1;\t\t/* received a packet with crc error */\n+\tunsigned code:1;\t/* received a packet with code error */\n+\tunsigned runt:1;\t/* received a packet less than 64 bytes\n+\t\t\t\t * with good crc */\n+\tunsigned frag:1;\t/* received a packet less than 64 bytes\n+\t\t\t\t * with bad crc */\n+\tunsigned trunc:1;\t/* current frame truncated due to rxram full */\n+\tunsigned align:1;\t/* this packet is alignment error */\n+\tunsigned vlan:1;\t/* this packet has vlan */\n+\tunsigned:3;\t\t/* reserved */\n+\tunsigned update:1;\n+\tunsigned short vtag;\t/* vlan tag */\n+\tunsigned:16;\n+};\n+/* FIXME: replace above bitfields with MASK/SHIFT defines below */\n+#define RX_PKT_STATUS_SIZE_MASK\t\t0x7FF\n+#define RX_PKT_STATUS_SIZE_SHIFT\t0\n+#define RX_PKT_STATUS_OK_MASK\t\t0x1\n+#define RX_PKT_STATUS_OK_SHIFT\t\t16\n+#define RX_PKT_STATUS_BCAST_MASK\t0x1\n+#define RX_PKT_STATUS_BCAST_SHIFT\t17\n+#define RX_PKT_STATUS_MCAST_MASK\t0x1\n+#define RX_PKT_STATUS_MCAST_SHIFT\t18\n+#define RX_PKT_STATUS_PAUSE_MASK\t0x1\n+#define RX_PKT_STATUS_PAUSE_SHIFT\t19\n+#define RX_PKT_STATUS_CTRL_MASK\t\t0x1\n+#define RX_PKT_STATUS_CTRL_SHIFT\t20\n+#define RX_PKT_STATUS_CRC_MASK\t\t0x1\n+#define RX_PKT_STATUS_CRC_SHIFT\t\t21\n+#define RX_PKT_STATUS_CODE_MASK\t\t0x1\n+#define RX_PKT_STATUS_CODE_SHIFT\t22\n+#define RX_PKT_STATUS_RUNT_MASK\t\t0x1\n+#define RX_PKT_STATUS_RUNT_SHIFT\t23\n+#define RX_PKT_STATUS_FRAG_MASK\t\t0x1\n+#define RX_PKT_STATUS_FRAG_SHIFT\t24\n+#define RX_PKT_STATUS_TRUNK_MASK\t0x1\n+#define RX_PKT_STATUS_TRUNK_SHIFT\t25\n+#define RX_PKT_STATUS_ALIGN_MASK\t0x1\n+#define RX_PKT_STATUS_ALIGN_SHIFT\t26\n+#define RX_PKT_STATUS_VLAN_MASK\t\t0x1\n+#define RX_PKT_STATUS_VLAN_SHIFT\t27\n+#define RX_PKT_STATUS_UPDATE_MASK\t0x1\n+#define RX_PKT_STATUS_UPDATE_SHIFT\t31\n+#define RX_PKT_STATUS_VLAN_TAG_MASK\t0xFFFF\n+#define RX_PKT_STATUS_VLAN_TAG_SHIFT\t32\n+\n+struct rx_desc {\n+\tstruct rx_pkt_status\tstatus;\n+\tunsigned char     \tpacket[1536-sizeof(struct rx_pkt_status)];\n+};\n+\n+enum atl2_speed_duplex {\n+\tatl2_10_half = 0,\n+\tatl2_10_full = 1,\n+\tatl2_100_half = 2,\n+\tatl2_100_full = 3\n+};\n+\n+struct atl2_spi_flash_dev {\n+\tconst char *manu_name;\t/* manufacturer id */\n+\t/* op-code */\n+\tu8 cmdWRSR;\n+\tu8 cmdREAD;\n+\tu8 cmdPROGRAM;\n+\tu8 cmdWREN;\n+\tu8 cmdWRDI;\n+\tu8 cmdRDSR;\n+\tu8 cmdRDID;\n+\tu8 cmdSECTOR_ERASE;\n+\tu8 cmdCHIP_ERASE;\n+};\n+\n+/* Structure containing variables used by the shared code (atl2_hw.c) */\n+struct atl2_hw {\n+\tu8 __iomem *hw_addr;\n+\tvoid *back;\n+\n+\tu8 preamble_len;\n+\tu8 max_retry;          /* Retransmission maximum, afterwards the\n+\t\t\t\t* packet will be discarded. */\n+\tu8 jam_ipg;            /* IPG to start JAM for collision based flow\n+\t\t\t\t* control in half-duplex mode. In unit of\n+\t\t\t\t* 8-bit time. */\n+\tu8 ipgt;               /* Desired back to back inter-packet gap. The\n+\t\t\t\t* default is 96-bit time. */\n+\tu8 min_ifg;            /* Minimum number of IFG to enforce in between\n+\t\t\t\t* RX frames. Frame gap below such IFP is\n+\t\t\t\t* dropped. */\n+\tu8 ipgr1;              /* 64bit Carrier-Sense window */\n+\tu8 ipgr2;              /* 96-bit IPG window */\n+\tu8 retry_buf;          /* When half-duplex mode, should hold some\n+\t\t\t\t* bytes for mac retry . (8*4bytes unit) */\n+\n+\tu16 fc_rxd_hi;\n+\tu16 fc_rxd_lo;\n+\tu16 lcol;              /* Collision Window */\n+\tu16 max_frame_size;\n+\n+\tu16 MediaType;\n+\tu16 autoneg_advertised;\n+\tu16 pci_cmd_word;\n+\n+\tu16 mii_autoneg_adv_reg;\n+\n+\tu32 mem_rang;\n+\tu32 txcw;\n+\tu32 mc_filter_type;\n+\tu32 num_mc_addrs;\n+\tu32 collision_delta;\n+\tu32 tx_packet_delta;\n+\tu16 phy_spd_default;\n+\n+\tu16 device_id;\n+\tu16 vendor_id;\n+\tu16 subsystem_id;\n+\tu16 subsystem_vendor_id;\n+\tu8 revision_id;\n+\n+\t/* spi flash */\n+\tu8 flash_vendor;\n+\n+\tu8 dma_fairness;\n+\tu8 mac_addr[NODE_ADDRESS_SIZE];\n+\tu8 perm_mac_addr[NODE_ADDRESS_SIZE];\n+\n+\t/* FIXME */\n+\t/* bool phy_preamble_sup; */\n+\tbool phy_configured;\n+};\n+\n+#endif /* _ATL2_HW_H_ */\n+\n+struct atl2_ring_header {\n+    /* pointer to the descriptor ring memory */\n+    void *desc;\n+    /* physical adress of the descriptor ring */\n+    dma_addr_t dma;\n+    /* length of descriptor ring in bytes */\n+    unsigned int size;\n+};\n+\n+/* board specific private data structure */\n+struct atl2_adapter {\n+\t/* OS defined structs */\n+\tstruct net_device *netdev;\n+\tstruct pci_dev *pdev;\n+\tstruct net_device_stats net_stats;\n+#ifdef NETIF_F_HW_VLAN_TX\n+\tstruct vlan_group *vlgrp;\n+#endif\n+\tu32 wol;\n+\tu16 link_speed;\n+\tu16 link_duplex;\n+\n+\tspinlock_t stats_lock;\n+\tspinlock_t tx_lock;\n+\n+\tstruct work_struct reset_task;\n+\tstruct work_struct link_chg_task;\n+\tstruct timer_list watchdog_timer;\n+\tstruct timer_list phy_config_timer;\n+\n+\tunsigned long cfg_phy;\n+\tbool mac_disabled;\n+\n+\t/* All Descriptor memory */\n+\tdma_addr_t\tring_dma;\n+\tvoid\t\t*ring_vir_addr;\n+\tint\t\tring_size;\n+\n+\tstruct tx_pkt_header\t*txd_ring;\n+\tdma_addr_t\ttxd_dma;\n+\n+\tstruct tx_pkt_status\t*txs_ring;\n+\tdma_addr_t\ttxs_dma;\n+\n+\tstruct rx_desc\t*rxd_ring;\n+\tdma_addr_t\trxd_dma;\n+\n+\tu32 txd_ring_size;         /* bytes per unit */\n+\tu32 txs_ring_size;         /* dwords per unit */\n+\tu32 rxd_ring_size;         /* 1536 bytes per unit */\n+\n+\t/* read /write ptr: */\n+\t/* host */\n+\tu32 txd_write_ptr;\n+\tu32 txs_next_clear;\n+\tu32 rxd_read_ptr;\n+\n+\t/* nic */\n+\tatomic_t txd_read_ptr;\n+\tatomic_t txs_write_ptr;\n+\tu32 rxd_write_ptr;\n+\n+\t/* Interrupt Moderator timer ( 2us resolution) */\n+\tu16 imt;\n+\t/* Interrupt Clear timer (2us resolution) */\n+\tu16 ict;\n+\n+\tunsigned long flags;\n+\t/* structs defined in atl2_hw.h */\n+\tu32 bd_number;     /* board number */\n+\tbool pci_using_64;\n+\tbool have_msi;\n+\tstruct atl2_hw hw;\n+\n+\tu32 usr_cmd;\n+\t/* FIXME */\n+\t/* u32 regs_buff[ATL2_REGS_LEN]; */\n+\tu32 pci_state[16];\n+\n+\tu32 *config_space;\n+};\n+\n+enum atl2_state_t {\n+\t__ATL2_TESTING,\n+\t__ATL2_RESETTING,\n+\t__ATL2_DOWN\n+};\n+\n+#endif /* _ATL2_H_ */\ndiff -puN include/linux/pci_ids.h~atl2-add-atl2-driver include/linux/pci_ids.h\n--- a/include/linux/pci_ids.h~atl2-add-atl2-driver\n+++ a/include/linux/pci_ids.h\n@@ -2225,6 +2225,7 @@\n \n #define PCI_VENDOR_ID_ATTANSIC\t\t0x1969\n #define PCI_DEVICE_ID_ATTANSIC_L1\t0x1048\n+#define PCI_DEVICE_ID_ATTANSIC_L2\t0x2048\n \n #define PCI_VENDOR_ID_JMICRON\t\t0x197B\n #define PCI_DEVICE_ID_JMICRON_JMB360\t0x2360\n",
    "prefixes": [
        "20/21"
    ]
}