summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorTian Fang <tfang@fb.com>2015-04-24 14:32:12 +0100
committerJavier Jardón <jjardon@gnome.org>2015-05-06 16:15:22 +0100
commit98f979f8a4842a4e6bf56e6b63aa334e3997ca18 (patch)
tree5b3f08aa369c8bf0be7779ebccb65c9fe8512259 /drivers/net
parent1e85856853e24e9013d142adaad38c2adc7e48ac (diff)
downloadlinux-stable-98f979f8a4842a4e6bf56e6b63aa334e3997ca18.tar.gz
Add support for aspeed hardware
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Kconfig3
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/ftgmac100_26.c1883
-rw-r--r--drivers/net/ftgmac100_26.h580
4 files changed, 2467 insertions, 0 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 231eeaf1d552..e017c36280da 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1889,6 +1889,9 @@ menuconfig NETDEV_1000
if NETDEV_1000
+config ASPEEDMAC
+ tristate "ASPEED MAC support"
+
config ACENIC
tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
depends on PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 017383ad5ec6..3c04c0bc627a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
obj-$(CONFIG_RIONET) += rionet.o
obj-$(CONFIG_SH_ETH) += sh_eth.o
+obj-$(CONFIG_ASPEEDMAC) += ftgmac100_26.o
#
# end link order section
diff --git a/drivers/net/ftgmac100_26.c b/drivers/net/ftgmac100_26.c
new file mode 100644
index 000000000000..8575293015e7
--- /dev/null
+++ b/drivers/net/ftgmac100_26.c
@@ -0,0 +1,1883 @@
+/********************************************************************************
+* File Name : ftgmac100_26.c
+*
+* Copyright (C) 2012-2020 ASPEED Technology Inc.
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by the Free Software Foundation;
+* either version 2 of the License, or (at your option) any later version.
+* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+********************************************************************************/
+//-----------------------------------------------------------------------------
+// "ASPEED MAC Driver, (Linux Kernel 2.6.15.7) 10/02/07 - by ASPEED\n"
+// Further improvements:
+//
+// -- Assume MAC1 has a PHY chip. Read the chip type and handle Marvell
+// or Broadcom, else don't touch PHY chip (if present).
+//
+// -- If MAC2 is on, check if U-Boot enabled the MII2DC+MII2DIO pins.
+// If yes, handle Marvell or Broadcom PHY. If no, assume sideband RMII
+// interface with no PHY chip.
+// 1.12/27/07 - by river@aspeed
+// Workaround for the gigabit hash function
+// 2.12/27/07 - by river@aspeed
+// Synchronize the EDORR bit with document, D[30], D[15] both are EDORR
+// 3.12/31/07 - by river@aspeed
+// Add aspeed_i2c_init and aspeed_i2c_read function for DHCP
+// 4.04/10/2008 - by river@aspeed
+// Synchronize the EDOTR bit with document, D[30] is EDOTR
+// 5.04/10/2008 - by river@aspeed
+// Remove the workaround for multicast hash function in A2 chip
+// SDK 0.19
+// 6.05/15/2008 - by river@aspeed
+// Fix bug of free sk_buff in wrong routine
+// 7.05/16/2008 - by river@aspeed
+// Fix bug of skb_over_panic()
+// 8.05/22/2008 - by river@aspeed
+// Support NCSI Feature
+// SDK 0.20
+// 9.07/02/2008 - by river@aspeed
+// Fix TX will drop packet bug
+// SDK 0.21
+//10.08/06/2008 - by river@aspeed
+// Add the netif_carrier_on() and netif_carrier_off()
+//11.08/06/2008 - by river@aspeed
+// Fix the timer did not work after device closed
+// SDK0.22
+//12.08/12/2008 - by river@aspeed
+// Support different PHY configuration
+// SDK0.23
+//13.10/14/2008 - by river@aspeed
+// Support Realtek RTL8211BN Gigabit PHY
+//14.11/17/2008 - by river@aspeed
+// Modify the allocate buffer to alignment to IP header
+// SDK0.26
+//15.07/28/2009 - by river@aspeed
+// Fix memory leakage problem in using multicast
+//16.07/28/2009 - by river@aspeed
+// tx_free field in the local structure should be integer
+//
+//
+//
+//AST2300 SDK 0.12
+//17.03/30/2010 - by river@aspeed
+// Modify for AST2300's hardware CLOCK/RESET/MULTI-PIN configuration
+//18.03/30/2010 - by river@aspeed
+// Fix does not report netif_carrier_on() and netif_carrier_off() when use MARVELL PHY
+//AST2300 SDK 0.13
+//17.06/10/2010 - by river@aspeed
+// Support AST2300 A0
+//18.06/10/2010 - by river@aspeed
+// EEPROM is at I2C channel 4 on AST2300 A0 EVB
+//AST2300 SDK 0.14
+//19.09/13/2010 - by river@aspeed
+// Support Realtek RTL8201EL 10/100M PHY
+//AST2400
+//20.06/25/2013 - by CC@aspeed
+// Support BCM54612E 10/100/1000M PHY
+//-----------------------------------------------------------------------------
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <mach/ftgmac100_drv.h>
+
+#include <linux/skbuff.h>
+
+#include "ftgmac100_26.h"
+
+#if defined(CONFIG_ARM)
+#include <mach/hardware.h>
+#include <asm/cacheflush.h>
+
+#elif defined(CONFIG_COLDFIRE)
+#include <asm/astsim.h>
+
+#else
+#err "Not define include for GMAC"
+#endif
+
+/*------------------------------------------------------------------------
+ .
+ . Configuration options, for the experienced user to change.
+ .
+ -------------------------------------------------------------------------*/
+
+/*
+ . DEBUGGING LEVELS
+ .
+ . 0 for normal operation
+ . 1 for slightly more details
+ . >2 for various levels of increasingly useless information
+ . 2 for interrupt tracking, status flags
+ . 3 for packet info
+ . 4 for complete packet dumps
+*/
+
+#define DO_PRINT(args...) printk(": " args)
+
+#define FTMAC100_DEBUG 1
+
+#if (FTMAC100_DEBUG > 2 )
+#define PRINTK3(args...) DO_PRINT(args)
+#else
+#define PRINTK3(args...)
+#endif
+
+#if FTMAC100_DEBUG > 1
+#define PRINTK2(args...) DO_PRINT(args)
+#else
+#define PRINTK2(args...)
+#endif
+
+#ifdef FTMAC100_DEBUG
+#define PRINTK(args...) DO_PRINT(args)
+#else
+#define PRINTK(args...)
+#endif
+
+/*
+ . A rather simple routine to print out a packet for debugging purposes.
+*/
+#if FTMAC100_DEBUG > 2
+static void print_packet( u8 *, int );
+#endif
+
+static int ftgmac100_wait_to_send_packet(struct sk_buff * skb, struct net_device * dev);
+
+static volatile int trans_busy = 0;
+
+
+void ftgmac100_phy_rw_waiting(unsigned int ioaddr)
+{
+ unsigned int tmp;
+
+ do {
+ mdelay(10);
+ tmp =inl(ioaddr + PHYCR_REG);
+ } while ((tmp&(PHY_READ_bit|PHY_WRITE_bit)) > 0);
+}
+
+
+/*------------------------------------------------------------
+ . Reads a register from the MII Management serial interface
+ .-------------------------------------------------------------*/
+static u16 ftgmac100_read_phy_register(unsigned int ioaddr, u8 phyaddr, u8 phyreg)
+{
+ unsigned int tmp;
+
+ if (phyaddr > 0x1f) // MII chip IDs are 5 bits long
+ return 0xffff;
+
+ tmp = inl(ioaddr + PHYCR_REG);
+ tmp &= 0x3000003F;
+ tmp |=(phyaddr<<16);
+ tmp |=(phyreg<<(16+5));
+ tmp |=PHY_READ_bit;
+
+ outl( tmp, ioaddr + PHYCR_REG );
+ ftgmac100_phy_rw_waiting(ioaddr);
+
+ return (inl(ioaddr + PHYDATA_REG)>>16);
+}
+
+
+/*------------------------------------------------------------
+ . Writes a register to the MII Management serial interface
+ .-------------------------------------------------------------*/
+static void ftgmac100_write_phy_register(unsigned int ioaddr,
+ u8 phyaddr, u8 phyreg, u16 phydata)
+{
+ unsigned int tmp;
+
+ if (phyaddr > 0x1f) // MII chip IDs are 5 bits long
+ return;
+
+ tmp = inl(ioaddr + PHYCR_REG);
+ tmp &= 0x3000003F;
+ tmp |=(phyaddr<<16);
+ tmp |=(phyreg<<(16+5));
+ tmp |=PHY_WRITE_bit;
+
+ outl( phydata, ioaddr + PHYDATA_REG );
+ outl( tmp, ioaddr + PHYCR_REG );
+ ftgmac100_phy_rw_waiting(ioaddr);
+}
+
+static void ast_gmac_set_mac(struct ftgmac100_priv *priv, const unsigned char *mac)
+{
+ unsigned int maddr = mac[0] << 8 | mac[1];
+ unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
+
+ iowrite32(maddr, priv->netdev->base_addr + MAC_MADR_REG);
+ iowrite32(laddr, priv->netdev->base_addr + MAC_LADR_REG);
+}
+
+/*
+ * MAC1 always has MII MDC+MDIO pins to access PHY registers. We assume MAC1
+ * always has a PHY chip, if MAC1 is enabled.
+ * U-Boot can enable MAC2 MDC+MDIO pins for a 2nd PHY, or MAC2 might be
+ * disabled (only one port), or it's sideband-RMII which has no PHY chip.
+ *
+ * Return miiPhyId==0 if the MAC cannot be accessed.
+ * Return miiPhyId==1 if the MAC registers are OK but it cannot carry traffic.
+ * Return miiPhyId==2 if the MAC can send/receive but it has no PHY chip.
+ * Else return the PHY 22-bit vendor ID, 6-bit model and 4-bit revision.
+ */
+static void getMacHwConfig( struct net_device* dev, struct AstMacHwConfig* out )
+{
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+
+// out->macId = dev->dev_id;
+//.. getMacAndPhy(dev, out);
+ out->miiPhyId = 0;
+
+ // We assume the Clock Stop register does not disable the MAC1 or MAC2 clock
+ // unless Reset Control also holds the MAC in reset.
+ // For now, we only support a PHY chip on the MAC's own MDC+MDIO bus.
+ if (out->phyAddr > 0x1f) {
+no_phy_access:
+ out->phyAddr = 0xff;
+ return;
+ }
+
+ if (priv->NCSI_support == 0) {
+ out->miiPhyId = ftgmac100_read_phy_register(dev->base_addr, out->phyAddr, 0x02);
+ if (out->miiPhyId == 0xFFFF) { //Realtek PHY at address 1
+ out->phyAddr = 1;
+ }
+ if (out->miiPhyId == 0x0362) {
+ out->phyAddr = 1;
+ }
+ out->miiPhyId = ftgmac100_read_phy_register(dev->base_addr, out->phyAddr, 0x02);
+ out->miiPhyId = (out->miiPhyId & 0xffff) << 16;
+ out->miiPhyId |= ftgmac100_read_phy_register(dev->base_addr, out->phyAddr, 0x03) & 0xffff;
+
+ switch (out->miiPhyId >> 16) {
+ case 0x0040: // Broadcom
+ case 0x0141: // Marvell
+ case 0x001c: // Realtek
+ case 0x0362: // BCM54612
+ break;
+
+ default:
+ // Leave miiPhyId for DO_PRINT(), but reset phyAddr.
+ // out->miiPhyId = 2;
+ goto no_phy_access;
+ break;
+ }
+ }
+ return;
+}
+
+
+static void ftgmac100_reset( struct net_device* dev )
+{
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+ struct AstMacHwConfig* ids = &priv->ids;
+ unsigned int tmp, speed, duplex;
+
+ getMacHwConfig(dev, ids);
+ PRINTK("%s:ftgmac100_reset, phyAddr=0x%x, miiPhyId=0x%04x_%04x\n",
+ dev->name, ids->phyAddr, (ids->miiPhyId >> 16), (ids->miiPhyId & 0xffff));
+
+ if (ids->miiPhyId < 1)
+ return; // Cannot access MAC registers
+
+ // Check the link speed and duplex.
+ // They are not valid until auto-neg is resolved, which is reg.1 bit[5],
+ // or the link is up, which is reg.1 bit[2].
+
+ if (ids->phyAddr < 0xff)
+ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x1);
+ else tmp = 0;
+
+ if (0==(tmp & (1u<<5 | 1u<<2)) || ids->phyAddr >= 0xff) {
+ // No PHY chip, or link has not negotiated.
+ speed = PHY_SPEED_100M;
+ duplex = 1;
+ netif_carrier_off(dev);
+ }
+ else if (((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) {
+ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x00);
+ duplex = (tmp & 0x0100) ? 1 : 0;
+ speed = (tmp & 0x2000) ? PHY_SPEED_100M : PHY_SPEED_10M;
+ }
+ else if (((ids->miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) ||
+ ((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) {
+ // Use reg.17_0.bit[15:13] for {speed[1:0], duplex}.
+ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x11);
+ duplex = (tmp & PHY_DUPLEX_mask)>>13;
+ speed = (tmp & PHY_SPEED_mask)>>14;
+ netif_carrier_on(dev);
+ }
+ else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
+ // Get link status
+ // First Switch shadow register selector
+ ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000);
+ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C);
+ if ( (tmp & 0x0080) == 0x0080 )
+ duplex = 0;
+ else
+ duplex = 1;
+
+ switch(tmp & 0x0018) {
+ case 0x0000:
+ speed = PHY_SPEED_1G; break;
+ case 0x0008:
+ speed = PHY_SPEED_100M; break;
+ case 0x0010:
+ speed = PHY_SPEED_10M; break;
+ default:
+ speed = PHY_SPEED_100M;
+ }
+ }
+ else {
+ // Assume Broadcom BCM5221. Use reg.18 bits [1:0] for {100Mb/s, fdx}.
+ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x18);
+ duplex = (tmp & 0x0001);
+ speed = (tmp & 0x0002) ? PHY_SPEED_100M : PHY_SPEED_10M;
+ }
+
+ if (speed == PHY_SPEED_1G) {
+ // Set SPEED_100_bit too, for consistency.
+ priv->maccr_val |= GMAC_MODE_bit | SPEED_100_bit;
+ tmp = inl( dev->base_addr + MACCR_REG );
+ tmp |= GMAC_MODE_bit | SPEED_100_bit;
+ outl(tmp, dev->base_addr + MACCR_REG );
+ } else {
+ priv->maccr_val &= ~(GMAC_MODE_bit | SPEED_100_bit);
+ tmp = inl( dev->base_addr + MACCR_REG );
+ tmp &= ~(GMAC_MODE_bit | SPEED_100_bit);
+ if (speed == PHY_SPEED_100M) {
+ priv->maccr_val |= SPEED_100_bit;
+ tmp |= SPEED_100_bit;
+ }
+ outl(tmp, dev->base_addr + MACCR_REG );
+ }
+ if (duplex)
+ priv->maccr_val |= FULLDUP_bit;
+ else
+ priv->maccr_val &= ~FULLDUP_bit;
+
+ outl( SW_RST_bit, dev->base_addr + MACCR_REG );
+
+#ifdef not_complete_yet
+ /* Setup for fast accesses if requested */
+ /* If the card/system can't handle it then there will */
+ /* be no recovery except for a hard reset or power cycle */
+ if (dev->dma)
+ {
+ outw( inw( dev->base_addr + CONFIG_REG ) | CONFIG_NO_WAIT,
+ dev->base_addr + CONFIG_REG );
+ }
+#endif /* end_of_not */
+
+ /* this should pause enough for the chip to be happy */
+ for (; (inl( dev->base_addr + MACCR_REG ) & SW_RST_bit) != 0; )
+ {
+ mdelay(10);
+ PRINTK3("RESET: reset not complete yet\n" );
+ }
+
+ outl( 0, dev->base_addr + IER_REG ); /* Disable all interrupts */
+}
+
+static void ftgmac100_enable( struct net_device *dev )
+{
+ int i;
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+ unsigned int tmp_rsize; //Richard
+ unsigned int rfifo_rsize; //Richard
+ unsigned int tfifo_rsize; //Richard
+ unsigned int rxbuf_size;
+
+ rxbuf_size = RX_BUF_SIZE & 0x3fff;
+ outl( rxbuf_size , dev->base_addr + RBSR_REG); //for NC Body
+
+ for (i=0; i<RXDES_NUM; ++i)
+ priv->rx_descs[i].RXPKT_RDY = RX_OWNBY_FTGMAC100; // owned by FTMAC100
+
+ priv->rx_idx = 0;
+
+ for (i=0; i<TXDES_NUM; ++i) {
+ priv->tx_descs[i].TXDMA_OWN = TX_OWNBY_SOFTWARE; // owned by software
+ priv->tx_skbuff[i] = 0;
+ }
+
+ priv->tx_idx = 0;
+ priv->old_tx = 0;
+ priv->tx_free=TXDES_NUM;
+
+ /* Set the MAC address */
+ ast_gmac_set_mac(priv, dev->dev_addr);
+
+ outl( priv->rx_descs_dma, dev->base_addr + RXR_BADR_REG);
+ outl( priv->tx_descs_dma, dev->base_addr + TXR_BADR_REG);
+ outl( 0x00001010, dev->base_addr + ITC_REG);
+
+ outl( (0UL<<TXPOLL_CNT)|(0x1<<RXPOLL_CNT), dev->base_addr + APTC_REG);
+ outl( 0x44f97, dev->base_addr + DBLAC_REG );
+
+ /// outl( inl(FCR_REG)|0x1, ioaddr + FCR_REG ); // enable flow control
+ /// outl( inl(BPR_REG)|0x1, ioaddr + BPR_REG ); // enable back pressure register
+
+ // +++++ Richard +++++ //
+ tmp_rsize = inl( dev->base_addr + FEAR_REG );
+ rfifo_rsize = tmp_rsize & 0x00000007;
+ tfifo_rsize = (tmp_rsize >> 3)& 0x00000007;
+
+ tmp_rsize = inl( dev->base_addr + TPAFCR_REG );
+ tmp_rsize &= ~0x3f000000;
+ tmp_rsize |= (tfifo_rsize << 27);
+ tmp_rsize |= (rfifo_rsize << 24);
+
+ outl(tmp_rsize, dev->base_addr + TPAFCR_REG);
+ // ----- Richard ----- //
+
+//river set MAHT0, MAHT1
+ if (priv->maccr_val & GMAC_MODE_bit) {
+ outl (priv->GigaBit_MAHT0, dev->base_addr + MAHT0_REG);
+ outl (priv->GigaBit_MAHT1, dev->base_addr + MAHT1_REG);
+ }
+ else {
+ outl (priv->Not_GigaBit_MAHT0, dev->base_addr + MAHT0_REG);
+ outl (priv->Not_GigaBit_MAHT1, dev->base_addr + MAHT1_REG);
+ }
+
+ /// enable trans/recv,...
+ outl(priv->maccr_val, dev->base_addr + MACCR_REG );
+#if 0
+//NCSI Start
+//DeSelect Package/ Select Package
+ if ((priv->NCSI_support == 1) || (priv->INTEL_NCSI_EVA_support == 1)) {
+ NCSI_Struct_Initialize(dev);
+ for (i = 0; i < 4; i++) {
+ DeSelect_Package (dev, i);
+ Package_Found = Select_Package (dev, i);
+ if (Package_Found == 1) {
+//AST2100/AST2050/AST1100 supports 1 slave only
+ priv->NCSI_Cap.Package_ID = i;
+ break;
+ }
+ }
+ if (Package_Found != 0) {
+//Initiali State
+ for (i = 0; i < 2; i++) { //Suppose 2 channels in current version, You could modify it to 0x1F to support 31 channels
+ Channel_Found = Clear_Initial_State(dev, i);
+ if (Channel_Found == 1) {
+ priv->NCSI_Cap.Channel_ID = i;
+ printk ("Found NCSI Network Controller at (%d, %d)\n", priv->NCSI_Cap.Package_ID, priv->NCSI_Cap.Channel_ID);
+//Get Version and Capabilities
+ Get_Version_ID(dev);
+ Get_Capabilities(dev);
+//Configuration
+ Select_Active_Package(dev);
+//Set MAC Address
+ Enable_Set_MAC_Address(dev);
+//Enable Broadcast Filter
+ Enable_Broadcast_Filter(dev);
+//Disable VLAN
+ Disable_VLAN(dev);
+//Enable AEN
+ Enable_AEN(dev);
+//Get Parameters
+ Get_Parameters(dev);
+//Enable TX
+ Enable_Network_TX(dev);
+//Enable Channel
+ Enable_Channel(dev);
+//Get Link Status
+Re_Get_Link_Status:
+ Link_Status = Get_Link_Status(dev);
+ if (Link_Status == LINK_UP) {
+ printk ("Using NCSI Network Controller (%d, %d)\n", priv->NCSI_Cap.Package_ID, priv->NCSI_Cap.Channel_ID);
+ netif_carrier_on(dev);
+ break;
+ }
+ else if ((Link_Status == LINK_DOWN) && (Re_Send < 2)) {
+ Re_Send++;
+ netif_carrier_off(dev);
+ goto Re_Get_Link_Status;
+ }
+//Disable TX
+ Disable_Network_TX(dev);
+//Disable Channel
+// Disable_Channel(dev);
+ Re_Send = 0;
+ Channel_Found = 0;
+ }
+ }
+ }
+ }
+ /* now, enable interrupts */
+#endif
+ if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) ||
+ ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) {
+ outl(
+ PHYSTS_CHG_bit |
+ AHB_ERR_bit |
+ TPKT_LOST_bit |
+ TPKT2E_bit |
+ RXBUF_UNAVA_bit |
+ RPKT2B_bit
+ ,dev->base_addr + IER_REG
+ );
+ }
+ else if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) ||
+ ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) {
+ outl(
+ AHB_ERR_bit |
+ TPKT_LOST_bit |
+ TPKT2E_bit |
+ RXBUF_UNAVA_bit |
+ RPKT2B_bit
+ ,dev->base_addr + IER_REG
+ );
+ }
+ else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
+ outl(
+// no link PHY link status pin PHYSTS_CHG_bit |
+ AHB_ERR_bit |
+ TPKT_LOST_bit |
+ TPKT2E_bit |
+ RXBUF_UNAVA_bit |
+ RPKT2B_bit
+ ,dev->base_addr + IER_REG
+ );
+ } else {
+ outl(
+// no link PHY link status pin PHYSTS_CHG_bit |
+ AHB_ERR_bit |
+ TPKT_LOST_bit |
+ TPKT2E_bit |
+ RXBUF_UNAVA_bit |
+ RPKT2B_bit
+ ,dev->base_addr + IER_REG
+ );
+ }
+}
+
+static void aspeed_mac_timer(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+ unsigned int status, tmp, speed, duplex, macSpeed;
+
+#ifdef CONFIG_ARCH_AST2300
+ //Fix issue for tx/rx arbiter lock
+ outl( 0xffffffff, dev->base_addr + TXPD_REG);
+#endif
+ status = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x01);
+
+ if (status & LINK_STATUS) { // Bit[2], Link Status, link is up
+ priv->timer.expires = jiffies + 10 * HZ;
+
+ if ((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) {
+ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x18);
+ duplex = (tmp & 0x0001);
+ speed = (tmp & 0x0002) ? PHY_SPEED_100M : PHY_SPEED_10M;
+ }
+ else if ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL) {
+ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x00);
+ duplex = (tmp & 0x0100) ? 1 : 0;
+ speed = (tmp & 0x2000) ? PHY_SPEED_100M : PHY_SPEED_10M;
+ }
+ else if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) ||
+ ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) {
+ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x11);
+ duplex = (tmp & PHY_DUPLEX_mask)>>13;
+ speed = (tmp & PHY_SPEED_mask)>>14;
+ }
+ else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
+ // Get link status
+ // First Switch shadow register selector
+ ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000);
+ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C);
+ if ( (tmp & 0x0080) == 0x0080 )
+ duplex = 0;
+ else
+ duplex = 1;
+
+ switch(tmp & 0x0018) {
+ case 0x0000:
+ speed = PHY_SPEED_1G;
+
+ break;
+ case 0x0008:
+ speed = PHY_SPEED_100M;
+
+ break;
+ case 0x0010:
+ speed = PHY_SPEED_10M;
+
+ break;
+ default:
+ speed = PHY_SPEED_100M;
+ }
+ }
+ else {
+ duplex = 1; speed = PHY_SPEED_100M;
+ }
+
+ macSpeed = ((priv->maccr_val & GMAC_MODE_bit)>>8 // Move bit[9] to bit[1]
+ | (priv->maccr_val & SPEED_100_bit)>>19); // bit[19] to bit[0]
+ // The MAC hardware ignores SPEED_100_bit if GMAC_MODE_bit is set.
+ if (macSpeed > PHY_SPEED_1G) macSpeed = PHY_SPEED_1G; // 0x3 --> 0x2
+
+ if ( ((priv->maccr_val & FULLDUP_bit)!=0) != duplex
+ || macSpeed != speed )
+ {
+ PRINTK("%s:aspeed_mac_timer, priv->maccr_val=0x%05x, PHY {speed,duplex}=%d,%d\n",
+ dev->name, priv->maccr_val, speed, duplex);
+ ftgmac100_reset(dev);
+ ftgmac100_enable(dev);
+ }
+ netif_carrier_on(dev);
+ }
+ else {
+ netif_carrier_off(dev);
+ priv->timer.expires = jiffies + 1 * HZ;
+ }
+ add_timer(&priv->timer);
+}
+
+/*
+ . Function: ftgmac100_shutdown
+ . Purpose: closes down the SMC91xxx chip.
+ . Method:
+ . 1. zero the interrupt mask
+ . 2. clear the enable receive flag
+ . 3. clear the enable xmit flags
+ .
+ . TODO:
+ . (1) maybe utilize power down mode.
+ . Why not yet? Because while the chip will go into power down mode,
+ . the manual says that it will wake up in response to any I/O requests
+ . in the register space. Empirical results do not show this working.
+*/
+static void ftgmac100_shutdown( unsigned int ioaddr )
+{
+ ///interrupt mask register
+ outl( 0, ioaddr + IER_REG );
+ /* enable trans/recv,... */
+ outl( 0, ioaddr + MACCR_REG );
+}
+
+/*
+ . Function: ftgmac100_wait_to_send_packet( struct sk_buff * skb, struct device * )
+ . Purpose:
+ . Attempt to allocate memory for a packet, if chip-memory is not
+ . available, then tell the card to generate an interrupt when it
+ . is available.
+ .
+ . Algorithm:
+ .
+ . o if the saved_skb is not currently null, then drop this packet
+ . on the floor. This should never happen, because of TBUSY.
+ . o if the saved_skb is null, then replace it with the current packet,
+ . o See if I can sending it now.
+ . o (NO): Enable interrupts and let the interrupt handler deal with it.
+ . o (YES):Send it now.
+*/
+static int ftgmac100_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev )
+{
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ volatile TX_DESC *cur_desc;
+ int length;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->tx_lock,flags);
+
+ if (skb==NULL)
+ {
+ DO_PRINT("%s(%d): NULL skb???\n", __FILE__,__LINE__);
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ return 0;
+ }
+
+ PRINTK3("%s:ftgmac100_wait_to_send_packet, skb=%x\n", dev->name, skb);
+ cur_desc = &priv->tx_descs[priv->tx_idx];
+
+#ifdef not_complete_yet
+ if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor
+ {
+ DO_PRINT("no empty transmit descriptor\n");
+ DO_PRINT("jiffies = %d\n", jiffies);
+ priv->stats.tx_dropped++;
+ netif_stop_queue(dev); /// waiting to do:
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+
+ return 1;
+ }
+#endif /* end_of_not */
+
+ if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor
+ {
+ DO_PRINT("no empty TX descriptor:0x%x:0x%x\n",
+ (unsigned int)cur_desc,((unsigned int *)cur_desc)[0]);
+ priv->stats.tx_dropped++;
+ netif_stop_queue(dev); /// waiting to do:
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+
+ return 1;
+ }
+ priv->tx_skbuff[priv->tx_idx] = skb;
+ length = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+ length = min(length, TX_BUF_SIZE);
+
+#if FTMAC100_DEBUG > 2
+ DO_PRINT("Transmitting Packet at 0x%x, skb->data = %x, len = %x\n",
+ (unsigned int)cur_desc->VIR_TXBUF_BADR, skb->data, length);
+ print_packet( skb->data, length );
+#endif
+
+ cur_desc->VIR_TXBUF_BADR = (unsigned long)skb->data;
+ cur_desc->TXBUF_BADR = virt_to_phys(skb->data);
+#ifndef CONFIG_CPU_FA52x_DCE
+ dmac_clean_range((void *)skb->data, (void *)(skb->data + length));
+#endif
+
+ //clean_dcache_range(skb->data, (char*)(skb->data + length));
+
+ cur_desc->TXBUF_Size = length;
+ cur_desc->LTS = 1;
+ cur_desc->FTS = 1;
+
+ cur_desc->TX2FIC = 0;
+ cur_desc->TXIC = 0;
+
+ cur_desc->TXDMA_OWN = TX_OWNBY_FTGMAC100;
+
+ outl( 0xffffffff, ioaddr + TXPD_REG);
+
+ priv->tx_idx = (priv->tx_idx + 1) % TXDES_NUM;
+ priv->stats.tx_packets++;
+ priv->tx_free--;
+
+ if (priv->tx_free <= 0) {
+ netif_stop_queue(dev);
+
+ }
+
+
+ dev->trans_start = jiffies;
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+
+ return 0;
+}
+
+static int ftgmac100_ringbuf_alloc(struct ftgmac100_priv *priv)
+{
+ int i;
+ struct sk_buff *skb;
+
+ priv->rx_descs = dma_alloc_coherent(priv->dev,
+ sizeof(RX_DESC)*RXDES_NUM,
+ &priv->rx_descs_dma, GFP_KERNEL);
+
+ if(!priv->rx_descs)
+ return -ENOMEM;
+
+ memset(priv->rx_descs, 0, sizeof(RX_DESC)*RXDES_NUM);
+ priv->rx_descs[RXDES_NUM-1].EDORR = 1;
+
+ for (i=0; i<RXDES_NUM; i++) {
+ dma_addr_t mapping;
+ skb = dev_alloc_skb(RX_BUF_SIZE + NET_IP_ALIGN);
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ priv->rx_skbuff[i] = skb;
+ if (skb == NULL) {
+ printk ("alloc_list: allocate Rx buffer error! ");
+ break;
+ }
+ mapping = dma_map_single(priv->dev, skb->data, skb->len, DMA_FROM_DEVICE);
+ skb->dev = priv->netdev; /* Mark as being used by this device. */
+ priv->rx_descs[i].RXBUF_BADR = mapping;
+ priv->rx_descs[i].VIR_RXBUF_BADR = skb->data;
+ }
+
+ priv->tx_descs = dma_alloc_coherent(priv->dev,
+ sizeof(TX_DESC)*TXDES_NUM,
+ &priv->tx_descs_dma ,GFP_KERNEL);
+
+ if(!priv->tx_descs)
+ return -ENOMEM;
+
+ memset((void*)priv->tx_descs, 0, sizeof(TX_DESC)*TXDES_NUM);
+ priv->tx_descs[TXDES_NUM-1].EDOTR = 1; // is last descriptor
+
+}
+
+#if FTMAC100_DEBUG > 2
+static void print_packet( u8 * buf, int length )
+{
+#if 1
+#if FTMAC100_DEBUG > 3
+ int i;
+ int remainder;
+ int lines;
+#endif
+
+
+#if FTMAC100_DEBUG > 3
+ lines = length / 16;
+ remainder = length % 16;
+
+ for ( i = 0; i < lines ; i ++ ) {
+ int cur;
+
+ for ( cur = 0; cur < 8; cur ++ ) {
+ u8 a, b;
+
+ a = *(buf ++ );
+ b = *(buf ++ );
+ DO_PRINT("%02x%02x ", a, b );
+ }
+ DO_PRINT("\n");
+ }
+ for ( i = 0; i < remainder/2 ; i++ ) {
+ u8 a, b;
+
+ a = *(buf ++ );
+ b = *(buf ++ );
+ DO_PRINT("%02x%02x ", a, b );
+ }
+ DO_PRINT("\n");
+#endif
+#endif
+}
+#endif
+
+/*------------------------------------------------------------
+ . Configures the specified PHY using Autonegotiation.
+ .-------------------------------------------------------------*/
+static void ftgmac100_phy_configure(struct net_device* dev)
+{
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ u32 tmp;
+// printk("priv->ids.miiPhyId = %x \n",priv->ids.miiPhyId);
+ switch (priv->ids.miiPhyId & PHYID_VENDOR_MASK) {
+ case PHYID_VENDOR_MARVELL:
+ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x12, 0x4400);
+ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x13 );
+ break;
+ case PHYID_VENDOR_REALTEK:
+ switch (priv->ids.miiPhyId) {
+ case PHYID_RTL8211:
+ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x12, 0x4400);
+ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x13 );
+ break;
+ case PHYID_RTL8201EL:
+ break;
+ case PHYID_RTL8201F:
+ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1f, 0x0007);
+ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x13 );
+ tmp &= ~(0x0030);
+ tmp |= 0x0008;
+ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x13, (u16) tmp);
+ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x11);
+ tmp &= ~(0x0fff);
+ tmp |= 0x0008;
+ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x11, (u16) tmp);
+ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1f, 0x0000);
+ break;
+ }
+ break;
+ case PHYID_VENDOR_BROADCOM:
+ switch (priv->ids.miiPhyId) {
+ case PHYID_BCM54612E:
+ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1C, 0x8C00); // Disable GTXCLK Clock Delay Enable
+ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x18, 0xF0E7); // Disable RGMII RXD to RXC Skew
+ break;
+ case PHYID_BCM5221A4:
+ default:
+ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1b);
+ tmp |= 0x0004;
+ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1b, (u16) tmp);
+ break;
+ }
+ break;
+ }
+}
+
+
+/*--------------------------------------------------------
+ . Called by the kernel to send a packet out into the void
+ . of the net. This routine is largely based on
+ . skeleton.c, from Becker.
+ .--------------------------------------------------------
+*/
+static void ftgmac100_timeout (struct net_device *dev)
+{
+ /* If we get here, some higher level has decided we are broken.
+ There should really be a "kick me" function call instead. */
+ DO_PRINT(KERN_WARNING "%s: transmit timed out? (jiffies=%ld)\n",
+ dev->name, jiffies);
+ /* "kick" the adaptor */
+ ftgmac100_reset( dev );
+ ftgmac100_enable( dev );
+
+ /* Reconfigure the PHY */
+ ftgmac100_phy_configure(dev);
+
+ netif_wake_queue(dev);
+ dev->trans_start = jiffies;
+}
+
+
+static void ftgmac100_free_tx (struct net_device *dev)
+{
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+ int entry = priv->old_tx % TXDES_NUM;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&priv->tx_lock,flags);
+
+ /* Free used tx skbuffs */
+
+ while ((priv->tx_descs[entry].TXDMA_OWN == TX_OWNBY_SOFTWARE) && (priv->tx_skbuff[entry] != NULL)) {
+ struct sk_buff *skb;
+
+ skb = priv->tx_skbuff[entry];
+ dev_kfree_skb_any (skb);
+ priv->tx_skbuff[entry] = 0;
+ entry = (entry + 1) % TXDES_NUM;
+ priv->tx_free++;
+ }
+
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ priv->old_tx = entry;
+ if ((netif_queue_stopped(dev)) && (priv->tx_free > 0)) {
+ netif_wake_queue (dev);
+ }
+}
+
+
+/*-------------------------------------------------------------
+ .
+ . ftgmac100_rcv - receive a packet from the card
+ .
+ . There is ( at least ) a packet waiting to be read from
+ . chip-memory.
+ .
+ . o Read the status
+ . o If an error, record it
+ . o otherwise, read in the packet
+ --------------------------------------------------------------
+*/
+// extern dce_dcache_invalidate_range(unsigned int start, unsigned int end);
+
+static void ftgmac100_rcv(struct net_device *dev)
+{
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ int packet_length;
+ int rcv_cnt;
+ volatile RX_DESC *cur_desc;
+ int cur_idx;
+ int have_package;
+ int have_frs;
+ int start_idx;
+ int count = 0;
+ int packet_full = 0;
+ int data_not_fragment = 1;
+
+ start_idx = priv->rx_idx;
+
+ for (rcv_cnt=0; rcv_cnt<RXDES_NUM ; ++rcv_cnt)
+ {
+ packet_length = 0;
+ cur_idx = priv->rx_idx;
+
+ have_package = 0;
+ have_frs = 0;
+
+ for (; (cur_desc = &priv->rx_descs[priv->rx_idx])->RXPKT_RDY==RX_OWNBY_SOFTWARE; )
+ {
+ have_package = 1;
+ priv->rx_idx = (priv->rx_idx+1)%RXDES_NUM;
+ count++;
+ if (count == RXDES_NUM) {
+ packet_full = 1;
+ }
+//DF_support
+ if (data_not_fragment == 1) {
+ if (!(cur_desc->DF)) {
+ data_not_fragment = 0;
+ }
+ }
+
+ if (cur_desc->FRS)
+ {
+ have_frs = 1;
+ if (cur_desc->RX_ERR || cur_desc->CRC_ERR || cur_desc->FTL ||
+ cur_desc->RUNT || cur_desc->RX_ODD_NB
+ // cur_desc->IPCS_FAIL || cur_desc->UDPCS_FAIL || cur_desc->TCPCS_FAIL
+ )
+ {
+ // #ifdef not_complete_yet
+ if (cur_desc->RX_ERR)
+ {
+ DO_PRINT("err: RX_ERR\n");
+ }
+ if (cur_desc->CRC_ERR)
+ {
+ // DO_PRINT("err: CRC_ERR\n");
+ }
+ if (cur_desc->FTL)
+ {
+ DO_PRINT("err: FTL\n");
+ }
+ if (cur_desc->RX_ODD_NB)
+ {
+ // DO_PRINT("err: RX_ODD_NB\n");
+ }
+// if (cur_desc->IPCS_FAIL || cur_desc->UDPCS_FAIL || cur_desc->TCPCS_FAIL)
+// {
+// DO_PRINT("err: CS FAIL\n");
+// }
+ // #endif /* end_of_not */
+ priv->stats.rx_errors++; // error frame....
+ break;
+ }
+//DF_support
+ if (cur_desc->DF) {
+ if (cur_desc->IPCS_FAIL || cur_desc->UDPCS_FAIL || cur_desc->TCPCS_FAIL)
+ {
+ DO_PRINT("err: CS FAIL\n");
+ priv->stats.rx_errors++; // error frame....
+ break;
+ }
+ }
+
+ if (cur_desc->MULTICAST)
+ {
+ priv->stats.multicast++;
+ }
+ if ((priv->NCSI_support == 1) || (priv->INTEL_NCSI_EVA_support == 1)) {
+ if (cur_desc->BROADCAST) {
+ if (*(unsigned short *)(cur_desc->VIR_RXBUF_BADR + 12) == NCSI_HEADER) {
+ printk ("AEN PACKET ARRIVED\n");
+ ftgmac100_reset(dev);
+ ftgmac100_enable(dev);
+ return;
+ }
+ }
+ }
+ }
+
+ packet_length += cur_desc->VDBC;
+
+// if ( cur_desc->LRS ) // packet's last frame
+// {
+ break;
+// }
+ }
+ if (have_package==0)
+ {
+ goto done;
+ }
+ if (!have_frs)
+ {
+ DO_PRINT("error, loss first\n");
+ priv->stats.rx_over_errors++;
+ }
+
+ if (packet_length > 0)
+ {
+ struct sk_buff * skb;
+ u8 * data = 0; if (data) { }
+
+ packet_length -= 4;
+
+ skb_put (skb = priv->rx_skbuff[cur_idx], packet_length);
+
+// Rx Offload DF_support
+
+ if (data_not_fragment) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ data_not_fragment = 1;
+ }
+
+#if FTMAC100_DEBUG > 2
+ DO_PRINT("Receiving Packet at 0x%x, packet len = %x\n",(unsigned int)data, packet_length);
+ print_packet( data, packet_length );
+#endif
+
+ skb->protocol = eth_type_trans(skb, dev );
+ netif_rx(skb);
+ priv->stats.rx_packets++;
+ priv->rx_skbuff[cur_idx] = NULL;
+ }
+ if (packet_full) {
+// DO_PRINT ("RX Buffer full before driver entered ISR\n");
+ goto done;
+ }
+ }
+
+done:
+
+ if (packet_full) {
+
+ struct sk_buff *skb;
+
+ for (cur_idx = 0; cur_idx < RXDES_NUM; cur_idx++)
+ {
+ if (priv->rx_skbuff[cur_idx] == NULL) {
+ skb = dev_alloc_skb (RX_BUF_SIZE + 16);
+ if (skb == NULL) {
+ printk (KERN_INFO
+ "%s: receive_packet: "
+ "Unable to re-allocate Rx skbuff.#%d\n",
+ dev->name, cur_idx);
+ }
+ priv->rx_skbuff[cur_idx] = skb;
+ skb->dev = dev;
+ // ASPEED: See earlier skb_reserve() cache alignment
+ skb_reserve (skb, 2);
+ dmac_inv_range ((void *)skb->data, (void *)skb->data + RX_BUF_SIZE);
+ priv->rx_descs[cur_idx].RXBUF_BADR = cpu_to_le32(virt_to_phys(skb->tail));
+ priv->rx_descs[cur_idx].VIR_RXBUF_BADR = cpu_to_le32((u32)skb->tail);
+ }
+ priv->rx_descs[cur_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100;
+ }
+ packet_full = 0;
+
+ }
+ else {
+ if (start_idx != priv->rx_idx) {
+ struct sk_buff *skb;
+
+ for (cur_idx = (start_idx+1)%RXDES_NUM; cur_idx != priv->rx_idx; cur_idx = (cur_idx+1)%RXDES_NUM)
+ {
+
+
+ //struct sk_buff *skb;
+ /* Dropped packets don't need to re-allocate */
+ if (priv->rx_skbuff[cur_idx] == NULL) {
+ skb = dev_alloc_skb (RX_BUF_SIZE + 16);
+ if (skb == NULL) {
+ printk (KERN_INFO
+ "%s: receive_packet: "
+ "Unable to re-allocate Rx skbuff.#%d\n",
+ dev->name, cur_idx);
+ break;
+ }
+ priv->rx_skbuff[cur_idx] = skb;
+ skb->dev = dev;
+ /* 16 byte align the IP header */
+ skb_reserve (skb, 2);
+ dmac_inv_range ((void *)skb->data,
+ (void *)skb->data + RX_BUF_SIZE);
+ priv->rx_descs[cur_idx].RXBUF_BADR = cpu_to_le32(virt_to_phys(skb->tail));
+ priv->rx_descs[cur_idx].VIR_RXBUF_BADR = cpu_to_le32((u32)skb->tail);
+ }
+
+ priv->rx_descs[cur_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100;
+ }
+
+
+ //struct sk_buff *skb;
+ /* Dropped packets don't need to re-allocate */
+ if (priv->rx_skbuff[start_idx] == NULL) {
+ skb = dev_alloc_skb (RX_BUF_SIZE + 16);
+ if (skb == NULL) {
+ printk (KERN_INFO
+ "%s: receive_packet: "
+ "Unable to re-allocate Rx skbuff.#%d\n",
+ dev->name, start_idx);
+ }
+ priv->rx_skbuff[start_idx] = skb;
+ skb->dev = dev;
+ /* 16 byte align the IP header */
+ skb_reserve (skb, 2);
+ dmac_inv_range ((void *)skb->data,
+ (void *)skb->data + RX_BUF_SIZE);
+ priv->rx_descs[start_idx].RXBUF_BADR = cpu_to_le32(virt_to_phys(skb->tail));
+ priv->rx_descs[start_idx].VIR_RXBUF_BADR = cpu_to_le32((u32)skb->tail);
+ }
+
+
+ priv->rx_descs[start_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100;
+ }
+ }
+ if (trans_busy == 1)
+ {
+ /// priv->maccr_val |= RXMAC_EN_bit;
+ outl( priv->maccr_val, ioaddr + MACCR_REG );
+ outl( inl(ioaddr + IER_REG) | RXBUF_UNAVA_bit, ioaddr + IER_REG);
+ }
+ return;
+}
+
+/*--------------------------------------------------------------------
+ .
+ . This is the main routine of the driver, to handle the net_device when
+ . it needs some attention.
+ .
+ . So:
+ . first, save state of the chipset
+ . branch off into routines to handle each case, and acknowledge
+ . each to the interrupt register
+ . and finally restore state.
+ .
+ ---------------------------------------------------------------------*/
+static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct net_device *dev = dev_id;
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ int timeout;
+ unsigned int tmp;
+ unsigned int mask; // interrupt mask
+ unsigned int status; // interrupt status
+
+// PRINTK3("%s: ftgmac100 interrupt started \n", dev->name);
+
+ if (dev == NULL) {
+ DO_PRINT(KERN_WARNING "%s: irq %d for unknown device.\n", dev->name, irq);
+ return IRQ_HANDLED;
+ }
+
+ /* read the interrupt status register */
+ mask = inl( ioaddr + IER_REG );
+
+ /* set a timeout value, so I don't stay here forever */
+
+ for (timeout=1; timeout>0; --timeout)
+ {
+ /* read the status flag, and mask it */
+ status = inl( ioaddr + ISR_REG ) & mask;
+
+ outl(status, ioaddr + ISR_REG ); //Richard, write to clear
+
+ if (!status )
+ {
+ break;
+ }
+
+ if (status & PHYSTS_CHG_bit) {
+ DO_PRINT("PHYSTS_CHG \n");
+ // Is this interrupt for changes of the PHYLINK pin?
+ // Note: PHYLINK is optional; not all boards connect it.
+ if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) ||
+ ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211))
+ {
+ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x13);
+ PRINTK("%s: PHY interrupt status, read_phy_reg(0x13) = 0x%04x\n",
+ dev->name, tmp);
+ tmp &= (PHY_SPEED_CHG_bit | PHY_DUPLEX_CHG_bit | PHY_LINK_CHG_bit);
+ }
+ else if ((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM)
+ {
+ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1a);
+ PRINTK("%s: PHY interrupt status, read_phy_reg(0x1a) = 0x%04x\n",
+ dev->name, tmp);
+ // Bits [3:1] are {duplex, speed, link} change interrupts.
+ tmp &= 0x000e;
+ }
+ else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
+ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1A);
+ PRINTK("%s: PHY interrupt status, read_phy_reg(0x1A) = 0x%04x\n",
+ dev->name, tmp);
+ tmp &= 0x000E;
+ }
+ else tmp = 0;
+
+ if (tmp) {
+ ftgmac100_reset(dev);
+ ftgmac100_enable(dev);
+ }
+ }
+
+#ifdef not_complete_yet
+ if (status & AHB_ERR_bit)
+ {
+ DO_PRINT("AHB_ERR \n");
+ }
+
+ if (status & RPKT_LOST_bit)
+ {
+ DO_PRINT("RPKT_LOST ");
+ }
+ if (status & RPKT2F_bit)
+ {
+ PRINTK2("RPKT_SAV ");
+ }
+
+ if (status & TPKT_LOST_bit)
+ {
+ PRINTK("XPKT_LOST ");
+ }
+ if (status & TPKT2E_bit)
+ {
+ PRINTK("XPKT_OK ");
+ }
+ if (status & NPTXBUF_UNAVA_bit)
+ {
+ PRINTK("NOTXBUF ");
+ }
+ if (status & TPKT2F_bit)
+ {
+ PRINTK("XPKT_FINISH ");
+ }
+
+ if (status & RPKT2B_bit)
+ {
+ DO_PRINT("RPKT_FINISH ");
+ }
+ PRINTK2("\n");
+#endif /* end_of_not */
+
+// PRINTK3(KERN_WARNING "%s: Handling interrupt status %x \n", dev->name, status);
+
+ if ( status & (TPKT2E_bit|TPKT_LOST_bit))
+ {
+ //free tx skb buf
+ ftgmac100_free_tx(dev);
+
+ }
+
+ if ( status & RPKT2B_bit )
+ {
+ ftgmac100_rcv(dev); //Richard
+ }
+ else if (status & RXBUF_UNAVA_bit)
+ {
+ outl( mask & ~RXBUF_UNAVA_bit, ioaddr + IER_REG);
+ trans_busy = 1;
+ /*
+ rcv_tq.sync = 0;
+ rcv_tq.routine = ftgmac100_rcv;
+ rcv_tq.data = dev;
+ queue_task(&rcv_tq, &tq_timer);
+ */
+
+ } else if (status & AHB_ERR_bit)
+ {
+ DO_PRINT("AHB ERR \n");
+ }
+ }
+
+// PRINTK3("%s: Interrupt done\n", dev->name);
+ return IRQ_HANDLED;
+}
+
+/*------------------------------------------------------------
+ . Get the current statistics.
+ . This may be called with the card open or closed.
+ .-------------------------------------------------------------*/
+static struct net_device_stats* ftgmac100_query_statistics(struct net_device *dev)
+{
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+
+ return &priv->stats;
+}
+
+#ifdef HAVE_MULTICAST
+
+// --------------------------------------------------------------------
+// Finds the CRC32 of a set of bytes.
+// Again, from Peter Cammaert's code.
+// --------------------------------------------------------------------
+static int crc32( char * s, int length )
+{
+ /* indices */
+ int perByte;
+ int perBit;
+ /* crc polynomial for Ethernet */
+ const u32 poly = 0xedb88320;
+ /* crc value - preinitialized to all 1's */
+ u32 crc_value = 0xffffffff;
+
+ for ( perByte = 0; perByte < length; perByte ++ ) {
+ unsigned char c;
+
+ c = *(s++);
+ for ( perBit = 0; perBit < 8; perBit++ ) {
+ crc_value = (crc_value>>1)^
+ (((crc_value^c)&0x01)?poly:0);
+ c >>= 1;
+ }
+ }
+ return crc_value;
+}
+
+/*
+ . Function: ftgmac100_setmulticast( struct net_device *dev, int count, struct dev_mc_list * addrs )
+ . Purpose:
+ . This sets the internal hardware table to filter out unwanted multicast
+ . packets before they take up memory.
+*/
+
+static void ftgmac100_setmulticast( struct net_device *dev, int count, struct dev_mc_list * addrs )
+{
+ struct dev_mc_list * cur_addr;
+ int crc_val;
+ unsigned int ioaddr = dev->base_addr;
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+ struct AstMacHwConfig* ids = &priv->ids;
+ unsigned long Combined_Channel_ID, i;
+ struct sk_buff * skb;
+ cur_addr = addrs;
+
+//TX
+#if 0
+ if (priv->NCSI_support == 1) {
+ skb = dev_alloc_skb (TX_BUF_SIZE + 16);
+ priv->InstanceID++;
+ priv->NCSI_Request.IID = priv->InstanceID;
+ priv->NCSI_Request.Command = SET_MAC_ADDRESS;
+ Combined_Channel_ID = (priv->NCSI_Cap.Package_ID << 5) + priv->NCSI_Cap.Channel_ID;
+ priv->NCSI_Request.Channel_ID = Combined_Channel_ID;
+ priv->NCSI_Request.Payload_Length = (8 << 8);
+ memcpy ((unsigned char *)skb->data, &priv->NCSI_Request, 30);
+ priv->NCSI_Request.Payload_Length = 8;
+ for (i = 0; i < 6; i++) {
+ priv->Payload_Data[i] = cur_addr->dmi_addr[i];
+ }
+ priv->Payload_Data[6] = 2; //MAC Address Num = 1 --> address filter 1, fixed in sample code
+ priv->Payload_Data[7] = MULTICAST_ADDRESS + 0 + ENABLE_MAC_ADDRESS_FILTER; //AT + Reserved + E
+ copy_data (dev, skb, priv->NCSI_Request.Payload_Length);
+ skb->len = 30 + priv->NCSI_Request.Payload_Length + 4;
+ ftgmac100_wait_to_send_packet(skb, dev);
+ }
+#endif
+ for (cur_addr = addrs ; cur_addr!=NULL ; cur_addr = cur_addr->next )
+ {
+ /* make sure this is a multicast address - shouldn't this be a given if we have it here ? */
+ if ( !( *cur_addr->dmi_addr & 1 ) )
+ {
+ continue;
+ }
+#if 1
+//A0, A1
+ crc_val = crc32( cur_addr->dmi_addr, 5 );
+ crc_val = (~(crc_val>>2)) & 0x3f;
+ if (crc_val >= 32)
+ {
+ outl(inl(ioaddr+MAHT1_REG) | (1UL<<(crc_val-32)), ioaddr+MAHT1_REG);
+ priv->GigaBit_MAHT1 = inl (ioaddr + MAHT1_REG);
+ }
+ else
+ {
+ outl(inl(ioaddr+MAHT0_REG) | (1UL<<crc_val), ioaddr+MAHT0_REG);
+ priv->GigaBit_MAHT0 = inl (ioaddr + MAHT0_REG);
+ }
+//10/100M
+ crc_val = crc32( cur_addr->dmi_addr, 6 );
+ crc_val = (~(crc_val>>2)) & 0x3f;
+ if (crc_val >= 32)
+ {
+ outl(inl(ioaddr+MAHT1_REG) | (1UL<<(crc_val-32)), ioaddr+MAHT1_REG);
+ priv->Not_GigaBit_MAHT1 = inl (ioaddr + MAHT1_REG);
+ }
+ else
+ {
+ outl(inl(ioaddr+MAHT0_REG) | (1UL<<crc_val), ioaddr+MAHT0_REG);
+ priv->Not_GigaBit_MAHT0 = inl (ioaddr + MAHT0_REG);
+ }
+#else
+//A2
+ crc_val = crc32( cur_addr->dmi_addr, 6 );
+ crc_val = (~(crc_val>>2)) & 0x3f;
+ if (crc_val >= 32)
+ {
+ outl(inl(ioaddr+MAHT1_REG) | (1UL<<(crc_val-32)), ioaddr+MAHT1_REG);
+ priv->Not_GigaBit_MAHT1 = inl (ioaddr + MAHT1_REG);
+ priv->GigaBit_MAHT1 = inl (ioaddr + MAHT1_REG);
+ }
+ else
+ {
+ outl(inl(ioaddr+MAHT0_REG) | (1UL<<crc_val), ioaddr+MAHT0_REG);
+ priv->Not_GigaBit_MAHT0 = inl (ioaddr + MAHT0_REG);
+ priv->GigaBit_MAHT0 = inl (ioaddr + MAHT0_REG);
+ }
+#endif
+ }
+}
+
+/*-----------------------------------------------------------
+ . ftgmac100_set_multicast_list
+ .
+ . This routine will, depending on the values passed to it,
+ . either make it accept multicast packets, go into
+ . promiscuous mode ( for TCPDUMP and cousins ) or accept
+ . a select set of multicast packets
+*/
+static void ftgmac100_set_multicast_list(struct net_device *dev)
+{
+ unsigned int ioaddr = dev->base_addr;
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+
+ PRINTK2("%s:ftgmac100_set_multicast_list\n", dev->name);
+
+ if (dev->flags & IFF_PROMISC)
+ priv->maccr_val |= RX_ALLADR_bit;
+ else
+ priv->maccr_val &= ~RX_ALLADR_bit;
+
+ if (dev->flags & IFF_ALLMULTI)
+ priv->maccr_val |= RX_MULTIPKT_bit;
+ else
+ priv->maccr_val &= ~RX_MULTIPKT_bit;
+
+ if (dev->mc_count)
+ {
+// PRINTK("set multicast\n");
+ priv->maccr_val |= RX_HT_EN_bit;
+ ftgmac100_setmulticast( dev, dev->mc_count, dev->mc_list );
+ }
+ else
+ {
+ priv->maccr_val &= ~RX_HT_EN_bit;
+ }
+
+ outl( priv->maccr_val, ioaddr + MACCR_REG );
+
+}
+#endif
+
+static int ast_gmac_stop(struct net_device *dev)
+{
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+
+ netif_stop_queue(dev);
+
+ /* clear everything */
+ ftgmac100_shutdown(dev->base_addr);
+ free_irq(dev->irq, dev);
+
+ if (priv->timer.function != NULL) {
+ del_timer_sync(&priv->timer);
+ }
+
+ if (priv->rx_descs)
+ dma_free_coherent( NULL, sizeof(RX_DESC)*RXDES_NUM, (void*)priv->rx_descs, (dma_addr_t)priv->rx_descs_dma );
+ if (priv->tx_descs)
+ dma_free_coherent( NULL, sizeof(TX_DESC)*TXDES_NUM, (void*)priv->tx_descs, (dma_addr_t)priv->tx_descs_dma );
+ if (priv->tx_buf)
+ dma_free_coherent( NULL, TX_BUF_SIZE*TXDES_NUM, (void*)priv->tx_buf, (dma_addr_t)priv->tx_buf_dma );
+ priv->rx_descs = NULL; priv->rx_descs_dma = 0;
+ priv->tx_descs = NULL; priv->tx_descs_dma = 0;
+ priv->tx_buf = NULL; priv->tx_buf_dma = 0;
+
+
+ return 0;
+}
+
+static struct proc_dir_entry *proc_ftgmac100;
+
+static int ftgmac100_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
+ int num;
+ int i;
+
+ num = sprintf(page, "priv->rx_idx = %d\n", priv->rx_idx);
+ for (i=0; i<RXDES_NUM; ++i)
+ {
+ num += sprintf(page + num, "[%d].RXDMA_OWN = %d\n", i, priv->rx_descs[i].RXPKT_RDY);
+ }
+ return num;
+}
+
+static int ftgmac100_open(struct net_device *netdev)
+{
+ struct ftgmac100_priv *priv = netdev_priv(netdev);
+ int err;
+
+ DO_PRINT("%s:ftgmac100_open\n", netdev->name);
+
+ priv->maccr_val = (CRC_APD_bit | RXMAC_EN_bit | TXMAC_EN_bit | RXDMA_EN_bit
+ | TXDMA_EN_bit | CRC_CHK_bit | RX_BROADPKT_bit | SPEED_100_bit | FULLDUP_bit);
+
+ ftgmac100_ringbuf_alloc(priv);
+
+
+ /* Grab the IRQ next. Beyond this, we will free the IRQ. */
+ err = request_irq(netdev->irq, (void *)&ftgmac100_interrupt,
+ IRQF_DISABLED, netdev->name, netdev);
+ if (err)
+ {
+ DO_PRINT("%s: unable to get IRQ %d (retval=%d).\n",
+ netdev->name, netdev->irq, err);
+ kfree(netdev->priv);
+ netdev->priv = NULL;
+ return err;
+ }
+
+
+ netif_start_queue(netdev);
+
+ /* reset the hardware */
+ ftgmac100_reset(netdev);
+ ftgmac100_enable(netdev);
+
+ if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) ||
+ ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL) ||
+ (priv->ids.miiPhyId == PHYID_BCM54612E)) {
+
+ init_timer(&priv->timer);
+ priv->timer.data = (unsigned long)netdev;
+ priv->timer.function = aspeed_mac_timer;
+ priv->timer.expires = jiffies + 1 * HZ;
+ add_timer (&priv->timer);
+ }
+
+ /* Configure the PHY */
+ ftgmac100_phy_configure(netdev);
+
+ netif_start_queue(netdev);
+ return 0;
+}
+
+static int __init ast_gmac_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct net_device *netdev;
+ struct ftgmac100_priv *priv;
+ struct ftgmac100_eth_data *ast_eth_data = pdev->dev.platform_data;;
+ int err;
+
+ if (!pdev)
+ return -ENODEV;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ /* setup net_device */
+ netdev = alloc_etherdev(sizeof(*priv));
+ if (!netdev) {
+ err = -ENOMEM;
+ goto err_alloc_etherdev;
+ }
+
+ netdev->irq = platform_get_irq(pdev, 0);
+ if (netdev->irq < 0) {
+ err = -ENXIO;
+ goto err_netdev;
+ }
+
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+
+// SET_ETHTOOL_OPS(netdev, &ftgmac100_ethtool_ops);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30))
+ netdev->netdev_ops = &ftgmac100_netdev_ops;
+#else
+ printk("ast_gmac_probe 5\n");
+
+ ether_setup(netdev);
+
+ netdev->open = ftgmac100_open;
+ netdev->stop = ast_gmac_stop;
+ netdev->hard_start_xmit = ftgmac100_wait_to_send_packet;
+ netdev->tx_timeout = ftgmac100_timeout;
+ netdev->get_stats = ftgmac100_query_statistics;
+//#ifdef HAVE_MULTICAST
+#if 0
+ netdev->set_multicast_list = &ftgmac100_set_multicast_list;
+#endif
+
+#endif
+
+
+#ifdef CONFIG_AST_NPAI
+// netdev->features = NETIF_F_GRO;
+// netdev->features = NETIF_F_IP_CSUM | NETIF_F_GRO;
+#endif
+
+ platform_set_drvdata(pdev, netdev);
+
+ /* setup private data */
+ priv = netdev_priv(netdev);
+ priv->netdev = netdev;
+ priv->dev = &pdev->dev;
+
+
+ priv->ids.macId = pdev->id;
+
+ priv->NCSI_support = ast_eth_data->NCSI_support;
+ priv->INTEL_NCSI_EVA_support= ast_eth_data->INTEL_NCSI_EVA_support;
+ spin_lock_init(&priv->tx_lock);
+
+#if 0
+ /* initialize NAPI */
+ netif_napi_add(netdev, &priv->napi, ftgmac100_poll, 64);
+#endif
+ /* map io memory */
+ res = request_mem_region(res->start, resource_size(res),
+ dev_name(&pdev->dev));
+ if (!res) {
+ dev_err(&pdev->dev, "Could not reserve memory region\n");
+ err = -ENOMEM;
+ goto err_req_mem;
+ }
+
+ netdev->base_addr = (u32)ioremap(res->start, resource_size(res));
+
+ if (!netdev->base_addr) {
+ dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
+ err = -EIO;
+ goto err_ioremap;
+ }
+
+// priv->irq = irq;
+#if 0//CONFIG_AST_MDIO
+ /* initialize mdio bus */
+ priv->mii_bus = mdiobus_alloc();
+ if (!priv->mii_bus) {
+ err = -EIO;
+ goto err_alloc_mdiobus;
+ }
+
+ priv->mii_bus->name = "ftgmac100_mdio";
+ snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "ftgmac100_mii.%d",pdev->id);
+
+ priv->mii_bus->priv = netdev;
+ priv->mii_bus->read = ftgmac100_mdiobus_read;
+ priv->mii_bus->write = ftgmac100_mdiobus_write;
+ priv->mii_bus->reset = ftgmac100_mdiobus_reset;
+ priv->mii_bus->irq = priv->phy_irq;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ priv->mii_bus->irq[i] = PHY_POLL;
+
+ err = mdiobus_register(priv->mii_bus);
+ if (err) {
+ dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
+ goto err_register_mdiobus;
+ }
+
+ err = ftgmac100_mii_probe(priv);
+ if (err) {
+ dev_err(&pdev->dev, "MII Probe failed!\n");
+ goto err_mii_probe;
+ }
+#endif
+ /* register network device */
+ err = register_netdev(netdev);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to register netdev\n");
+ goto err_alloc_mdiobus;
+ }
+
+// printk("irq %d, mapped at %x\n", netdev->irq, (u32)netdev->base_addr);
+
+ if (!is_valid_ether_addr(netdev->dev_addr)) {
+ random_ether_addr(netdev->dev_addr);
+ printk("generated random MAC address %pM\n",
+ netdev->dev_addr);
+ }
+#if 0
+ if ((proc_ftgmac100 = create_proc_entry( dev->name, 0, 0 )))
+ {
+ proc_ftgmac100->read_proc = ftgmac100_read_proc;
+ proc_ftgmac100->data = dev;
+ proc_ftgmac100->owner = THIS_MODULE;
+ }
+#endif
+ return 0;
+
+//err_register_netdev:
+// phy_disconnect(priv->phydev);
+//err_mii_probe:
+// mdiobus_unregister(priv->mii_bus);
+//err_register_mdiobus:
+// mdiobus_free(priv->mii_bus);
+err_alloc_mdiobus:
+ iounmap((void __iomem *)netdev->base_addr);
+err_ioremap:
+ release_resource(res);
+err_req_mem:
+// netif_napi_del(&priv->napi);
+ platform_set_drvdata(pdev, NULL);
+err_netdev:
+ free_netdev(netdev);
+err_alloc_etherdev:
+ return err;
+
+}
+
+static int __devexit ast_gmac_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+// struct ftgmac100_priv *priv = netdev_priv(dev);
+
+// remove_proc_entry(dev->name, 0);
+
+ unregister_netdev(dev);
+
+#ifdef CONFIG_MII_PHY
+ phy_disconnect(priv->phydev);
+ mdiobus_unregister(priv->mii_bus);
+ mdiobus_free(priv->mii_bus);
+#endif
+
+ iounmap((void __iomem *)dev->base_addr);
+
+#ifdef CONFIG_AST_NPAI
+ netif_napi_del(&priv->napi);
+#endif
+
+ platform_set_drvdata(pdev, NULL);
+ free_netdev(dev);
+ return 0;
+}
+
+static struct platform_driver ast_gmac_driver = {
+ .remove = __devexit_p(ast_gmac_remove),
+ .driver = {
+ .name = "ast_gmac",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ast_gmac_init(void)
+{
+ return platform_driver_probe(&ast_gmac_driver, ast_gmac_probe);
+}
+
+static void __exit ast_gmac_exit(void)
+{
+ platform_driver_unregister(&ast_gmac_driver);
+}
+
+module_init(ast_gmac_init)
+module_exit(ast_gmac_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("ASPEED Technology Inc.");
+MODULE_DESCRIPTION("NIC driver for AST Series");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ftgmac100_26.h b/drivers/net/ftgmac100_26.h
new file mode 100644
index 000000000000..f145b05a4d43
--- /dev/null
+++ b/drivers/net/ftgmac100_26.h
@@ -0,0 +1,580 @@
+/********************************************************************************
+* File Name : ftgmac100_26.h
+*
+* Copyright (C) 2012-2020 ASPEED Technology Inc.
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by the Free Software Foundation;
+* either version 2 of the License, or (at your option) any later version.
+* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+********************************************************************************/
+// --------------------------------------------------------------------
+
+#ifndef FTMAC100_H
+#define FTMAC100_H
+
+#define HAVE_MULTICAST
+
+#define ISR_REG 0x00 // interrups status register
+#define IER_REG 0x04 // interrupt maks register
+#define MAC_MADR_REG 0x08 // MAC address (Most significant)
+#define MAC_LADR_REG 0x0c // MAC address (Least significant)
+
+#define MAHT0_REG 0x10 // Multicast Address Hash Table 0 register
+#define MAHT1_REG 0x14 // Multicast Address Hash Table 1 register
+#define TXPD_REG 0x18 // Transmit Poll Demand register
+#define RXPD_REG 0x1c // Receive Poll Demand register
+#define TXR_BADR_REG 0x20 // Transmit Ring Base Address register
+#define RXR_BADR_REG 0x24 // Receive Ring Base Address register
+
+#define HPTXPD_REG 0x28 //
+#define HPTXR_BADR_REG 0x2c //
+
+#define ITC_REG 0x30 // interrupt timer control register
+#define APTC_REG 0x34 // Automatic Polling Timer control register
+#define DBLAC_REG 0x38 // DMA Burst Length and Arbitration control register
+
+#define DMAFIFOS_REG 0x3c //
+#define FEAR_REG 0x44 //
+#define TPAFCR_REG 0x48 //
+#define RBSR_REG 0x4c //for NC Body
+#define MACCR_REG 0x50 // MAC control register
+#define MACSR_REG 0x54 // MAC status register
+#define PHYCR_REG 0x60 // PHY control register
+#define PHYDATA_REG 0x64 // PHY Write Data register
+#define FCR_REG 0x68 // Flow Control register
+#define BPR_REG 0x6c // back pressure register
+#define WOLCR_REG 0x70 // Wake-On-Lan control register
+#define WOLSR_REG 0x74 // Wake-On-Lan status register
+#define WFCRC_REG 0x78 // Wake-up Frame CRC register
+#define WFBM1_REG 0x80 // wake-up frame byte mask 1st double word register
+#define WFBM2_REG 0x84 // wake-up frame byte mask 2nd double word register
+#define WFBM3_REG 0x88 // wake-up frame byte mask 3rd double word register
+#define WFBM4_REG 0x8c // wake-up frame byte mask 4th double word register
+
+#define NPTXR_PTR_REG 0x90 //
+#define HPTXR_PTR_REG 0x94 //
+#define RXR_PTR_REG 0x98 //
+
+
+// --------------------------------------------------------------------
+// ISR_REG ¤Î IMR_REG
+// --------------------------------------------------------------------
+#define HPTXBUF_UNAVA_bit (1UL<<10)
+#define PHYSTS_CHG_bit (1UL<<9)
+#define AHB_ERR_bit (1UL<<8)
+#define TPKT_LOST_bit (1UL<<7)
+#define NPTXBUF_UNAVA_bit (1UL<<6)
+#define TPKT2F_bit (1UL<<5)
+#define TPKT2E_bit (1UL<<4)
+#define RPKT_LOST_bit (1UL<<3)
+#define RXBUF_UNAVA_bit (1UL<<2)
+#define RPKT2F_bit (1UL<<1)
+#define RPKT2B_bit (1UL<<0)
+
+
+// --------------------------------------------------------------------
+// APTC_REG
+// --------------------------------------------------------------------
+
+
+typedef struct
+{
+ u32 RXPOLL_CNT:4;
+ u32 RXPOLL_TIME_SEL:1;
+ u32 Reserved1:3;
+ u32 TXPOLL_CNT:4;
+ u32 TXPOLL_TIME_SEL:1;
+ u32 Reserved2:19;
+}FTGMAC100_APTCR_Status;
+
+// --------------------------------------------------------------------
+// PHYCR_REG
+// --------------------------------------------------------------------
+#define PHY_RE_AUTO_bit (1UL<<9)
+#define PHY_READ_bit (1UL<<26)
+#define PHY_WRITE_bit (1UL<<27)
+// --------------------------------------------------------------------
+// PHYCR_REG
+// --------------------------------------------------------------------
+#define PHY_AUTO_OK_bit (1UL<<5)
+// --------------------------------------------------------------------
+// PHY INT_STAT_REG
+// --------------------------------------------------------------------
+#define PHY_SPEED_CHG_bit (1UL<<14)
+#define PHY_DUPLEX_CHG_bit (1UL<<13)
+#define PHY_LINK_CHG_bit (1UL<<10)
+#define PHY_AUTO_COMP_bit (1UL<<11)
+// --------------------------------------------------------------------
+// PHY SPE_STAT_REG
+// --------------------------------------------------------------------
+#define PHY_RESOLVED_bit (1UL<<11)
+#define PHY_SPEED_mask 0xC000
+#define PHY_SPEED_10M 0x0
+#define PHY_SPEED_100M 0x1
+#define PHY_SPEED_1G 0x2
+#define PHY_DUPLEX_mask 0x2000
+//#define PHY_FULLDUPLEX 0x1
+#define PHY_SPEED_DUPLEX_MASK 0x01E0
+#define PHY_100M_DUPLEX 0x0100
+#define PHY_100M_HALF 0x0080
+#define PHY_10M_DUPLEX 0x0040
+#define PHY_10M_HALF 0x0020
+#define LINK_STATUS 0x04
+
+
+// --------------------------------------------------------------------
+// MACCR_REG
+// --------------------------------------------------------------------
+
+#define SW_RST_bit (1UL<<31) // software reset/
+#define DIRPATH_bit (1UL<<21)
+#define RX_IPCS_FAIL_bit (1UL<<20) //
+#define SPEED_100_bit (1UL<<19) //
+#define RX_UDPCS_FAIL_bit (1UL<<18) //
+#define RX_BROADPKT_bit (1UL<<17) // Receiving broadcast packet
+#define RX_MULTIPKT_bit (1UL<<16) // receiving multicast packet
+#define RX_HT_EN_bit (1UL<<15)
+#define RX_ALLADR_bit (1UL<<14) // not check incoming packet's destination address
+#define JUMBO_LF_bit (1UL<<13) //
+#define RX_RUNT_bit (1UL<<12) // Store incoming packet even its length is les than 64 byte
+#define CRC_CHK_bit (1UL<<11) //
+#define CRC_APD_bit (1UL<<10) // append crc to transmit packet
+#define GMAC_MODE_bit (1UL<<9) //
+#define FULLDUP_bit (1UL<<8) // full duplex
+#define ENRX_IN_HALFTX_bit (1UL<<7) //
+#define LOOP_EN_bit (1UL<<6) // Internal loop-back
+#define HPTXR_EN_bit (1UL<<5) //
+#define REMOVE_VLAN_bit (1UL<<4) //
+//#define MDC_SEL_bit (1UL<<13) // set MDC as TX_CK/10
+//#define RX_FTL_bit (1UL<<11) // Store incoming packet even its length is great than 1518 byte
+#define RXMAC_EN_bit (1UL<<3) // receiver enable
+#define TXMAC_EN_bit (1UL<<2) // transmitter enable
+#define RXDMA_EN_bit (1UL<<1) // enable DMA receiving channel
+#define TXDMA_EN_bit (1UL<<0) // enable DMA transmitting channel
+
+
+// --------------------------------------------------------------------
+// SCU_REG
+// --------------------------------------------------------------------
+#define SCU_PROTECT_KEY_REG 0x0
+#define SCU_PROT_KEY_MAGIC 0x1688a8a8
+#define SCU_RESET_CONTROL_REG 0x04
+#define SCU_RESET_MAC1 (1u << 11)
+#define SCU_RESET_MAC2 (1u << 12)
+
+#define SCU_HARDWARE_TRAPPING_REG 0x70
+#define SCU_HT_MAC_INTF_LSBIT 6
+#define SCU_HT_MAC_INTERFACE (0x7u << SCU_HT_MAC_INTF_LSBIT)
+#define MAC_INTF_SINGLE_PORT_MODES (1u<<0/*GMII*/ | 1u<<3/*MII_ONLY*/ | 1u<<4/*RMII_ONLY*/)
+#define SCU_HT_MAC_GMII 0x0u
+// MII and MII mode
+#define SCU_HT_MAC_MII_MII 0x1u
+#define SCU_HT_MAC_MII_ONLY 0x3u
+#define SCU_HT_MAC_RMII_ONLY 0x4u
+
+/*
+SCU88 D[31]: MAC1 MDIO
+SCU88 D[30]: MAC1 MDC
+SCU90 D[2]: MAC2 MDC/MDIO
+SCU80 D[0]: MAC1 Link
+SCU80 D[1]: MAC2 Link
+*/
+#define SCU_MULTIFUNCTION_PIN_REG 0x74
+#define SCU_MULTIFUNCTION_PIN_CTL1_REG 0x80
+#define SCU_MULTIFUNCTION_PIN_CTL3_REG 0x88
+#define SCU_MULTIFUNCTION_PIN_CTL5_REG 0x90
+#define SCU_MFP_MAC2_PHYLINK (1u << 1)
+#define SCU_MFP_MAC1_PHYLINK (1u << 0)
+#define SCU_MFP_MAC2_MII_INTF (1u << 21)
+#define SCU_MFP_MAC2_MDC_MDIO (1u << 2)
+#define SCU_MFP_MAC1_MDIO (1u << 31)
+#define SCU_MFP_MAC1_MDC (1u << 30)
+#define SCU_SILICON_REVISION_REG 0x7C
+#define SCU_SCRATCH_REG 0x40
+
+
+
+// --------------------------------------------------------------------
+// NCSI
+// --------------------------------------------------------------------
+
+//NCSI define & structure
+//NC-SI Command Packet
+typedef struct {
+//Ethernet Header
+ unsigned char DA[6];
+ unsigned char SA[6];
+ unsigned short EtherType; //DMTF NC-SI
+//NC-SI Control Packet
+ unsigned char MC_ID; //Management Controller should set this field to 0x00
+ unsigned char Header_Revision; //For NC-SI 1.0 spec, this field has to set 0x01
+ unsigned char Reserved_1; //Reserved has to set to 0x00
+ unsigned char IID; //Instance ID
+ unsigned char Command;
+ unsigned char Channel_ID;
+ unsigned short Payload_Length; //Payload Length = 12 bits, 4 bits are reserved
+ unsigned long Reserved_2;
+ unsigned long Reserved_3;
+} NCSI_Command_Packet;
+
+//Command and Response Type
+#define CLEAR_INITIAL_STATE 0x00 //M
+#define SELECT_PACKAGE 0x01 //M
+#define DESELECT_PACKAGE 0x02 //M
+#define ENABLE_CHANNEL 0x03 //M
+#define DISABLE_CHANNEL 0x04 //M
+#define RESET_CHANNEL 0x05 //M
+#define ENABLE_CHANNEL_NETWORK_TX 0x06 //M
+#define DISABLE_CHANNEL_NETWORK_TX 0x07 //M
+#define AEN_ENABLE 0x08
+#define SET_LINK 0x09 //M
+#define GET_LINK_STATUS 0x0A //M
+#define SET_VLAN_FILTER 0x0B //M
+#define ENABLE_VLAN 0x0C //M
+#define DISABLE_VLAN 0x0D //M
+#define SET_MAC_ADDRESS 0x0E //M
+#define ENABLE_BROADCAST_FILTERING 0x10 //M
+#define DISABLE_BROADCAST_FILTERING 0x11 //M
+#define ENABLE_GLOBAL_MULTICAST_FILTERING 0x12
+#define DISABLE_GLOBAL_MULTICAST_FILTERING 0x13
+#define SET_NCSI_FLOW_CONTROL 0x14
+#define GET_VERSION_ID 0x15 //M
+#define GET_CAPABILITIES 0x16 //M
+#define GET_PARAMETERS 0x17 //M
+#define GET_CONTROLLER_PACKET_STATISTICS 0x18
+#define GET_NCSI_STATISTICS 0x19
+#define GET_NCSI_PASS_THROUGH_STATISTICS 0x1A
+
+//NC-SI Response Packet
+typedef struct {
+ unsigned char DA[6];
+ unsigned char SA[6];
+ unsigned short EtherType; //DMTF NC-SI
+//NC-SI Control Packet
+ unsigned char MC_ID; //Management Controller should set this field to 0x00
+ unsigned char Header_Revision; //For NC-SI 1.0 spec, this field has to set 0x01
+ unsigned char Reserved_1; //Reserved has to set to 0x00
+ unsigned char IID; //Instance ID
+ unsigned char Command;
+ unsigned char Channel_ID;
+ unsigned short Payload_Length; //Payload Length = 12 bits, 4 bits are reserved
+ unsigned short Reserved_2;
+ unsigned short Reserved_3;
+ unsigned short Reserved_4;
+ unsigned short Reserved_5;
+ unsigned short Response_Code;
+ unsigned short Reason_Code;
+ unsigned char Payload_Data[64];
+} NCSI_Response_Packet;
+
+//Standard Response Code
+#define COMMAND_COMPLETED 0x00
+#define COMMAND_FAILED 0x01
+#define COMMAND_UNAVAILABLE 0x02
+#define COMMAND_UNSUPPORTED 0x03
+
+//Standard Reason Code
+#define NO_ERROR 0x0000
+#define INTERFACE_INITIALIZATION_REQUIRED 0x0001
+#define PARAMETER_IS_INVALID 0x0002
+#define CHANNEL_NOT_READY 0x0003
+#define PACKAGE_NOT_READY 0x0004
+#define INVALID_PAYLOAD_LENGTH 0x0005
+#define UNKNOWN_COMMAND_TYPE 0x7FFF
+
+
+struct AEN_Packet {
+//Ethernet Header
+ unsigned char DA[6];
+ unsigned char SA[6]; //Network Controller SA = FF:FF:FF:FF:FF:FF
+ unsigned short EtherType; //DMTF NC-SI
+//AEN Packet Format
+ unsigned char MC_ID; //Network Controller should set this field to 0x00
+ unsigned char Header_Revision; //For NC-SI 1.0 spec, this field has to set 0x01
+ unsigned char Reserved_1; //Reserved has to set to 0x00
+// unsigned char IID = 0x00; //Instance ID = 0 in Network Controller
+// unsigned char Command = 0xFF; //AEN = 0xFF
+ unsigned char Channel_ID;
+// unsigned short Payload_Length = 0x04; //Payload Length = 4 in Network Controller AEN Packet
+ unsigned long Reserved_2;
+ unsigned long Reserved_3;
+ unsigned char AEN_Type;
+// unsigned char Reserved_4[3] = {0x00, 0x00, 0x00};
+ unsigned long Optional_AEN_Data;
+ unsigned long Payload_Checksum;
+};
+
+//AEN Type
+#define LINK_STATUS_CHANGE 0x0
+#define CONFIGURATION_REQUIRED 0x1
+#define HOST_NC_DRIVER_STATUS_CHANGE 0x2
+
+typedef struct {
+ unsigned char Package_ID;
+ unsigned char Channel_ID;
+ unsigned long Capabilities_Flags;
+ unsigned long Broadcast_Packet_Filter_Capabilities;
+ unsigned long Multicast_Packet_Filter_Capabilities;
+ unsigned long Buffering_Capabilities;
+ unsigned long AEN_Control_Support;
+} NCSI_Capability;
+NCSI_Capability NCSI_Cap;
+
+//SET_MAC_ADDRESS
+#define UNICAST (0x00 << 5)
+#define MULTICAST_ADDRESS (0x01 << 5)
+#define DISABLE_MAC_ADDRESS_FILTER 0x00
+#define ENABLE_MAC_ADDRESS_FILTER 0x01
+
+//GET_LINK_STATUS
+#define LINK_DOWN 0
+#define LINK_UP 1
+
+#define NCSI_LOOP 1500000
+#define RETRY_COUNT 1
+
+#define NCSI_HEADER 0xF888 //Reversed because of 0x88 is low byte, 0xF8 is high byte in memory
+
+// --------------------------------------------------------------------
+// Receive Ring descriptor structure
+// --------------------------------------------------------------------
+
+typedef struct
+{
+ // RXDES0
+ u32 VDBC:14;//0~10
+ u32 Reserved1:1; //11~15
+ u32 Reserved3:1;
+ u32 MULTICAST:1; //16
+ u32 BROADCAST:1; //17
+ u32 RX_ERR:1; //18
+ u32 CRC_ERR:1; //19
+ u32 FTL:1;
+ u32 RUNT:1;
+ u32 RX_ODD_NB:1;
+ u32 FIFO_FULL:1;
+ u32 PAUSE_OPCODE:1;
+ u32 PAUSE_FRAME:1;
+ u32 Reserved2:2;
+ u32 LRS:1;
+ u32 FRS:1;
+ u32 EDORR:1;
+ u32 RXPKT_RDY:1; // 1 ==> owned by FTMAC100, 0 ==> owned by software
+
+ // RXDES1
+ u32 VLAN_TAGC:16;
+ u32 Reserved4:4;
+ u32 PROTL_TYPE:2;
+ u32 LLC_PKT:1;
+ u32 DF:1;
+ u32 VLAN_AVA:1;
+ u32 TCPCS_FAIL:1;
+ u32 UDPCS_FAIL:1;
+ u32 IPCS_FAIL:1;
+ u32 Reserved5:4;
+
+ // RXDES2
+ u32 Reserved6:32;
+
+ // RXDES3
+ u32 RXBUF_BADR;
+
+ u32 VIR_RXBUF_BADR; // not defined, the virtual address of receive buffer is placed here
+
+ u32 RESERVED;
+ u32 RESERVED1;
+ u32 RESERVED2;
+}RX_DESC;
+
+
+typedef struct
+{
+ // TXDES0
+ u32 TXBUF_Size:14;
+ u32 Reserved1:1;
+ u32 Reserved2:1;
+ u32 Reserved3:3;
+ u32 CRC_ERR:1;
+ u32 Reserved4:8;
+ u32 LTS:1;
+ u32 FTS:1;
+ u32 EDOTR:1;
+ u32 TXDMA_OWN:1;
+
+ // TXDES1
+ u32 VLAN_TAGC:16;
+ u32 INS_VLAN:1;
+ u32 TCPCS_EN:1;
+ u32 UDPCS_EN:1;
+ u32 IPCS_EN:1;
+ u32 Reserved5:2;
+ u32 LLC_PKT:1;
+ u32 Reserved6:7;
+ u32 TX2FIC:1;
+ u32 TXIC:1;
+
+ // TXDES2
+ u32 Reserved7:32;
+
+ // TXDES3
+ u32 TXBUF_BADR;
+
+ u32 VIR_TXBUF_BADR; // Reserve, the virtual address of transmit buffer is placed here
+
+ u32 RESERVED;
+ u32 RESERVED1;
+ u32 RESERVED2;
+
+}TX_DESC;
+
+
+
+// waiting to do:
+#define TXPOLL_CNT 8
+#define RXPOLL_CNT 0
+
+#define TX_OWNBY_SOFTWARE 0
+#define TX_OWNBY_FTGMAC100 1
+
+
+#define RX_OWNBY_SOFTWARE 1
+#define RX_OWNBY_FTGMAC100 0
+
+// --------------------------------------------------------------------
+// driver related definition
+// --------------------------------------------------------------------
+
+
+//#define RXDES_NUM 64//64 // we defined 32 descriptor for OTG issue
+#define RXDES_NUM 32
+
+#define RX_BUF_SIZE 1536
+
+#define TXDES_NUM 32
+#define TX_BUF_SIZE 1536
+
+#define PHYID_VENDOR_MASK 0xfffffc00
+#define PHYID_VENDOR_MODEL_MASK 0xfffffff0
+#define PHYID_MODEL_MASK 0x000003f0
+#define PHYID_REVISION_MASK 0x0000000f
+#define PHYID_VENDOR_MARVELL 0x01410c00
+#define PHYID_VENDOR_BROADCOM 0x00406000
+#define PHYID_VENDOR_REALTEK 0x001cc800
+
+#define PHYID_BCM5221A4 0x004061e4
+//#define PHYID_RTL8201EL 0x001cc815
+#define PHYID_RTL8201EL 0x001cc810
+#define PHYID_RTL8201F 0x001cc816
+#define PHYID_RTL8211 0x001cc910
+#define PHYID_RTL8211E 0x001cc915
+#define PHYID_BCM54612E 0x03625E6A
+
+
+/* store this information for the driver.. */
+
+struct AstMacHwConfig {
+ unsigned char phyAddr; // See IP_phy_addr[] encoding
+ unsigned char macId;
+ unsigned char isRevA0;
+ unsigned char isRevA2;
+ unsigned char pad[1];
+ unsigned int miiPhyId;
+};
+
+struct ftgmac100_priv {
+
+ // these are things that the kernel wants me to keep, so users
+ // can find out semi-useless statistics of how well the card is
+ // performing
+ struct net_device_stats stats;
+
+ struct AstMacHwConfig ids;
+
+ struct net_device *netdev;
+ struct device *dev;
+
+ // Set to true during the auto-negotiation sequence
+ int autoneg_active;
+
+ // Last contents of PHY Register 18
+ u32 lastPhy18;
+
+ spinlock_t tx_lock;
+
+ //RX ..
+ volatile RX_DESC *rx_descs; // receive ring base address
+ struct sk_buff *rx_skbuff[RXDES_NUM];
+ u32 rx_descs_dma; // receive ring physical base address
+ int rx_idx; // receive descriptor
+
+ //TX ..
+ volatile TX_DESC *tx_descs;
+ u32 tx_descs_dma;
+ char *tx_buf;
+ int tx_buf_dma;
+ int tx_idx;
+ int old_tx;
+ struct sk_buff *tx_skbuff[TXDES_NUM];
+
+ int maccr_val;
+ struct timer_list timer;
+ u32 GigaBit_MAHT0;
+ u32 GigaBit_MAHT1;
+ u32 Not_GigaBit_MAHT0;
+ u32 Not_GigaBit_MAHT1;
+ NCSI_Command_Packet NCSI_Request;
+ NCSI_Response_Packet NCSI_Respond;
+ NCSI_Capability NCSI_Cap;
+ unsigned int InstanceID;
+ unsigned int Retry;
+ unsigned char Payload_Data[16];
+ unsigned char Payload_Pad[4];
+ unsigned long Payload_Checksum;
+ int tx_free;
+ unsigned long NCSI_support;
+ unsigned long INTEL_NCSI_EVA_support;
+};
+
+
+#define FTGMAC100_STROBE_TIME (10*HZ)
+///#define FTMAC100_STROBE_TIME 1
+
+//I2C define for EEPROM
+#define AC_TIMING 0x77743335
+#define ALL_CLEAR 0xFFFFFFFF
+#define MASTER_ENABLE 0x01
+#define SLAVE_ENABLE 0x02
+#define LOOP_COUNT 0x100000
+
+
+#define I2C_BASE 0x1e78A000
+#define I2C_FUNCTION_CONTROL_REGISTER 0x00
+#define I2C_AC_TIMING_REGISTER_1 0x04
+#define I2C_AC_TIMING_REGISTER_2 0x08
+#define I2C_INTERRUPT_CONTROL_REGISTER 0x0C
+#define I2C_INTERRUPT_STATUS_REGISTER 0x10
+#define I2C_COMMAND_REGISTER 0x14
+#define I2C_BYTE_BUFFER_REGISTER 0x20
+
+
+#define MASTER_START_COMMAND (1 << 0)
+#define MASTER_TX_COMMAND (1 << 1)
+#define MASTER_RX_COMMAND (1 << 3)
+#define RX_COMMAND_LIST (1 << 4)
+#define MASTER_STOP_COMMAND (1 << 5)
+
+#define TX_ACK (1 << 0)
+#define TX_NACK (1 << 1)
+#define RX_DONE (1 << 2)
+#define STOP_DONE (1 << 4)
+
+
+
+#endif /* _SMC_91111_H_ */
+
+