--- ./drivers/net/r8169.c 2005-09-26 13:32:54.000000000 +0400 +++ ./drivers/net/r8169.c 2005-10-21 11:09:29.755805000 +0400 @@ -1,72 +1,104 @@ /* ========================================================================= - r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver for Linux kernel 2.4.x. + r8169.c: A RealTek RTL8169s/8110s Gigabit Ethernet driver for Linux kernel 2.4.x. -------------------------------------------------------------------- History: Feb 4 2002 - created initially by ShuChen . May 20 2002 - Add link status force-mode and TBI mode support. ========================================================================= - 1. The media can be forced in 5 modes. - Command: 'insmod r8169 media = SET_MEDIA' - Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex. - - SET_MEDIA can be: - _10_Half = 0x01 - _10_Full = 0x02 - _100_Half = 0x04 - _100_Full = 0x08 - _1000_Full = 0x10 - - 2. Support TBI mode. -========================================================================= -VERSION 1.1 <2002/10/4> + +RTL8169_VERSION "1.1" <2002/10/4> The bit4:0 of MII register 4 is called "selector field", and have to be 00001b to indicate support of IEEE std 802.3 during NWay process of - exchanging Link Code Word (FLP). - -VERSION 1.2 <2002/11/30> - - - Large style cleanup - - Use ether_crc in stock kernel (linux/crc32.h) - - Copy mc_filter setup code from 8139cp - (includes an optimization, and avoids set_bit use) + exchanging Link Code Word (FLP). +RTL8169_VERSION "1.2" <2003/6/17> + Update driver module name. + Modify ISR. + Add chip mcfg. + +RTL8169_VERSION "1.3" <2003/6/20> + Add chip pcfg. + Add priv->phy_timer_t, rtl8169_phy_timer_t_handler() + Add rtl8169_hw_PHY_config() + Add rtl8169_hw_PHY_reset() + +RTL8169_VERSION "1.4" <2003/7/14> + Add tx_bytes, rx_bytes. + +RTL8169_VERSION "1.5" <2003/7/18> + Set 0x0000 to PHY at offset 0x0b. + Modify chip mcfg, pcfg + Force media for multiple card. +RTL8169_VERSION "1.6" <2003/8/25> + Modify receive data buffer. + +RTL8169_VERSION "1.7" <2003/9/18> + Add Jumbo Frame support. + +RTL8169_VERSION "1.8" <2003/10/21> + Performance and CPU Utilizaion Enhancement. + +RTL8169_VERSION "1.9" <2003/12/29> + Enable Tx/Rx flow control. + +RTL8169_VERSION "2.0" <2004/03/26> + Beta version. + Support for linux 2.6.x + +RTL8169_VERSION "2.1" <2004/07/05> + Modify parameters. + +RTL8169_VERSION "2.2" <2004/08/09> + Add.pci_dma_sync_single. + Add pci_alloc_consistent()/pci_free_consistent(). + Revise parameters. + Recognize our interrupt for linux 2.6.x. */ + #include #include #include #include #include -#include -#include +#include + +#include #include -#include -#include -#define RTL8169_VERSION "1.2" -#define MODULENAME "r8169" +#define RTL8169_VERSION "2.2" +#define MODULENAME "RTL8169s/8110s" #define RTL8169_DRIVER_NAME MODULENAME " Gigabit Ethernet driver " RTL8169_VERSION #define PFX MODULENAME ": " + +#undef RTL8169_DEBUG +#undef RTL8169_JUMBO_FRAME_SUPPORT +#undef RTL8169_HW_FLOW_CONTROL_SUPPORT + + +#undef RTL8169_IOCTL_SUPPORT +#undef RTL8169_DYNAMIC_CONTROL +#define RTL8169_USE_IO + + #ifdef RTL8169_DEBUG -#define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#define dprintk(fmt, args...) do { printk(PFX fmt, ## args) } while (0) + #define assert(expr) \ + if(!(expr)) { printk( "Assertion failed! %s,%s,%s,line=%d\n", #expr,__FILE__,__FUNCTION__,__LINE__); } + #define DBG_PRINT( fmt, args...) printk("r8169: " fmt, ## args); #else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ + #define assert(expr) do {} while (0) + #define DBG_PRINT( fmt, args...) ; +#endif // end of #ifdef RTL8169_DEBUG + /* media options */ #define MAX_UNITS 8 -static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; +static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ static int max_interrupt_work = 20; @@ -76,148 +108,158 @@ static int max_interrupt_work = 20; static int multicast_filter_limit = 32; /* MAC address length*/ -#define MAC_ADDR_LEN 6 +#define MAC_ADDR_LEN 6 + +#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ +#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ +#define TX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ +#define ETTh 0x3F /* 0x3F means NO threshold */ + +#define ETH_HDR_LEN 14 +#define DEFAULT_MTU 1500 +#define DEFAULT_RX_BUF_LEN 1536 -/* max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 -#define TX_FIFO_THRESH 256 /* In bytes */ +#ifdef RTL8169_JUMBO_FRAME_SUPPORT +#define MAX_JUMBO_FRAME_MTU ( 10000 ) +#define MAX_RX_SKBDATA_SIZE ( MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN ) +#else +#define MAX_RX_SKBDATA_SIZE 1600 +#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT + + +#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ + +//#define NUM_TX_DESC 64 /* Number of Tx descriptor registers*/ +//#define NUM_RX_DESC 64 /* Number of Rx descriptor registers*/ +#define NUM_TX_DESC 1024 /* Number of Tx descriptor registers*/ +#define NUM_RX_DESC 1024 /* Number of Rx descriptor registers*/ -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 64 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL_MIN_IO_SIZE 0x80 -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (HZ) +#define RTL_MIN_IO_SIZE 0x80 +#define TX_TIMEOUT (6*HZ) +#define RTL8169_TIMER_EXPIRE_TIME 100 //100 + +#ifdef RTL8169_USE_IO +#define RTL_W8(reg, val8) outb ((val8), ioaddr + (reg)) +#define RTL_W16(reg, val16) outw ((val16), ioaddr + (reg)) +#define RTL_W32(reg, val32) outl ((val32), ioaddr + (reg)) +#define RTL_R8(reg) inb (ioaddr + (reg)) +#define RTL_R16(reg) inw (ioaddr + (reg)) +#define RTL_R32(reg) ((unsigned long) inl (ioaddr + (reg))) +#else /* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_VER_B = 0x00, - /* RTL_GIGA_MAC_VER_C = 0x03, */ - RTL_GIGA_MAC_VER_D = 0x01, - RTL_GIGA_MAC_VER_E = 0x02 -}; +#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) +#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) +#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) +#define RTL_R8(reg) readb (ioaddr + (reg)) +#define RTL_R16(reg) readw (ioaddr + (reg)) +#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) +#endif + +#define MCFG_METHOD_1 0x01 +#define MCFG_METHOD_2 0x02 +#define MCFG_METHOD_3 0x03 +#define MCFG_METHOD_4 0x04 + +#define PCFG_METHOD_1 0x01 //PHY Reg 0x03 bit0-3 == 0x0000 +#define PCFG_METHOD_2 0x02 //PHY Reg 0x03 bit0-3 == 0x0001 +#define PCFG_METHOD_3 0x03 //PHY Reg 0x03 bit0-3 == 0x0002 -enum phy_version { - RTL_GIGA_PHY_VER_C = 0x03, /* PHY Reg 0x03 bit0-3 == 0x0000 */ - RTL_GIGA_PHY_VER_D = 0x04, /* PHY Reg 0x03 bit0-3 == 0x0000 */ - RTL_GIGA_PHY_VER_E = 0x05, /* PHY Reg 0x03 bit0-3 == 0x0000 */ - RTL_GIGA_PHY_VER_F = 0x06, /* PHY Reg 0x03 bit0-3 == 0x0001 */ - RTL_GIGA_PHY_VER_G = 0x07, /* PHY Reg 0x03 bit0-3 == 0x0002 */ -}; +#ifdef RTL8169_DYNAMIC_CONTROL +#include "r8169_callback.h" +#endif //end #ifdef RTL8169_DYNAMIC_CONTROL -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } const static struct { const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ + u8 mcfg; /* depend on RTL8169 docs */ + u32 RxConfigMask; /* should clear the bits supported by this chip */ } rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_B, 0xff7e1880), - _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_D, 0xff7e1880), - _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_E, 0xff7e1880) + { "RTL8169", MCFG_METHOD_1, 0xff7e1880 }, + { "RTL8169s/8110s", MCFG_METHOD_2, 0xff7e1880 }, + { "RTL8169s/8110s", MCFG_METHOD_3, 0xff7e1880 }, }; -#undef _R -static struct pci_device_id rtl8169_pci_tbl[] = { - {0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + +static struct pci_device_id rtl8169_pci_tbl[] __devinitdata = { + { 0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, {0,}, }; -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); -static int rx_copybreak = 200; +MODULE_DEVICE_TABLE (pci, rtl8169_pci_tbl); + enum RTL8169_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, + MAC0 = 0x0, + MAR0 = 0x8, + TxDescStartAddr = 0x20, + TxHDescStartAddr= 0x28, + FLASH = 0x30, + ERSR = 0x36, + ChipCmd = 0x37, + TxPoll = 0x38, IntrMask = 0x3C, IntrStatus = 0x3E, TxConfig = 0x40, RxConfig = 0x44, RxMissed = 0x4C, Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, + Config0 = 0x51, + Config1 = 0x52, + Config2 = 0x53, + Config3 = 0x54, + Config4 = 0x55, + Config5 = 0x56, MultiIntr = 0x5C, - PHYAR = 0x60, - TBICSR = 0x64, + PHYAR = 0x60, + TBICSR = 0x64, TBI_ANAR = 0x68, TBI_LPAR = 0x6A, PHYstatus = 0x6C, RxMaxSize = 0xDA, CPlusCmd = 0xE0, - RxDescAddrLow = 0xE4, - RxDescAddrHigh = 0xE8, - EarlyTxThres = 0xEC, - FuncEvent = 0xF0, - FuncEventMask = 0xF4, - FuncPresetState = 0xF8, - FuncForceEvent = 0xFC, + RxDescStartAddr = 0xE4, + ETThReg = 0xEC, + FuncEvent = 0xF0, + FuncEventMask = 0xF4, + FuncPresetState = 0xF8, + FuncForceEvent = 0xFC, }; enum RTL8169_register_content { - /*InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x80, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, + /*InterruptStatusBits*/ + SYSErr = 0x8000, + PCSTimeout = 0x4000, + SWInt = 0x0100, + TxDescUnavail = 0x80, + RxFIFOOver = 0x40, + LinkChg = 0x20, + RxOverflow = 0x10, + TxErr = 0x08, + TxOK = 0x04, + RxErr = 0x02, + RxOK = 0x01, - /*RxStatusDesc */ + /*RxStatusDesc*/ RxRES = 0x00200000, RxCRC = 0x00080000, - RxRUNT = 0x00100000, + RxRUNT= 0x00100000, RxRWT = 0x00400000, - /*ChipCmdBits */ + /*ChipCmdBits*/ CmdReset = 0x10, CmdRxEnb = 0x08, CmdTxEnb = 0x04, RxBufEmpty = 0x01, - /*Cfg9346Bits */ + /*Cfg9346Bits*/ Cfg9346_Lock = 0x00, Cfg9346_Unlock = 0xC0, - /*rx_mode_bits */ + /*rx_mode_bits*/ AcceptErr = 0x20, AcceptRunt = 0x10, AcceptBroadcast = 0x08, @@ -225,1492 +267,1689 @@ enum RTL8169_register_content { AcceptMyPhys = 0x02, AcceptAllPhys = 0x01, - /*RxConfigBits */ + /*RxConfigBits*/ RxCfgFIFOShift = 13, RxCfgDMAShift = 8, - /*TxConfigBits */ + /*TxConfigBits*/ TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ + TxDMAShift = 8, - /* CPlusCmd p.31 */ - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - - /*rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, + /*rtl8169_PHYstatus*/ + TBI_Enable = 0x80, + TxFlowCtrl = 0x40, + RxFlowCtrl = 0x20, + _1000bpsF = 0x10, + _100bps = 0x08, + _10bps = 0x04, + LinkStatus = 0x02, + FullDup = 0x01, - /*GIGABIT_PHY_registers */ + /*GIGABIT_PHY_registers*/ PHY_CTRL_REG = 0, PHY_STAT_REG = 1, PHY_AUTO_NEGO_REG = 4, PHY_1000_CTRL_REG = 9, - /*GIGABIT_PHY_REG_BIT */ - PHY_Restart_Auto_Nego = 0x0200, - PHY_Enable_Auto_Nego = 0x1000, + /*GIGABIT_PHY_REG_BIT*/ + PHY_Restart_Auto_Nego = 0x0200, + PHY_Enable_Auto_Nego = 0x1000, //PHY_STAT_REG = 1; - PHY_Auto_Neco_Comp = 0x0020, + PHY_Auto_Neco_Comp = 0x0020, //PHY_AUTO_NEGO_REG = 4; - PHY_Cap_10_Half = 0x0020, - PHY_Cap_10_Full = 0x0040, - PHY_Cap_100_Half = 0x0080, - PHY_Cap_100_Full = 0x0100, + PHY_Cap_10_Half = 0x0020, + PHY_Cap_10_Full = 0x0040, + PHY_Cap_100_Half = 0x0080, + PHY_Cap_100_Full = 0x0100, //PHY_1000_CTRL_REG = 9; - PHY_Cap_1000_Full = 0x0200, + PHY_Cap_1000_Full = 0x0200, + PHY_Cap_1000_Half = 0x0100, - PHY_Cap_Null = 0x0, + PHY_Cap_PAUSE = 0x0400, + PHY_Cap_ASYM_PAUSE = 0x0800, + + PHY_Cap_Null = 0x0, /*_MediaType*/ - _10_Half = 0x01, - _10_Full = 0x02, - _100_Half = 0x04, - _100_Full = 0x08, - _1000_Full = 0x10, + _10_Half = 0x01, + _10_Full = 0x02, + _100_Half = 0x04, + _100_Full = 0x08, + _1000_Full = 0x10, /*_TBICSRBit*/ - TBILinkOK = 0x02000000, + TBILinkOK = 0x02000000, }; + + enum _DescStatusBit { - OWNbit = 0x80000000, - EORbit = 0x40000000, - FSbit = 0x20000000, - LSbit = 0x10000000, + OWNbit = 0x80000000, + EORbit = 0x40000000, + FSbit = 0x20000000, + LSbit = 0x10000000, }; -#define RsvdMask 0x3fffc000 struct TxDesc { - u32 status; - u32 vlan_tag; - u64 addr; + u32 status; + u32 vlan_tag; + u32 buf_addr; + u32 buf_Haddr; }; struct RxDesc { - u32 status; - u32 vlan_tag; - u64 addr; + u32 status; + u32 vlan_tag; + u32 buf_addr; + u32 buf_Haddr; }; + +typedef struct timer_list rt_timer_t; + + struct rtl8169_private { - void *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device_stats stats; /* statistics of net device */ - spinlock_t lock; /* spin lock flag */ + unsigned long ioaddr; /* memory map physical address*/ + struct pci_dev *pci_dev; /* Index of PCI device */ + struct net_device_stats stats; /* statistics of net device */ + spinlock_t lock; /* spin lock flag */ int chipset; - int mac_version; - int phy_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */ - struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Index of Transmit data buffer */ - struct timer_list timer; + int mcfg; + int pcfg; + rt_timer_t r8169_timer; + unsigned long expire_time; + unsigned long phy_link_down_cnt; - u16 cp_cmd; + unsigned long cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ + unsigned long cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ + unsigned long dirty_tx; + struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */ + struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */ + struct sk_buff *Tx_skbuff[NUM_TX_DESC];/* Index of Transmit data buffer */ + struct sk_buff *Rx_skbuff[NUM_RX_DESC];/* Receive data buffer */ + unsigned char drvinit_fail; + + dma_addr_t txdesc_array_dma_addr[NUM_TX_DESC]; + dma_addr_t rxdesc_array_dma_addr[NUM_RX_DESC]; + dma_addr_t rx_skbuff_dma_addr[NUM_RX_DESC]; + + void *txdesc_space; + dma_addr_t txdesc_phy_dma_addr; + int sizeof_txdesc_space; + + void *rxdesc_space; + dma_addr_t rxdesc_phy_dma_addr; + int sizeof_rxdesc_space; + + int curr_mtu_size; + int tx_pkt_len; + int rx_pkt_len; + + int hw_rx_pkt_len; + +#ifdef RTL8169_DYNAMIC_CONTROL + struct r8169_cb_t rt; +#endif //end #ifdef RTL8169_DYNAMIC_CONTROL + + unsigned char linkstatus; }; -MODULE_AUTHOR("Realtek"); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(rx_copybreak, "i"); + +MODULE_AUTHOR ("Realtek"); +MODULE_DESCRIPTION ("RealTek RTL-8169 Gigabit Ethernet driver"); +MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_LICENSE("GPL"); -static int rtl8169_open(struct net_device *dev); -static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance, - struct pt_regs *regs); -static int rtl8169_init_ring(struct net_device *dev); -static void rtl8169_hw_start(struct net_device *dev); -static int rtl8169_close(struct net_device *dev); -static void rtl8169_set_rx_mode(struct net_device *dev); -static void rtl8169_tx_timeout(struct net_device *dev); + +static int rtl8169_open (struct net_device *dev); +static int rtl8169_start_xmit (struct sk_buff *skb, struct net_device *dev); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +typedef int irqreturn_t; +#define IRQ_NONE 0 +#define IRQ_HANDLED 1 +static void rtl8169_interrupt (int irq, void *dev_instance, struct pt_regs *regs); +#else +static irqreturn_t rtl8169_interrupt (int irq, void *dev_instance, struct pt_regs *regs); +#endif + +static void rtl8169_init_ring (struct net_device *dev); +static void rtl8169_hw_start (struct net_device *dev); +static int rtl8169_close (struct net_device *dev); +static inline u32 ether_crc (int length, unsigned char *data); +static void rtl8169_set_rx_mode (struct net_device *dev); +static void rtl8169_tx_timeout (struct net_device *dev); static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev); -static const u16 rtl8169_intr_mask = - RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -#define PHY_Cap_10_Half_Or_Less PHY_Cap_10_Half -#define PHY_Cap_10_Full_Or_Less PHY_Cap_10_Full | PHY_Cap_10_Half_Or_Less -#define PHY_Cap_100_Half_Or_Less PHY_Cap_100_Half | PHY_Cap_10_Full_Or_Less -#define PHY_Cap_100_Full_Or_Less PHY_Cap_100_Full | PHY_Cap_100_Half_Or_Less +#ifdef RTL8169_JUMBO_FRAME_SUPPORT +static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); +#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT + +static void rtl8169_hw_PHY_config (struct net_device *dev); +static void rtl8169_hw_PHY_reset(struct net_device *dev); +static const u16 rtl8169_intr_mask = LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK ; +static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift) | 0x0000000E; + + +#define RTL8169_WRITE_GMII_REG_BIT( ioaddr, reg, bitnum, bitval )\ +{ \ + int val; \ + if( bitval == 1 ){ val = ( RTL8169_READ_GMII_REG( ioaddr, reg ) | (bitval< 0; i--) { + for( i = 2000; i > 0 ; i -- ){ // Check if the RTL8169 has completed writing to the specified MII register - if (!(RTL_R32(PHYAR) & 0x80000000)) { + if( ! (RTL_R32(PHYAR)&0x80000000) ){ break; - } else { - udelay(100); } - } + else{ + udelay(100); + }// end of if( ! (RTL_R32(PHYAR)&0x80000000) ) + }// end of for() loop } - -static int mdio_read(void *ioaddr, int RegAddr) +//================================================================= +int RTL8169_READ_GMII_REG( unsigned long ioaddr, int RegAddr ) { int i, value = -1; - RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16); + RTL_W32 ( PHYAR, 0x0 | (RegAddr&0xFF)<<16 ); udelay(1000); - for (i = 2000; i > 0; i--) { + for( i = 2000; i > 0 ; i -- ){ // Check if the RTL8169 has completed retrieving data from the specified MII register - if (RTL_R32(PHYAR) & 0x80000000) { - value = (int) (RTL_R32(PHYAR) & 0xFFFF); + if( RTL_R32(PHYAR) & 0x80000000 ){ + value = (int)( RTL_R32(PHYAR)&0xFFFF ); break; } - udelay(100); - } + else{ + udelay(100); + }// end of if( RTL_R32(PHYAR) & 0x80000000 ) + }// end of for() loop return value; } -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = dev->priv; - - strcpy(info->driver, RTL8169_DRIVER_NAME); - strcpy(info->version, RTL8169_VERSION ); - strcpy(info->bus_info, pci_name(tp->pci_dev)); -} - -static struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, -}; -static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum, - int bitval) -{ - int val; +#ifdef RTL8169_IOCTL_SUPPORT +#include "r8169_ioctl.c" +#endif //end #ifdef RTL8169_IOCTL_SUPPORT - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, void *ioaddr) -{ - const struct { - u32 mask; - int mac_version; - } mac_info[] = { - { 0x1 << 26, RTL_GIGA_MAC_VER_E }, - { 0x1 << 23, RTL_GIGA_MAC_VER_D }, - { 0x00000000, RTL_GIGA_MAC_VER_B } /* Catch-all */ - }, *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig) & 0x7c800000; - while ((reg & p->mask) != p->mask) - p++; - tp->mac_version = p->mac_version; -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - struct { - int version; - char *msg; - } mac_print[] = { - { RTL_GIGA_MAC_VER_E, "RTL_GIGA_MAC_VER_E" }, - { RTL_GIGA_MAC_VER_D, "RTL_GIGA_MAC_VER_D" }, - { RTL_GIGA_MAC_VER_B, "RTL_GIGA_MAC_VER_B" }, - { 0, NULL } - }, *p; - - for (p = mac_print; p->msg; p++) { - if (tp->mac_version == p->version) { - dprintk("mac_version == %s (%04d)\n", p->msg, - p->version); - return; - } - } - dprintk("mac_version == Unknown\n"); -} - -static void rtl8169_get_phy_version(struct rtl8169_private *tp, void *ioaddr) -{ - const struct { - u16 mask; - u16 set; - int phy_version; - } phy_info[] = { - { 0x000f, 0x0002, RTL_GIGA_PHY_VER_G }, - { 0x000f, 0x0001, RTL_GIGA_PHY_VER_F }, - { 0x000f, 0x0000, RTL_GIGA_PHY_VER_E }, - { 0x0000, 0x0000, RTL_GIGA_PHY_VER_D } /* Catch-all */ - }, *p = phy_info; - u16 reg; - - reg = mdio_read(ioaddr, 3) & 0xffff; - while ((reg & p->mask) != p->set) - p++; - tp->phy_version = p->phy_version; -} - -static void rtl8169_print_phy_version(struct rtl8169_private *tp) -{ - struct { - int version; - char *msg; - u32 reg; - } phy_print[] = { - { RTL_GIGA_PHY_VER_G, "RTL_GIGA_PHY_VER_G", 0x0002 }, - { RTL_GIGA_PHY_VER_F, "RTL_GIGA_PHY_VER_F", 0x0001 }, - { RTL_GIGA_PHY_VER_E, "RTL_GIGA_PHY_VER_E", 0x0000 }, - { RTL_GIGA_PHY_VER_D, "RTL_GIGA_PHY_VER_D", 0x0000 }, - { 0, NULL, 0x0000 } - }, *p; - - for (p = phy_print; p->msg; p++) { - if (tp->phy_version == p->version) { - dprintk("phy_version == %s (%04x)\n", p->msg, p->reg); - return; - } - } - dprintk("phy_version == Unknown\n"); -} - -static void rtl8169_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - int i; - rtl8169_print_mac_version(tp); - rtl8169_print_phy_version(tp); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_B) - return; - if (tp->phy_version >= RTL_GIGA_PHY_VER_F) - return; - - dprintk("MAC version != 0 && PHY version == 0 or 1\n"); - dprintk("Do final_reg2.cfg\n"); - - /* Shazam ! */ +#ifdef RTL8169_DYNAMIC_CONTROL +#include "r8169_callback.c" +#endif - // phy config for RTL8169s mac_version C chip - mdio_write(ioaddr, 31, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 21, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 24, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0 +#define rtl8169_request_timer( timer, timer_expires, timer_func, timer_data ) \ +{ \ + init_timer(timer); \ + timer->expires = (unsigned long)(jiffies + timer_expires); \ + timer->data = (unsigned long)(timer_data); \ + timer->function = (void *)(timer_func); \ + add_timer(timer); \ + DBG_PRINT("request_timer at 0x%08lx\n", (unsigned long)timer); \ } -static void rtl8169_hw_phy_reset(struct net_device *dev) -{ - struct rtl8169_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - int i, val; +#define rtl8169_delete_timer( del_timer_t ) \ +{ \ + del_timer(del_timer_t); \ + DBG_PRINT("delete_timer at 0x%08lx\n", (unsigned long)del_timer_t); \ +} - printk(KERN_WARNING PFX "%s: Reset RTL8169s PHY\n", dev->name); +#define rtl8169_mod_timer( timer, timer_expires ) \ +{ \ + mod_timer( timer, jiffies + timer_expires ); \ +} - val = (mdio_read(ioaddr, 0) | 0x8000) & 0xffff; - mdio_write(ioaddr, 0, val); - for (i = 50; i >= 0; i--) { - if (!(mdio_read(ioaddr, 0) & 0x8000)) - break; - udelay(100); /* Gross */ - } - if (i < 0) { - printk(KERN_WARNING PFX "%s: no PHY Reset ack. Giving up.\n", - dev->name); - } -} -static void rtl8169_phy_timer(unsigned long __opaque) +//====================================================================================================== +//====================================================================================================== +void rtl8169_phy_timer_t_handler( void *timer_data ) { - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = dev->priv; - struct timer_list *timer = &tp->timer; - void *ioaddr = tp->mmio_addr; + struct net_device *dev = (struct net_device *)timer_data; + struct rtl8169_private *priv = (struct rtl8169_private *) (dev->priv); + unsigned long ioaddr = priv->ioaddr; - assert(tp->mac_version > RTL_GIGA_MAC_VER_B); - assert(tp->phy_version < RTL_GIGA_PHY_VER_G); - - if (RTL_R8(PHYstatus) & LinkStatus) - tp->phy_link_down_cnt = 0; - else { - tp->phy_link_down_cnt++; - if (tp->phy_link_down_cnt >= 12) { - int reg; + assert( priv->mcfg > MCFG_METHOD_1 ); + assert( priv->pcfg < PCFG_METHOD_3 ); + if( RTL_R8(PHYstatus) & LinkStatus ){ + priv->phy_link_down_cnt = 0 ; + } + else{ + priv->phy_link_down_cnt ++ ; + if( priv->phy_link_down_cnt >= 12 ){ // If link on 1000, perform phy reset. - reg = mdio_read(ioaddr, PHY_1000_CTRL_REG); - if (reg & PHY_Cap_1000_Full) - rtl8169_hw_phy_reset(dev); + if( RTL8169_READ_GMII_REG( ioaddr, PHY_1000_CTRL_REG ) & PHY_Cap_1000_Full ) + { + DBG_PRINT("rtl8169_hw_PHY_reset\n"); + rtl8169_hw_PHY_reset( dev ); + } - tp->phy_link_down_cnt = 0; + priv->phy_link_down_cnt = 0 ; } } - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); + //--------------------------------------------------------------------------- + //mod_timer is a more efficient way to update the expire field of an active timer. + //--------------------------------------------------------------------------- +// rtl8169_mod_timer( (&priv->phy_timer_t), 100 ); } -static inline void rtl8169_delete_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = dev->priv; - struct timer_list *timer = &tp->timer; - if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || - (tp->phy_version >= RTL_GIGA_PHY_VER_G)) - return; - del_timer_sync(timer); +//====================================================================================================== +//====================================================================================================== +void rtl8169_timer_handler( void *timer_data ) +{ + struct net_device *dev = (struct net_device *)timer_data; + struct rtl8169_private *priv = (struct rtl8169_private *) (dev->priv); - tp->phy_link_down_cnt = 0; -} + if( (priv->mcfg > MCFG_METHOD_1) && (priv->pcfg < PCFG_METHOD_3) ){ + DBG_PRINT("FIX PCS -> rtl8169_phy_timer_t_handler\n"); + priv->phy_link_down_cnt = 0; + rtl8169_phy_timer_t_handler( timer_data ); + } -static inline void rtl8169_request_timer(struct net_device *dev) -{ - struct rtl8169_private *tp = dev->priv; - struct timer_list *timer = &tp->timer; - if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || - (tp->phy_version >= RTL_GIGA_PHY_VER_G)) - return; +#ifdef RTL8169_DYNAMIC_CONTROL + { + struct r8169_cb_t *rt = &(priv->rt); + if( priv->linkstatus == _1000_Full ){ + r8169_callback(rt); + } + } +#endif //end #ifdef RTL8169_DYNAMIC_CONTROL - tp->phy_link_down_cnt = 0; - init_timer(timer); - timer->expires = jiffies + RTL8169_PHY_TIMEOUT; - timer->data = (unsigned long)(dev); - timer->function = rtl8169_phy_timer; - add_timer(timer); + rtl8169_mod_timer( (&priv->r8169_timer), priv->expire_time ); } -static int __devinit -rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, - void **ioaddr_out) + + +//====================================================================================================== +//====================================================================================================== +static int __devinit rtl8169_init_board ( struct pci_dev *pdev, struct net_device **dev_out, unsigned long *ioaddr_out) { - void *ioaddr = NULL; + unsigned long ioaddr = 0; struct net_device *dev; - struct rtl8169_private *tp; + struct rtl8169_private *priv; + int rc, i; unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - int rc, i, acpi_idle_state = 0, pm_cap; - assert(pdev != NULL); - assert(ioaddr_out != NULL); + assert (pdev != NULL); + assert (ioaddr_out != NULL); - *ioaddr_out = NULL; + *ioaddr_out = 0; *dev_out = NULL; - // dev zeroed in alloc_etherdev - dev = alloc_etherdev(sizeof (*tp)); + // dev zeroed in init_etherdev +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + dev = init_etherdev (NULL, sizeof (*priv)); +#else + dev = alloc_etherdev (sizeof (*priv)); +#endif + if (dev == NULL) { - printk(KERN_ERR PFX "unable to alloc new ethernet\n"); + printk (KERN_ERR PFX "unable to alloc new ethernet\n"); return -ENOMEM; } SET_MODULE_OWNER(dev); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) SET_NETDEV_DEV(dev, &pdev->dev); - tp = dev->priv; +#endif + + priv = dev->priv; // enable device (incl. PCI PM wakeup and hotplug setup) - rc = pci_enable_device(pdev); - if (rc) { - printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name); + rc = pci_enable_device (pdev); + if (rc) goto err_out; - } - - /* save power state before pci_enable_device overwrites it */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap) { - u16 pwr_command; - pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); - acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; - } else { - printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n"); - goto err_out_free_res; - } - - mmio_start = pci_resource_start(pdev, 1); - mmio_end = pci_resource_end(pdev, 1); - mmio_flags = pci_resource_flags(pdev, 1); - mmio_len = pci_resource_len(pdev, 1); + mmio_start = pci_resource_start (pdev, 1); + mmio_end = pci_resource_end (pdev, 1); + mmio_flags = pci_resource_flags (pdev, 1); + mmio_len = pci_resource_len (pdev, 1); // make sure PCI base addr 1 is MMIO if (!(mmio_flags & IORESOURCE_MEM)) { - printk(KERN_ERR PFX - "region #1 not an MMIO resource, aborting\n"); + printk (KERN_ERR PFX "region #1 not an MMIO resource, aborting\n"); rc = -ENODEV; - goto err_out_disable; + goto err_out; } + // check for weird/broken PCI region reporting - if (mmio_len < RTL_MIN_IO_SIZE) { - printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n"); + if ( mmio_len < RTL_MIN_IO_SIZE ) { + printk (KERN_ERR PFX "Invalid PCI region size(s), aborting\n"); rc = -ENODEV; - goto err_out_disable; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc) { - printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name); - goto err_out_disable; + goto err_out; } - tp->cp_cmd = PCIMulRW | RxChkSum; - - if ((sizeof(dma_addr_t) > 32) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) - tp->cp_cmd |= PCIDAC; - else { - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc < 0) { - printk(KERN_ERR PFX "DMA configuration failed.\n"); - goto err_out_free_res; - } - } + rc = pci_request_regions (pdev, dev->name); + if (rc) + goto err_out; // enable PCI bus-mastering - pci_set_master(pdev); + pci_set_master (pdev); - // ioremap MMIO region - ioaddr = ioremap(mmio_start, mmio_len); - if (ioaddr == NULL) { - printk(KERN_ERR PFX "cannot remap MMIO, aborting\n"); +#ifdef RTL8169_USE_IO + ioaddr = pci_resource_start(pdev, 0); +#else + // ioremap MMIO region + ioaddr = (unsigned long)ioremap (mmio_start, mmio_len); + if (ioaddr == 0) { + printk (KERN_ERR PFX "cannot remap MMIO, aborting\n"); rc = -EIO; goto err_out_free_res; } +#endif - // Soft reset the chip. - RTL_W8(ChipCmd, CmdReset); + // Soft reset the chip. + RTL_W8 ( ChipCmd, CmdReset); // Check that the chip has finished the reset. - for (i = 1000; i > 0; i--) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) + for (i = 1000; i > 0; i--){ + if ( (RTL_R8(ChipCmd) & CmdReset) == 0){ break; - udelay(10); + } + else{ + udelay (10); + } } - // Identify chip attached to board - rtl8169_get_mac_version(tp, ioaddr); - rtl8169_get_phy_version(tp, ioaddr); - - rtl8169_print_mac_version(tp); - rtl8169_print_phy_version(tp); + // identify config method + { + unsigned long val32 = (RTL_R32(TxConfig)&0x7c800000); - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mac_version == rtl_chip_info[i].mac_version) - break; + if( val32 == (0x1<<28) ){ + priv->mcfg = MCFG_METHOD_4; + } + else if( val32 == (0x1<<26) ){ + priv->mcfg = MCFG_METHOD_3; + } + else if( val32 == (0x1<<23) ){ + priv->mcfg = MCFG_METHOD_2; + } + else if( val32 == 0x00000000 ){ + priv->mcfg = MCFG_METHOD_1; + } + else{ + priv->mcfg = MCFG_METHOD_1; + } } - if (i < 0) { - /* Unknown chip: assume array element #0, original RTL-8169 */ - printk(KERN_DEBUG PFX - "PCI device %s: unknown chip version, assuming %s\n", - pci_name(pdev), rtl_chip_info[0].name); - i++; + { + unsigned char val8 = (unsigned char)(RTL8169_READ_GMII_REG(ioaddr,3)&0x000f); + if( val8 == 0x00 ){ + priv->pcfg = PCFG_METHOD_1; + } + else if( val8 == 0x01 ){ + priv->pcfg = PCFG_METHOD_2; + } + else if( val8 == 0x02 ){ + priv->pcfg = PCFG_METHOD_3; + } + else{ + priv->pcfg = PCFG_METHOD_3; + } + } + + + for (i = ARRAY_SIZE (rtl_chip_info) - 1; i >= 0; i--){ + if (priv->mcfg == rtl_chip_info[i].mcfg) { + priv->chipset = i; + goto match; + } } - tp->chipset = i; + //if unknown chip, assume array element #0, original RTL-8169 in this case + printk (KERN_DEBUG PFX "PCI device %s: unknown chip version, assuming RTL-8169\n", pdev->slot_name); + priv->chipset = 0; + +match: *ioaddr_out = ioaddr; *dev_out = dev; return 0; +#ifndef RTL8169_USE_IO err_out_free_res: - pci_release_regions(pdev); - -err_out_disable: - pci_disable_device(pdev); + pci_release_regions (pdev); +#endif err_out: - free_netdev(dev); + unregister_netdev (dev); + kfree (dev); return rc; } -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + + + + + + +//====================================================================================================== +static int __devinit rtl8169_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev = NULL; - struct rtl8169_private *tp = NULL; - void *ioaddr = NULL; + struct rtl8169_private *priv = NULL; + unsigned long ioaddr = 0; static int board_idx = -1; - static int printed_version = 0; - int i, rc; + int i; int option = -1, Cap10_100 = 0, Cap1000 = 0; - assert(pdev != NULL); - assert(ent != NULL); + + assert (pdev != NULL); + assert (ent != NULL); board_idx++; - if (!printed_version) { - printk(KERN_INFO RTL8169_DRIVER_NAME " loaded\n"); - printed_version = 1; + + i = rtl8169_init_board (pdev, &dev, &ioaddr); + if (i < 0) { + return i; } - rc = rtl8169_init_board(pdev, &dev, &ioaddr); - if (rc) - return rc; + priv = dev->priv; + + assert (ioaddr != NULL); + assert (dev != NULL); + assert (priv != NULL); + + // Get MAC address // + for (i = 0; i < MAC_ADDR_LEN ; i++){ + dev->dev_addr[i] = RTL_R8( MAC0 + i ); + } - tp = dev->priv; - assert(ioaddr != NULL); - assert(dev != NULL); - assert(tp != NULL); - - // Get MAC address. FIXME: read EEPROM - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - - dev->open = rtl8169_open; - dev->hard_start_xmit = rtl8169_start_xmit; - dev->get_stats = rtl8169_get_stats; - dev->ethtool_ops = &rtl8169_ethtool_ops; - dev->stop = rtl8169_close; - dev->tx_timeout = rtl8169_tx_timeout; + dev->open = rtl8169_open; + dev->hard_start_xmit = rtl8169_start_xmit; + dev->get_stats = rtl8169_get_stats; + dev->stop = rtl8169_close; + dev->tx_timeout = rtl8169_tx_timeout; dev->set_multicast_list = rtl8169_set_rx_mode; - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; -// dev->do_ioctl = mii_ioctl; - - tp = dev->priv; // private data // - tp->pci_dev = pdev; - tp->mmio_addr = ioaddr; - - spin_lock_init(&tp->lock); - - rc = register_netdev(dev); - if (rc) { - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); - return rc; - } - - printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n", dev->name, - rtl_chip_info[tp->chipset].name); - - pci_set_drvdata(pdev, dev); - - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - rtl_chip_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], dev->irq); + dev->watchdog_timeo = TX_TIMEOUT; + dev->irq = pdev->irq; + dev->base_addr = (unsigned long) ioaddr; + +#ifdef RTL8169_JUMBO_FRAME_SUPPORT + dev->change_mtu = rtl8169_change_mtu; +#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT + +#ifdef RTL8169_IOCTL_SUPPORT + dev->do_ioctl = rtl8169_ioctl; +#endif //end #ifdef RTL8169_IOCTL_SUPPORT + +#ifdef RTL8169_DYNAMIC_CONTROL + priv->rt.dev = dev; +#endif //end #ifdef RTL8169_DYNAMIC_CONTROL + + priv = dev->priv; // private data // + priv->pci_dev = pdev; + priv->ioaddr = ioaddr; + +//#ifdef RTL8169_JUMBO_FRAME_SUPPORT + priv->curr_mtu_size = dev->mtu; + priv->tx_pkt_len = dev->mtu + ETH_HDR_LEN; + priv->rx_pkt_len = dev->mtu + ETH_HDR_LEN; + priv->hw_rx_pkt_len = priv->rx_pkt_len + 8; +//#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT + + DBG_PRINT("-------------------------- \n"); + DBG_PRINT("dev->mtu = %d \n", dev->mtu); + DBG_PRINT("priv->curr_mtu_size = %d \n", priv->curr_mtu_size); + DBG_PRINT("priv->tx_pkt_len = %d \n", priv->tx_pkt_len); + DBG_PRINT("priv->rx_pkt_len = %d \n", priv->rx_pkt_len); + DBG_PRINT("priv->hw_rx_pkt_len = %d \n", priv->hw_rx_pkt_len); + DBG_PRINT("-------------------------- \n"); + + spin_lock_init (&priv->lock); + + register_netdev (dev); + + pci_set_drvdata(pdev, dev); // pdev->driver_data = data; + + + printk (KERN_DEBUG "%s: Identified chip type is '%s'.\n",dev->name,rtl_chip_info[priv->chipset].name); + printk (KERN_INFO "%s: %s at 0x%lx, " + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " + "IRQ %d\n", + dev->name, + RTL8169_DRIVER_NAME, + dev->base_addr, + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5], + dev->irq); + - rtl8169_hw_phy_config(dev); + // Config PHY + rtl8169_hw_PHY_config(dev); - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); + DBG_PRINT("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); + RTL_W8( 0x82, 0x01 ); - if (tp->mac_version < RTL_GIGA_MAC_VER_E) { - dprintk("Set PCI Latency=0x40\n"); + if( priv->mcfg < MCFG_METHOD_3 ){ + DBG_PRINT("Set PCI Latency=0x40\n"); pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); } - if (tp->mac_version == RTL_GIGA_MAC_VER_D) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 + if( priv->mcfg == MCFG_METHOD_2 ){ + DBG_PRINT("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); + RTL_W8( 0x82, 0x01 ); + DBG_PRINT("Set PHY Reg 0x0bh = 0x00h\n"); + RTL8169_WRITE_GMII_REG( ioaddr, 0x0b, 0x0000 ); //w 0x0b 15 0 0 } // if TBI is not endbled - if (!(RTL_R8(PHYstatus) & TBI_Enable)) { - int val = mdio_read(ioaddr, PHY_AUTO_NEGO_REG); + if( !(RTL_R8(PHYstatus) & TBI_Enable) ){ + int val = RTL8169_READ_GMII_REG( ioaddr, PHY_AUTO_NEGO_REG ); + +#ifdef RTL8169_HW_FLOW_CONTROL_SUPPORT + val |= PHY_Cap_PAUSE | PHY_Cap_ASYM_PAUSE ; +#endif //end #define RTL8169_HW_FLOW_CONTROL_SUPPORT option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; // Force RTL8169 in 10/100/1000 Full/Half mode. - if (option > 0) { - printk(KERN_INFO "%s: Force-mode Enabled.\n", - dev->name); - Cap10_100 = 0, Cap1000 = 0; - switch (option) { - case _10_Half: - Cap10_100 = PHY_Cap_10_Half_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _10_Full: - Cap10_100 = PHY_Cap_10_Full_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _100_Half: - Cap10_100 = PHY_Cap_100_Half_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _100_Full: - Cap10_100 = PHY_Cap_100_Full_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _1000_Full: - Cap10_100 = PHY_Cap_100_Full_Or_Less; - Cap1000 = PHY_Cap_1000_Full; - break; - default: - break; + if( option > 0 ){ + printk(KERN_INFO "%s: Force-mode Enabled. \n", dev->name); + Cap10_100 = 0; + Cap1000 = 0; + switch( option ){ + case _10_Half: + Cap10_100 = PHY_Cap_10_Half; + Cap1000 = PHY_Cap_Null; + break; + case _10_Full: + Cap10_100 = PHY_Cap_10_Full | PHY_Cap_10_Half; + Cap1000 = PHY_Cap_Null; + break; + case _100_Half: + Cap10_100 = PHY_Cap_100_Half | PHY_Cap_10_Full | PHY_Cap_10_Half; + Cap1000 = PHY_Cap_Null; + break; + case _100_Full: + Cap10_100 = PHY_Cap_100_Full | PHY_Cap_100_Half | PHY_Cap_10_Full | PHY_Cap_10_Half; + Cap1000 = PHY_Cap_Null; + break; + case _1000_Full: + Cap10_100 = PHY_Cap_100_Full | PHY_Cap_100_Half | PHY_Cap_10_Full | PHY_Cap_10_Half; + Cap1000 = PHY_Cap_1000_Full; + break; + default: + break; } - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F)); //leave PHY_AUTO_NEGO_REG bit4:0 unchanged - mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000); - } else { - printk(KERN_INFO "%s: Auto-negotiation Enabled.\n", - dev->name); + RTL8169_WRITE_GMII_REG( ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | ( val&0xC1F ) ); //leave PHY_AUTO_NEGO_REG bit4:0 unchanged + RTL8169_WRITE_GMII_REG( ioaddr, PHY_1000_CTRL_REG, Cap1000 ); + } + else{ + printk(KERN_INFO "%s: Auto-negotiation Enabled.\n", dev->name); // enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, - PHY_Cap_100_Full_Or_Less | (val & 0x1f)); + RTL8169_WRITE_GMII_REG( ioaddr, PHY_AUTO_NEGO_REG, + PHY_Cap_10_Half | PHY_Cap_10_Full | PHY_Cap_100_Half | PHY_Cap_100_Full | ( val&0xC1F ) ); // enable 1000 Full Mode - mdio_write(ioaddr, PHY_1000_CTRL_REG, - PHY_Cap_1000_Full); - - } +// RTL8169_WRITE_GMII_REG( ioaddr, PHY_1000_CTRL_REG, PHY_Cap_1000_Full ); + RTL8169_WRITE_GMII_REG( ioaddr, PHY_1000_CTRL_REG, PHY_Cap_1000_Full | PHY_Cap_1000_Half); //rtl8168 + + }// end of if( option > 0 ) // Enable auto-negotiation and restart auto-nigotiation - mdio_write(ioaddr, PHY_CTRL_REG, - PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); + RTL8169_WRITE_GMII_REG( ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego ); udelay(100); // wait for auto-negotiation process - for (i = 10000; i > 0; i--) { + for( i = 10000; i > 0; i-- ){ //check if auto-negotiation complete - if (mdio_read(ioaddr, PHY_STAT_REG) & - PHY_Auto_Neco_Comp) { + if( RTL8169_READ_GMII_REG(ioaddr, PHY_STAT_REG) & PHY_Auto_Neco_Comp ){ udelay(100); option = RTL_R8(PHYstatus); - if (option & _1000bpsF) { - printk(KERN_INFO - "%s: 1000Mbps Full-duplex operation.\n", - dev->name); - } else { - printk(KERN_INFO - "%s: %sMbps %s-duplex operation.\n", - dev->name, - (option & _100bps) ? "100" : - "10", - (option & FullDup) ? "Full" : - "Half"); + if( option & _1000bpsF ){ + printk(KERN_INFO "%s: 1000Mbps Full-duplex operation.\n", dev->name); + } + else{ + printk(KERN_INFO "%s: %sMbps %s-duplex operation.\n", dev->name, + (option & _100bps) ? "100" : "10", (option & FullDup) ? "Full" : "Half" ); } break; - } else { + } + else{ udelay(100); + }// end of if( RTL8169_READ_GMII_REG(ioaddr, 1) & 0x20 ) + }// end for-loop to wait for auto-negotiation process + + option = RTL_R8(PHYstatus); + if( option & _1000bpsF ){ + priv->linkstatus = _1000_Full; + } + else{ + if(option & _100bps){ + priv->linkstatus = (option & FullDup) ? _100_Full : _100_Half; + } + else{ + priv->linkstatus = (option & FullDup) ? _10_Full : _10_Half; } - } // end for-loop to wait for auto-negotiation process + } + DBG_PRINT("priv->linkstatus = 0x%02x\n", priv->linkstatus); - } else { + }// end of TBI is not enabled + else{ udelay(100); - printk(KERN_INFO - "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n", - dev->name, - (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed"); + DBG_PRINT("1000Mbps Full-duplex operation, TBI Link %s!\n",(RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed" ); - } + }// end of TBI is not enabled return 0; } -static void __devexit -rtl8169_remove_one(struct pci_dev *pdev) + + + + + + +//====================================================================================================== +static void __devexit rtl8169_remove_one (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; - assert(dev != NULL); - assert(tp != NULL); + assert (dev != NULL); + assert (priv != NULL); - unregister_netdev(dev); - iounmap(tp->mmio_addr); - pci_release_regions(pdev); + unregister_netdev (dev); + +#ifdef RTL8169_USE_IO +#else + iounmap ((void *)(dev->base_addr)); +#endif + pci_release_regions (pdev); - pci_disable_device(pdev); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + kfree (dev); +#else free_netdev(dev); - pci_set_drvdata(pdev, NULL); +#endif + + pci_set_drvdata (pdev, NULL); } -#ifdef CONFIG_PM -static int rtl8169_suspend(struct pci_dev *pdev, u32 state) + + + + + +//====================================================================================================== +static int rtl8169_open (struct net_device *dev) { - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - unsigned long flags; + struct rtl8169_private *priv = dev->priv; + struct pci_dev *pdev = priv->pci_dev; + int retval; +// u8 diff; +// u32 TxPhyAddr, RxPhyAddr; + + + if( priv->drvinit_fail == 1 ){ + printk("%s: Gigabit driver open failed.\n", dev->name ); + return -ENOMEM; + } + + retval = request_irq (dev->irq, rtl8169_interrupt, SA_SHIRQ, dev->name, dev); + if (retval) { + return retval; + } + + //2004-05-11 + // Allocate tx/rx descriptor space + priv->sizeof_txdesc_space = NUM_TX_DESC * sizeof(struct TxDesc)+256; + priv->txdesc_space = pci_alloc_consistent( pdev, priv->sizeof_txdesc_space, &priv->txdesc_phy_dma_addr ); + if( priv->txdesc_space == NULL ){ + printk("%s: Gigabit driver alloc txdesc_space failed.\n", dev->name ); + return -ENOMEM; + } + priv->sizeof_rxdesc_space = NUM_RX_DESC * sizeof(struct RxDesc)+256; + priv->rxdesc_space = pci_alloc_consistent( pdev, priv->sizeof_rxdesc_space, &priv->rxdesc_phy_dma_addr ); + if( priv->rxdesc_space == NULL ){ + printk("%s: Gigabit driver alloc rxdesc_space failed.\n", dev->name ); + return -ENOMEM; + } + + if(priv->txdesc_phy_dma_addr & 0xff){ + printk("%s: Gigabit driver txdesc_phy_dma_addr is not 256-bytes-aligned.\n", dev->name ); + } + if(priv->rxdesc_phy_dma_addr & 0xff){ + printk("%s: Gigabit driver rxdesc_phy_dma_addr is not 256-bytes-aligned.\n", dev->name ); + } + // Set tx/rx descriptor space + priv->TxDescArray = (struct TxDesc *)priv->txdesc_space; + priv->RxDescArray = (struct RxDesc *)priv->rxdesc_space; + + { + int i; + struct sk_buff *skb = NULL; + + for(i=0;iRx_skbuff[i] = skb; + } + else{ + printk("%s: Gigabit driver failed to allocate skbuff.\n", dev->name); + priv->drvinit_fail = 1; + } + } + } + + + ////////////////////////////////////////////////////////////////////////////// + rtl8169_init_ring (dev); + rtl8169_hw_start (dev); + + + // ------------------------------------------------------ + DBG_PRINT("FIX PCS -> rtl8169_request_timer\n"); + priv->expire_time = RTL8169_TIMER_EXPIRE_TIME; + rtl8169_request_timer( (&priv->r8169_timer), priv->expire_time, rtl8169_timer_handler, ((void *)dev) ); //in open() + + + DBG_PRINT("%s: %s() alloc_rxskb_cnt = %d\n", dev->name, __FUNCTION__, alloc_rxskb_cnt ); - if (!netif_running(dev)) - return 0; - - netif_device_detach(dev); - netif_stop_queue(dev); - spin_lock_irqsave(&tp->lock, flags); - - /* Disable interrupts, stop Rx and Tx */ - RTL_W16(IntrMask, 0); - RTL_W8(ChipCmd, 0); - - /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); - spin_unlock_irqrestore(&tp->lock, flags); - return 0; -} -static int rtl8169_resume(struct pci_dev *pdev) +}//end of rtl8169_open (struct net_device *dev) + + + + + + + + +//====================================================================================================== +static void rtl8169_hw_PHY_reset(struct net_device *dev) { - struct net_device *dev = pci_get_drvdata(pdev); + int val, phy_reset_expiretime = 50; + struct rtl8169_private *priv = dev->priv; + unsigned long ioaddr = priv->ioaddr; - if (!netif_running(dev)) - return 0; + DBG_PRINT("%s: Reset RTL8169s PHY\n", dev->name); - netif_device_attach(dev); - rtl8169_hw_start(dev); + val = ( RTL8169_READ_GMII_REG( ioaddr, 0 ) | 0x8000 ) & 0xffff; + RTL8169_WRITE_GMII_REG( ioaddr, 0, val ); - return 0; + do //waiting for phy reset + { + if( RTL8169_READ_GMII_REG( ioaddr, 0 ) & 0x8000 ){ + phy_reset_expiretime --; + udelay(100); + } + else{ + break; + } + }while( phy_reset_expiretime >= 0 ); + + assert( phy_reset_expiretime > 0 ); } - -#endif /* CONFIG_PM */ -static int -rtl8169_open(struct net_device *dev) + + + +//====================================================================================================== +static void rtl8169_hw_PHY_config (struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; - struct pci_dev *pdev = tp->pci_dev; - int retval; + struct rtl8169_private *priv = dev->priv; + void *ioaddr = (void*)priv->ioaddr; + + DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n",priv->mcfg,priv->pcfg); - retval = - request_irq(dev->irq, rtl8169_interrupt, SA_SHIRQ, dev->name, dev); - if (retval < 0) - goto out; - - retval = -ENOMEM; - - /* - * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); - if (!tp->TxDescArray) - goto err_free_irq; - - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); - if (!tp->RxDescArray) - goto err_free_tx; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx; - - rtl8169_hw_start(dev); - - rtl8169_request_timer(dev); -out: - return retval; - -err_free_rx: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); -err_free_tx: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); -err_free_irq: - free_irq(dev->irq, dev); - goto out; + if( priv->mcfg == MCFG_METHOD_4 ){ + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1F, 0x0001 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1b, 0x841e ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x0e, 0x7bfb ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x09, 0x273a ); + + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1F, 0x0002 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x01, 0x90D0 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1F, 0x0000 ); + }else if((priv->mcfg == MCFG_METHOD_2)||(priv->mcfg == MCFG_METHOD_3)){ + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1F, 0x0001 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x15, 0x1000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x18, 0x65C7 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0x0000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x03, 0x00A1 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x02, 0x0008 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x01, 0x1020 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x00, 0x1000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0x0800 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0x0000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0x7000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x03, 0xFF41 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x02, 0xDE60 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x01, 0x0140 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x00, 0x0077 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0x7800 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0x7000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0xA000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x03, 0xDF01 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x02, 0xDF20 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x01, 0xFF95 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x00, 0xFA00 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0xA800 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0xA000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0xB000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x03, 0xFF41 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x02, 0xDE20 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x01, 0x0140 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x00, 0x00BB ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0xB800 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0xB000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0xF000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x03, 0xDF01 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x02, 0xDF20 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x01, 0xFF95 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x00, 0xBF00 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0xF800 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0xF000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0x0000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1F, 0x0000 ); + RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x0B, 0x0000 ); + } + else{ + DBG_PRINT("priv->mcfg=%d. Discard hw PHY config.\n",priv->mcfg); + } } -static void -rtl8169_hw_start(struct net_device *dev) + + + + + + + + + +//====================================================================================================== +static void rtl8169_hw_start (struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; + struct rtl8169_private *priv = dev->priv; + unsigned long ioaddr = priv->ioaddr; u32 i; + /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); + RTL_W8 ( ChipCmd, CmdReset); /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - else - udelay(10); + for (i = 1000; i > 0; i--){ + if ((RTL_R8( ChipCmd ) & CmdReset) == 0) break; + else udelay (10); } - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - RTL_W8(EarlyTxThres, EarlyTxThld); + RTL_W8 ( Cfg9346, Cfg9346_Unlock); + RTL_W8 ( ChipCmd, CmdTxEnb | CmdRxEnb); + RTL_W8 ( ETThReg, ETTh); // For gigabit rtl8169 - RTL_W16(RxMaxSize, RxPacketMaxSize); + RTL_W16 ( RxMaxSize, (unsigned short)priv->hw_rx_pkt_len ); // Set Rx Config register - i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset]. - RxConfigMask); - RTL_W32(RxConfig, i); + i = rtl8169_rx_config | ( RTL_R32( RxConfig ) & rtl_chip_info[priv->chipset].RxConfigMask); + RTL_W32 ( RxConfig, i); + /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, - (TX_DMA_BURST << TxDMAShift) | (InterFrameGap << - TxInterFrameGapShift)); - tp->cp_cmd |= RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, tp->cp_cmd); + RTL_W32 ( TxConfig, (TX_DMA_BURST << TxDMAShift) | (InterFrameGap << TxInterFrameGapShift) ); - if (tp->mac_version == RTL_GIGA_MAC_VER_D) { - dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14) | PCIMulRW; - RTL_W16(CPlusCmd, tp->cp_cmd); - } - tp->cur_rx = 0; - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK)); - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32)); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32)); - RTL_W8(Cfg9346, Cfg9346_Lock); - udelay(10); + RTL_W16( CPlusCmd, RTL_R16(CPlusCmd) ); - RTL_W32(RxMissed, 0); + if( priv->mcfg == MCFG_METHOD_2 || + priv->mcfg == MCFG_METHOD_3) + { + RTL_W16( CPlusCmd, (RTL_R16(CPlusCmd)|(1<<14)|(1<<3)) ); + DBG_PRINT("Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n"); + } + else + { + RTL_W16( CPlusCmd, (RTL_R16(CPlusCmd)|(1<<3)) ); + DBG_PRINT("Set MAC Reg C+CR Offset 0xE0: bit-3.\n"); + } - rtl8169_set_rx_mode(dev); + { + //RTL_W16(0xE2, 0x1517); + //RTL_W16(0xE2, 0x152a); + //RTL_W16(0xE2, 0x282a); + RTL_W16(0xE2, 0x0000); + } - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); + priv->cur_rx = 0; - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, rtl8169_intr_mask); + RTL_W32 ( TxDescStartAddr, priv->txdesc_phy_dma_addr); + RTL_W32 ( TxDescStartAddr + 4, 0x00); + RTL_W32 ( RxDescStartAddr, priv->rxdesc_phy_dma_addr); + RTL_W32 ( RxDescStartAddr + 4, 0x00); - netif_start_queue(dev); + RTL_W8 ( Cfg9346, Cfg9346_Lock ); + udelay (10); -} + RTL_W32 ( RxMissed, 0 ); -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = 0x0badbadbadbadbadull; - desc->status &= ~cpu_to_le32(OWNbit | RsvdMask); -} + rtl8169_set_rx_mode (dev); -static void rtl8169_free_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, - struct RxDesc *desc) -{ - pci_unmap_single(pdev, le64_to_cpu(desc->addr), RX_BUF_SIZE, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} + RTL_W16 ( MultiIntr, RTL_R16(MultiIntr) & 0xF000); -static inline void rtl8169_return_to_asic(struct RxDesc *desc) -{ - desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE); -} + RTL_W16 ( IntrMask, rtl8169_intr_mask); -static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping) -{ - desc->addr = cpu_to_le64(mapping); - desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE); -} + netif_start_queue (dev); -static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev, - struct sk_buff **sk_buff, struct RxDesc *desc) -{ - struct sk_buff *skb; - dma_addr_t mapping; - int ret = 0; +}//end of rtl8169_hw_start (struct net_device *dev) - skb = dev_alloc_skb(RX_BUF_SIZE); - if (!skb) - goto err_out; - skb->dev = dev; - skb_reserve(skb, 2); - *sk_buff = skb; - mapping = pci_map_single(pdev, skb->tail, RX_BUF_SIZE, - PCI_DMA_FROMDEVICE); - rtl8169_give_to_asic(desc, mapping); -out: - return ret; -err_out: - ret = -ENOMEM; - rtl8169_make_unusable_by_asic(desc); - goto out; -} -static void rtl8169_rx_clear(struct rtl8169_private *tp) +//====================================================================================================== +static void rtl8169_init_ring (struct net_device *dev) { + struct rtl8169_private *priv = dev->priv; + struct pci_dev *pdev = priv->pci_dev; int i; + struct sk_buff *skb; + - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp->pci_dev, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } + priv->cur_rx = 0; + priv->cur_tx = 0; + priv->dirty_tx = 0; + memset(priv->TxDescArray, 0x0, NUM_TX_DESC*sizeof(struct TxDesc)); + memset(priv->RxDescArray, 0x0, NUM_RX_DESC*sizeof(struct RxDesc)); + + + for (i=0 ; iTx_skbuff[i]=NULL; + priv->txdesc_array_dma_addr[i] = pci_map_single(pdev, &priv->TxDescArray[i], sizeof(struct TxDesc), PCI_DMA_TODEVICE); } -} -static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) -{ - u32 cur; - - for (cur = start; end - cur > 0; cur++) { - int ret, i = cur % NUM_RX_DESC; + for (i=0; i RxDescArray[i].status = cpu_to_le32((OWNbit | EORbit) | (unsigned long)priv->hw_rx_pkt_len); + } + else{ + priv->RxDescArray[i].status = cpu_to_le32(OWNbit | (unsigned long)priv->hw_rx_pkt_len); + } - if (tp->Rx_skbuff[i]) - continue; - - ret = rtl8169_alloc_rx_skb(tp->pci_dev, dev, tp->Rx_skbuff + i, - tp->RxDescArray + i); - if (ret < 0) - break; + {//----------------------------------------------------------------------- + skb = priv->Rx_skbuff[i]; + priv->rx_skbuff_dma_addr[i] = pci_map_single(pdev, skb->data, MAX_RX_SKBDATA_SIZE, PCI_DMA_FROMDEVICE); + + if( skb != NULL ){ + priv->RxDescArray[i].buf_addr = cpu_to_le32(priv->rx_skbuff_dma_addr[i]); + priv->RxDescArray[i].buf_Haddr = 0; + } + else{ + DBG_PRINT("%s: %s() Rx_skbuff == NULL\n", dev->name, __FUNCTION__); + priv->drvinit_fail = 1; + } + }//----------------------------------------------------------------------- + priv->rxdesc_array_dma_addr[i] = pci_map_single(pdev, &priv->RxDescArray[i], sizeof(struct RxDesc), PCI_DMA_TODEVICE); + pci_dma_sync_single(pdev, priv->rxdesc_array_dma_addr[i], sizeof(struct RxDesc), PCI_DMA_TODEVICE); } - return cur - start; } -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->status |= cpu_to_le32(EORbit); -} -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = dev->priv; - tp->cur_rx = tp->dirty_rx = 0; - tp->cur_tx = tp->dirty_tx = 0; - memset(tp->TxDescArray, 0x0, NUM_TX_DESC * sizeof (struct TxDesc)); - memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof (struct RxDesc)); - memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) - goto err_out; - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - return 0; +//====================================================================================================== +static void rtl8169_tx_clear (struct rtl8169_private *priv) +{ + int i; -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; + priv->cur_tx = 0; + for ( i = 0 ; i < NUM_TX_DESC ; i++ ){ + if ( priv->Tx_skbuff[i] != NULL ) { + dev_kfree_skb ( priv->Tx_skbuff[i] ); + priv->Tx_skbuff[i] = NULL; + priv->stats.tx_dropped++; + } + } } -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, - struct TxDesc *desc) -{ - u32 len = sk_buff[0]->len; - pci_unmap_single(pdev, le64_to_cpu(desc->addr), - len < ETH_ZLEN ? ETH_ZLEN : len, PCI_DMA_TODEVICE); - desc->addr = 0x00; - *sk_buff = NULL; -} -static void -rtl8169_tx_clear(struct rtl8169_private *tp) -{ - int i; - tp->cur_tx = 0; - for (i = 0; i < NUM_TX_DESC; i++) { - struct sk_buff *skb = tp->Tx_skbuff[i]; - if (skb) { - rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + i, - tp->TxDescArray + i); - dev_kfree_skb(skb); - tp->stats.tx_dropped++; - } - } -} -static void -rtl8169_tx_timeout(struct net_device *dev) + +//====================================================================================================== +static void rtl8169_tx_timeout (struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; + struct rtl8169_private *priv = dev->priv; + unsigned long ioaddr = priv->ioaddr; u8 tmp8; /* disable Tx, if not already */ - tmp8 = RTL_R8(ChipCmd); - if (tmp8 & CmdTxEnb) - RTL_W8(ChipCmd, tmp8 & ~CmdTxEnb); + tmp8 = RTL_R8( ChipCmd ); + if (tmp8 & CmdTxEnb){ + RTL_W8 ( ChipCmd, tmp8 & ~CmdTxEnb); + } /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16(IntrMask, 0x0000); + RTL_W16 ( IntrMask, 0x0000); /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irq(&tp->lock); - rtl8169_tx_clear(tp); - spin_unlock_irq(&tp->lock); + spin_lock_irq (&priv->lock); + rtl8169_tx_clear (priv); + spin_unlock_irq (&priv->lock); + - /* ...and finally, reset everything */ - rtl8169_hw_start(dev); + rtl8169_hw_start (dev); - netif_wake_queue(dev); + netif_wake_queue (dev); } -static int -rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct rtl8169_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - int entry = tp->cur_tx % NUM_TX_DESC; - u32 len = skb->len; - if (unlikely(skb->len < ETH_ZLEN)) { - skb = skb_padto(skb, ETH_ZLEN); - if (!skb) - goto err_update_stats; - len = ETH_ZLEN; - } - - spin_lock_irq(&tp->lock); - if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) { - dma_addr_t mapping; - mapping = pci_map_single(tp->pci_dev, skb->data, len, - PCI_DMA_TODEVICE); - tp->Tx_skbuff[entry] = skb; - tp->TxDescArray[entry].addr = cpu_to_le64(mapping); - tp->TxDescArray[entry].status = cpu_to_le32(OWNbit | FSbit | - LSbit | len | (EORbit * !((entry + 1) % NUM_TX_DESC))); - - RTL_W8(TxPoll, 0x40); //set polling bit - dev->trans_start = jiffies; +//====================================================================================================== +static int rtl8169_start_xmit (struct sk_buff *skb, struct net_device *dev) +{ + struct rtl8169_private *priv = dev->priv; + unsigned long ioaddr = priv->ioaddr; + struct pci_dev *pdev = priv->pci_dev; + int entry = priv->cur_tx % NUM_TX_DESC; + int buf_len = 60; + dma_addr_t txbuf_dma_addr; - tp->cur_tx++; - } else - goto err_drop; + spin_lock_irq (&priv->lock); + if( (le32_to_cpu(priv->TxDescArray[entry].status) & OWNbit)==0 ){ - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) { - netif_stop_queue(dev); - } -out: - spin_unlock_irq(&tp->lock); + priv->Tx_skbuff[entry] = skb; + txbuf_dma_addr = pci_map_single(pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + + priv->TxDescArray[entry].buf_addr = cpu_to_le32(txbuf_dma_addr); + DBG_PRINT("%s: TX pkt_size = %d\n", __FUNCTION__, skb->len); + if( skb->len <= priv->tx_pkt_len ){ + buf_len = skb->len; + } + else{ + printk("%s: Error -- Tx packet size(%d) > mtu(%d)+14\n", dev->name, skb->len, dev->mtu); + buf_len = priv->tx_pkt_len; + } - return 0; + if( entry != (NUM_TX_DESC-1) ){ + priv->TxDescArray[entry].status = cpu_to_le32((OWNbit | FSbit | LSbit) | buf_len); + } + else{ + priv->TxDescArray[entry].status = cpu_to_le32((OWNbit | EORbit | FSbit | LSbit) | buf_len); + } -err_drop: - dev_kfree_skb(skb); -err_update_stats: - tp->stats.tx_dropped++; - goto out; -} - -static void -rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp, - void *ioaddr) -{ - unsigned long dirty_tx, tx_left; - - assert(dev != NULL); - assert(tp != NULL); - assert(ioaddr != NULL); - - dirty_tx = tp->dirty_tx; - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; - struct sk_buff *skb = tp->Tx_skbuff[entry]; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].status); - if (status & OWNbit) - break; + pci_dma_sync_single(pdev, priv->txdesc_array_dma_addr[entry], sizeof(struct TxDesc), PCI_DMA_TODEVICE); - /* FIXME: is it really accurate for TxErr ? */ - tp->stats.tx_bytes += skb->len >= ETH_ZLEN ? - skb->len : ETH_ZLEN; - tp->stats.tx_packets++; - rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + entry, - tp->TxDescArray + entry); - dev_kfree_skb_irq(skb); - tp->Tx_skbuff[entry] = NULL; - dirty_tx++; - tx_left--; - } + RTL_W8 ( TxPoll, 0x40); //set polling bit - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); + dev->trans_start = jiffies; + + priv->stats.tx_bytes += ( (skb->len > ETH_ZLEN) ? skb->len : ETH_ZLEN); + priv->cur_tx++; + }//end of if( (priv->TxDescArray[entry].status & 0x80000000)==0 ) + + spin_unlock_irq (&priv->lock); + + if ( (priv->cur_tx - NUM_TX_DESC) == priv->dirty_tx ){ + netif_stop_queue (dev); + } + else{ + if (netif_queue_stopped (dev)){ + netif_wake_queue (dev); + } } + + return 0; } -static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, - struct RxDesc *desc, - struct net_device *dev) -{ - int ret = -1; - if (pkt_size < rx_copybreak) { - struct sk_buff *skb; - skb = dev_alloc_skb(pkt_size + 2); - if (skb) { - skb->dev = dev; - skb_reserve(skb, 2); - eth_copy_and_sum(skb, sk_buff[0]->tail, pkt_size, 0); - *sk_buff = skb; - rtl8169_return_to_asic(desc); - ret = 0; + + + + +//====================================================================================================== +static void rtl8169_tx_interrupt (struct net_device *dev, struct rtl8169_private *priv, unsigned long ioaddr) +{ + unsigned long dirty_tx, tx_left=0; + int entry = priv->cur_tx % NUM_TX_DESC; + int txloop_cnt = 0; + + assert (dev != NULL); + assert (priv != NULL); + assert (ioaddr != NULL); + + + dirty_tx = priv->dirty_tx; + tx_left = priv->cur_tx - dirty_tx; + + while( (tx_left > 0) && (txloop_cnt < max_interrupt_work) ){ + if( (le32_to_cpu(priv->TxDescArray[entry].status) & OWNbit) == 0 ){ + +#ifdef RTL8169_DYNAMIC_CONTROL + r8169_callback_tx(&(priv->rt), 1, priv->Tx_skbuff[dirty_tx % NUM_TX_DESC]->len); +#endif //end #ifdef RTL8169_DYNAMIC_CONTROL + + dev_kfree_skb_irq( priv->Tx_skbuff[dirty_tx % NUM_TX_DESC] ); + priv->Tx_skbuff[dirty_tx % NUM_TX_DESC] = NULL; + priv->stats.tx_packets++; + dirty_tx++; + tx_left--; + entry++; } + txloop_cnt ++; + } + + if (priv->dirty_tx != dirty_tx) { + priv->dirty_tx = dirty_tx; + if (netif_queue_stopped (dev)) + netif_wake_queue (dev); } - return ret; } -static void -rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, - void *ioaddr) + + + + + +//====================================================================================================== +static void rtl8169_rx_interrupt (struct net_device *dev, struct rtl8169_private *priv, unsigned long ioaddr) { - unsigned long cur_rx, rx_left; - int delta; + struct pci_dev *pdev = priv->pci_dev; + int cur_rx; + int pkt_size = 0 ; + int rxdesc_cnt = 0; + int ret; + struct sk_buff *n_skb = NULL; + struct sk_buff *cur_skb; + struct sk_buff *rx_skb; + struct RxDesc *rxdesc; - assert(dev != NULL); - assert(tp != NULL); - assert(ioaddr != NULL); + assert (dev != NULL); + assert (priv != NULL); + assert (ioaddr != NULL); - cur_rx = tp->cur_rx; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - while (rx_left > 0) { - int entry = cur_rx % NUM_RX_DESC; - u32 status; + cur_rx = priv->cur_rx; - rmb(); - status = le32_to_cpu(tp->RxDescArray[entry].status); + rxdesc = &priv->RxDescArray[cur_rx]; + pci_dma_sync_single(pdev, priv->rxdesc_array_dma_addr[cur_rx], sizeof(struct RxDesc), PCI_DMA_FROMDEVICE); - if (status & OWNbit) - break; - if (status & RxRES) { + while ( ((le32_to_cpu(rxdesc->status) & OWNbit)== 0) && (rxdesc_cnt < max_interrupt_work) ){ + + rxdesc_cnt++; + + if( le32_to_cpu(rxdesc->status) & RxRES ){ printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name); - tp->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - tp->stats.rx_length_errors++; - if (status & RxCRC) - tp->stats.rx_crc_errors++; - } else { - struct RxDesc *desc = tp->RxDescArray + entry; - struct sk_buff *skb = tp->Rx_skbuff[entry]; - int pkt_size = (status & 0x00001FFF) - 4; - void (*pci_action)(struct pci_dev *, dma_addr_t, - size_t, int) = pci_dma_sync_single_for_device; - - - pci_dma_sync_single_for_cpu(tp->pci_dev, - le64_to_cpu(desc->addr), RX_BUF_SIZE, - PCI_DMA_FROMDEVICE); - - if (rtl8169_try_rx_copy(&skb, pkt_size, desc, dev)) { - pci_action = pci_unmap_single; - tp->Rx_skbuff[entry] = NULL; + priv->stats.rx_errors++; + if ( le32_to_cpu(rxdesc->status) & (RxRWT|RxRUNT) ) + priv->stats.rx_length_errors++; + if ( le32_to_cpu(rxdesc->status) & RxCRC) + priv->stats.rx_crc_errors++; + } + else{ + pkt_size=(int)(le32_to_cpu(rxdesc->status) & 0x00001FFF)-4; + + if( pkt_size > priv->rx_pkt_len ){ + printk("%s: Error -- Rx packet size(%d) > mtu(%d)+14\n", dev->name, pkt_size, dev->mtu); + pkt_size = priv->rx_pkt_len; } - pci_action(tp->pci_dev, le64_to_cpu(desc->addr), - RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + DBG_PRINT("%s: RX pkt_size = %d\n", __FUNCTION__, pkt_size); - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - - dev->last_rx = jiffies; - tp->stats.rx_bytes += pkt_size; - tp->stats.rx_packets++; - } - - cur_rx++; - rx_left--; - } + {// ----------------------------------------------------- + rx_skb = priv->Rx_skbuff[cur_rx]; + n_skb = RTL8169_ALLOC_RXSKB(MAX_RX_SKBDATA_SIZE); + if( n_skb != NULL ) { + skb_reserve (n_skb, 2); // 16 byte align the IP fields. // + + // Indicate rx_skb + if( rx_skb != NULL ){ + rx_skb->dev = dev; + pci_dma_sync_single(pdev, priv->rx_skbuff_dma_addr[cur_rx], sizeof(struct RxDesc), PCI_DMA_FROMDEVICE); + + skb_put ( rx_skb, pkt_size ); + rx_skb->protocol = eth_type_trans ( rx_skb, dev ); + ret = RTL8169_NETIF_RX (rx_skb); + +// dev->last_rx = jiffies; + priv->stats.rx_bytes += pkt_size; + priv->stats.rx_packets++; + +#ifdef RTL8169_DYNAMIC_CONTROL + r8169_callback_rx( &(priv->rt), 1, pkt_size); +#endif //end #ifdef RTL8169_DYNAMIC_CONTROL + + }//end if( rx_skb != NULL ) + + priv->Rx_skbuff[cur_rx] = n_skb; + } + else{ + DBG_PRINT("%s: Allocate n_skb failed!\n",__FUNCTION__ ); + priv->Rx_skbuff[cur_rx] = rx_skb; + } + + + // Update rx descriptor + if( cur_rx == (NUM_RX_DESC-1) ){ + priv->RxDescArray[cur_rx].status = cpu_to_le32((OWNbit | EORbit) | (unsigned long)priv->hw_rx_pkt_len); + } + else{ + priv->RxDescArray[cur_rx].status = cpu_to_le32(OWNbit | (unsigned long)priv->hw_rx_pkt_len); + } + + cur_skb = priv->Rx_skbuff[cur_rx]; - tp->cur_rx = cur_rx; + if( cur_skb != NULL ){ + priv->rx_skbuff_dma_addr[cur_rx] = pci_map_single(pdev, cur_skb->data, MAX_RX_SKBDATA_SIZE, PCI_DMA_FROMDEVICE); + rxdesc->buf_addr = cpu_to_le32(priv->rx_skbuff_dma_addr[cur_rx]); + } + else{ + DBG_PRINT("%s: %s() cur_skb == NULL\n", dev->name, __FUNCTION__); + } + + }//------------------------------------------------------------ + + }// end of if( priv->RxDescArray[cur_rx].status & RxRES ) + + cur_rx = (cur_rx +1) % NUM_RX_DESC; + rxdesc = &priv->RxDescArray[cur_rx]; + pci_dma_sync_single(pdev, priv->rxdesc_array_dma_addr[cur_rx], sizeof(struct RxDesc), PCI_DMA_FROMDEVICE); + + }// end of while ( (priv->RxDescArray[cur_rx].status & 0x80000000)== 0) + + if( rxdesc_cnt >= max_interrupt_work ){ + DBG_PRINT("%s: Too much work at Rx interrupt.\n", dev->name); + } - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (delta > 0) - tp->dirty_rx += delta; - else if (delta < 0) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); + priv->cur_rx = cur_rx; } + + + + + + + +//====================================================================================================== /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -static irqreturn_t -rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static void rtl8169_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +#else +static irqreturn_t rtl8169_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +#endif { struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *priv = dev->priv; int boguscnt = max_interrupt_work; - void *ioaddr = tp->mmio_addr; + unsigned long ioaddr = priv->ioaddr; int status = 0; - int handled = 0; + irqreturn_t interrupt_handled = IRQ_NONE; + + RTL_W16 ( IntrMask, 0x0000); do { status = RTL_R16(IntrStatus); - /* hotplug/major error/no more work/shared irq */ - if ((status == 0xFFFF) || !status) + if (status == 0xFFFF) break; - handled = 1; -/* - if (status & RxUnderrun) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; -*/ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - if (!(status & rtl8169_intr_mask)) + RTL_W16( IntrStatus, status ); + + + if ( (status & rtl8169_intr_mask ) == 0 ) break; + else + interrupt_handled = IRQ_HANDLED; + + + // Rx interrupt +// if (status & (RxOK | RxErr /* | LinkChg | RxOverflow | RxFIFOOver*/)){ + rtl8169_rx_interrupt (dev, priv, ioaddr); +// } - // Rx interrupt - if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) { - rtl8169_rx_interrupt(dev, tp, ioaddr); - } // Tx interrupt - if (status & (TxOK | TxErr)) { - spin_lock(&tp->lock); - rtl8169_tx_interrupt(dev, tp, ioaddr); - spin_unlock(&tp->lock); - } +// if (status & (TxOK | TxErr)) { + spin_lock (&priv->lock); + rtl8169_tx_interrupt (dev, priv, ioaddr); + spin_unlock (&priv->lock); +// } boguscnt--; } while (boguscnt > 0); if (boguscnt <= 0) { - printk(KERN_WARNING "%s: Too much work at interrupt!\n", - dev->name); - /* Clear all interrupt sources. */ - RTL_W16(IntrStatus, 0xffff); + DBG_PRINT("%s: Too much work at interrupt!\n", dev->name); + RTL_W16( IntrStatus, 0xffff); // Clear all interrupt sources } - return IRQ_RETVAL(handled); + + RTL_W16 ( IntrMask, rtl8169_intr_mask); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + return interrupt_handled; +#endif } -static int -rtl8169_close(struct net_device *dev) + + + + + + +//====================================================================================================== +static int rtl8169_close (struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; - struct pci_dev *pdev = tp->pci_dev; - void *ioaddr = tp->mmio_addr; + struct rtl8169_private *priv = dev->priv; + unsigned long ioaddr = priv->ioaddr; + int i; + + // ----------------------------------------- + rtl8169_delete_timer( &(priv->r8169_timer) ); - netif_stop_queue(dev); - rtl8169_delete_timer(dev); + netif_stop_queue (dev); - spin_lock_irq(&tp->lock); + spin_lock_irq (&priv->lock); - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8(ChipCmd, 0x00); + /* Stop the chip's Tx and Rx processes. */ + RTL_W8 ( ChipCmd, 0x00); /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16(IntrMask, 0x0000); + RTL_W16 ( IntrMask, 0x0000); /* Update the error counts. */ - tp->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); + priv->stats.rx_missed_errors += RTL_R32(RxMissed); + RTL_W32( RxMissed, 0); - spin_unlock_irq(&tp->lock); + spin_unlock_irq (&priv->lock); - synchronize_irq(dev->irq); - free_irq(dev->irq, dev); - - rtl8169_tx_clear(tp); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + synchronize_irq (); +#else + synchronize_irq (dev->irq); +#endif + free_irq (dev->irq, dev); - rtl8169_rx_clear(tp); + rtl8169_tx_clear (priv); + + //2004-05-11 + if(priv->txdesc_space != NULL){ + pci_free_consistent( + priv->pci_dev, + priv->sizeof_txdesc_space, + priv->txdesc_space, + priv->txdesc_phy_dma_addr + ); + priv->txdesc_space = NULL; + } + + if(priv->rxdesc_space != NULL){ + pci_free_consistent( + priv->pci_dev, + priv->sizeof_rxdesc_space, + priv->rxdesc_space, + priv->rxdesc_phy_dma_addr + ); + priv->rxdesc_space = NULL; + } + + priv->TxDescArray = NULL; + priv->RxDescArray = NULL; + + {//----------------------------------------------------------------------------- + for(i=0;iRx_skbuff[i] != NULL ) { + RTL8169_FREE_RXSKB ( priv->Rx_skbuff[i] ); + } + } + }//----------------------------------------------------------------------------- - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; + DBG_PRINT("%s: %s() alloc_rxskb_cnt = %d\n", dev->name, __FUNCTION__, alloc_rxskb_cnt ); return 0; } -static void -rtl8169_set_rx_mode(struct net_device *dev) + + + + + + +//====================================================================================================== +static unsigned const ethernet_polynomial = 0x04c11db7U; +static inline u32 ether_crc (int length, unsigned char *data) +{ + int crc = -1; + + while (--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 0; bit < 8; bit++, current_octet >>= 1) + crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); + } + + return crc; +} + + + + + + + + +//====================================================================================================== +static void rtl8169_set_rx_mode (struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; + struct rtl8169_private *priv = dev->priv; + unsigned long ioaddr = priv->ioaddr; unsigned long flags; u32 mc_filter[2]; /* Multicast hash filter */ int i, rx_mode; - u32 tmp = 0; + u32 tmp=0; + if (dev->flags & IFF_PROMISC) { /* Unconditionally log net taps. */ - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; + printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { + } else if ((dev->mc_count > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; } else { struct dev_mc_list *mclist; - rx_mode = AcceptBroadcast | AcceptMyPhys; + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) + { + set_bit (ether_crc (ETH_ALEN, mclist->dmi_addr) >> 26, mc_filter); + } +#else + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) + { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); rx_mode |= AcceptMulticast; } +#endif } - spin_lock_irqsave(&tp->lock, flags); + spin_lock_irqsave (&priv->lock, flags); + + tmp = rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) & rtl_chip_info[priv->chipset].RxConfigMask); + + RTL_W32 ( RxConfig, tmp); + RTL_W32 ( MAR0 + 0, mc_filter[0]); + RTL_W32 ( MAR0 + 4, mc_filter[1]); + + spin_unlock_irqrestore (&priv->lock, flags); + +}//end of rtl8169_set_rx_mode (struct net_device *dev) + + + + + + + +//================================================================================ +struct net_device_stats *rtl8169_get_stats(struct net_device *dev) - tmp = - rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) & - rtl_chip_info[tp->chipset]. - RxConfigMask); - - RTL_W32(RxConfig, tmp); - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -/** - * rtl8169_get_stats - Get rtl8169 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8169 - */ -static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - unsigned long flags; + struct rtl8169_private *priv = dev->priv; - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return &tp->stats; + return &priv->stats; } + + + + + + + +//================================================================================ static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl8169_init_one, - .remove = __devexit_p(rtl8169_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, -#endif + name: MODULENAME, + id_table: rtl8169_pci_tbl, + probe: rtl8169_init_one, + remove: rtl8169_remove_one, + suspend: NULL, + resume: NULL, }; -static int __init -rtl8169_init_module(void) + + + + +//====================================================================================================== +static int __init rtl8169_init_module (void) { - return pci_module_init(&rtl8169_pci_driver); + return pci_module_init (&rtl8169_pci_driver); // pci_register_driver (drv) } -static void __exit -rtl8169_cleanup_module(void) + + + +//====================================================================================================== +static void __exit rtl8169_cleanup_module (void) { - pci_unregister_driver(&rtl8169_pci_driver); + pci_unregister_driver (&rtl8169_pci_driver); } + +#ifdef RTL8169_JUMBO_FRAME_SUPPORT +static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) +{ + struct rtl8169_private *priv = dev->priv; + unsigned long ioaddr = priv->ioaddr; + + if( new_mtu > MAX_JUMBO_FRAME_MTU ){ + printk("%s: Error -- new_mtu(%d) > MAX_JUMBO_FRAME_MTU(%d).\n", dev->name, new_mtu, MAX_JUMBO_FRAME_MTU); + return -1; + } + + dev->mtu = new_mtu; + + priv->curr_mtu_size = new_mtu; + priv->tx_pkt_len = new_mtu + ETH_HDR_LEN; + priv->rx_pkt_len = new_mtu + ETH_HDR_LEN; + priv->hw_rx_pkt_len = priv->rx_pkt_len + 8; + + RTL_W8 ( Cfg9346, Cfg9346_Unlock); + RTL_W16 ( RxMaxSize, (unsigned short)priv->hw_rx_pkt_len ); + RTL_W8 ( Cfg9346, Cfg9346_Lock); + + DBG_PRINT("-------------------------- \n"); + DBG_PRINT("dev->mtu = %d \n", dev->mtu); + DBG_PRINT("priv->curr_mtu_size = %d \n", priv->curr_mtu_size); + DBG_PRINT("priv->rx_pkt_len = %d \n", priv->rx_pkt_len); + DBG_PRINT("priv->tx_pkt_len = %d \n", priv->tx_pkt_len); + DBG_PRINT("RTL_W16( RxMaxSize, %d )\n", priv->hw_rx_pkt_len); + DBG_PRINT("-------------------------- \n"); + + rtl8169_close (dev); + rtl8169_open (dev); + + return 0; +} +#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT + + + + + + + + + + + +//====================================================================================================== module_init(rtl8169_init_module); module_exit(rtl8169_cleanup_module);