1*1b8adde7SWilliam Kucharski /************************************************************************** 2*1b8adde7SWilliam Kucharski * ns83820.c: Etherboot device driver for the National Semiconductor 83820 3*1b8adde7SWilliam Kucharski * Written 2004 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 * ns83820.c by Benjamin LaHaise with contributions 21*1b8adde7SWilliam Kucharski * for Linux kernel 2.4.x. 22*1b8adde7SWilliam Kucharski * 23*1b8adde7SWilliam Kucharski * Linux Driver Version 0.20, 20020610 24*1b8adde7SWilliam Kucharski * 25*1b8adde7SWilliam Kucharski * This development of this Etherboot driver was funded by: 26*1b8adde7SWilliam Kucharski * 27*1b8adde7SWilliam Kucharski * NXTV: http://www.nxtv.com/ 28*1b8adde7SWilliam Kucharski * 29*1b8adde7SWilliam Kucharski * REVISION HISTORY: 30*1b8adde7SWilliam Kucharski * ================ 31*1b8adde7SWilliam Kucharski * 32*1b8adde7SWilliam Kucharski * v1.0 02-16-2004 timlegge Initial port of Linux driver 33*1b8adde7SWilliam Kucharski * v1.1 02-19-2004 timlegge More rohbust transmit and poll 34*1b8adde7SWilliam Kucharski * 35*1b8adde7SWilliam Kucharski * Indent Options: indent -kr -i8 36*1b8adde7SWilliam Kucharski ***************************************************************************/ 37*1b8adde7SWilliam Kucharski 38*1b8adde7SWilliam Kucharski /* to get some global routines like printf */ 39*1b8adde7SWilliam Kucharski #include "etherboot.h" 40*1b8adde7SWilliam Kucharski /* to get the interface to the body of the program */ 41*1b8adde7SWilliam Kucharski #include "nic.h" 42*1b8adde7SWilliam Kucharski /* to get the PCI support functions, if this is a PCI NIC */ 43*1b8adde7SWilliam Kucharski #include "pci.h" 44*1b8adde7SWilliam Kucharski 45*1b8adde7SWilliam Kucharski #if ARCH == ia64 /* Support 64-bit addressing */ 46*1b8adde7SWilliam Kucharski #define USE_64BIT_ADDR 47*1b8adde7SWilliam Kucharski #endif 48*1b8adde7SWilliam Kucharski 49*1b8adde7SWilliam Kucharski //#define DDEBUG 50*1b8adde7SWilliam Kucharski #ifdef DDEBUG 51*1b8adde7SWilliam Kucharski #define dprintf(x) printf x 52*1b8adde7SWilliam Kucharski #else 53*1b8adde7SWilliam Kucharski #define dprintf(x) 54*1b8adde7SWilliam Kucharski #endif 55*1b8adde7SWilliam Kucharski 56*1b8adde7SWilliam Kucharski typedef unsigned char u8; 57*1b8adde7SWilliam Kucharski typedef signed char s8; 58*1b8adde7SWilliam Kucharski typedef unsigned short u16; 59*1b8adde7SWilliam Kucharski typedef signed short s16; 60*1b8adde7SWilliam Kucharski typedef unsigned int u32; 61*1b8adde7SWilliam Kucharski typedef signed int s32; 62*1b8adde7SWilliam Kucharski 63*1b8adde7SWilliam Kucharski #define HZ 100 64*1b8adde7SWilliam Kucharski 65*1b8adde7SWilliam Kucharski /* Condensed operations for readability. */ 66*1b8adde7SWilliam Kucharski #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) 67*1b8adde7SWilliam Kucharski #define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) 68*1b8adde7SWilliam Kucharski 69*1b8adde7SWilliam Kucharski /* NIC specific static variables go here */ 70*1b8adde7SWilliam Kucharski 71*1b8adde7SWilliam Kucharski /* Global parameters. See MODULE_PARM near the bottom. */ 72*1b8adde7SWilliam Kucharski // static int ihr = 2; 73*1b8adde7SWilliam Kucharski static int reset_phy = 0; 74*1b8adde7SWilliam Kucharski static int lnksts = 0; /* CFG_LNKSTS bit polarity */ 75*1b8adde7SWilliam Kucharski 76*1b8adde7SWilliam Kucharski #if defined(CONFIG_HIGHMEM64G) || defined(__ia64__) 77*1b8adde7SWilliam Kucharski #define USE_64BIT_ADDR "+" 78*1b8adde7SWilliam Kucharski #endif 79*1b8adde7SWilliam Kucharski 80*1b8adde7SWilliam Kucharski #if defined(USE_64BIT_ADDR) 81*1b8adde7SWilliam Kucharski #define TRY_DAC 1 82*1b8adde7SWilliam Kucharski #else 83*1b8adde7SWilliam Kucharski #define TRY_DAC 0 84*1b8adde7SWilliam Kucharski #endif 85*1b8adde7SWilliam Kucharski 86*1b8adde7SWilliam Kucharski /* tunables */ 87*1b8adde7SWilliam Kucharski #define RX_BUF_SIZE 1500 /* 8192 */ 88*1b8adde7SWilliam Kucharski 89*1b8adde7SWilliam Kucharski /* Must not exceed ~65000. */ 90*1b8adde7SWilliam Kucharski #define NR_RX_DESC 64 91*1b8adde7SWilliam Kucharski #define NR_TX_DESC 1 92*1b8adde7SWilliam Kucharski 93*1b8adde7SWilliam Kucharski /* not tunable *//* Extra 6 bytes for 64 bit alignment (divisable by 8) */ 94*1b8adde7SWilliam Kucharski #define REAL_RX_BUF_SIZE (RX_BUF_SIZE + 14 + 6) /* rx/tx mac addr + type */ 95*1b8adde7SWilliam Kucharski 96*1b8adde7SWilliam Kucharski #define MIN_TX_DESC_FREE 8 97*1b8adde7SWilliam Kucharski 98*1b8adde7SWilliam Kucharski /* register defines */ 99*1b8adde7SWilliam Kucharski #define CFGCS 0x04 100*1b8adde7SWilliam Kucharski 101*1b8adde7SWilliam Kucharski #define CR_TXE 0x00000001 102*1b8adde7SWilliam Kucharski #define CR_TXD 0x00000002 103*1b8adde7SWilliam Kucharski /* Ramit : Here's a tip, don't do a RXD immediately followed by an RXE 104*1b8adde7SWilliam Kucharski * The Receive engine skips one descriptor and moves 105*1b8adde7SWilliam Kucharski * onto the next one!! */ 106*1b8adde7SWilliam Kucharski #define CR_RXE 0x00000004 107*1b8adde7SWilliam Kucharski #define CR_RXD 0x00000008 108*1b8adde7SWilliam Kucharski #define CR_TXR 0x00000010 109*1b8adde7SWilliam Kucharski #define CR_RXR 0x00000020 110*1b8adde7SWilliam Kucharski #define CR_SWI 0x00000080 111*1b8adde7SWilliam Kucharski #define CR_RST 0x00000100 112*1b8adde7SWilliam Kucharski 113*1b8adde7SWilliam Kucharski #define PTSCR_EEBIST_FAIL 0x00000001 114*1b8adde7SWilliam Kucharski #define PTSCR_EEBIST_EN 0x00000002 115*1b8adde7SWilliam Kucharski #define PTSCR_EELOAD_EN 0x00000004 116*1b8adde7SWilliam Kucharski #define PTSCR_RBIST_FAIL 0x000001b8 117*1b8adde7SWilliam Kucharski #define PTSCR_RBIST_DONE 0x00000200 118*1b8adde7SWilliam Kucharski #define PTSCR_RBIST_EN 0x00000400 119*1b8adde7SWilliam Kucharski #define PTSCR_RBIST_RST 0x00002000 120*1b8adde7SWilliam Kucharski 121*1b8adde7SWilliam Kucharski #define MEAR_EEDI 0x00000001 122*1b8adde7SWilliam Kucharski #define MEAR_EEDO 0x00000002 123*1b8adde7SWilliam Kucharski #define MEAR_EECLK 0x00000004 124*1b8adde7SWilliam Kucharski #define MEAR_EESEL 0x00000008 125*1b8adde7SWilliam Kucharski #define MEAR_MDIO 0x00000010 126*1b8adde7SWilliam Kucharski #define MEAR_MDDIR 0x00000020 127*1b8adde7SWilliam Kucharski #define MEAR_MDC 0x00000040 128*1b8adde7SWilliam Kucharski 129*1b8adde7SWilliam Kucharski #define ISR_TXDESC3 0x40000000 130*1b8adde7SWilliam Kucharski #define ISR_TXDESC2 0x20000000 131*1b8adde7SWilliam Kucharski #define ISR_TXDESC1 0x10000000 132*1b8adde7SWilliam Kucharski #define ISR_TXDESC0 0x08000000 133*1b8adde7SWilliam Kucharski #define ISR_RXDESC3 0x04000000 134*1b8adde7SWilliam Kucharski #define ISR_RXDESC2 0x02000000 135*1b8adde7SWilliam Kucharski #define ISR_RXDESC1 0x01000000 136*1b8adde7SWilliam Kucharski #define ISR_RXDESC0 0x00800000 137*1b8adde7SWilliam Kucharski #define ISR_TXRCMP 0x00400000 138*1b8adde7SWilliam Kucharski #define ISR_RXRCMP 0x00200000 139*1b8adde7SWilliam Kucharski #define ISR_DPERR 0x00100000 140*1b8adde7SWilliam Kucharski #define ISR_SSERR 0x00080000 141*1b8adde7SWilliam Kucharski #define ISR_RMABT 0x00040000 142*1b8adde7SWilliam Kucharski #define ISR_RTABT 0x00020000 143*1b8adde7SWilliam Kucharski #define ISR_RXSOVR 0x00010000 144*1b8adde7SWilliam Kucharski #define ISR_HIBINT 0x00008000 145*1b8adde7SWilliam Kucharski #define ISR_PHY 0x00004000 146*1b8adde7SWilliam Kucharski #define ISR_PME 0x00002000 147*1b8adde7SWilliam Kucharski #define ISR_SWI 0x00001000 148*1b8adde7SWilliam Kucharski #define ISR_MIB 0x00000800 149*1b8adde7SWilliam Kucharski #define ISR_TXURN 0x00000400 150*1b8adde7SWilliam Kucharski #define ISR_TXIDLE 0x00000200 151*1b8adde7SWilliam Kucharski #define ISR_TXERR 0x00000100 152*1b8adde7SWilliam Kucharski #define ISR_TXDESC 0x00000080 153*1b8adde7SWilliam Kucharski #define ISR_TXOK 0x00000040 154*1b8adde7SWilliam Kucharski #define ISR_RXORN 0x00000020 155*1b8adde7SWilliam Kucharski #define ISR_RXIDLE 0x00000010 156*1b8adde7SWilliam Kucharski #define ISR_RXEARLY 0x00000008 157*1b8adde7SWilliam Kucharski #define ISR_RXERR 0x00000004 158*1b8adde7SWilliam Kucharski #define ISR_RXDESC 0x00000002 159*1b8adde7SWilliam Kucharski #define ISR_RXOK 0x00000001 160*1b8adde7SWilliam Kucharski 161*1b8adde7SWilliam Kucharski #define TXCFG_CSI 0x80000000 162*1b8adde7SWilliam Kucharski #define TXCFG_HBI 0x40000000 163*1b8adde7SWilliam Kucharski #define TXCFG_MLB 0x20000000 164*1b8adde7SWilliam Kucharski #define TXCFG_ATP 0x10000000 165*1b8adde7SWilliam Kucharski #define TXCFG_ECRETRY 0x00800000 166*1b8adde7SWilliam Kucharski #define TXCFG_BRST_DIS 0x00080000 167*1b8adde7SWilliam Kucharski #define TXCFG_MXDMA1024 0x00000000 168*1b8adde7SWilliam Kucharski #define TXCFG_MXDMA512 0x00700000 169*1b8adde7SWilliam Kucharski #define TXCFG_MXDMA256 0x00600000 170*1b8adde7SWilliam Kucharski #define TXCFG_MXDMA128 0x00500000 171*1b8adde7SWilliam Kucharski #define TXCFG_MXDMA64 0x00400000 172*1b8adde7SWilliam Kucharski #define TXCFG_MXDMA32 0x00300000 173*1b8adde7SWilliam Kucharski #define TXCFG_MXDMA16 0x00200000 174*1b8adde7SWilliam Kucharski #define TXCFG_MXDMA8 0x00100000 175*1b8adde7SWilliam Kucharski 176*1b8adde7SWilliam Kucharski #define CFG_LNKSTS 0x80000000 177*1b8adde7SWilliam Kucharski #define CFG_SPDSTS 0x60000000 178*1b8adde7SWilliam Kucharski #define CFG_SPDSTS1 0x40000000 179*1b8adde7SWilliam Kucharski #define CFG_SPDSTS0 0x20000000 180*1b8adde7SWilliam Kucharski #define CFG_DUPSTS 0x10000000 181*1b8adde7SWilliam Kucharski #define CFG_TBI_EN 0x01000000 182*1b8adde7SWilliam Kucharski #define CFG_MODE_1000 0x00400000 183*1b8adde7SWilliam Kucharski /* Ramit : Dont' ever use AUTO_1000, it never works and is buggy. 184*1b8adde7SWilliam Kucharski * Read the Phy response and then configure the MAC accordingly */ 185*1b8adde7SWilliam Kucharski #define CFG_AUTO_1000 0x00200000 186*1b8adde7SWilliam Kucharski #define CFG_PINT_CTL 0x001c0000 187*1b8adde7SWilliam Kucharski #define CFG_PINT_DUPSTS 0x00100000 188*1b8adde7SWilliam Kucharski #define CFG_PINT_LNKSTS 0x00080000 189*1b8adde7SWilliam Kucharski #define CFG_PINT_SPDSTS 0x00040000 190*1b8adde7SWilliam Kucharski #define CFG_TMRTEST 0x00020000 191*1b8adde7SWilliam Kucharski #define CFG_MRM_DIS 0x00010000 192*1b8adde7SWilliam Kucharski #define CFG_MWI_DIS 0x00008000 193*1b8adde7SWilliam Kucharski #define CFG_T64ADDR 0x00004000 194*1b8adde7SWilliam Kucharski #define CFG_PCI64_DET 0x00002000 195*1b8adde7SWilliam Kucharski #define CFG_DATA64_EN 0x00001000 196*1b8adde7SWilliam Kucharski #define CFG_M64ADDR 0x00000800 197*1b8adde7SWilliam Kucharski #define CFG_PHY_RST 0x00000400 198*1b8adde7SWilliam Kucharski #define CFG_PHY_DIS 0x00000200 199*1b8adde7SWilliam Kucharski #define CFG_EXTSTS_EN 0x00000100 200*1b8adde7SWilliam Kucharski #define CFG_REQALG 0x00000080 201*1b8adde7SWilliam Kucharski #define CFG_SB 0x00000040 202*1b8adde7SWilliam Kucharski #define CFG_POW 0x00000020 203*1b8adde7SWilliam Kucharski #define CFG_EXD 0x00000010 204*1b8adde7SWilliam Kucharski #define CFG_PESEL 0x00000008 205*1b8adde7SWilliam Kucharski #define CFG_BROM_DIS 0x00000004 206*1b8adde7SWilliam Kucharski #define CFG_EXT_125 0x00000002 207*1b8adde7SWilliam Kucharski #define CFG_BEM 0x00000001 208*1b8adde7SWilliam Kucharski 209*1b8adde7SWilliam Kucharski #define EXTSTS_UDPPKT 0x00200000 210*1b8adde7SWilliam Kucharski #define EXTSTS_TCPPKT 0x00080000 211*1b8adde7SWilliam Kucharski #define EXTSTS_IPPKT 0x00020000 212*1b8adde7SWilliam Kucharski 213*1b8adde7SWilliam Kucharski #define SPDSTS_POLARITY (CFG_SPDSTS1 | CFG_SPDSTS0 | CFG_DUPSTS | (lnksts ? CFG_LNKSTS : 0)) 214*1b8adde7SWilliam Kucharski 215*1b8adde7SWilliam Kucharski #define MIBC_MIBS 0x00000008 216*1b8adde7SWilliam Kucharski #define MIBC_ACLR 0x00000004 217*1b8adde7SWilliam Kucharski #define MIBC_FRZ 0x00000002 218*1b8adde7SWilliam Kucharski #define MIBC_WRN 0x00000001 219*1b8adde7SWilliam Kucharski 220*1b8adde7SWilliam Kucharski #define PCR_PSEN (1 << 31) 221*1b8adde7SWilliam Kucharski #define PCR_PS_MCAST (1 << 30) 222*1b8adde7SWilliam Kucharski #define PCR_PS_DA (1 << 29) 223*1b8adde7SWilliam Kucharski #define PCR_STHI_8 (3 << 23) 224*1b8adde7SWilliam Kucharski #define PCR_STLO_4 (1 << 23) 225*1b8adde7SWilliam Kucharski #define PCR_FFHI_8K (3 << 21) 226*1b8adde7SWilliam Kucharski #define PCR_FFLO_4K (1 << 21) 227*1b8adde7SWilliam Kucharski #define PCR_PAUSE_CNT 0xFFFE 228*1b8adde7SWilliam Kucharski 229*1b8adde7SWilliam Kucharski #define RXCFG_AEP 0x80000000 230*1b8adde7SWilliam Kucharski #define RXCFG_ARP 0x40000000 231*1b8adde7SWilliam Kucharski #define RXCFG_STRIPCRC 0x20000000 232*1b8adde7SWilliam Kucharski #define RXCFG_RX_FD 0x10000000 233*1b8adde7SWilliam Kucharski #define RXCFG_ALP 0x08000000 234*1b8adde7SWilliam Kucharski #define RXCFG_AIRL 0x04000000 235*1b8adde7SWilliam Kucharski #define RXCFG_MXDMA512 0x00700000 236*1b8adde7SWilliam Kucharski #define RXCFG_DRTH 0x0000003e 237*1b8adde7SWilliam Kucharski #define RXCFG_DRTH0 0x00000002 238*1b8adde7SWilliam Kucharski 239*1b8adde7SWilliam Kucharski #define RFCR_RFEN 0x80000000 240*1b8adde7SWilliam Kucharski #define RFCR_AAB 0x40000000 241*1b8adde7SWilliam Kucharski #define RFCR_AAM 0x20000000 242*1b8adde7SWilliam Kucharski #define RFCR_AAU 0x10000000 243*1b8adde7SWilliam Kucharski #define RFCR_APM 0x08000000 244*1b8adde7SWilliam Kucharski #define RFCR_APAT 0x07800000 245*1b8adde7SWilliam Kucharski #define RFCR_APAT3 0x04000000 246*1b8adde7SWilliam Kucharski #define RFCR_APAT2 0x02000000 247*1b8adde7SWilliam Kucharski #define RFCR_APAT1 0x01000000 248*1b8adde7SWilliam Kucharski #define RFCR_APAT0 0x00800000 249*1b8adde7SWilliam Kucharski #define RFCR_AARP 0x00400000 250*1b8adde7SWilliam Kucharski #define RFCR_MHEN 0x00200000 251*1b8adde7SWilliam Kucharski #define RFCR_UHEN 0x00100000 252*1b8adde7SWilliam Kucharski #define RFCR_ULM 0x00080000 253*1b8adde7SWilliam Kucharski 254*1b8adde7SWilliam Kucharski #define VRCR_RUDPE 0x00000080 255*1b8adde7SWilliam Kucharski #define VRCR_RTCPE 0x00000040 256*1b8adde7SWilliam Kucharski #define VRCR_RIPE 0x00000020 257*1b8adde7SWilliam Kucharski #define VRCR_IPEN 0x00000010 258*1b8adde7SWilliam Kucharski #define VRCR_DUTF 0x00000008 259*1b8adde7SWilliam Kucharski #define VRCR_DVTF 0x00000004 260*1b8adde7SWilliam Kucharski #define VRCR_VTREN 0x00000002 261*1b8adde7SWilliam Kucharski #define VRCR_VTDEN 0x00000001 262*1b8adde7SWilliam Kucharski 263*1b8adde7SWilliam Kucharski #define VTCR_PPCHK 0x00000008 264*1b8adde7SWilliam Kucharski #define VTCR_GCHK 0x00000004 265*1b8adde7SWilliam Kucharski #define VTCR_VPPTI 0x00000002 266*1b8adde7SWilliam Kucharski #define VTCR_VGTI 0x00000001 267*1b8adde7SWilliam Kucharski 268*1b8adde7SWilliam Kucharski #define CR 0x00 269*1b8adde7SWilliam Kucharski #define CFG 0x04 270*1b8adde7SWilliam Kucharski #define MEAR 0x08 271*1b8adde7SWilliam Kucharski #define PTSCR 0x0c 272*1b8adde7SWilliam Kucharski #define ISR 0x10 273*1b8adde7SWilliam Kucharski #define IMR 0x14 274*1b8adde7SWilliam Kucharski #define IER 0x18 275*1b8adde7SWilliam Kucharski #define IHR 0x1c 276*1b8adde7SWilliam Kucharski #define TXDP 0x20 277*1b8adde7SWilliam Kucharski #define TXDP_HI 0x24 278*1b8adde7SWilliam Kucharski #define TXCFG 0x28 279*1b8adde7SWilliam Kucharski #define GPIOR 0x2c 280*1b8adde7SWilliam Kucharski #define RXDP 0x30 281*1b8adde7SWilliam Kucharski #define RXDP_HI 0x34 282*1b8adde7SWilliam Kucharski #define RXCFG 0x38 283*1b8adde7SWilliam Kucharski #define PQCR 0x3c 284*1b8adde7SWilliam Kucharski #define WCSR 0x40 285*1b8adde7SWilliam Kucharski #define PCR 0x44 286*1b8adde7SWilliam Kucharski #define RFCR 0x48 287*1b8adde7SWilliam Kucharski #define RFDR 0x4c 288*1b8adde7SWilliam Kucharski 289*1b8adde7SWilliam Kucharski #define SRR 0x58 290*1b8adde7SWilliam Kucharski 291*1b8adde7SWilliam Kucharski #define VRCR 0xbc 292*1b8adde7SWilliam Kucharski #define VTCR 0xc0 293*1b8adde7SWilliam Kucharski #define VDR 0xc4 294*1b8adde7SWilliam Kucharski #define CCSR 0xcc 295*1b8adde7SWilliam Kucharski 296*1b8adde7SWilliam Kucharski #define TBICR 0xe0 297*1b8adde7SWilliam Kucharski #define TBISR 0xe4 298*1b8adde7SWilliam Kucharski #define TANAR 0xe8 299*1b8adde7SWilliam Kucharski #define TANLPAR 0xec 300*1b8adde7SWilliam Kucharski #define TANER 0xf0 301*1b8adde7SWilliam Kucharski #define TESR 0xf4 302*1b8adde7SWilliam Kucharski 303*1b8adde7SWilliam Kucharski #define TBICR_MR_AN_ENABLE 0x00001000 304*1b8adde7SWilliam Kucharski #define TBICR_MR_RESTART_AN 0x00000200 305*1b8adde7SWilliam Kucharski 306*1b8adde7SWilliam Kucharski #define TBISR_MR_LINK_STATUS 0x00000020 307*1b8adde7SWilliam Kucharski #define TBISR_MR_AN_COMPLETE 0x00000004 308*1b8adde7SWilliam Kucharski 309*1b8adde7SWilliam Kucharski #define TANAR_PS2 0x00000100 310*1b8adde7SWilliam Kucharski #define TANAR_PS1 0x00000080 311*1b8adde7SWilliam Kucharski #define TANAR_HALF_DUP 0x00000040 312*1b8adde7SWilliam Kucharski #define TANAR_FULL_DUP 0x00000020 313*1b8adde7SWilliam Kucharski 314*1b8adde7SWilliam Kucharski #define GPIOR_GP5_OE 0x00000200 315*1b8adde7SWilliam Kucharski #define GPIOR_GP4_OE 0x00000100 316*1b8adde7SWilliam Kucharski #define GPIOR_GP3_OE 0x00000080 317*1b8adde7SWilliam Kucharski #define GPIOR_GP2_OE 0x00000040 318*1b8adde7SWilliam Kucharski #define GPIOR_GP1_OE 0x00000020 319*1b8adde7SWilliam Kucharski #define GPIOR_GP3_OUT 0x00000004 320*1b8adde7SWilliam Kucharski #define GPIOR_GP1_OUT 0x00000001 321*1b8adde7SWilliam Kucharski 322*1b8adde7SWilliam Kucharski #define LINK_AUTONEGOTIATE 0x01 323*1b8adde7SWilliam Kucharski #define LINK_DOWN 0x02 324*1b8adde7SWilliam Kucharski #define LINK_UP 0x04 325*1b8adde7SWilliam Kucharski 326*1b8adde7SWilliam Kucharski 327*1b8adde7SWilliam Kucharski #define __kick_rx() writel(CR_RXE, ns->base + CR) 328*1b8adde7SWilliam Kucharski 329*1b8adde7SWilliam Kucharski #define kick_rx() do { \ 330*1b8adde7SWilliam Kucharski dprintf(("kick_rx: maybe kicking\n")); \ 331*1b8adde7SWilliam Kucharski writel(virt_to_le32desc(&rx_ring[ns->cur_rx]), ns->base + RXDP); \ 332*1b8adde7SWilliam Kucharski if (ns->next_rx == ns->next_empty) \ 333*1b8adde7SWilliam Kucharski printf("uh-oh: next_rx == next_empty???\n"); \ 334*1b8adde7SWilliam Kucharski __kick_rx(); \ 335*1b8adde7SWilliam Kucharski } while(0) 336*1b8adde7SWilliam Kucharski 337*1b8adde7SWilliam Kucharski 338*1b8adde7SWilliam Kucharski #ifdef USE_64BIT_ADDR 339*1b8adde7SWilliam Kucharski #define HW_ADDR_LEN 8 340*1b8adde7SWilliam Kucharski #else 341*1b8adde7SWilliam Kucharski #define HW_ADDR_LEN 4 342*1b8adde7SWilliam Kucharski #endif 343*1b8adde7SWilliam Kucharski 344*1b8adde7SWilliam Kucharski #define CMDSTS_OWN 0x80000000 345*1b8adde7SWilliam Kucharski #define CMDSTS_MORE 0x40000000 346*1b8adde7SWilliam Kucharski #define CMDSTS_INTR 0x20000000 347*1b8adde7SWilliam Kucharski #define CMDSTS_ERR 0x10000000 348*1b8adde7SWilliam Kucharski #define CMDSTS_OK 0x08000000 349*1b8adde7SWilliam Kucharski #define CMDSTS_LEN_MASK 0x0000ffff 350*1b8adde7SWilliam Kucharski 351*1b8adde7SWilliam Kucharski #define CMDSTS_DEST_MASK 0x01800000 352*1b8adde7SWilliam Kucharski #define CMDSTS_DEST_SELF 0x00800000 353*1b8adde7SWilliam Kucharski #define CMDSTS_DEST_MULTI 0x01000000 354*1b8adde7SWilliam Kucharski 355*1b8adde7SWilliam Kucharski #define DESC_SIZE 8 /* Should be cache line sized */ 356*1b8adde7SWilliam Kucharski 357*1b8adde7SWilliam Kucharski #ifdef USE_64BIT_ADDR 358*1b8adde7SWilliam Kucharski struct ring_desc { 359*1b8adde7SWilliam Kucharski uint64_t link; 360*1b8adde7SWilliam Kucharski uint64_t bufptr; 361*1b8adde7SWilliam Kucharski u32 cmdsts; 362*1b8adde7SWilliam Kucharski u32 extsts; /* Extended status field */ 363*1b8adde7SWilliam Kucharski }; 364*1b8adde7SWilliam Kucharski #else 365*1b8adde7SWilliam Kucharski struct ring_desc { 366*1b8adde7SWilliam Kucharski u32 link; 367*1b8adde7SWilliam Kucharski u32 bufptr; 368*1b8adde7SWilliam Kucharski u32 cmdsts; 369*1b8adde7SWilliam Kucharski u32 extsts; /* Extended status field */ 370*1b8adde7SWilliam Kucharski }; 371*1b8adde7SWilliam Kucharski #endif 372*1b8adde7SWilliam Kucharski 373*1b8adde7SWilliam Kucharski /* Define the TX Descriptor */ 374*1b8adde7SWilliam Kucharski static struct ring_desc tx_ring[NR_TX_DESC] 375*1b8adde7SWilliam Kucharski __attribute__ ((aligned(8))); 376*1b8adde7SWilliam Kucharski 377*1b8adde7SWilliam Kucharski /* Create a static buffer of size REAL_RX_BUF_SIZE for each 378*1b8adde7SWilliam Kucharski TX Descriptor. All descriptors point to a 379*1b8adde7SWilliam Kucharski part of this buffer */ 380*1b8adde7SWilliam Kucharski static unsigned char txb[NR_TX_DESC * REAL_RX_BUF_SIZE]; 381*1b8adde7SWilliam Kucharski 382*1b8adde7SWilliam Kucharski /* Define the TX Descriptor */ 383*1b8adde7SWilliam Kucharski static struct ring_desc rx_ring[NR_RX_DESC] 384*1b8adde7SWilliam Kucharski __attribute__ ((aligned(8))); 385*1b8adde7SWilliam Kucharski 386*1b8adde7SWilliam Kucharski /* Create a static buffer of size REAL_RX_BUF_SIZE for each 387*1b8adde7SWilliam Kucharski RX Descriptor All descriptors point to a 388*1b8adde7SWilliam Kucharski part of this buffer */ 389*1b8adde7SWilliam Kucharski static unsigned char rxb[NR_RX_DESC * REAL_RX_BUF_SIZE] 390*1b8adde7SWilliam Kucharski __attribute__ ((aligned(8))); 391*1b8adde7SWilliam Kucharski 392*1b8adde7SWilliam Kucharski /* Private Storage for the NIC */ 393*1b8adde7SWilliam Kucharski struct ns83820_private { 394*1b8adde7SWilliam Kucharski u8 *base; 395*1b8adde7SWilliam Kucharski int up; 396*1b8adde7SWilliam Kucharski long idle; 397*1b8adde7SWilliam Kucharski u32 *next_rx_desc; 398*1b8adde7SWilliam Kucharski u16 next_rx, next_empty; 399*1b8adde7SWilliam Kucharski u32 cur_rx; 400*1b8adde7SWilliam Kucharski u32 *descs; 401*1b8adde7SWilliam Kucharski unsigned ihr; 402*1b8adde7SWilliam Kucharski u32 CFG_cache; 403*1b8adde7SWilliam Kucharski u32 MEAR_cache; 404*1b8adde7SWilliam Kucharski u32 IMR_cache; 405*1b8adde7SWilliam Kucharski int linkstate; 406*1b8adde7SWilliam Kucharski u16 tx_done_idx; 407*1b8adde7SWilliam Kucharski u16 tx_idx; 408*1b8adde7SWilliam Kucharski u16 tx_intr_idx; 409*1b8adde7SWilliam Kucharski u32 phy_descs; 410*1b8adde7SWilliam Kucharski u32 *tx_descs; 411*1b8adde7SWilliam Kucharski 412*1b8adde7SWilliam Kucharski } nsx; 413*1b8adde7SWilliam Kucharski static struct ns83820_private *ns; 414*1b8adde7SWilliam Kucharski 415*1b8adde7SWilliam Kucharski static void phy_intr(struct nic *nic __unused) 416*1b8adde7SWilliam Kucharski { 417*1b8adde7SWilliam Kucharski static char *speeds[] = 418*1b8adde7SWilliam Kucharski { "10", "100", "1000", "1000(?)", "1000F" }; 419*1b8adde7SWilliam Kucharski u32 cfg, new_cfg; 420*1b8adde7SWilliam Kucharski u32 tbisr, tanar, tanlpar; 421*1b8adde7SWilliam Kucharski int speed, fullduplex, newlinkstate; 422*1b8adde7SWilliam Kucharski 423*1b8adde7SWilliam Kucharski cfg = readl(ns->base + CFG) ^ SPDSTS_POLARITY; 424*1b8adde7SWilliam Kucharski if (ns->CFG_cache & CFG_TBI_EN) { 425*1b8adde7SWilliam Kucharski /* we have an optical transceiver */ 426*1b8adde7SWilliam Kucharski tbisr = readl(ns->base + TBISR); 427*1b8adde7SWilliam Kucharski tanar = readl(ns->base + TANAR); 428*1b8adde7SWilliam Kucharski tanlpar = readl(ns->base + TANLPAR); 429*1b8adde7SWilliam Kucharski dprintf(("phy_intr: tbisr=%hX, tanar=%hX, tanlpar=%hX\n", 430*1b8adde7SWilliam Kucharski tbisr, tanar, tanlpar)); 431*1b8adde7SWilliam Kucharski 432*1b8adde7SWilliam Kucharski if ((fullduplex = (tanlpar & TANAR_FULL_DUP) 433*1b8adde7SWilliam Kucharski && (tanar & TANAR_FULL_DUP))) { 434*1b8adde7SWilliam Kucharski 435*1b8adde7SWilliam Kucharski /* both of us are full duplex */ 436*1b8adde7SWilliam Kucharski writel(readl(ns->base + TXCFG) 437*1b8adde7SWilliam Kucharski | TXCFG_CSI | TXCFG_HBI | TXCFG_ATP, 438*1b8adde7SWilliam Kucharski ns->base + TXCFG); 439*1b8adde7SWilliam Kucharski writel(readl(ns->base + RXCFG) | RXCFG_RX_FD, 440*1b8adde7SWilliam Kucharski ns->base + RXCFG); 441*1b8adde7SWilliam Kucharski /* Light up full duplex LED */ 442*1b8adde7SWilliam Kucharski writel(readl(ns->base + GPIOR) | GPIOR_GP1_OUT, 443*1b8adde7SWilliam Kucharski ns->base + GPIOR); 444*1b8adde7SWilliam Kucharski 445*1b8adde7SWilliam Kucharski } else if (((tanlpar & TANAR_HALF_DUP) 446*1b8adde7SWilliam Kucharski && (tanar & TANAR_HALF_DUP)) 447*1b8adde7SWilliam Kucharski || ((tanlpar & TANAR_FULL_DUP) 448*1b8adde7SWilliam Kucharski && (tanar & TANAR_HALF_DUP)) 449*1b8adde7SWilliam Kucharski || ((tanlpar & TANAR_HALF_DUP) 450*1b8adde7SWilliam Kucharski && (tanar & TANAR_FULL_DUP))) { 451*1b8adde7SWilliam Kucharski 452*1b8adde7SWilliam Kucharski /* one or both of us are half duplex */ 453*1b8adde7SWilliam Kucharski writel((readl(ns->base + TXCFG) 454*1b8adde7SWilliam Kucharski & ~(TXCFG_CSI | TXCFG_HBI)) | TXCFG_ATP, 455*1b8adde7SWilliam Kucharski ns->base + TXCFG); 456*1b8adde7SWilliam Kucharski writel(readl(ns->base + RXCFG) & ~RXCFG_RX_FD, 457*1b8adde7SWilliam Kucharski ns->base + RXCFG); 458*1b8adde7SWilliam Kucharski /* Turn off full duplex LED */ 459*1b8adde7SWilliam Kucharski writel(readl(ns->base + GPIOR) & ~GPIOR_GP1_OUT, 460*1b8adde7SWilliam Kucharski ns->base + GPIOR); 461*1b8adde7SWilliam Kucharski } 462*1b8adde7SWilliam Kucharski 463*1b8adde7SWilliam Kucharski speed = 4; /* 1000F */ 464*1b8adde7SWilliam Kucharski 465*1b8adde7SWilliam Kucharski } else { 466*1b8adde7SWilliam Kucharski /* we have a copper transceiver */ 467*1b8adde7SWilliam Kucharski new_cfg = 468*1b8adde7SWilliam Kucharski ns->CFG_cache & ~(CFG_SB | CFG_MODE_1000 | CFG_SPDSTS); 469*1b8adde7SWilliam Kucharski 470*1b8adde7SWilliam Kucharski if (cfg & CFG_SPDSTS1) 471*1b8adde7SWilliam Kucharski new_cfg |= CFG_MODE_1000; 472*1b8adde7SWilliam Kucharski else 473*1b8adde7SWilliam Kucharski new_cfg &= ~CFG_MODE_1000; 474*1b8adde7SWilliam Kucharski 475*1b8adde7SWilliam Kucharski speed = ((cfg / CFG_SPDSTS0) & 3); 476*1b8adde7SWilliam Kucharski fullduplex = (cfg & CFG_DUPSTS); 477*1b8adde7SWilliam Kucharski 478*1b8adde7SWilliam Kucharski if (fullduplex) 479*1b8adde7SWilliam Kucharski new_cfg |= CFG_SB; 480*1b8adde7SWilliam Kucharski 481*1b8adde7SWilliam Kucharski if ((cfg & CFG_LNKSTS) && 482*1b8adde7SWilliam Kucharski ((new_cfg ^ ns->CFG_cache) & CFG_MODE_1000)) { 483*1b8adde7SWilliam Kucharski writel(new_cfg, ns->base + CFG); 484*1b8adde7SWilliam Kucharski ns->CFG_cache = new_cfg; 485*1b8adde7SWilliam Kucharski } 486*1b8adde7SWilliam Kucharski 487*1b8adde7SWilliam Kucharski ns->CFG_cache &= ~CFG_SPDSTS; 488*1b8adde7SWilliam Kucharski ns->CFG_cache |= cfg & CFG_SPDSTS; 489*1b8adde7SWilliam Kucharski } 490*1b8adde7SWilliam Kucharski 491*1b8adde7SWilliam Kucharski newlinkstate = (cfg & CFG_LNKSTS) ? LINK_UP : LINK_DOWN; 492*1b8adde7SWilliam Kucharski 493*1b8adde7SWilliam Kucharski if (newlinkstate & LINK_UP && ns->linkstate != newlinkstate) { 494*1b8adde7SWilliam Kucharski printf("link now %s mbps, %s duplex and up.\n", 495*1b8adde7SWilliam Kucharski speeds[speed], fullduplex ? "full" : "half"); 496*1b8adde7SWilliam Kucharski } else if (newlinkstate & LINK_DOWN 497*1b8adde7SWilliam Kucharski && ns->linkstate != newlinkstate) { 498*1b8adde7SWilliam Kucharski printf("link now down.\n"); 499*1b8adde7SWilliam Kucharski } 500*1b8adde7SWilliam Kucharski ns->linkstate = newlinkstate; 501*1b8adde7SWilliam Kucharski } 502*1b8adde7SWilliam Kucharski static void ns83820_set_multicast(struct nic *nic __unused); 503*1b8adde7SWilliam Kucharski static void ns83820_setup_rx(struct nic *nic) 504*1b8adde7SWilliam Kucharski { 505*1b8adde7SWilliam Kucharski unsigned i; 506*1b8adde7SWilliam Kucharski ns->idle = 1; 507*1b8adde7SWilliam Kucharski ns->next_rx = 0; 508*1b8adde7SWilliam Kucharski ns->next_rx_desc = ns->descs; 509*1b8adde7SWilliam Kucharski ns->next_empty = 0; 510*1b8adde7SWilliam Kucharski ns->cur_rx = 0; 511*1b8adde7SWilliam Kucharski 512*1b8adde7SWilliam Kucharski 513*1b8adde7SWilliam Kucharski for (i = 0; i < NR_RX_DESC; i++) { 514*1b8adde7SWilliam Kucharski rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]); 515*1b8adde7SWilliam Kucharski rx_ring[i].bufptr = 516*1b8adde7SWilliam Kucharski virt_to_le32desc(&rxb[i * REAL_RX_BUF_SIZE]); 517*1b8adde7SWilliam Kucharski rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE); 518*1b8adde7SWilliam Kucharski rx_ring[i].extsts = cpu_to_le32(0); 519*1b8adde7SWilliam Kucharski } 520*1b8adde7SWilliam Kucharski // No need to wrap the ring 521*1b8adde7SWilliam Kucharski // rx_ring[i].link = virt_to_le32desc(&rx_ring[0]); 522*1b8adde7SWilliam Kucharski writel(0, ns->base + RXDP_HI); 523*1b8adde7SWilliam Kucharski writel(virt_to_le32desc(&rx_ring[0]), ns->base + RXDP); 524*1b8adde7SWilliam Kucharski 525*1b8adde7SWilliam Kucharski dprintf(("starting receiver\n")); 526*1b8adde7SWilliam Kucharski 527*1b8adde7SWilliam Kucharski writel(0x0001, ns->base + CCSR); 528*1b8adde7SWilliam Kucharski writel(0, ns->base + RFCR); 529*1b8adde7SWilliam Kucharski writel(0x7fc00000, ns->base + RFCR); 530*1b8adde7SWilliam Kucharski writel(0xffc00000, ns->base + RFCR); 531*1b8adde7SWilliam Kucharski 532*1b8adde7SWilliam Kucharski ns->up = 1; 533*1b8adde7SWilliam Kucharski 534*1b8adde7SWilliam Kucharski phy_intr(nic); 535*1b8adde7SWilliam Kucharski 536*1b8adde7SWilliam Kucharski /* Okay, let it rip */ 537*1b8adde7SWilliam Kucharski ns->IMR_cache |= ISR_PHY; 538*1b8adde7SWilliam Kucharski ns->IMR_cache |= ISR_RXRCMP; 539*1b8adde7SWilliam Kucharski //dev->IMR_cache |= ISR_RXERR; 540*1b8adde7SWilliam Kucharski //dev->IMR_cache |= ISR_RXOK; 541*1b8adde7SWilliam Kucharski ns->IMR_cache |= ISR_RXORN; 542*1b8adde7SWilliam Kucharski ns->IMR_cache |= ISR_RXSOVR; 543*1b8adde7SWilliam Kucharski ns->IMR_cache |= ISR_RXDESC; 544*1b8adde7SWilliam Kucharski ns->IMR_cache |= ISR_RXIDLE; 545*1b8adde7SWilliam Kucharski ns->IMR_cache |= ISR_TXDESC; 546*1b8adde7SWilliam Kucharski ns->IMR_cache |= ISR_TXIDLE; 547*1b8adde7SWilliam Kucharski 548*1b8adde7SWilliam Kucharski // No reason to enable interupts... 549*1b8adde7SWilliam Kucharski // writel(ns->IMR_cache, ns->base + IMR); 550*1b8adde7SWilliam Kucharski // writel(1, ns->base + IER); 551*1b8adde7SWilliam Kucharski ns83820_set_multicast(nic); 552*1b8adde7SWilliam Kucharski kick_rx(); 553*1b8adde7SWilliam Kucharski } 554*1b8adde7SWilliam Kucharski 555*1b8adde7SWilliam Kucharski 556*1b8adde7SWilliam Kucharski static void ns83820_do_reset(struct nic *nic __unused, u32 which) 557*1b8adde7SWilliam Kucharski { 558*1b8adde7SWilliam Kucharski dprintf(("resetting chip...\n")); 559*1b8adde7SWilliam Kucharski writel(which, ns->base + CR); 560*1b8adde7SWilliam Kucharski do { 561*1b8adde7SWilliam Kucharski 562*1b8adde7SWilliam Kucharski } while (readl(ns->base + CR) & which); 563*1b8adde7SWilliam Kucharski dprintf(("okay!\n")); 564*1b8adde7SWilliam Kucharski } 565*1b8adde7SWilliam Kucharski 566*1b8adde7SWilliam Kucharski static void ns83820_reset(struct nic *nic) 567*1b8adde7SWilliam Kucharski { 568*1b8adde7SWilliam Kucharski unsigned i; 569*1b8adde7SWilliam Kucharski dprintf(("ns83820_reset\n")); 570*1b8adde7SWilliam Kucharski 571*1b8adde7SWilliam Kucharski writel(0, ns->base + PQCR); 572*1b8adde7SWilliam Kucharski 573*1b8adde7SWilliam Kucharski ns83820_setup_rx(nic); 574*1b8adde7SWilliam Kucharski 575*1b8adde7SWilliam Kucharski for (i = 0; i < NR_TX_DESC; i++) { 576*1b8adde7SWilliam Kucharski tx_ring[i].link = 0; 577*1b8adde7SWilliam Kucharski tx_ring[i].bufptr = 0; 578*1b8adde7SWilliam Kucharski tx_ring[i].cmdsts = cpu_to_le32(0); 579*1b8adde7SWilliam Kucharski tx_ring[i].extsts = cpu_to_le32(0); 580*1b8adde7SWilliam Kucharski } 581*1b8adde7SWilliam Kucharski 582*1b8adde7SWilliam Kucharski ns->tx_idx = 0; 583*1b8adde7SWilliam Kucharski ns->tx_done_idx = 0; 584*1b8adde7SWilliam Kucharski writel(0, ns->base + TXDP_HI); 585*1b8adde7SWilliam Kucharski return; 586*1b8adde7SWilliam Kucharski } 587*1b8adde7SWilliam Kucharski static void ns83820_getmac(struct nic *nic __unused, u8 * mac) 588*1b8adde7SWilliam Kucharski { 589*1b8adde7SWilliam Kucharski unsigned i; 590*1b8adde7SWilliam Kucharski for (i = 0; i < 3; i++) { 591*1b8adde7SWilliam Kucharski u32 data; 592*1b8adde7SWilliam Kucharski /* Read from the perfect match memory: this is loaded by 593*1b8adde7SWilliam Kucharski * the chip from the EEPROM via the EELOAD self test. 594*1b8adde7SWilliam Kucharski */ 595*1b8adde7SWilliam Kucharski writel(i * 2, ns->base + RFCR); 596*1b8adde7SWilliam Kucharski data = readl(ns->base + RFDR); 597*1b8adde7SWilliam Kucharski *mac++ = data; 598*1b8adde7SWilliam Kucharski *mac++ = data >> 8; 599*1b8adde7SWilliam Kucharski } 600*1b8adde7SWilliam Kucharski } 601*1b8adde7SWilliam Kucharski 602*1b8adde7SWilliam Kucharski static void ns83820_set_multicast(struct nic *nic __unused) 603*1b8adde7SWilliam Kucharski { 604*1b8adde7SWilliam Kucharski u8 *rfcr = ns->base + RFCR; 605*1b8adde7SWilliam Kucharski u32 and_mask = 0xffffffff; 606*1b8adde7SWilliam Kucharski u32 or_mask = 0; 607*1b8adde7SWilliam Kucharski u32 val; 608*1b8adde7SWilliam Kucharski 609*1b8adde7SWilliam Kucharski /* Support Multicast */ 610*1b8adde7SWilliam Kucharski and_mask &= ~(RFCR_AAU | RFCR_AAM); 611*1b8adde7SWilliam Kucharski or_mask |= RFCR_AAM; 612*1b8adde7SWilliam Kucharski val = (readl(rfcr) & and_mask) | or_mask; 613*1b8adde7SWilliam Kucharski /* Ramit : RFCR Write Fix doc says RFEN must be 0 modify other bits */ 614*1b8adde7SWilliam Kucharski writel(val & ~RFCR_RFEN, rfcr); 615*1b8adde7SWilliam Kucharski writel(val, rfcr); 616*1b8adde7SWilliam Kucharski 617*1b8adde7SWilliam Kucharski } 618*1b8adde7SWilliam Kucharski static void ns83820_run_bist(struct nic *nic __unused, const char *name, 619*1b8adde7SWilliam Kucharski u32 enable, u32 done, u32 fail) 620*1b8adde7SWilliam Kucharski { 621*1b8adde7SWilliam Kucharski int timed_out = 0; 622*1b8adde7SWilliam Kucharski long start; 623*1b8adde7SWilliam Kucharski u32 status; 624*1b8adde7SWilliam Kucharski int loops = 0; 625*1b8adde7SWilliam Kucharski 626*1b8adde7SWilliam Kucharski dprintf(("start %s\n", name)) 627*1b8adde7SWilliam Kucharski 628*1b8adde7SWilliam Kucharski start = currticks(); 629*1b8adde7SWilliam Kucharski 630*1b8adde7SWilliam Kucharski writel(enable, ns->base + PTSCR); 631*1b8adde7SWilliam Kucharski for (;;) { 632*1b8adde7SWilliam Kucharski loops++; 633*1b8adde7SWilliam Kucharski status = readl(ns->base + PTSCR); 634*1b8adde7SWilliam Kucharski if (!(status & enable)) 635*1b8adde7SWilliam Kucharski break; 636*1b8adde7SWilliam Kucharski if (status & done) 637*1b8adde7SWilliam Kucharski break; 638*1b8adde7SWilliam Kucharski if (status & fail) 639*1b8adde7SWilliam Kucharski break; 640*1b8adde7SWilliam Kucharski if ((currticks() - start) >= HZ) { 641*1b8adde7SWilliam Kucharski timed_out = 1; 642*1b8adde7SWilliam Kucharski break; 643*1b8adde7SWilliam Kucharski } 644*1b8adde7SWilliam Kucharski } 645*1b8adde7SWilliam Kucharski 646*1b8adde7SWilliam Kucharski if (status & fail) 647*1b8adde7SWilliam Kucharski printf("%s failed! (0x%hX & 0x%hX)\n", name, status, fail); 648*1b8adde7SWilliam Kucharski else if (timed_out) 649*1b8adde7SWilliam Kucharski printf("run_bist %s timed out! (%hX)\n", name, status); 650*1b8adde7SWilliam Kucharski dprintf(("done %s in %d loops\n", name, loops)); 651*1b8adde7SWilliam Kucharski } 652*1b8adde7SWilliam Kucharski 653*1b8adde7SWilliam Kucharski /************************************* 654*1b8adde7SWilliam Kucharski Check Link 655*1b8adde7SWilliam Kucharski *************************************/ 656*1b8adde7SWilliam Kucharski static void ns83820_check_intr(struct nic *nic) { 657*1b8adde7SWilliam Kucharski int i; 658*1b8adde7SWilliam Kucharski u32 isr = readl(ns->base + ISR); 659*1b8adde7SWilliam Kucharski if(ISR_PHY & isr) 660*1b8adde7SWilliam Kucharski phy_intr(nic); 661*1b8adde7SWilliam Kucharski if(( ISR_RXIDLE | ISR_RXDESC | ISR_RXERR) & isr) 662*1b8adde7SWilliam Kucharski kick_rx(); 663*1b8adde7SWilliam Kucharski for (i = 0; i < NR_RX_DESC; i++) { 664*1b8adde7SWilliam Kucharski if (rx_ring[i].cmdsts == CMDSTS_OWN) { 665*1b8adde7SWilliam Kucharski // rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]); 666*1b8adde7SWilliam Kucharski rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE); 667*1b8adde7SWilliam Kucharski } 668*1b8adde7SWilliam Kucharski } 669*1b8adde7SWilliam Kucharski } 670*1b8adde7SWilliam Kucharski /************************************************************************** 671*1b8adde7SWilliam Kucharski POLL - Wait for a frame 672*1b8adde7SWilliam Kucharski ***************************************************************************/ 673*1b8adde7SWilliam Kucharski static int ns83820_poll(struct nic *nic, int retrieve) 674*1b8adde7SWilliam Kucharski { 675*1b8adde7SWilliam Kucharski /* return true if there's an ethernet packet ready to read */ 676*1b8adde7SWilliam Kucharski /* nic->packet should contain data on return */ 677*1b8adde7SWilliam Kucharski /* nic->packetlen should contain length of data */ 678*1b8adde7SWilliam Kucharski u32 cmdsts; 679*1b8adde7SWilliam Kucharski int entry = ns->cur_rx; 680*1b8adde7SWilliam Kucharski 681*1b8adde7SWilliam Kucharski ns83820_check_intr(nic); 682*1b8adde7SWilliam Kucharski 683*1b8adde7SWilliam Kucharski cmdsts = le32_to_cpu(rx_ring[entry].cmdsts); 684*1b8adde7SWilliam Kucharski 685*1b8adde7SWilliam Kucharski if ( ! ( (CMDSTS_OWN & (cmdsts)) && (cmdsts != (CMDSTS_OWN)) ) ) 686*1b8adde7SWilliam Kucharski return 0; 687*1b8adde7SWilliam Kucharski 688*1b8adde7SWilliam Kucharski if ( ! retrieve ) return 1; 689*1b8adde7SWilliam Kucharski 690*1b8adde7SWilliam Kucharski if (! (CMDSTS_OK & cmdsts) ) 691*1b8adde7SWilliam Kucharski return 0; 692*1b8adde7SWilliam Kucharski 693*1b8adde7SWilliam Kucharski nic->packetlen = cmdsts & 0xffff; 694*1b8adde7SWilliam Kucharski memcpy(nic->packet, 695*1b8adde7SWilliam Kucharski rxb + (entry * REAL_RX_BUF_SIZE), 696*1b8adde7SWilliam Kucharski nic->packetlen); 697*1b8adde7SWilliam Kucharski // rx_ring[entry].link = 0; 698*1b8adde7SWilliam Kucharski rx_ring[entry].cmdsts = cpu_to_le32(CMDSTS_OWN); 699*1b8adde7SWilliam Kucharski 700*1b8adde7SWilliam Kucharski ns->cur_rx = ++ns->cur_rx % NR_RX_DESC; 701*1b8adde7SWilliam Kucharski 702*1b8adde7SWilliam Kucharski if (ns->cur_rx == 0) /* We have wrapped the ring */ 703*1b8adde7SWilliam Kucharski kick_rx(); 704*1b8adde7SWilliam Kucharski 705*1b8adde7SWilliam Kucharski return 1; 706*1b8adde7SWilliam Kucharski } 707*1b8adde7SWilliam Kucharski 708*1b8adde7SWilliam Kucharski static inline void kick_tx(struct nic *nic __unused) 709*1b8adde7SWilliam Kucharski { 710*1b8adde7SWilliam Kucharski dprintf(("kick_tx\n")); 711*1b8adde7SWilliam Kucharski writel(CR_TXE, ns->base + CR); 712*1b8adde7SWilliam Kucharski } 713*1b8adde7SWilliam Kucharski 714*1b8adde7SWilliam Kucharski /************************************************************************** 715*1b8adde7SWilliam Kucharski TRANSMIT - Transmit a frame 716*1b8adde7SWilliam Kucharski ***************************************************************************/ 717*1b8adde7SWilliam Kucharski static void ns83820_transmit(struct nic *nic, const char *d, /* Destination */ 718*1b8adde7SWilliam Kucharski unsigned int t, /* Type */ 719*1b8adde7SWilliam Kucharski unsigned int s, /* size */ 720*1b8adde7SWilliam Kucharski const char *p) 721*1b8adde7SWilliam Kucharski { /* Packet */ 722*1b8adde7SWilliam Kucharski /* send the packet to destination */ 723*1b8adde7SWilliam Kucharski 724*1b8adde7SWilliam Kucharski u16 nstype; 725*1b8adde7SWilliam Kucharski u32 cmdsts, extsts; 726*1b8adde7SWilliam Kucharski int cur_tx = 0; 727*1b8adde7SWilliam Kucharski u32 isr = readl(ns->base + ISR); 728*1b8adde7SWilliam Kucharski if (ISR_TXIDLE & isr) 729*1b8adde7SWilliam Kucharski kick_tx(nic); 730*1b8adde7SWilliam Kucharski /* point to the current txb incase multiple tx_rings are used */ 731*1b8adde7SWilliam Kucharski memcpy(txb, d, ETH_ALEN); 732*1b8adde7SWilliam Kucharski memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN); 733*1b8adde7SWilliam Kucharski nstype = htons((u16) t); 734*1b8adde7SWilliam Kucharski memcpy(txb + 2 * ETH_ALEN, (u8 *) & nstype, 2); 735*1b8adde7SWilliam Kucharski memcpy(txb + ETH_HLEN, p, s); 736*1b8adde7SWilliam Kucharski s += ETH_HLEN; 737*1b8adde7SWilliam Kucharski s &= 0x0FFF; 738*1b8adde7SWilliam Kucharski while (s < ETH_ZLEN) 739*1b8adde7SWilliam Kucharski txb[s++] = '\0'; 740*1b8adde7SWilliam Kucharski 741*1b8adde7SWilliam Kucharski /* Setup the transmit descriptor */ 742*1b8adde7SWilliam Kucharski extsts = 0; 743*1b8adde7SWilliam Kucharski extsts |= EXTSTS_UDPPKT; 744*1b8adde7SWilliam Kucharski 745*1b8adde7SWilliam Kucharski tx_ring[cur_tx].bufptr = virt_to_le32desc(&txb); 746*1b8adde7SWilliam Kucharski tx_ring[cur_tx].extsts = cpu_to_le32(extsts); 747*1b8adde7SWilliam Kucharski 748*1b8adde7SWilliam Kucharski cmdsts = cpu_to_le32(0); 749*1b8adde7SWilliam Kucharski cmdsts |= cpu_to_le32(CMDSTS_OWN | s); 750*1b8adde7SWilliam Kucharski tx_ring[cur_tx].cmdsts = cpu_to_le32(cmdsts); 751*1b8adde7SWilliam Kucharski 752*1b8adde7SWilliam Kucharski writel(virt_to_le32desc(&tx_ring[0]), ns->base + TXDP); 753*1b8adde7SWilliam Kucharski kick_tx(nic); 754*1b8adde7SWilliam Kucharski } 755*1b8adde7SWilliam Kucharski 756*1b8adde7SWilliam Kucharski /************************************************************************** 757*1b8adde7SWilliam Kucharski DISABLE - Turn off ethernet interface 758*1b8adde7SWilliam Kucharski ***************************************************************************/ 759*1b8adde7SWilliam Kucharski static void ns83820_disable(struct dev *dev) 760*1b8adde7SWilliam Kucharski { 761*1b8adde7SWilliam Kucharski /* put the card in its initial state */ 762*1b8adde7SWilliam Kucharski /* This function serves 3 purposes. 763*1b8adde7SWilliam Kucharski * This disables DMA and interrupts so we don't receive 764*1b8adde7SWilliam Kucharski * unexpected packets or interrupts from the card after 765*1b8adde7SWilliam Kucharski * etherboot has finished. 766*1b8adde7SWilliam Kucharski * This frees resources so etherboot may use 767*1b8adde7SWilliam Kucharski * this driver on another interface 768*1b8adde7SWilliam Kucharski * This allows etherboot to reinitialize the interface 769*1b8adde7SWilliam Kucharski * if something is something goes wrong. 770*1b8adde7SWilliam Kucharski */ 771*1b8adde7SWilliam Kucharski /* disable interrupts */ 772*1b8adde7SWilliam Kucharski writel(0, ns->base + IMR); 773*1b8adde7SWilliam Kucharski writel(0, ns->base + IER); 774*1b8adde7SWilliam Kucharski readl(ns->base + IER); 775*1b8adde7SWilliam Kucharski 776*1b8adde7SWilliam Kucharski ns->up = 0; 777*1b8adde7SWilliam Kucharski 778*1b8adde7SWilliam Kucharski ns83820_do_reset((struct nic *) dev, CR_RST); 779*1b8adde7SWilliam Kucharski 780*1b8adde7SWilliam Kucharski ns->IMR_cache &= 781*1b8adde7SWilliam Kucharski ~(ISR_RXOK | ISR_RXDESC | ISR_RXERR | ISR_RXEARLY | 782*1b8adde7SWilliam Kucharski ISR_RXIDLE); 783*1b8adde7SWilliam Kucharski writel(ns->IMR_cache, ns->base + IMR); 784*1b8adde7SWilliam Kucharski 785*1b8adde7SWilliam Kucharski /* touch the pci bus... */ 786*1b8adde7SWilliam Kucharski readl(ns->base + IMR); 787*1b8adde7SWilliam Kucharski 788*1b8adde7SWilliam Kucharski /* assumes the transmitter is already disabled and reset */ 789*1b8adde7SWilliam Kucharski writel(0, ns->base + RXDP_HI); 790*1b8adde7SWilliam Kucharski writel(0, ns->base + RXDP); 791*1b8adde7SWilliam Kucharski } 792*1b8adde7SWilliam Kucharski 793*1b8adde7SWilliam Kucharski /************************************************************************** 794*1b8adde7SWilliam Kucharski IRQ - Enable, Disable, or Force interrupts 795*1b8adde7SWilliam Kucharski ***************************************************************************/ 796*1b8adde7SWilliam Kucharski static void ns83820_irq(struct nic *nic __unused, irq_action_t action __unused) 797*1b8adde7SWilliam Kucharski { 798*1b8adde7SWilliam Kucharski switch ( action ) { 799*1b8adde7SWilliam Kucharski case DISABLE : 800*1b8adde7SWilliam Kucharski break; 801*1b8adde7SWilliam Kucharski case ENABLE : 802*1b8adde7SWilliam Kucharski break; 803*1b8adde7SWilliam Kucharski case FORCE : 804*1b8adde7SWilliam Kucharski break; 805*1b8adde7SWilliam Kucharski } 806*1b8adde7SWilliam Kucharski } 807*1b8adde7SWilliam Kucharski 808*1b8adde7SWilliam Kucharski /************************************************************************** 809*1b8adde7SWilliam Kucharski PROBE - Look for an adapter, this routine's visible to the outside 810*1b8adde7SWilliam Kucharski ***************************************************************************/ 811*1b8adde7SWilliam Kucharski 812*1b8adde7SWilliam Kucharski #define board_found 1 813*1b8adde7SWilliam Kucharski #define valid_link 0 814*1b8adde7SWilliam Kucharski static int ns83820_probe(struct dev *dev, struct pci_device *pci) 815*1b8adde7SWilliam Kucharski { 816*1b8adde7SWilliam Kucharski struct nic *nic = (struct nic *) dev; 817*1b8adde7SWilliam Kucharski int sz; 818*1b8adde7SWilliam Kucharski long addr; 819*1b8adde7SWilliam Kucharski int using_dac = 0; 820*1b8adde7SWilliam Kucharski 821*1b8adde7SWilliam Kucharski if (pci->ioaddr == 0) 822*1b8adde7SWilliam Kucharski return 0; 823*1b8adde7SWilliam Kucharski 824*1b8adde7SWilliam Kucharski printf("ns83820.c: Found %s, vendor=0x%hX, device=0x%hX\n", 825*1b8adde7SWilliam Kucharski pci->name, pci->vendor, pci->dev_id); 826*1b8adde7SWilliam Kucharski 827*1b8adde7SWilliam Kucharski /* point to private storage */ 828*1b8adde7SWilliam Kucharski ns = &nsx; 829*1b8adde7SWilliam Kucharski 830*1b8adde7SWilliam Kucharski adjust_pci_device(pci); 831*1b8adde7SWilliam Kucharski 832*1b8adde7SWilliam Kucharski addr = pci_bar_start(pci, PCI_BASE_ADDRESS_1); 833*1b8adde7SWilliam Kucharski sz = pci_bar_size(pci, PCI_BASE_ADDRESS_1); 834*1b8adde7SWilliam Kucharski 835*1b8adde7SWilliam Kucharski ns->base = ioremap(addr, (1UL << 12)); 836*1b8adde7SWilliam Kucharski // ns->base = ioremap(addr, sz); 837*1b8adde7SWilliam Kucharski 838*1b8adde7SWilliam Kucharski if (!ns->base) 839*1b8adde7SWilliam Kucharski return 0; 840*1b8adde7SWilliam Kucharski 841*1b8adde7SWilliam Kucharski nic->irqno = 0; 842*1b8adde7SWilliam Kucharski nic->ioaddr = pci->ioaddr & ~3; 843*1b8adde7SWilliam Kucharski 844*1b8adde7SWilliam Kucharski /* disable interrupts */ 845*1b8adde7SWilliam Kucharski writel(0, ns->base + IMR); 846*1b8adde7SWilliam Kucharski writel(0, ns->base + IER); 847*1b8adde7SWilliam Kucharski readl(ns->base + IER); 848*1b8adde7SWilliam Kucharski 849*1b8adde7SWilliam Kucharski ns->IMR_cache = 0; 850*1b8adde7SWilliam Kucharski 851*1b8adde7SWilliam Kucharski ns83820_do_reset(nic, CR_RST); 852*1b8adde7SWilliam Kucharski 853*1b8adde7SWilliam Kucharski /* Must reset the ram bist before running it */ 854*1b8adde7SWilliam Kucharski writel(PTSCR_RBIST_RST, ns->base + PTSCR); 855*1b8adde7SWilliam Kucharski ns83820_run_bist(nic, "sram bist", PTSCR_RBIST_EN, 856*1b8adde7SWilliam Kucharski PTSCR_RBIST_DONE, PTSCR_RBIST_FAIL); 857*1b8adde7SWilliam Kucharski ns83820_run_bist(nic, "eeprom bist", PTSCR_EEBIST_EN, 0, 858*1b8adde7SWilliam Kucharski PTSCR_EEBIST_FAIL); 859*1b8adde7SWilliam Kucharski ns83820_run_bist(nic, "eeprom load", PTSCR_EELOAD_EN, 0, 0); 860*1b8adde7SWilliam Kucharski 861*1b8adde7SWilliam Kucharski /* I love config registers */ 862*1b8adde7SWilliam Kucharski ns->CFG_cache = readl(ns->base + CFG); 863*1b8adde7SWilliam Kucharski 864*1b8adde7SWilliam Kucharski if ((ns->CFG_cache & CFG_PCI64_DET)) { 865*1b8adde7SWilliam Kucharski printf("%s: detected 64 bit PCI data bus.\n", pci->name); 866*1b8adde7SWilliam Kucharski /*dev->CFG_cache |= CFG_DATA64_EN; */ 867*1b8adde7SWilliam Kucharski if (!(ns->CFG_cache & CFG_DATA64_EN)) 868*1b8adde7SWilliam Kucharski printf 869*1b8adde7SWilliam Kucharski ("%s: EEPROM did not enable 64 bit bus. Disabled.\n", 870*1b8adde7SWilliam Kucharski pci->name); 871*1b8adde7SWilliam Kucharski } else 872*1b8adde7SWilliam Kucharski ns->CFG_cache &= ~(CFG_DATA64_EN); 873*1b8adde7SWilliam Kucharski 874*1b8adde7SWilliam Kucharski ns->CFG_cache &= (CFG_TBI_EN | CFG_MRM_DIS | CFG_MWI_DIS | 875*1b8adde7SWilliam Kucharski CFG_T64ADDR | CFG_DATA64_EN | CFG_EXT_125 | 876*1b8adde7SWilliam Kucharski CFG_M64ADDR); 877*1b8adde7SWilliam Kucharski ns->CFG_cache |= 878*1b8adde7SWilliam Kucharski CFG_PINT_DUPSTS | CFG_PINT_LNKSTS | CFG_PINT_SPDSTS | 879*1b8adde7SWilliam Kucharski CFG_EXTSTS_EN | CFG_EXD | CFG_PESEL; 880*1b8adde7SWilliam Kucharski ns->CFG_cache |= CFG_REQALG; 881*1b8adde7SWilliam Kucharski ns->CFG_cache |= CFG_POW; 882*1b8adde7SWilliam Kucharski ns->CFG_cache |= CFG_TMRTEST; 883*1b8adde7SWilliam Kucharski 884*1b8adde7SWilliam Kucharski /* When compiled with 64 bit addressing, we must always enable 885*1b8adde7SWilliam Kucharski * the 64 bit descriptor format. 886*1b8adde7SWilliam Kucharski */ 887*1b8adde7SWilliam Kucharski #ifdef USE_64BIT_ADDR 888*1b8adde7SWilliam Kucharski ns->CFG_cache |= CFG_M64ADDR; 889*1b8adde7SWilliam Kucharski #endif 890*1b8adde7SWilliam Kucharski 891*1b8adde7SWilliam Kucharski //FIXME: Enable section on dac or remove this 892*1b8adde7SWilliam Kucharski if (using_dac) 893*1b8adde7SWilliam Kucharski ns->CFG_cache |= CFG_T64ADDR; 894*1b8adde7SWilliam Kucharski 895*1b8adde7SWilliam Kucharski /* Big endian mode does not seem to do what the docs suggest */ 896*1b8adde7SWilliam Kucharski ns->CFG_cache &= ~CFG_BEM; 897*1b8adde7SWilliam Kucharski 898*1b8adde7SWilliam Kucharski /* setup optical transceiver if we have one */ 899*1b8adde7SWilliam Kucharski if (ns->CFG_cache & CFG_TBI_EN) { 900*1b8adde7SWilliam Kucharski dprintf(("%s: enabling optical transceiver\n", pci->name)); 901*1b8adde7SWilliam Kucharski writel(readl(ns->base + GPIOR) | 0x3e8, ns->base + GPIOR); 902*1b8adde7SWilliam Kucharski 903*1b8adde7SWilliam Kucharski /* setup auto negotiation feature advertisement */ 904*1b8adde7SWilliam Kucharski writel(readl(ns->base + TANAR) 905*1b8adde7SWilliam Kucharski | TANAR_HALF_DUP | TANAR_FULL_DUP, 906*1b8adde7SWilliam Kucharski ns->base + TANAR); 907*1b8adde7SWilliam Kucharski 908*1b8adde7SWilliam Kucharski /* start auto negotiation */ 909*1b8adde7SWilliam Kucharski writel(TBICR_MR_AN_ENABLE | TBICR_MR_RESTART_AN, 910*1b8adde7SWilliam Kucharski ns->base + TBICR); 911*1b8adde7SWilliam Kucharski writel(TBICR_MR_AN_ENABLE, ns->base + TBICR); 912*1b8adde7SWilliam Kucharski ns->linkstate = LINK_AUTONEGOTIATE; 913*1b8adde7SWilliam Kucharski 914*1b8adde7SWilliam Kucharski ns->CFG_cache |= CFG_MODE_1000; 915*1b8adde7SWilliam Kucharski } 916*1b8adde7SWilliam Kucharski writel(ns->CFG_cache, ns->base + CFG); 917*1b8adde7SWilliam Kucharski dprintf(("CFG: %hX\n", ns->CFG_cache)); 918*1b8adde7SWilliam Kucharski 919*1b8adde7SWilliam Kucharski /* FIXME: reset_phy is defaulted to 0, should we reset anyway? */ 920*1b8adde7SWilliam Kucharski if (reset_phy) { 921*1b8adde7SWilliam Kucharski dprintf(("%s: resetting phy\n", pci->name)); 922*1b8adde7SWilliam Kucharski writel(ns->CFG_cache | CFG_PHY_RST, ns->base + CFG); 923*1b8adde7SWilliam Kucharski writel(ns->CFG_cache, ns->base + CFG); 924*1b8adde7SWilliam Kucharski } 925*1b8adde7SWilliam Kucharski #if 0 /* Huh? This sets the PCI latency register. Should be done via 926*1b8adde7SWilliam Kucharski * the PCI layer. FIXME. 927*1b8adde7SWilliam Kucharski */ 928*1b8adde7SWilliam Kucharski if (readl(dev->base + SRR)) 929*1b8adde7SWilliam Kucharski writel(readl(dev->base + 0x20c) | 0xfe00, 930*1b8adde7SWilliam Kucharski dev->base + 0x20c); 931*1b8adde7SWilliam Kucharski #endif 932*1b8adde7SWilliam Kucharski 933*1b8adde7SWilliam Kucharski /* Note! The DMA burst size interacts with packet 934*1b8adde7SWilliam Kucharski * transmission, such that the largest packet that 935*1b8adde7SWilliam Kucharski * can be transmitted is 8192 - FLTH - burst size. 936*1b8adde7SWilliam Kucharski * If only the transmit fifo was larger... 937*1b8adde7SWilliam Kucharski */ 938*1b8adde7SWilliam Kucharski /* Ramit : 1024 DMA is not a good idea, it ends up banging 939*1b8adde7SWilliam Kucharski * some DELL and COMPAQ SMP systems */ 940*1b8adde7SWilliam Kucharski writel(TXCFG_CSI | TXCFG_HBI | TXCFG_ATP | TXCFG_MXDMA512 941*1b8adde7SWilliam Kucharski | ((1600 / 32) * 0x100), ns->base + TXCFG); 942*1b8adde7SWilliam Kucharski 943*1b8adde7SWilliam Kucharski /* Set Rx to full duplex, don't accept runt, errored, long or length 944*1b8adde7SWilliam Kucharski * range errored packets. Use 512 byte DMA. 945*1b8adde7SWilliam Kucharski */ 946*1b8adde7SWilliam Kucharski /* Ramit : 1024 DMA is not a good idea, it ends up banging 947*1b8adde7SWilliam Kucharski * some DELL and COMPAQ SMP systems 948*1b8adde7SWilliam Kucharski * Turn on ALP, only we are accpeting Jumbo Packets */ 949*1b8adde7SWilliam Kucharski writel(RXCFG_AEP | RXCFG_ARP | RXCFG_AIRL | RXCFG_RX_FD 950*1b8adde7SWilliam Kucharski | RXCFG_STRIPCRC 951*1b8adde7SWilliam Kucharski //| RXCFG_ALP 952*1b8adde7SWilliam Kucharski | (RXCFG_MXDMA512) | 0, ns->base + RXCFG); 953*1b8adde7SWilliam Kucharski 954*1b8adde7SWilliam Kucharski /* Disable priority queueing */ 955*1b8adde7SWilliam Kucharski writel(0, ns->base + PQCR); 956*1b8adde7SWilliam Kucharski 957*1b8adde7SWilliam Kucharski /* Enable IP checksum validation and detetion of VLAN headers. 958*1b8adde7SWilliam Kucharski * Note: do not set the reject options as at least the 0x102 959*1b8adde7SWilliam Kucharski * revision of the chip does not properly accept IP fragments 960*1b8adde7SWilliam Kucharski * at least for UDP. 961*1b8adde7SWilliam Kucharski */ 962*1b8adde7SWilliam Kucharski /* Ramit : Be sure to turn on RXCFG_ARP if VLAN's are enabled, since 963*1b8adde7SWilliam Kucharski * the MAC it calculates the packetsize AFTER stripping the VLAN 964*1b8adde7SWilliam Kucharski * header, and if a VLAN Tagged packet of 64 bytes is received (like 965*1b8adde7SWilliam Kucharski * a ping with a VLAN header) then the card, strips the 4 byte VLAN 966*1b8adde7SWilliam Kucharski * tag and then checks the packet size, so if RXCFG_ARP is not enabled, 967*1b8adde7SWilliam Kucharski * it discrards it!. These guys...... 968*1b8adde7SWilliam Kucharski */ 969*1b8adde7SWilliam Kucharski writel(VRCR_IPEN | VRCR_VTDEN, ns->base + VRCR); 970*1b8adde7SWilliam Kucharski 971*1b8adde7SWilliam Kucharski /* Enable per-packet TCP/UDP/IP checksumming */ 972*1b8adde7SWilliam Kucharski writel(VTCR_PPCHK, ns->base + VTCR); 973*1b8adde7SWilliam Kucharski 974*1b8adde7SWilliam Kucharski /* Ramit : Enable async and sync pause frames */ 975*1b8adde7SWilliam Kucharski // writel(0, ns->base + PCR); 976*1b8adde7SWilliam Kucharski writel((PCR_PS_MCAST | PCR_PS_DA | PCR_PSEN | PCR_FFLO_4K | 977*1b8adde7SWilliam Kucharski PCR_FFHI_8K | PCR_STLO_4 | PCR_STHI_8 | PCR_PAUSE_CNT), 978*1b8adde7SWilliam Kucharski ns->base + PCR); 979*1b8adde7SWilliam Kucharski 980*1b8adde7SWilliam Kucharski /* Disable Wake On Lan */ 981*1b8adde7SWilliam Kucharski writel(0, ns->base + WCSR); 982*1b8adde7SWilliam Kucharski 983*1b8adde7SWilliam Kucharski ns83820_getmac(nic, nic->node_addr); 984*1b8adde7SWilliam Kucharski printf("%! at ioaddr 0x%hX, ", nic->node_addr, ns->base); 985*1b8adde7SWilliam Kucharski 986*1b8adde7SWilliam Kucharski if (using_dac) { 987*1b8adde7SWilliam Kucharski dprintf(("%s: using 64 bit addressing.\n", pci->name)); 988*1b8adde7SWilliam Kucharski } 989*1b8adde7SWilliam Kucharski 990*1b8adde7SWilliam Kucharski dprintf(("%s: DP83820 %d.%d: %! io=0x%hX\n", 991*1b8adde7SWilliam Kucharski pci->name, 992*1b8adde7SWilliam Kucharski (unsigned) readl(ns->base + SRR) >> 8, 993*1b8adde7SWilliam Kucharski (unsigned) readl(ns->base + SRR) & 0xff, 994*1b8adde7SWilliam Kucharski nic->node_addr, pci->ioaddr)); 995*1b8adde7SWilliam Kucharski 996*1b8adde7SWilliam Kucharski #ifdef PHY_CODE_IS_FINISHED 997*1b8adde7SWilliam Kucharski ns83820_probe_phy(dev); 998*1b8adde7SWilliam Kucharski #endif 999*1b8adde7SWilliam Kucharski 1000*1b8adde7SWilliam Kucharski ns83820_reset(nic); 1001*1b8adde7SWilliam Kucharski /* point to NIC specific routines */ 1002*1b8adde7SWilliam Kucharski dev->disable = ns83820_disable; 1003*1b8adde7SWilliam Kucharski nic->poll = ns83820_poll; 1004*1b8adde7SWilliam Kucharski nic->transmit = ns83820_transmit; 1005*1b8adde7SWilliam Kucharski nic->irq = ns83820_irq; 1006*1b8adde7SWilliam Kucharski return 1; 1007*1b8adde7SWilliam Kucharski } 1008*1b8adde7SWilliam Kucharski 1009*1b8adde7SWilliam Kucharski static struct pci_id ns83820_nics[] = { 1010*1b8adde7SWilliam Kucharski PCI_ROM(0x100b, 0x0022, "ns83820", "National Semiconductor 83820"), 1011*1b8adde7SWilliam Kucharski }; 1012*1b8adde7SWilliam Kucharski 1013*1b8adde7SWilliam Kucharski struct pci_driver ns83820_driver = { 1014*1b8adde7SWilliam Kucharski .type = NIC_DRIVER, 1015*1b8adde7SWilliam Kucharski .name = "NS83820/PCI", 1016*1b8adde7SWilliam Kucharski .probe = ns83820_probe, 1017*1b8adde7SWilliam Kucharski .ids = ns83820_nics, 1018*1b8adde7SWilliam Kucharski .id_count = sizeof(ns83820_nics) / sizeof(ns83820_nics[0]), 1019*1b8adde7SWilliam Kucharski .class = 0, 1020*1b8adde7SWilliam Kucharski }; 1021