1*1b8adde7SWilliam Kucharski /************************************************************************** 2*1b8adde7SWilliam Kucharski * r8169.c: Etherboot device driver for the RealTek RTL-8169 Gigabit 3*1b8adde7SWilliam Kucharski * Written 2003 by Timothy Legge <tlegge@rogers.com> 4*1b8adde7SWilliam Kucharski * 5*1b8adde7SWilliam Kucharski * This program is free software; you can redistribute it and/or modify 6*1b8adde7SWilliam Kucharski * it under the terms of the GNU General Public License as published by 7*1b8adde7SWilliam Kucharski * the Free Software Foundation; either version 2 of the License, or 8*1b8adde7SWilliam Kucharski * (at your option) any later version. 9*1b8adde7SWilliam Kucharski * 10*1b8adde7SWilliam Kucharski * This program is distributed in the hope that it will be useful, 11*1b8adde7SWilliam Kucharski * but WITHOUT ANY WARRANTY; without even the implied warranty of 12*1b8adde7SWilliam Kucharski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*1b8adde7SWilliam Kucharski * GNU General Public License for more details. 14*1b8adde7SWilliam Kucharski * 15*1b8adde7SWilliam Kucharski * You should have received a copy of the GNU General Public License 16*1b8adde7SWilliam Kucharski * along with this program; if not, write to the Free Software 17*1b8adde7SWilliam Kucharski * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18*1b8adde7SWilliam Kucharski * 19*1b8adde7SWilliam Kucharski * Portions of this code based on: 20*1b8adde7SWilliam Kucharski * r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver 21*1b8adde7SWilliam Kucharski * for Linux kernel 2.4.x. 22*1b8adde7SWilliam Kucharski * 23*1b8adde7SWilliam Kucharski * Written 2002 ShuChen <shuchen@realtek.com.tw> 24*1b8adde7SWilliam Kucharski * See Linux Driver for full information 25*1b8adde7SWilliam Kucharski * 26*1b8adde7SWilliam Kucharski * Linux Driver Version 1.27a, 10.02.2002 27*1b8adde7SWilliam Kucharski * 28*1b8adde7SWilliam Kucharski * Thanks to: 29*1b8adde7SWilliam Kucharski * Jean Chen of RealTek Semiconductor Corp. for 30*1b8adde7SWilliam Kucharski * providing the evaluation NIC used to develop 31*1b8adde7SWilliam Kucharski * this driver. RealTek's support for Etherboot 32*1b8adde7SWilliam Kucharski * is appreciated. 33*1b8adde7SWilliam Kucharski * 34*1b8adde7SWilliam Kucharski * REVISION HISTORY: 35*1b8adde7SWilliam Kucharski * ================ 36*1b8adde7SWilliam Kucharski * 37*1b8adde7SWilliam Kucharski * v1.0 11-26-2003 timlegge Initial port of Linux driver 38*1b8adde7SWilliam Kucharski * v1.5 01-17-2004 timlegge Initial driver output cleanup 39*1b8adde7SWilliam Kucharski * v1.6 03-27-2004 timlegge Additional Cleanup 40*1b8adde7SWilliam Kucharski * 41*1b8adde7SWilliam Kucharski * Indent Options: indent -kr -i8 42*1b8adde7SWilliam Kucharski ***************************************************************************/ 43*1b8adde7SWilliam Kucharski 44*1b8adde7SWilliam Kucharski /* to get some global routines like printf */ 45*1b8adde7SWilliam Kucharski #include "etherboot.h" 46*1b8adde7SWilliam Kucharski /* to get the interface to the body of the program */ 47*1b8adde7SWilliam Kucharski #include "nic.h" 48*1b8adde7SWilliam Kucharski /* to get the PCI support functions, if this is a PCI NIC */ 49*1b8adde7SWilliam Kucharski #include "pci.h" 50*1b8adde7SWilliam Kucharski #include "timer.h" 51*1b8adde7SWilliam Kucharski 52*1b8adde7SWilliam Kucharski #define drv_version "v1.6" 53*1b8adde7SWilliam Kucharski #define drv_date "03-27-2004" 54*1b8adde7SWilliam Kucharski 55*1b8adde7SWilliam Kucharski typedef unsigned char u8; 56*1b8adde7SWilliam Kucharski typedef signed char s8; 57*1b8adde7SWilliam Kucharski typedef unsigned short u16; 58*1b8adde7SWilliam Kucharski typedef signed short s16; 59*1b8adde7SWilliam Kucharski typedef unsigned int u32; 60*1b8adde7SWilliam Kucharski typedef signed int s32; 61*1b8adde7SWilliam Kucharski 62*1b8adde7SWilliam Kucharski #define HZ 1000 63*1b8adde7SWilliam Kucharski 64*1b8adde7SWilliam Kucharski static u32 ioaddr; 65*1b8adde7SWilliam Kucharski 66*1b8adde7SWilliam Kucharski #ifdef EDEBUG 67*1b8adde7SWilliam Kucharski #define dprintf(x) printf x 68*1b8adde7SWilliam Kucharski #else 69*1b8adde7SWilliam Kucharski #define dprintf(x) 70*1b8adde7SWilliam Kucharski #endif 71*1b8adde7SWilliam Kucharski 72*1b8adde7SWilliam Kucharski /* Condensed operations for readability. */ 73*1b8adde7SWilliam Kucharski #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) 74*1b8adde7SWilliam Kucharski #define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) 75*1b8adde7SWilliam Kucharski 76*1b8adde7SWilliam Kucharski #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 77*1b8adde7SWilliam Kucharski 78*1b8adde7SWilliam Kucharski /* media options 79*1b8adde7SWilliam Kucharski _10_Half = 0x01, 80*1b8adde7SWilliam Kucharski _10_Full = 0x02, 81*1b8adde7SWilliam Kucharski _100_Half = 0x04, 82*1b8adde7SWilliam Kucharski _100_Full = 0x08, 83*1b8adde7SWilliam Kucharski _1000_Full = 0x10, 84*1b8adde7SWilliam Kucharski */ 85*1b8adde7SWilliam Kucharski static int media = -1; 86*1b8adde7SWilliam Kucharski 87*1b8adde7SWilliam Kucharski #if 0 88*1b8adde7SWilliam Kucharski /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ 89*1b8adde7SWilliam Kucharski static int max_interrupt_work = 20; 90*1b8adde7SWilliam Kucharski #endif 91*1b8adde7SWilliam Kucharski 92*1b8adde7SWilliam Kucharski #if 0 93*1b8adde7SWilliam Kucharski /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). 94*1b8adde7SWilliam Kucharski The RTL chips use a 64 element hash table based on the Ethernet CRC. */ 95*1b8adde7SWilliam Kucharski static int multicast_filter_limit = 32; 96*1b8adde7SWilliam Kucharski #endif 97*1b8adde7SWilliam Kucharski 98*1b8adde7SWilliam Kucharski /* MAC address length*/ 99*1b8adde7SWilliam Kucharski #define MAC_ADDR_LEN 6 100*1b8adde7SWilliam Kucharski 101*1b8adde7SWilliam Kucharski /* max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4).*/ 102*1b8adde7SWilliam Kucharski #define MAX_ETH_FRAME_SIZE 1536 103*1b8adde7SWilliam Kucharski 104*1b8adde7SWilliam Kucharski #define TX_FIFO_THRESH 256 /* In bytes */ 105*1b8adde7SWilliam Kucharski 106*1b8adde7SWilliam Kucharski #define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ 107*1b8adde7SWilliam Kucharski #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ 108*1b8adde7SWilliam Kucharski #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ 109*1b8adde7SWilliam Kucharski #define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ 110*1b8adde7SWilliam Kucharski #define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */ 111*1b8adde7SWilliam Kucharski #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ 112*1b8adde7SWilliam Kucharski 113*1b8adde7SWilliam Kucharski #define NUM_TX_DESC 1 /* Number of Tx descriptor registers */ 114*1b8adde7SWilliam Kucharski #define NUM_RX_DESC 4 /* Number of Rx descriptor registers */ 115*1b8adde7SWilliam Kucharski #define RX_BUF_SIZE 1536 /* Rx Buffer size */ 116*1b8adde7SWilliam Kucharski 117*1b8adde7SWilliam Kucharski #define RTL_MIN_IO_SIZE 0x80 118*1b8adde7SWilliam Kucharski #define TX_TIMEOUT (6*HZ) 119*1b8adde7SWilliam Kucharski 120*1b8adde7SWilliam Kucharski /* write/read MMIO register */ 121*1b8adde7SWilliam Kucharski #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) 122*1b8adde7SWilliam Kucharski #define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) 123*1b8adde7SWilliam Kucharski #define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) 124*1b8adde7SWilliam Kucharski #define RTL_R8(reg) readb (ioaddr + (reg)) 125*1b8adde7SWilliam Kucharski #define RTL_R16(reg) readw (ioaddr + (reg)) 126*1b8adde7SWilliam Kucharski #define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) 127*1b8adde7SWilliam Kucharski 128*1b8adde7SWilliam Kucharski enum RTL8169_registers { 129*1b8adde7SWilliam Kucharski MAC0 = 0, /* Ethernet hardware address. */ 130*1b8adde7SWilliam Kucharski MAR0 = 8, /* Multicast filter. */ 131*1b8adde7SWilliam Kucharski TxDescStartAddr = 0x20, 132*1b8adde7SWilliam Kucharski TxHDescStartAddr = 0x28, 133*1b8adde7SWilliam Kucharski FLASH = 0x30, 134*1b8adde7SWilliam Kucharski ERSR = 0x36, 135*1b8adde7SWilliam Kucharski ChipCmd = 0x37, 136*1b8adde7SWilliam Kucharski TxPoll = 0x38, 137*1b8adde7SWilliam Kucharski IntrMask = 0x3C, 138*1b8adde7SWilliam Kucharski IntrStatus = 0x3E, 139*1b8adde7SWilliam Kucharski TxConfig = 0x40, 140*1b8adde7SWilliam Kucharski RxConfig = 0x44, 141*1b8adde7SWilliam Kucharski RxMissed = 0x4C, 142*1b8adde7SWilliam Kucharski Cfg9346 = 0x50, 143*1b8adde7SWilliam Kucharski Config0 = 0x51, 144*1b8adde7SWilliam Kucharski Config1 = 0x52, 145*1b8adde7SWilliam Kucharski Config2 = 0x53, 146*1b8adde7SWilliam Kucharski Config3 = 0x54, 147*1b8adde7SWilliam Kucharski Config4 = 0x55, 148*1b8adde7SWilliam Kucharski Config5 = 0x56, 149*1b8adde7SWilliam Kucharski MultiIntr = 0x5C, 150*1b8adde7SWilliam Kucharski PHYAR = 0x60, 151*1b8adde7SWilliam Kucharski TBICSR = 0x64, 152*1b8adde7SWilliam Kucharski TBI_ANAR = 0x68, 153*1b8adde7SWilliam Kucharski TBI_LPAR = 0x6A, 154*1b8adde7SWilliam Kucharski PHYstatus = 0x6C, 155*1b8adde7SWilliam Kucharski RxMaxSize = 0xDA, 156*1b8adde7SWilliam Kucharski CPlusCmd = 0xE0, 157*1b8adde7SWilliam Kucharski RxDescStartAddr = 0xE4, 158*1b8adde7SWilliam Kucharski EarlyTxThres = 0xEC, 159*1b8adde7SWilliam Kucharski FuncEvent = 0xF0, 160*1b8adde7SWilliam Kucharski FuncEventMask = 0xF4, 161*1b8adde7SWilliam Kucharski FuncPresetState = 0xF8, 162*1b8adde7SWilliam Kucharski FuncForceEvent = 0xFC, 163*1b8adde7SWilliam Kucharski }; 164*1b8adde7SWilliam Kucharski 165*1b8adde7SWilliam Kucharski enum RTL8169_register_content { 166*1b8adde7SWilliam Kucharski /*InterruptStatusBits */ 167*1b8adde7SWilliam Kucharski SYSErr = 0x8000, 168*1b8adde7SWilliam Kucharski PCSTimeout = 0x4000, 169*1b8adde7SWilliam Kucharski SWInt = 0x0100, 170*1b8adde7SWilliam Kucharski TxDescUnavail = 0x80, 171*1b8adde7SWilliam Kucharski RxFIFOOver = 0x40, 172*1b8adde7SWilliam Kucharski RxUnderrun = 0x20, 173*1b8adde7SWilliam Kucharski RxOverflow = 0x10, 174*1b8adde7SWilliam Kucharski TxErr = 0x08, 175*1b8adde7SWilliam Kucharski TxOK = 0x04, 176*1b8adde7SWilliam Kucharski RxErr = 0x02, 177*1b8adde7SWilliam Kucharski RxOK = 0x01, 178*1b8adde7SWilliam Kucharski 179*1b8adde7SWilliam Kucharski /*RxStatusDesc */ 180*1b8adde7SWilliam Kucharski RxRES = 0x00200000, 181*1b8adde7SWilliam Kucharski RxCRC = 0x00080000, 182*1b8adde7SWilliam Kucharski RxRUNT = 0x00100000, 183*1b8adde7SWilliam Kucharski RxRWT = 0x00400000, 184*1b8adde7SWilliam Kucharski 185*1b8adde7SWilliam Kucharski /*ChipCmdBits */ 186*1b8adde7SWilliam Kucharski CmdReset = 0x10, 187*1b8adde7SWilliam Kucharski CmdRxEnb = 0x08, 188*1b8adde7SWilliam Kucharski CmdTxEnb = 0x04, 189*1b8adde7SWilliam Kucharski RxBufEmpty = 0x01, 190*1b8adde7SWilliam Kucharski 191*1b8adde7SWilliam Kucharski /*Cfg9346Bits */ 192*1b8adde7SWilliam Kucharski Cfg9346_Lock = 0x00, 193*1b8adde7SWilliam Kucharski Cfg9346_Unlock = 0xC0, 194*1b8adde7SWilliam Kucharski 195*1b8adde7SWilliam Kucharski /*rx_mode_bits */ 196*1b8adde7SWilliam Kucharski AcceptErr = 0x20, 197*1b8adde7SWilliam Kucharski AcceptRunt = 0x10, 198*1b8adde7SWilliam Kucharski AcceptBroadcast = 0x08, 199*1b8adde7SWilliam Kucharski AcceptMulticast = 0x04, 200*1b8adde7SWilliam Kucharski AcceptMyPhys = 0x02, 201*1b8adde7SWilliam Kucharski AcceptAllPhys = 0x01, 202*1b8adde7SWilliam Kucharski 203*1b8adde7SWilliam Kucharski /*RxConfigBits */ 204*1b8adde7SWilliam Kucharski RxCfgFIFOShift = 13, 205*1b8adde7SWilliam Kucharski RxCfgDMAShift = 8, 206*1b8adde7SWilliam Kucharski 207*1b8adde7SWilliam Kucharski /*TxConfigBits */ 208*1b8adde7SWilliam Kucharski TxInterFrameGapShift = 24, 209*1b8adde7SWilliam Kucharski TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ 210*1b8adde7SWilliam Kucharski 211*1b8adde7SWilliam Kucharski /*rtl8169_PHYstatus */ 212*1b8adde7SWilliam Kucharski TBI_Enable = 0x80, 213*1b8adde7SWilliam Kucharski TxFlowCtrl = 0x40, 214*1b8adde7SWilliam Kucharski RxFlowCtrl = 0x20, 215*1b8adde7SWilliam Kucharski _1000bpsF = 0x10, 216*1b8adde7SWilliam Kucharski _100bps = 0x08, 217*1b8adde7SWilliam Kucharski _10bps = 0x04, 218*1b8adde7SWilliam Kucharski LinkStatus = 0x02, 219*1b8adde7SWilliam Kucharski FullDup = 0x01, 220*1b8adde7SWilliam Kucharski 221*1b8adde7SWilliam Kucharski /*GIGABIT_PHY_registers */ 222*1b8adde7SWilliam Kucharski PHY_CTRL_REG = 0, 223*1b8adde7SWilliam Kucharski PHY_STAT_REG = 1, 224*1b8adde7SWilliam Kucharski PHY_AUTO_NEGO_REG = 4, 225*1b8adde7SWilliam Kucharski PHY_1000_CTRL_REG = 9, 226*1b8adde7SWilliam Kucharski 227*1b8adde7SWilliam Kucharski /*GIGABIT_PHY_REG_BIT */ 228*1b8adde7SWilliam Kucharski PHY_Restart_Auto_Nego = 0x0200, 229*1b8adde7SWilliam Kucharski PHY_Enable_Auto_Nego = 0x1000, 230*1b8adde7SWilliam Kucharski 231*1b8adde7SWilliam Kucharski /* PHY_STAT_REG = 1; */ 232*1b8adde7SWilliam Kucharski PHY_Auto_Neco_Comp = 0x0020, 233*1b8adde7SWilliam Kucharski 234*1b8adde7SWilliam Kucharski /* PHY_AUTO_NEGO_REG = 4; */ 235*1b8adde7SWilliam Kucharski PHY_Cap_10_Half = 0x0020, 236*1b8adde7SWilliam Kucharski PHY_Cap_10_Full = 0x0040, 237*1b8adde7SWilliam Kucharski PHY_Cap_100_Half = 0x0080, 238*1b8adde7SWilliam Kucharski PHY_Cap_100_Full = 0x0100, 239*1b8adde7SWilliam Kucharski 240*1b8adde7SWilliam Kucharski /* PHY_1000_CTRL_REG = 9; */ 241*1b8adde7SWilliam Kucharski PHY_Cap_1000_Full = 0x0200, 242*1b8adde7SWilliam Kucharski 243*1b8adde7SWilliam Kucharski PHY_Cap_Null = 0x0, 244*1b8adde7SWilliam Kucharski 245*1b8adde7SWilliam Kucharski /*_MediaType*/ 246*1b8adde7SWilliam Kucharski _10_Half = 0x01, 247*1b8adde7SWilliam Kucharski _10_Full = 0x02, 248*1b8adde7SWilliam Kucharski _100_Half = 0x04, 249*1b8adde7SWilliam Kucharski _100_Full = 0x08, 250*1b8adde7SWilliam Kucharski _1000_Full = 0x10, 251*1b8adde7SWilliam Kucharski 252*1b8adde7SWilliam Kucharski /*_TBICSRBit*/ 253*1b8adde7SWilliam Kucharski TBILinkOK = 0x02000000, 254*1b8adde7SWilliam Kucharski }; 255*1b8adde7SWilliam Kucharski 256*1b8adde7SWilliam Kucharski static struct { 257*1b8adde7SWilliam Kucharski const char *name; 258*1b8adde7SWilliam Kucharski u8 version; /* depend on RTL8169 docs */ 259*1b8adde7SWilliam Kucharski u32 RxConfigMask; /* should clear the bits supported by this chip */ 260*1b8adde7SWilliam Kucharski } rtl_chip_info[] = { 261*1b8adde7SWilliam Kucharski { 262*1b8adde7SWilliam Kucharski "RTL-8169", 0x00, 0xff7e1880,},}; 263*1b8adde7SWilliam Kucharski 264*1b8adde7SWilliam Kucharski enum _DescStatusBit { 265*1b8adde7SWilliam Kucharski OWNbit = 0x80000000, 266*1b8adde7SWilliam Kucharski EORbit = 0x40000000, 267*1b8adde7SWilliam Kucharski FSbit = 0x20000000, 268*1b8adde7SWilliam Kucharski LSbit = 0x10000000, 269*1b8adde7SWilliam Kucharski }; 270*1b8adde7SWilliam Kucharski 271*1b8adde7SWilliam Kucharski struct TxDesc { 272*1b8adde7SWilliam Kucharski u32 status; 273*1b8adde7SWilliam Kucharski u32 vlan_tag; 274*1b8adde7SWilliam Kucharski u32 buf_addr; 275*1b8adde7SWilliam Kucharski u32 buf_Haddr; 276*1b8adde7SWilliam Kucharski }; 277*1b8adde7SWilliam Kucharski 278*1b8adde7SWilliam Kucharski struct RxDesc { 279*1b8adde7SWilliam Kucharski u32 status; 280*1b8adde7SWilliam Kucharski u32 vlan_tag; 281*1b8adde7SWilliam Kucharski u32 buf_addr; 282*1b8adde7SWilliam Kucharski u32 buf_Haddr; 283*1b8adde7SWilliam Kucharski }; 284*1b8adde7SWilliam Kucharski 285*1b8adde7SWilliam Kucharski /* The descriptors for this card are required to be aligned on 286*1b8adde7SWilliam Kucharski 256 byte boundaries. As the align attribute does not do more than 287*1b8adde7SWilliam Kucharski 16 bytes of alignment it requires some extra steps. Add 256 to the 288*1b8adde7SWilliam Kucharski size of the array and the init_ring adjusts the alignment */ 289*1b8adde7SWilliam Kucharski 290*1b8adde7SWilliam Kucharski /* Define the TX Descriptor */ 291*1b8adde7SWilliam Kucharski static u8 tx_ring[NUM_TX_DESC * sizeof(struct TxDesc) + 256]; 292*1b8adde7SWilliam Kucharski 293*1b8adde7SWilliam Kucharski /* Create a static buffer of size RX_BUF_SZ for each 294*1b8adde7SWilliam Kucharski TX Descriptor. All descriptors point to a 295*1b8adde7SWilliam Kucharski part of this buffer */ 296*1b8adde7SWilliam Kucharski static unsigned char txb[NUM_TX_DESC * RX_BUF_SIZE]; 297*1b8adde7SWilliam Kucharski 298*1b8adde7SWilliam Kucharski /* Define the RX Descriptor */ 299*1b8adde7SWilliam Kucharski static u8 rx_ring[NUM_RX_DESC * sizeof(struct TxDesc) + 256]; 300*1b8adde7SWilliam Kucharski 301*1b8adde7SWilliam Kucharski /* Create a static buffer of size RX_BUF_SZ for each 302*1b8adde7SWilliam Kucharski RX Descriptor All descriptors point to a 303*1b8adde7SWilliam Kucharski part of this buffer */ 304*1b8adde7SWilliam Kucharski static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE]; 305*1b8adde7SWilliam Kucharski 306*1b8adde7SWilliam Kucharski struct rtl8169_private { 307*1b8adde7SWilliam Kucharski void *mmio_addr; /* memory map physical address */ 308*1b8adde7SWilliam Kucharski int chipset; 309*1b8adde7SWilliam Kucharski unsigned long cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ 310*1b8adde7SWilliam Kucharski unsigned long cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ 311*1b8adde7SWilliam Kucharski unsigned char *TxDescArrays; /* Index of Tx Descriptor buffer */ 312*1b8adde7SWilliam Kucharski unsigned char *RxDescArrays; /* Index of Rx Descriptor buffer */ 313*1b8adde7SWilliam Kucharski struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */ 314*1b8adde7SWilliam Kucharski struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */ 315*1b8adde7SWilliam Kucharski unsigned char *RxBufferRing[NUM_RX_DESC]; /* Index of Rx Buffer array */ 316*1b8adde7SWilliam Kucharski unsigned char *Tx_skbuff[NUM_TX_DESC]; 317*1b8adde7SWilliam Kucharski } tpx; 318*1b8adde7SWilliam Kucharski 319*1b8adde7SWilliam Kucharski static struct rtl8169_private *tpc; 320*1b8adde7SWilliam Kucharski 321*1b8adde7SWilliam Kucharski static const u16 rtl8169_intr_mask = 322*1b8adde7SWilliam Kucharski SYSErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | 323*1b8adde7SWilliam Kucharski TxOK | RxErr | RxOK; 324*1b8adde7SWilliam Kucharski static const unsigned int rtl8169_rx_config = 325*1b8adde7SWilliam Kucharski (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); 326*1b8adde7SWilliam Kucharski 327*1b8adde7SWilliam Kucharski void mdio_write(int RegAddr, int value) 328*1b8adde7SWilliam Kucharski { 329*1b8adde7SWilliam Kucharski int i; 330*1b8adde7SWilliam Kucharski 331*1b8adde7SWilliam Kucharski RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value); 332*1b8adde7SWilliam Kucharski udelay(1000); 333*1b8adde7SWilliam Kucharski 334*1b8adde7SWilliam Kucharski for (i = 2000; i > 0; i--) { 335*1b8adde7SWilliam Kucharski /* Check if the RTL8169 has completed writing to the specified MII register */ 336*1b8adde7SWilliam Kucharski if (!(RTL_R32(PHYAR) & 0x80000000)) { 337*1b8adde7SWilliam Kucharski break; 338*1b8adde7SWilliam Kucharski } else { 339*1b8adde7SWilliam Kucharski udelay(100); 340*1b8adde7SWilliam Kucharski } 341*1b8adde7SWilliam Kucharski } 342*1b8adde7SWilliam Kucharski } 343*1b8adde7SWilliam Kucharski 344*1b8adde7SWilliam Kucharski int mdio_read(int RegAddr) 345*1b8adde7SWilliam Kucharski { 346*1b8adde7SWilliam Kucharski int i, value = -1; 347*1b8adde7SWilliam Kucharski 348*1b8adde7SWilliam Kucharski RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16); 349*1b8adde7SWilliam Kucharski udelay(1000); 350*1b8adde7SWilliam Kucharski 351*1b8adde7SWilliam Kucharski for (i = 2000; i > 0; i--) { 352*1b8adde7SWilliam Kucharski /* Check if the RTL8169 has completed retrieving data from the specified MII register */ 353*1b8adde7SWilliam Kucharski if (RTL_R32(PHYAR) & 0x80000000) { 354*1b8adde7SWilliam Kucharski value = (int) (RTL_R32(PHYAR) & 0xFFFF); 355*1b8adde7SWilliam Kucharski break; 356*1b8adde7SWilliam Kucharski } else { 357*1b8adde7SWilliam Kucharski udelay(100); 358*1b8adde7SWilliam Kucharski } 359*1b8adde7SWilliam Kucharski } 360*1b8adde7SWilliam Kucharski return value; 361*1b8adde7SWilliam Kucharski } 362*1b8adde7SWilliam Kucharski 363*1b8adde7SWilliam Kucharski static int rtl8169_init_board(struct pci_device *pdev) 364*1b8adde7SWilliam Kucharski { 365*1b8adde7SWilliam Kucharski int i; 366*1b8adde7SWilliam Kucharski unsigned long rtreg_base, rtreg_len; 367*1b8adde7SWilliam Kucharski u32 tmp; 368*1b8adde7SWilliam Kucharski 369*1b8adde7SWilliam Kucharski rtreg_base = pci_bar_start(pdev, PCI_BASE_ADDRESS_1); 370*1b8adde7SWilliam Kucharski rtreg_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_1); 371*1b8adde7SWilliam Kucharski 372*1b8adde7SWilliam Kucharski /* check for weird/broken PCI region reporting */ 373*1b8adde7SWilliam Kucharski if (rtreg_len < RTL_MIN_IO_SIZE) { 374*1b8adde7SWilliam Kucharski printf("Invalid PCI region size(s), aborting\n"); 375*1b8adde7SWilliam Kucharski } 376*1b8adde7SWilliam Kucharski 377*1b8adde7SWilliam Kucharski adjust_pci_device(pdev); 378*1b8adde7SWilliam Kucharski /* pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); */ 379*1b8adde7SWilliam Kucharski 380*1b8adde7SWilliam Kucharski /* ioremap MMIO region */ 381*1b8adde7SWilliam Kucharski ioaddr = (unsigned long) ioremap(rtreg_base, rtreg_len); 382*1b8adde7SWilliam Kucharski if (ioaddr == 0) 383*1b8adde7SWilliam Kucharski return 0; 384*1b8adde7SWilliam Kucharski 385*1b8adde7SWilliam Kucharski tpc->mmio_addr = &ioaddr; 386*1b8adde7SWilliam Kucharski /* Soft reset the chip. */ 387*1b8adde7SWilliam Kucharski RTL_W8(ChipCmd, CmdReset); 388*1b8adde7SWilliam Kucharski 389*1b8adde7SWilliam Kucharski /* Check that the chip has finished the reset. */ 390*1b8adde7SWilliam Kucharski for (i = 1000; i > 0; i--) 391*1b8adde7SWilliam Kucharski if ((RTL_R8(ChipCmd) & CmdReset) == 0) 392*1b8adde7SWilliam Kucharski break; 393*1b8adde7SWilliam Kucharski else 394*1b8adde7SWilliam Kucharski udelay(10); 395*1b8adde7SWilliam Kucharski 396*1b8adde7SWilliam Kucharski /* identify chip attached to board */ 397*1b8adde7SWilliam Kucharski tmp = RTL_R32(TxConfig); 398*1b8adde7SWilliam Kucharski tmp = ((tmp & 0x7c000000) + ((tmp & 0x00800000) << 2)) >> 24; 399*1b8adde7SWilliam Kucharski 400*1b8adde7SWilliam Kucharski for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) 401*1b8adde7SWilliam Kucharski if (tmp == rtl_chip_info[i].version) { 402*1b8adde7SWilliam Kucharski tpc->chipset = i; 403*1b8adde7SWilliam Kucharski goto match; 404*1b8adde7SWilliam Kucharski } 405*1b8adde7SWilliam Kucharski /* if unknown chip, assume array element #0, original RTL-8169 in this case */ 406*1b8adde7SWilliam Kucharski dprintf(("PCI device: unknown chip version, assuming RTL-8169\n")); 407*1b8adde7SWilliam Kucharski dprintf(("PCI device: TxConfig = 0x%hX\n", 408*1b8adde7SWilliam Kucharski (unsigned long) RTL_R32(TxConfig))); 409*1b8adde7SWilliam Kucharski tpc->chipset = 0; 410*1b8adde7SWilliam Kucharski return 1; 411*1b8adde7SWilliam Kucharski match: 412*1b8adde7SWilliam Kucharski return 0; 413*1b8adde7SWilliam Kucharski 414*1b8adde7SWilliam Kucharski } 415*1b8adde7SWilliam Kucharski 416*1b8adde7SWilliam Kucharski /************************************************************************** 417*1b8adde7SWilliam Kucharski IRQ - Wait for a frame 418*1b8adde7SWilliam Kucharski ***************************************************************************/ 419*1b8adde7SWilliam Kucharski void r8169_irq ( struct nic *nic __unused, irq_action_t action ) { 420*1b8adde7SWilliam Kucharski int intr_status = 0; 421*1b8adde7SWilliam Kucharski int interested = RxUnderrun | RxOverflow | RxFIFOOver | RxErr | RxOK; 422*1b8adde7SWilliam Kucharski 423*1b8adde7SWilliam Kucharski switch ( action ) { 424*1b8adde7SWilliam Kucharski case DISABLE: 425*1b8adde7SWilliam Kucharski case ENABLE: 426*1b8adde7SWilliam Kucharski intr_status = RTL_R16(IntrStatus); 427*1b8adde7SWilliam Kucharski /* h/w no longer present (hotplug?) or major error, 428*1b8adde7SWilliam Kucharski bail */ 429*1b8adde7SWilliam Kucharski if (intr_status == 0xFFFF) 430*1b8adde7SWilliam Kucharski break; 431*1b8adde7SWilliam Kucharski 432*1b8adde7SWilliam Kucharski intr_status = intr_status & ~interested; 433*1b8adde7SWilliam Kucharski if ( action == ENABLE ) 434*1b8adde7SWilliam Kucharski intr_status = intr_status | interested; 435*1b8adde7SWilliam Kucharski RTL_W16(IntrMask, intr_status); 436*1b8adde7SWilliam Kucharski break; 437*1b8adde7SWilliam Kucharski case FORCE : 438*1b8adde7SWilliam Kucharski RTL_W8(TxPoll, (RTL_R8(TxPoll) | 0x01)); 439*1b8adde7SWilliam Kucharski break; 440*1b8adde7SWilliam Kucharski } 441*1b8adde7SWilliam Kucharski } 442*1b8adde7SWilliam Kucharski 443*1b8adde7SWilliam Kucharski /************************************************************************** 444*1b8adde7SWilliam Kucharski POLL - Wait for a frame 445*1b8adde7SWilliam Kucharski ***************************************************************************/ 446*1b8adde7SWilliam Kucharski static int r8169_poll(struct nic *nic, int retreive) 447*1b8adde7SWilliam Kucharski { 448*1b8adde7SWilliam Kucharski /* return true if there's an ethernet packet ready to read */ 449*1b8adde7SWilliam Kucharski /* nic->packet should contain data on return */ 450*1b8adde7SWilliam Kucharski /* nic->packetlen should contain length of data */ 451*1b8adde7SWilliam Kucharski int cur_rx; 452*1b8adde7SWilliam Kucharski unsigned int intr_status = 0; 453*1b8adde7SWilliam Kucharski cur_rx = tpc->cur_rx; 454*1b8adde7SWilliam Kucharski if ((tpc->RxDescArray[cur_rx].status & OWNbit) == 0) { 455*1b8adde7SWilliam Kucharski /* There is a packet ready */ 456*1b8adde7SWilliam Kucharski if(!retreive) 457*1b8adde7SWilliam Kucharski return 1; 458*1b8adde7SWilliam Kucharski intr_status = RTL_R16(IntrStatus); 459*1b8adde7SWilliam Kucharski /* h/w no longer present (hotplug?) or major error, 460*1b8adde7SWilliam Kucharski bail */ 461*1b8adde7SWilliam Kucharski if (intr_status == 0xFFFF) 462*1b8adde7SWilliam Kucharski return 0; 463*1b8adde7SWilliam Kucharski RTL_W16(IntrStatus, intr_status & 464*1b8adde7SWilliam Kucharski ~(RxFIFOOver | RxOverflow | RxOK)); 465*1b8adde7SWilliam Kucharski 466*1b8adde7SWilliam Kucharski if (!(tpc->RxDescArray[cur_rx].status & RxRES)) { 467*1b8adde7SWilliam Kucharski nic->packetlen = (int) (tpc->RxDescArray[cur_rx]. 468*1b8adde7SWilliam Kucharski status & 0x00001FFF) - 4; 469*1b8adde7SWilliam Kucharski memcpy(nic->packet, tpc->RxBufferRing[cur_rx], 470*1b8adde7SWilliam Kucharski nic->packetlen); 471*1b8adde7SWilliam Kucharski if (cur_rx == NUM_RX_DESC - 1) 472*1b8adde7SWilliam Kucharski tpc->RxDescArray[cur_rx].status = 473*1b8adde7SWilliam Kucharski (OWNbit | EORbit) + RX_BUF_SIZE; 474*1b8adde7SWilliam Kucharski else 475*1b8adde7SWilliam Kucharski tpc->RxDescArray[cur_rx].status = 476*1b8adde7SWilliam Kucharski OWNbit + RX_BUF_SIZE; 477*1b8adde7SWilliam Kucharski tpc->RxDescArray[cur_rx].buf_addr = 478*1b8adde7SWilliam Kucharski virt_to_bus(tpc->RxBufferRing[cur_rx]); 479*1b8adde7SWilliam Kucharski } else 480*1b8adde7SWilliam Kucharski printf("Error Rx"); 481*1b8adde7SWilliam Kucharski /* FIXME: shouldn't I reset the status on an error */ 482*1b8adde7SWilliam Kucharski cur_rx = (cur_rx + 1) % NUM_RX_DESC; 483*1b8adde7SWilliam Kucharski tpc->cur_rx = cur_rx; 484*1b8adde7SWilliam Kucharski RTL_W16(IntrStatus, intr_status & 485*1b8adde7SWilliam Kucharski (RxFIFOOver | RxOverflow | RxOK)); 486*1b8adde7SWilliam Kucharski 487*1b8adde7SWilliam Kucharski return 1; 488*1b8adde7SWilliam Kucharski 489*1b8adde7SWilliam Kucharski } 490*1b8adde7SWilliam Kucharski tpc->cur_rx = cur_rx; 491*1b8adde7SWilliam Kucharski /* FIXME: There is no reason to do this as cur_rx did not change */ 492*1b8adde7SWilliam Kucharski 493*1b8adde7SWilliam Kucharski return (0); /* initially as this is called to flush the input */ 494*1b8adde7SWilliam Kucharski 495*1b8adde7SWilliam Kucharski } 496*1b8adde7SWilliam Kucharski 497*1b8adde7SWilliam Kucharski /************************************************************************** 498*1b8adde7SWilliam Kucharski TRANSMIT - Transmit a frame 499*1b8adde7SWilliam Kucharski ***************************************************************************/ 500*1b8adde7SWilliam Kucharski static void r8169_transmit(struct nic *nic, const char *d, /* Destination */ 501*1b8adde7SWilliam Kucharski unsigned int t, /* Type */ 502*1b8adde7SWilliam Kucharski unsigned int s, /* size */ 503*1b8adde7SWilliam Kucharski const char *p) 504*1b8adde7SWilliam Kucharski { /* Packet */ 505*1b8adde7SWilliam Kucharski /* send the packet to destination */ 506*1b8adde7SWilliam Kucharski 507*1b8adde7SWilliam Kucharski u16 nstype; 508*1b8adde7SWilliam Kucharski u32 to; 509*1b8adde7SWilliam Kucharski u8 *ptxb; 510*1b8adde7SWilliam Kucharski int entry = tpc->cur_tx % NUM_TX_DESC; 511*1b8adde7SWilliam Kucharski 512*1b8adde7SWilliam Kucharski /* point to the current txb incase multiple tx_rings are used */ 513*1b8adde7SWilliam Kucharski ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE]; 514*1b8adde7SWilliam Kucharski memcpy(ptxb, d, ETH_ALEN); 515*1b8adde7SWilliam Kucharski memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN); 516*1b8adde7SWilliam Kucharski nstype = htons((u16) t); 517*1b8adde7SWilliam Kucharski memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2); 518*1b8adde7SWilliam Kucharski memcpy(ptxb + ETH_HLEN, p, s); 519*1b8adde7SWilliam Kucharski s += ETH_HLEN; 520*1b8adde7SWilliam Kucharski s &= 0x0FFF; 521*1b8adde7SWilliam Kucharski while (s < ETH_ZLEN) 522*1b8adde7SWilliam Kucharski ptxb[s++] = '\0'; 523*1b8adde7SWilliam Kucharski 524*1b8adde7SWilliam Kucharski tpc->TxDescArray[entry].buf_addr = virt_to_bus(ptxb); 525*1b8adde7SWilliam Kucharski if (entry != (NUM_TX_DESC - 1)) 526*1b8adde7SWilliam Kucharski tpc->TxDescArray[entry].status = 527*1b8adde7SWilliam Kucharski (OWNbit | FSbit | LSbit) | ((s > ETH_ZLEN) ? s : 528*1b8adde7SWilliam Kucharski ETH_ZLEN); 529*1b8adde7SWilliam Kucharski else 530*1b8adde7SWilliam Kucharski tpc->TxDescArray[entry].status = 531*1b8adde7SWilliam Kucharski (OWNbit | EORbit | FSbit | LSbit) | ((s > ETH_ZLEN) ? s 532*1b8adde7SWilliam Kucharski : ETH_ZLEN); 533*1b8adde7SWilliam Kucharski RTL_W8(TxPoll, 0x40); /* set polling bit */ 534*1b8adde7SWilliam Kucharski 535*1b8adde7SWilliam Kucharski tpc->cur_tx++; 536*1b8adde7SWilliam Kucharski to = currticks() + TX_TIMEOUT; 537*1b8adde7SWilliam Kucharski while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */ 538*1b8adde7SWilliam Kucharski 539*1b8adde7SWilliam Kucharski if (currticks() >= to) { 540*1b8adde7SWilliam Kucharski printf("TX Time Out"); 541*1b8adde7SWilliam Kucharski } 542*1b8adde7SWilliam Kucharski } 543*1b8adde7SWilliam Kucharski 544*1b8adde7SWilliam Kucharski static void rtl8169_set_rx_mode(struct nic *nic __unused) 545*1b8adde7SWilliam Kucharski { 546*1b8adde7SWilliam Kucharski u32 mc_filter[2]; /* Multicast hash filter */ 547*1b8adde7SWilliam Kucharski int rx_mode; 548*1b8adde7SWilliam Kucharski u32 tmp = 0; 549*1b8adde7SWilliam Kucharski 550*1b8adde7SWilliam Kucharski /* IFF_ALLMULTI */ 551*1b8adde7SWilliam Kucharski /* Too many to filter perfectly -- accept all multicasts. */ 552*1b8adde7SWilliam Kucharski rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; 553*1b8adde7SWilliam Kucharski mc_filter[1] = mc_filter[0] = 0xffffffff; 554*1b8adde7SWilliam Kucharski 555*1b8adde7SWilliam Kucharski tmp = 556*1b8adde7SWilliam Kucharski rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) & 557*1b8adde7SWilliam Kucharski rtl_chip_info[tpc->chipset]. 558*1b8adde7SWilliam Kucharski RxConfigMask); 559*1b8adde7SWilliam Kucharski 560*1b8adde7SWilliam Kucharski RTL_W32(RxConfig, tmp); 561*1b8adde7SWilliam Kucharski RTL_W32(MAR0 + 0, mc_filter[0]); 562*1b8adde7SWilliam Kucharski RTL_W32(MAR0 + 4, mc_filter[1]); 563*1b8adde7SWilliam Kucharski } 564*1b8adde7SWilliam Kucharski static void rtl8169_hw_start(struct nic *nic) 565*1b8adde7SWilliam Kucharski { 566*1b8adde7SWilliam Kucharski u32 i; 567*1b8adde7SWilliam Kucharski 568*1b8adde7SWilliam Kucharski /* Soft reset the chip. */ 569*1b8adde7SWilliam Kucharski RTL_W8(ChipCmd, CmdReset); 570*1b8adde7SWilliam Kucharski 571*1b8adde7SWilliam Kucharski /* Check that the chip has finished the reset. */ 572*1b8adde7SWilliam Kucharski for (i = 1000; i > 0; i--) { 573*1b8adde7SWilliam Kucharski if ((RTL_R8(ChipCmd) & CmdReset) == 0) 574*1b8adde7SWilliam Kucharski break; 575*1b8adde7SWilliam Kucharski else 576*1b8adde7SWilliam Kucharski udelay(10); 577*1b8adde7SWilliam Kucharski } 578*1b8adde7SWilliam Kucharski 579*1b8adde7SWilliam Kucharski RTL_W8(Cfg9346, Cfg9346_Unlock); 580*1b8adde7SWilliam Kucharski RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); 581*1b8adde7SWilliam Kucharski RTL_W8(EarlyTxThres, EarlyTxThld); 582*1b8adde7SWilliam Kucharski 583*1b8adde7SWilliam Kucharski /* For gigabit rtl8169 */ 584*1b8adde7SWilliam Kucharski RTL_W16(RxMaxSize, RxPacketMaxSize); 585*1b8adde7SWilliam Kucharski 586*1b8adde7SWilliam Kucharski /* Set Rx Config register */ 587*1b8adde7SWilliam Kucharski i = rtl8169_rx_config | (RTL_R32(RxConfig) & 588*1b8adde7SWilliam Kucharski rtl_chip_info[tpc->chipset].RxConfigMask); 589*1b8adde7SWilliam Kucharski RTL_W32(RxConfig, i); 590*1b8adde7SWilliam Kucharski 591*1b8adde7SWilliam Kucharski /* Set DMA burst size and Interframe Gap Time */ 592*1b8adde7SWilliam Kucharski RTL_W32(TxConfig, 593*1b8adde7SWilliam Kucharski (TX_DMA_BURST << TxDMAShift) | (InterFrameGap << 594*1b8adde7SWilliam Kucharski TxInterFrameGapShift)); 595*1b8adde7SWilliam Kucharski 596*1b8adde7SWilliam Kucharski 597*1b8adde7SWilliam Kucharski tpc->cur_rx = 0; 598*1b8adde7SWilliam Kucharski 599*1b8adde7SWilliam Kucharski RTL_W32(TxDescStartAddr, virt_to_le32desc(tpc->TxDescArray)); 600*1b8adde7SWilliam Kucharski RTL_W32(RxDescStartAddr, virt_to_le32desc(tpc->RxDescArray)); 601*1b8adde7SWilliam Kucharski RTL_W8(Cfg9346, Cfg9346_Lock); 602*1b8adde7SWilliam Kucharski udelay(10); 603*1b8adde7SWilliam Kucharski 604*1b8adde7SWilliam Kucharski RTL_W32(RxMissed, 0); 605*1b8adde7SWilliam Kucharski 606*1b8adde7SWilliam Kucharski rtl8169_set_rx_mode(nic); 607*1b8adde7SWilliam Kucharski 608*1b8adde7SWilliam Kucharski /* no early-rx interrupts */ 609*1b8adde7SWilliam Kucharski RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); 610*1b8adde7SWilliam Kucharski } 611*1b8adde7SWilliam Kucharski 612*1b8adde7SWilliam Kucharski static void rtl8169_init_ring(struct nic *nic __unused) 613*1b8adde7SWilliam Kucharski { 614*1b8adde7SWilliam Kucharski int i; 615*1b8adde7SWilliam Kucharski 616*1b8adde7SWilliam Kucharski tpc->cur_rx = 0; 617*1b8adde7SWilliam Kucharski tpc->cur_tx = 0; 618*1b8adde7SWilliam Kucharski memset(tpc->TxDescArray, 0x0, NUM_TX_DESC * sizeof(struct TxDesc)); 619*1b8adde7SWilliam Kucharski memset(tpc->RxDescArray, 0x0, NUM_RX_DESC * sizeof(struct RxDesc)); 620*1b8adde7SWilliam Kucharski 621*1b8adde7SWilliam Kucharski for (i = 0; i < NUM_TX_DESC; i++) { 622*1b8adde7SWilliam Kucharski tpc->Tx_skbuff[i] = &txb[i]; 623*1b8adde7SWilliam Kucharski } 624*1b8adde7SWilliam Kucharski 625*1b8adde7SWilliam Kucharski for (i = 0; i < NUM_RX_DESC; i++) { 626*1b8adde7SWilliam Kucharski if (i == (NUM_RX_DESC - 1)) 627*1b8adde7SWilliam Kucharski tpc->RxDescArray[i].status = 628*1b8adde7SWilliam Kucharski (OWNbit | EORbit) + RX_BUF_SIZE; 629*1b8adde7SWilliam Kucharski else 630*1b8adde7SWilliam Kucharski tpc->RxDescArray[i].status = OWNbit + RX_BUF_SIZE; 631*1b8adde7SWilliam Kucharski 632*1b8adde7SWilliam Kucharski tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; 633*1b8adde7SWilliam Kucharski tpc->RxDescArray[i].buf_addr = 634*1b8adde7SWilliam Kucharski virt_to_bus(tpc->RxBufferRing[i]); 635*1b8adde7SWilliam Kucharski } 636*1b8adde7SWilliam Kucharski } 637*1b8adde7SWilliam Kucharski 638*1b8adde7SWilliam Kucharski /************************************************************************** 639*1b8adde7SWilliam Kucharski RESET - Finish setting up the ethernet interface 640*1b8adde7SWilliam Kucharski ***************************************************************************/ 641*1b8adde7SWilliam Kucharski static void r8169_reset(struct nic *nic) 642*1b8adde7SWilliam Kucharski { 643*1b8adde7SWilliam Kucharski int i; 644*1b8adde7SWilliam Kucharski u8 diff; 645*1b8adde7SWilliam Kucharski u32 TxPhyAddr, RxPhyAddr; 646*1b8adde7SWilliam Kucharski 647*1b8adde7SWilliam Kucharski tpc->TxDescArrays = tx_ring; 648*1b8adde7SWilliam Kucharski if (tpc->TxDescArrays == 0) 649*1b8adde7SWilliam Kucharski printf("Allot Error"); 650*1b8adde7SWilliam Kucharski /* Tx Desscriptor needs 256 bytes alignment; */ 651*1b8adde7SWilliam Kucharski TxPhyAddr = virt_to_bus(tpc->TxDescArrays); 652*1b8adde7SWilliam Kucharski diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8)); 653*1b8adde7SWilliam Kucharski TxPhyAddr += diff; 654*1b8adde7SWilliam Kucharski tpc->TxDescArray = (struct TxDesc *) (tpc->TxDescArrays + diff); 655*1b8adde7SWilliam Kucharski 656*1b8adde7SWilliam Kucharski tpc->RxDescArrays = rx_ring; 657*1b8adde7SWilliam Kucharski /* Rx Desscriptor needs 256 bytes alignment; */ 658*1b8adde7SWilliam Kucharski RxPhyAddr = virt_to_bus(tpc->RxDescArrays); 659*1b8adde7SWilliam Kucharski diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8)); 660*1b8adde7SWilliam Kucharski RxPhyAddr += diff; 661*1b8adde7SWilliam Kucharski tpc->RxDescArray = (struct RxDesc *) (tpc->RxDescArrays + diff); 662*1b8adde7SWilliam Kucharski 663*1b8adde7SWilliam Kucharski if (tpc->TxDescArrays == NULL || tpc->RxDescArrays == NULL) { 664*1b8adde7SWilliam Kucharski printf("Allocate RxDescArray or TxDescArray failed\n"); 665*1b8adde7SWilliam Kucharski return; 666*1b8adde7SWilliam Kucharski } 667*1b8adde7SWilliam Kucharski 668*1b8adde7SWilliam Kucharski rtl8169_init_ring(nic); 669*1b8adde7SWilliam Kucharski rtl8169_hw_start(nic); 670*1b8adde7SWilliam Kucharski /* Construct a perfect filter frame with the mac address as first match 671*1b8adde7SWilliam Kucharski * and broadcast for all others */ 672*1b8adde7SWilliam Kucharski for (i = 0; i < 192; i++) 673*1b8adde7SWilliam Kucharski txb[i] = 0xFF; 674*1b8adde7SWilliam Kucharski 675*1b8adde7SWilliam Kucharski txb[0] = nic->node_addr[0]; 676*1b8adde7SWilliam Kucharski txb[1] = nic->node_addr[1]; 677*1b8adde7SWilliam Kucharski txb[2] = nic->node_addr[2]; 678*1b8adde7SWilliam Kucharski txb[3] = nic->node_addr[3]; 679*1b8adde7SWilliam Kucharski txb[4] = nic->node_addr[4]; 680*1b8adde7SWilliam Kucharski txb[5] = nic->node_addr[5]; 681*1b8adde7SWilliam Kucharski } 682*1b8adde7SWilliam Kucharski 683*1b8adde7SWilliam Kucharski /************************************************************************** 684*1b8adde7SWilliam Kucharski DISABLE - Turn off ethernet interface 685*1b8adde7SWilliam Kucharski ***************************************************************************/ 686*1b8adde7SWilliam Kucharski static void r8169_disable(struct dev *dev __unused) 687*1b8adde7SWilliam Kucharski { 688*1b8adde7SWilliam Kucharski int i; 689*1b8adde7SWilliam Kucharski /* Stop the chip's Tx and Rx DMA processes. */ 690*1b8adde7SWilliam Kucharski RTL_W8(ChipCmd, 0x00); 691*1b8adde7SWilliam Kucharski 692*1b8adde7SWilliam Kucharski /* Disable interrupts by clearing the interrupt mask. */ 693*1b8adde7SWilliam Kucharski RTL_W16(IntrMask, 0x0000); 694*1b8adde7SWilliam Kucharski 695*1b8adde7SWilliam Kucharski RTL_W32(RxMissed, 0); 696*1b8adde7SWilliam Kucharski 697*1b8adde7SWilliam Kucharski tpc->TxDescArrays = NULL; 698*1b8adde7SWilliam Kucharski tpc->RxDescArrays = NULL; 699*1b8adde7SWilliam Kucharski tpc->TxDescArray = NULL; 700*1b8adde7SWilliam Kucharski tpc->RxDescArray = NULL; 701*1b8adde7SWilliam Kucharski for (i = 0; i < NUM_RX_DESC; i++) { 702*1b8adde7SWilliam Kucharski tpc->RxBufferRing[i] = NULL; 703*1b8adde7SWilliam Kucharski } 704*1b8adde7SWilliam Kucharski } 705*1b8adde7SWilliam Kucharski 706*1b8adde7SWilliam Kucharski /************************************************************************** 707*1b8adde7SWilliam Kucharski PROBE - Look for an adapter, this routine's visible to the outside 708*1b8adde7SWilliam Kucharski ***************************************************************************/ 709*1b8adde7SWilliam Kucharski 710*1b8adde7SWilliam Kucharski #define board_found 1 711*1b8adde7SWilliam Kucharski #define valid_link 0 712*1b8adde7SWilliam Kucharski static int r8169_probe(struct dev *dev, struct pci_device *pci) 713*1b8adde7SWilliam Kucharski { 714*1b8adde7SWilliam Kucharski struct nic *nic = (struct nic *) dev; 715*1b8adde7SWilliam Kucharski static int board_idx = -1; 716*1b8adde7SWilliam Kucharski static int printed_version = 0; 717*1b8adde7SWilliam Kucharski int i, rc; 718*1b8adde7SWilliam Kucharski int option = -1, Cap10_100 = 0, Cap1000 = 0; 719*1b8adde7SWilliam Kucharski 720*1b8adde7SWilliam Kucharski printf("r8169.c: Found %s, Vendor=%hX Device=%hX\n", 721*1b8adde7SWilliam Kucharski pci->name, pci->vendor, pci->dev_id); 722*1b8adde7SWilliam Kucharski 723*1b8adde7SWilliam Kucharski board_idx++; 724*1b8adde7SWilliam Kucharski 725*1b8adde7SWilliam Kucharski printed_version = 1; 726*1b8adde7SWilliam Kucharski 727*1b8adde7SWilliam Kucharski /* point to private storage */ 728*1b8adde7SWilliam Kucharski tpc = &tpx; 729*1b8adde7SWilliam Kucharski 730*1b8adde7SWilliam Kucharski rc = rtl8169_init_board(pci); /* Return code is meaningless */ 731*1b8adde7SWilliam Kucharski 732*1b8adde7SWilliam Kucharski /* Get MAC address. FIXME: read EEPROM */ 733*1b8adde7SWilliam Kucharski for (i = 0; i < MAC_ADDR_LEN; i++) 734*1b8adde7SWilliam Kucharski nic->node_addr[i] = RTL_R8(MAC0 + i); 735*1b8adde7SWilliam Kucharski 736*1b8adde7SWilliam Kucharski dprintf(("%s: Identified chip type is '%s'.\n", pci->name, 737*1b8adde7SWilliam Kucharski rtl_chip_info[tpc->chipset].name)); 738*1b8adde7SWilliam Kucharski /* Print out some hardware info */ 739*1b8adde7SWilliam Kucharski printf("%s: %! at ioaddr %hX, ", pci->name, nic->node_addr, 740*1b8adde7SWilliam Kucharski ioaddr); 741*1b8adde7SWilliam Kucharski 742*1b8adde7SWilliam Kucharski /* if TBI is not endbled */ 743*1b8adde7SWilliam Kucharski if (!(RTL_R8(PHYstatus) & TBI_Enable)) { 744*1b8adde7SWilliam Kucharski int val = mdio_read(PHY_AUTO_NEGO_REG); 745*1b8adde7SWilliam Kucharski 746*1b8adde7SWilliam Kucharski option = media; 747*1b8adde7SWilliam Kucharski /* Force RTL8169 in 10/100/1000 Full/Half mode. */ 748*1b8adde7SWilliam Kucharski if (option > 0) { 749*1b8adde7SWilliam Kucharski printf(" Force-mode Enabled.\n"); 750*1b8adde7SWilliam Kucharski Cap10_100 = 0, Cap1000 = 0; 751*1b8adde7SWilliam Kucharski switch (option) { 752*1b8adde7SWilliam Kucharski case _10_Half: 753*1b8adde7SWilliam Kucharski Cap10_100 = PHY_Cap_10_Half; 754*1b8adde7SWilliam Kucharski Cap1000 = PHY_Cap_Null; 755*1b8adde7SWilliam Kucharski break; 756*1b8adde7SWilliam Kucharski case _10_Full: 757*1b8adde7SWilliam Kucharski Cap10_100 = PHY_Cap_10_Full; 758*1b8adde7SWilliam Kucharski Cap1000 = PHY_Cap_Null; 759*1b8adde7SWilliam Kucharski break; 760*1b8adde7SWilliam Kucharski case _100_Half: 761*1b8adde7SWilliam Kucharski Cap10_100 = PHY_Cap_100_Half; 762*1b8adde7SWilliam Kucharski Cap1000 = PHY_Cap_Null; 763*1b8adde7SWilliam Kucharski break; 764*1b8adde7SWilliam Kucharski case _100_Full: 765*1b8adde7SWilliam Kucharski Cap10_100 = PHY_Cap_100_Full; 766*1b8adde7SWilliam Kucharski Cap1000 = PHY_Cap_Null; 767*1b8adde7SWilliam Kucharski break; 768*1b8adde7SWilliam Kucharski case _1000_Full: 769*1b8adde7SWilliam Kucharski Cap10_100 = PHY_Cap_Null; 770*1b8adde7SWilliam Kucharski Cap1000 = PHY_Cap_1000_Full; 771*1b8adde7SWilliam Kucharski break; 772*1b8adde7SWilliam Kucharski default: 773*1b8adde7SWilliam Kucharski break; 774*1b8adde7SWilliam Kucharski } 775*1b8adde7SWilliam Kucharski /* leave PHY_AUTO_NEGO_REG bit4:0 unchanged */ 776*1b8adde7SWilliam Kucharski mdio_write(PHY_AUTO_NEGO_REG, 777*1b8adde7SWilliam Kucharski Cap10_100 | (val & 0x1F)); 778*1b8adde7SWilliam Kucharski mdio_write(PHY_1000_CTRL_REG, Cap1000); 779*1b8adde7SWilliam Kucharski } else { 780*1b8adde7SWilliam Kucharski dprintf(("Auto-negotiation Enabled.\n", 781*1b8adde7SWilliam Kucharski pci->name)); 782*1b8adde7SWilliam Kucharski 783*1b8adde7SWilliam Kucharski /* enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged */ 784*1b8adde7SWilliam Kucharski mdio_write(PHY_AUTO_NEGO_REG, 785*1b8adde7SWilliam Kucharski PHY_Cap_10_Half | PHY_Cap_10_Full | 786*1b8adde7SWilliam Kucharski PHY_Cap_100_Half | PHY_Cap_100_Full | 787*1b8adde7SWilliam Kucharski (val & 0x1F)); 788*1b8adde7SWilliam Kucharski 789*1b8adde7SWilliam Kucharski /* enable 1000 Full Mode */ 790*1b8adde7SWilliam Kucharski mdio_write(PHY_1000_CTRL_REG, PHY_Cap_1000_Full); 791*1b8adde7SWilliam Kucharski 792*1b8adde7SWilliam Kucharski } 793*1b8adde7SWilliam Kucharski 794*1b8adde7SWilliam Kucharski /* Enable auto-negotiation and restart auto-nigotiation */ 795*1b8adde7SWilliam Kucharski mdio_write(PHY_CTRL_REG, 796*1b8adde7SWilliam Kucharski PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); 797*1b8adde7SWilliam Kucharski udelay(100); 798*1b8adde7SWilliam Kucharski 799*1b8adde7SWilliam Kucharski /* wait for auto-negotiation process */ 800*1b8adde7SWilliam Kucharski for (i = 10000; i > 0; i--) { 801*1b8adde7SWilliam Kucharski /* Check if auto-negotiation complete */ 802*1b8adde7SWilliam Kucharski if (mdio_read(PHY_STAT_REG) & PHY_Auto_Neco_Comp) { 803*1b8adde7SWilliam Kucharski udelay(100); 804*1b8adde7SWilliam Kucharski option = RTL_R8(PHYstatus); 805*1b8adde7SWilliam Kucharski if (option & _1000bpsF) { 806*1b8adde7SWilliam Kucharski printf 807*1b8adde7SWilliam Kucharski ("1000Mbps Full-duplex operation.\n"); 808*1b8adde7SWilliam Kucharski } else { 809*1b8adde7SWilliam Kucharski printf 810*1b8adde7SWilliam Kucharski ("%sMbps %s-duplex operation.\n", 811*1b8adde7SWilliam Kucharski (option & _100bps) ? "100" : 812*1b8adde7SWilliam Kucharski "10", 813*1b8adde7SWilliam Kucharski (option & FullDup) ? "Full" : 814*1b8adde7SWilliam Kucharski "Half"); 815*1b8adde7SWilliam Kucharski } 816*1b8adde7SWilliam Kucharski break; 817*1b8adde7SWilliam Kucharski } else { 818*1b8adde7SWilliam Kucharski udelay(100); 819*1b8adde7SWilliam Kucharski } 820*1b8adde7SWilliam Kucharski } /* end for-loop to wait for auto-negotiation process */ 821*1b8adde7SWilliam Kucharski 822*1b8adde7SWilliam Kucharski } else { 823*1b8adde7SWilliam Kucharski udelay(100); 824*1b8adde7SWilliam Kucharski printf 825*1b8adde7SWilliam Kucharski ("%s: 1000Mbps Full-duplex operation, TBI Link %s!\n", 826*1b8adde7SWilliam Kucharski pci->name, 827*1b8adde7SWilliam Kucharski (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed"); 828*1b8adde7SWilliam Kucharski 829*1b8adde7SWilliam Kucharski } 830*1b8adde7SWilliam Kucharski 831*1b8adde7SWilliam Kucharski r8169_reset(nic); 832*1b8adde7SWilliam Kucharski /* point to NIC specific routines */ 833*1b8adde7SWilliam Kucharski dev->disable = r8169_disable; 834*1b8adde7SWilliam Kucharski nic->poll = r8169_poll; 835*1b8adde7SWilliam Kucharski nic->transmit = r8169_transmit; 836*1b8adde7SWilliam Kucharski nic->irqno = pci->irq; 837*1b8adde7SWilliam Kucharski nic->irq = r8169_irq; 838*1b8adde7SWilliam Kucharski nic->ioaddr = ioaddr; 839*1b8adde7SWilliam Kucharski return 1; 840*1b8adde7SWilliam Kucharski 841*1b8adde7SWilliam Kucharski } 842*1b8adde7SWilliam Kucharski 843*1b8adde7SWilliam Kucharski static struct pci_id r8169_nics[] = { 844*1b8adde7SWilliam Kucharski PCI_ROM(0x10ec, 0x8169, "r8169", "RealTek RTL8169 Gigabit Ethernet"), 845*1b8adde7SWilliam Kucharski }; 846*1b8adde7SWilliam Kucharski 847*1b8adde7SWilliam Kucharski struct pci_driver r8169_driver = { 848*1b8adde7SWilliam Kucharski .type = NIC_DRIVER, 849*1b8adde7SWilliam Kucharski .name = "r8169/PCI", 850*1b8adde7SWilliam Kucharski .probe = r8169_probe, 851*1b8adde7SWilliam Kucharski .ids = r8169_nics, 852*1b8adde7SWilliam Kucharski .id_count = sizeof(r8169_nics) / sizeof(r8169_nics[0]), 853*1b8adde7SWilliam Kucharski .class = 0, 854*1b8adde7SWilliam Kucharski }; 855