1*1b8adde7SWilliam Kucharski /* rhine.c:Fast Ethernet driver for Linux. */ 2*1b8adde7SWilliam Kucharski /* 3*1b8adde7SWilliam Kucharski Adapted 09-jan-2000 by Paolo Marini (paolom@prisma-eng.it) 4*1b8adde7SWilliam Kucharski 5*1b8adde7SWilliam Kucharski originally written by Donald Becker. 6*1b8adde7SWilliam Kucharski 7*1b8adde7SWilliam Kucharski This software may be used and distributed according to the terms 8*1b8adde7SWilliam Kucharski of the GNU Public License (GPL), incorporated herein by reference. 9*1b8adde7SWilliam Kucharski Drivers derived from this code also fall under the GPL and must retain 10*1b8adde7SWilliam Kucharski this authorship and copyright notice. 11*1b8adde7SWilliam Kucharski 12*1b8adde7SWilliam Kucharski Under no circumstances are the authors responsible for 13*1b8adde7SWilliam Kucharski the proper functioning of this software, nor do the authors assume any 14*1b8adde7SWilliam Kucharski responsibility for damages incurred with its use. 15*1b8adde7SWilliam Kucharski 16*1b8adde7SWilliam Kucharski This driver is designed for the VIA VT86C100A Rhine-II PCI Fast Ethernet 17*1b8adde7SWilliam Kucharski controller. 18*1b8adde7SWilliam Kucharski 19*1b8adde7SWilliam Kucharski */ 20*1b8adde7SWilliam Kucharski 21*1b8adde7SWilliam Kucharski static const char *version = "rhine.c v1.0.1 2003-02-06\n"; 22*1b8adde7SWilliam Kucharski 23*1b8adde7SWilliam Kucharski /* A few user-configurable values. */ 24*1b8adde7SWilliam Kucharski 25*1b8adde7SWilliam Kucharski /* Size of the in-memory receive ring. */ 26*1b8adde7SWilliam Kucharski #define RX_BUF_LEN_IDX 3 /* 0==8K, 1==16K, 2==32K, 3==64K */ 27*1b8adde7SWilliam Kucharski #define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) 28*1b8adde7SWilliam Kucharski 29*1b8adde7SWilliam Kucharski /* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ 30*1b8adde7SWilliam Kucharski #define TX_BUF_SIZE 1536 31*1b8adde7SWilliam Kucharski #define RX_BUF_SIZE 1536 32*1b8adde7SWilliam Kucharski 33*1b8adde7SWilliam Kucharski /* PCI Tuning Parameters 34*1b8adde7SWilliam Kucharski Threshold is bytes transferred to chip before transmission starts. */ 35*1b8adde7SWilliam Kucharski #define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ 36*1b8adde7SWilliam Kucharski 37*1b8adde7SWilliam Kucharski /* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. */ 38*1b8adde7SWilliam Kucharski #define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */ 39*1b8adde7SWilliam Kucharski #define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */ 40*1b8adde7SWilliam Kucharski #define TX_DMA_BURST 4 41*1b8adde7SWilliam Kucharski 42*1b8adde7SWilliam Kucharski /* Operational parameters that usually are not changed. */ 43*1b8adde7SWilliam Kucharski /* Time in jiffies before concluding the transmitter is hung. */ 44*1b8adde7SWilliam Kucharski #define TX_TIMEOUT ((2000*HZ)/1000) 45*1b8adde7SWilliam Kucharski 46*1b8adde7SWilliam Kucharski #include "etherboot.h" 47*1b8adde7SWilliam Kucharski #include "nic.h" 48*1b8adde7SWilliam Kucharski #include "pci.h" 49*1b8adde7SWilliam Kucharski 50*1b8adde7SWilliam Kucharski /* define all ioaddr */ 51*1b8adde7SWilliam Kucharski 52*1b8adde7SWilliam Kucharski #define byPAR0 ioaddr 53*1b8adde7SWilliam Kucharski #define byRCR ioaddr + 6 54*1b8adde7SWilliam Kucharski #define byTCR ioaddr + 7 55*1b8adde7SWilliam Kucharski #define byCR0 ioaddr + 8 56*1b8adde7SWilliam Kucharski #define byCR1 ioaddr + 9 57*1b8adde7SWilliam Kucharski #define byISR0 ioaddr + 0x0c 58*1b8adde7SWilliam Kucharski #define byISR1 ioaddr + 0x0d 59*1b8adde7SWilliam Kucharski #define byIMR0 ioaddr + 0x0e 60*1b8adde7SWilliam Kucharski #define byIMR1 ioaddr + 0x0f 61*1b8adde7SWilliam Kucharski #define byMAR0 ioaddr + 0x10 62*1b8adde7SWilliam Kucharski #define byMAR1 ioaddr + 0x11 63*1b8adde7SWilliam Kucharski #define byMAR2 ioaddr + 0x12 64*1b8adde7SWilliam Kucharski #define byMAR3 ioaddr + 0x13 65*1b8adde7SWilliam Kucharski #define byMAR4 ioaddr + 0x14 66*1b8adde7SWilliam Kucharski #define byMAR5 ioaddr + 0x15 67*1b8adde7SWilliam Kucharski #define byMAR6 ioaddr + 0x16 68*1b8adde7SWilliam Kucharski #define byMAR7 ioaddr + 0x17 69*1b8adde7SWilliam Kucharski #define dwCurrentRxDescAddr ioaddr + 0x18 70*1b8adde7SWilliam Kucharski #define dwCurrentTxDescAddr ioaddr + 0x1c 71*1b8adde7SWilliam Kucharski #define dwCurrentRDSE0 ioaddr + 0x20 72*1b8adde7SWilliam Kucharski #define dwCurrentRDSE1 ioaddr + 0x24 73*1b8adde7SWilliam Kucharski #define dwCurrentRDSE2 ioaddr + 0x28 74*1b8adde7SWilliam Kucharski #define dwCurrentRDSE3 ioaddr + 0x2c 75*1b8adde7SWilliam Kucharski #define dwNextRDSE0 ioaddr + 0x30 76*1b8adde7SWilliam Kucharski #define dwNextRDSE1 ioaddr + 0x34 77*1b8adde7SWilliam Kucharski #define dwNextRDSE2 ioaddr + 0x38 78*1b8adde7SWilliam Kucharski #define dwNextRDSE3 ioaddr + 0x3c 79*1b8adde7SWilliam Kucharski #define dwCurrentTDSE0 ioaddr + 0x40 80*1b8adde7SWilliam Kucharski #define dwCurrentTDSE1 ioaddr + 0x44 81*1b8adde7SWilliam Kucharski #define dwCurrentTDSE2 ioaddr + 0x48 82*1b8adde7SWilliam Kucharski #define dwCurrentTDSE3 ioaddr + 0x4c 83*1b8adde7SWilliam Kucharski #define dwNextTDSE0 ioaddr + 0x50 84*1b8adde7SWilliam Kucharski #define dwNextTDSE1 ioaddr + 0x54 85*1b8adde7SWilliam Kucharski #define dwNextTDSE2 ioaddr + 0x58 86*1b8adde7SWilliam Kucharski #define dwNextTDSE3 ioaddr + 0x5c 87*1b8adde7SWilliam Kucharski #define dwCurrRxDMAPtr ioaddr + 0x60 88*1b8adde7SWilliam Kucharski #define dwCurrTxDMAPtr ioaddr + 0x64 89*1b8adde7SWilliam Kucharski #define byMPHY ioaddr + 0x6c 90*1b8adde7SWilliam Kucharski #define byMIISR ioaddr + 0x6d 91*1b8adde7SWilliam Kucharski #define byBCR0 ioaddr + 0x6e 92*1b8adde7SWilliam Kucharski #define byBCR1 ioaddr + 0x6f 93*1b8adde7SWilliam Kucharski #define byMIICR ioaddr + 0x70 94*1b8adde7SWilliam Kucharski #define byMIIAD ioaddr + 0x71 95*1b8adde7SWilliam Kucharski #define wMIIDATA ioaddr + 0x72 96*1b8adde7SWilliam Kucharski #define byEECSR ioaddr + 0x74 97*1b8adde7SWilliam Kucharski #define byTEST ioaddr + 0x75 98*1b8adde7SWilliam Kucharski #define byGPIO ioaddr + 0x76 99*1b8adde7SWilliam Kucharski #define byCFGA ioaddr + 0x78 100*1b8adde7SWilliam Kucharski #define byCFGB ioaddr + 0x79 101*1b8adde7SWilliam Kucharski #define byCFGC ioaddr + 0x7a 102*1b8adde7SWilliam Kucharski #define byCFGD ioaddr + 0x7b 103*1b8adde7SWilliam Kucharski #define wTallyCntMPA ioaddr + 0x7c 104*1b8adde7SWilliam Kucharski #define wTallyCntCRC ioaddr + 0x7d 105*1b8adde7SWilliam Kucharski #define bySTICKHW ioaddr + 0x83 106*1b8adde7SWilliam Kucharski #define byWOLcrClr ioaddr + 0xA4 107*1b8adde7SWilliam Kucharski #define byWOLcgClr ioaddr + 0xA7 108*1b8adde7SWilliam Kucharski #define byPwrcsrClr ioaddr + 0xAC 109*1b8adde7SWilliam Kucharski 110*1b8adde7SWilliam Kucharski /*--------------------- Exioaddr Definitions -------------------------*/ 111*1b8adde7SWilliam Kucharski 112*1b8adde7SWilliam Kucharski /* 113*1b8adde7SWilliam Kucharski * Bits in the RCR register 114*1b8adde7SWilliam Kucharski */ 115*1b8adde7SWilliam Kucharski 116*1b8adde7SWilliam Kucharski #define RCR_RRFT2 0x80 117*1b8adde7SWilliam Kucharski #define RCR_RRFT1 0x40 118*1b8adde7SWilliam Kucharski #define RCR_RRFT0 0x20 119*1b8adde7SWilliam Kucharski #define RCR_PROM 0x10 120*1b8adde7SWilliam Kucharski #define RCR_AB 0x08 121*1b8adde7SWilliam Kucharski #define RCR_AM 0x04 122*1b8adde7SWilliam Kucharski #define RCR_AR 0x02 123*1b8adde7SWilliam Kucharski #define RCR_SEP 0x01 124*1b8adde7SWilliam Kucharski 125*1b8adde7SWilliam Kucharski /* 126*1b8adde7SWilliam Kucharski * Bits in the TCR register 127*1b8adde7SWilliam Kucharski */ 128*1b8adde7SWilliam Kucharski 129*1b8adde7SWilliam Kucharski #define TCR_RTSF 0x80 130*1b8adde7SWilliam Kucharski #define TCR_RTFT1 0x40 131*1b8adde7SWilliam Kucharski #define TCR_RTFT0 0x20 132*1b8adde7SWilliam Kucharski #define TCR_OFSET 0x08 133*1b8adde7SWilliam Kucharski #define TCR_LB1 0x04 /* loopback[1] */ 134*1b8adde7SWilliam Kucharski #define TCR_LB0 0x02 /* loopback[0] */ 135*1b8adde7SWilliam Kucharski 136*1b8adde7SWilliam Kucharski /* 137*1b8adde7SWilliam Kucharski * Bits in the CR0 register 138*1b8adde7SWilliam Kucharski */ 139*1b8adde7SWilliam Kucharski 140*1b8adde7SWilliam Kucharski #define CR0_RDMD 0x40 /* rx descriptor polling demand */ 141*1b8adde7SWilliam Kucharski #define CR0_TDMD 0x20 /* tx descriptor polling demand */ 142*1b8adde7SWilliam Kucharski #define CR0_TXON 0x10 143*1b8adde7SWilliam Kucharski #define CR0_RXON 0x08 144*1b8adde7SWilliam Kucharski #define CR0_STOP 0x04 /* stop NIC, default = 1 */ 145*1b8adde7SWilliam Kucharski #define CR0_STRT 0x02 /* start NIC */ 146*1b8adde7SWilliam Kucharski #define CR0_INIT 0x01 /* start init process */ 147*1b8adde7SWilliam Kucharski 148*1b8adde7SWilliam Kucharski 149*1b8adde7SWilliam Kucharski /* 150*1b8adde7SWilliam Kucharski * Bits in the CR1 register 151*1b8adde7SWilliam Kucharski */ 152*1b8adde7SWilliam Kucharski 153*1b8adde7SWilliam Kucharski #define CR1_SFRST 0x80 /* software reset */ 154*1b8adde7SWilliam Kucharski #define CR1_RDMD1 0x40 /* RDMD1 */ 155*1b8adde7SWilliam Kucharski #define CR1_TDMD1 0x20 /* TDMD1 */ 156*1b8adde7SWilliam Kucharski #define CR1_KEYPAG 0x10 /* turn on par/key */ 157*1b8adde7SWilliam Kucharski #define CR1_DPOLL 0x08 /* disable rx/tx auto polling */ 158*1b8adde7SWilliam Kucharski #define CR1_FDX 0x04 /* full duplex mode */ 159*1b8adde7SWilliam Kucharski #define CR1_ETEN 0x02 /* early tx mode */ 160*1b8adde7SWilliam Kucharski #define CR1_EREN 0x01 /* early rx mode */ 161*1b8adde7SWilliam Kucharski 162*1b8adde7SWilliam Kucharski /* 163*1b8adde7SWilliam Kucharski * Bits in the CR register 164*1b8adde7SWilliam Kucharski */ 165*1b8adde7SWilliam Kucharski 166*1b8adde7SWilliam Kucharski #define CR_RDMD 0x0040 /* rx descriptor polling demand */ 167*1b8adde7SWilliam Kucharski #define CR_TDMD 0x0020 /* tx descriptor polling demand */ 168*1b8adde7SWilliam Kucharski #define CR_TXON 0x0010 169*1b8adde7SWilliam Kucharski #define CR_RXON 0x0008 170*1b8adde7SWilliam Kucharski #define CR_STOP 0x0004 /* stop NIC, default = 1 */ 171*1b8adde7SWilliam Kucharski #define CR_STRT 0x0002 /* start NIC */ 172*1b8adde7SWilliam Kucharski #define CR_INIT 0x0001 /* start init process */ 173*1b8adde7SWilliam Kucharski #define CR_SFRST 0x8000 /* software reset */ 174*1b8adde7SWilliam Kucharski #define CR_RDMD1 0x4000 /* RDMD1 */ 175*1b8adde7SWilliam Kucharski #define CR_TDMD1 0x2000 /* TDMD1 */ 176*1b8adde7SWilliam Kucharski #define CR_KEYPAG 0x1000 /* turn on par/key */ 177*1b8adde7SWilliam Kucharski #define CR_DPOLL 0x0800 /* disable rx/tx auto polling */ 178*1b8adde7SWilliam Kucharski #define CR_FDX 0x0400 /* full duplex mode */ 179*1b8adde7SWilliam Kucharski #define CR_ETEN 0x0200 /* early tx mode */ 180*1b8adde7SWilliam Kucharski #define CR_EREN 0x0100 /* early rx mode */ 181*1b8adde7SWilliam Kucharski 182*1b8adde7SWilliam Kucharski /* 183*1b8adde7SWilliam Kucharski * Bits in the IMR0 register 184*1b8adde7SWilliam Kucharski */ 185*1b8adde7SWilliam Kucharski 186*1b8adde7SWilliam Kucharski #define IMR0_CNTM 0x80 187*1b8adde7SWilliam Kucharski #define IMR0_BEM 0x40 188*1b8adde7SWilliam Kucharski #define IMR0_RUM 0x20 189*1b8adde7SWilliam Kucharski #define IMR0_TUM 0x10 190*1b8adde7SWilliam Kucharski #define IMR0_TXEM 0x08 191*1b8adde7SWilliam Kucharski #define IMR0_RXEM 0x04 192*1b8adde7SWilliam Kucharski #define IMR0_PTXM 0x02 193*1b8adde7SWilliam Kucharski #define IMR0_PRXM 0x01 194*1b8adde7SWilliam Kucharski 195*1b8adde7SWilliam Kucharski /* define imrshadow */ 196*1b8adde7SWilliam Kucharski 197*1b8adde7SWilliam Kucharski #define IMRShadow 0x5AFF 198*1b8adde7SWilliam Kucharski 199*1b8adde7SWilliam Kucharski /* 200*1b8adde7SWilliam Kucharski * Bits in the IMR1 register 201*1b8adde7SWilliam Kucharski */ 202*1b8adde7SWilliam Kucharski 203*1b8adde7SWilliam Kucharski #define IMR1_INITM 0x80 204*1b8adde7SWilliam Kucharski #define IMR1_SRCM 0x40 205*1b8adde7SWilliam Kucharski #define IMR1_NBFM 0x10 206*1b8adde7SWilliam Kucharski #define IMR1_PRAIM 0x08 207*1b8adde7SWilliam Kucharski #define IMR1_RES0M 0x04 208*1b8adde7SWilliam Kucharski #define IMR1_ETM 0x02 209*1b8adde7SWilliam Kucharski #define IMR1_ERM 0x01 210*1b8adde7SWilliam Kucharski 211*1b8adde7SWilliam Kucharski /* 212*1b8adde7SWilliam Kucharski * Bits in the ISR register 213*1b8adde7SWilliam Kucharski */ 214*1b8adde7SWilliam Kucharski 215*1b8adde7SWilliam Kucharski #define ISR_INITI 0x8000 216*1b8adde7SWilliam Kucharski #define ISR_SRCI 0x4000 217*1b8adde7SWilliam Kucharski #define ISR_ABTI 0x2000 218*1b8adde7SWilliam Kucharski #define ISR_NORBF 0x1000 219*1b8adde7SWilliam Kucharski #define ISR_PKTRA 0x0800 220*1b8adde7SWilliam Kucharski #define ISR_RES0 0x0400 221*1b8adde7SWilliam Kucharski #define ISR_ETI 0x0200 222*1b8adde7SWilliam Kucharski #define ISR_ERI 0x0100 223*1b8adde7SWilliam Kucharski #define ISR_CNT 0x0080 224*1b8adde7SWilliam Kucharski #define ISR_BE 0x0040 225*1b8adde7SWilliam Kucharski #define ISR_RU 0x0020 226*1b8adde7SWilliam Kucharski #define ISR_TU 0x0010 227*1b8adde7SWilliam Kucharski #define ISR_TXE 0x0008 228*1b8adde7SWilliam Kucharski #define ISR_RXE 0x0004 229*1b8adde7SWilliam Kucharski #define ISR_PTX 0x0002 230*1b8adde7SWilliam Kucharski #define ISR_PRX 0x0001 231*1b8adde7SWilliam Kucharski 232*1b8adde7SWilliam Kucharski /* 233*1b8adde7SWilliam Kucharski * Bits in the ISR0 register 234*1b8adde7SWilliam Kucharski */ 235*1b8adde7SWilliam Kucharski 236*1b8adde7SWilliam Kucharski #define ISR0_CNT 0x80 237*1b8adde7SWilliam Kucharski #define ISR0_BE 0x40 238*1b8adde7SWilliam Kucharski #define ISR0_RU 0x20 239*1b8adde7SWilliam Kucharski #define ISR0_TU 0x10 240*1b8adde7SWilliam Kucharski #define ISR0_TXE 0x08 241*1b8adde7SWilliam Kucharski #define ISR0_RXE 0x04 242*1b8adde7SWilliam Kucharski #define ISR0_PTX 0x02 243*1b8adde7SWilliam Kucharski #define ISR0_PRX 0x01 244*1b8adde7SWilliam Kucharski 245*1b8adde7SWilliam Kucharski /* 246*1b8adde7SWilliam Kucharski * Bits in the ISR1 register 247*1b8adde7SWilliam Kucharski */ 248*1b8adde7SWilliam Kucharski 249*1b8adde7SWilliam Kucharski #define ISR1_INITI 0x80 250*1b8adde7SWilliam Kucharski #define ISR1_SRCI 0x40 251*1b8adde7SWilliam Kucharski #define ISR1_NORBF 0x10 252*1b8adde7SWilliam Kucharski #define ISR1_PKTRA 0x08 253*1b8adde7SWilliam Kucharski #define ISR1_ETI 0x02 254*1b8adde7SWilliam Kucharski #define ISR1_ERI 0x01 255*1b8adde7SWilliam Kucharski 256*1b8adde7SWilliam Kucharski /* ISR ABNORMAL CONDITION */ 257*1b8adde7SWilliam Kucharski 258*1b8adde7SWilliam Kucharski #define ISR_ABNORMAL ISR_BE+ISR_RU+ISR_TU+ISR_CNT+ISR_NORBF+ISR_PKTRA 259*1b8adde7SWilliam Kucharski 260*1b8adde7SWilliam Kucharski /* 261*1b8adde7SWilliam Kucharski * Bits in the MIISR register 262*1b8adde7SWilliam Kucharski */ 263*1b8adde7SWilliam Kucharski 264*1b8adde7SWilliam Kucharski #define MIISR_MIIERR 0x08 265*1b8adde7SWilliam Kucharski #define MIISR_MRERR 0x04 266*1b8adde7SWilliam Kucharski #define MIISR_LNKFL 0x02 267*1b8adde7SWilliam Kucharski #define MIISR_SPEED 0x01 268*1b8adde7SWilliam Kucharski 269*1b8adde7SWilliam Kucharski /* 270*1b8adde7SWilliam Kucharski * Bits in the MIICR register 271*1b8adde7SWilliam Kucharski */ 272*1b8adde7SWilliam Kucharski 273*1b8adde7SWilliam Kucharski #define MIICR_MAUTO 0x80 274*1b8adde7SWilliam Kucharski #define MIICR_RCMD 0x40 275*1b8adde7SWilliam Kucharski #define MIICR_WCMD 0x20 276*1b8adde7SWilliam Kucharski #define MIICR_MDPM 0x10 277*1b8adde7SWilliam Kucharski #define MIICR_MOUT 0x08 278*1b8adde7SWilliam Kucharski #define MIICR_MDO 0x04 279*1b8adde7SWilliam Kucharski #define MIICR_MDI 0x02 280*1b8adde7SWilliam Kucharski #define MIICR_MDC 0x01 281*1b8adde7SWilliam Kucharski 282*1b8adde7SWilliam Kucharski /* 283*1b8adde7SWilliam Kucharski * Bits in the EECSR register 284*1b8adde7SWilliam Kucharski */ 285*1b8adde7SWilliam Kucharski 286*1b8adde7SWilliam Kucharski #define EECSR_EEPR 0x80 /* eeprom programed status, 73h means programed */ 287*1b8adde7SWilliam Kucharski #define EECSR_EMBP 0x40 /* eeprom embeded programming */ 288*1b8adde7SWilliam Kucharski #define EECSR_AUTOLD 0x20 /* eeprom content reload */ 289*1b8adde7SWilliam Kucharski #define EECSR_DPM 0x10 /* eeprom direct programming */ 290*1b8adde7SWilliam Kucharski #define EECSR_CS 0x08 /* eeprom CS pin */ 291*1b8adde7SWilliam Kucharski #define EECSR_SK 0x04 /* eeprom SK pin */ 292*1b8adde7SWilliam Kucharski #define EECSR_DI 0x02 /* eeprom DI pin */ 293*1b8adde7SWilliam Kucharski #define EECSR_DO 0x01 /* eeprom DO pin */ 294*1b8adde7SWilliam Kucharski 295*1b8adde7SWilliam Kucharski /* 296*1b8adde7SWilliam Kucharski * Bits in the BCR0 register 297*1b8adde7SWilliam Kucharski */ 298*1b8adde7SWilliam Kucharski 299*1b8adde7SWilliam Kucharski #define BCR0_CRFT2 0x20 300*1b8adde7SWilliam Kucharski #define BCR0_CRFT1 0x10 301*1b8adde7SWilliam Kucharski #define BCR0_CRFT0 0x08 302*1b8adde7SWilliam Kucharski #define BCR0_DMAL2 0x04 303*1b8adde7SWilliam Kucharski #define BCR0_DMAL1 0x02 304*1b8adde7SWilliam Kucharski #define BCR0_DMAL0 0x01 305*1b8adde7SWilliam Kucharski 306*1b8adde7SWilliam Kucharski /* 307*1b8adde7SWilliam Kucharski * Bits in the BCR1 register 308*1b8adde7SWilliam Kucharski */ 309*1b8adde7SWilliam Kucharski 310*1b8adde7SWilliam Kucharski #define BCR1_CTSF 0x20 311*1b8adde7SWilliam Kucharski #define BCR1_CTFT1 0x10 312*1b8adde7SWilliam Kucharski #define BCR1_CTFT0 0x08 313*1b8adde7SWilliam Kucharski #define BCR1_POT2 0x04 314*1b8adde7SWilliam Kucharski #define BCR1_POT1 0x02 315*1b8adde7SWilliam Kucharski #define BCR1_POT0 0x01 316*1b8adde7SWilliam Kucharski 317*1b8adde7SWilliam Kucharski /* 318*1b8adde7SWilliam Kucharski * Bits in the CFGA register 319*1b8adde7SWilliam Kucharski */ 320*1b8adde7SWilliam Kucharski 321*1b8adde7SWilliam Kucharski #define CFGA_EELOAD 0x80 /* enable eeprom embeded and direct programming */ 322*1b8adde7SWilliam Kucharski #define CFGA_JUMPER 0x40 323*1b8adde7SWilliam Kucharski #define CFGA_MTGPIO 0x08 324*1b8adde7SWilliam Kucharski #define CFGA_T10EN 0x02 325*1b8adde7SWilliam Kucharski #define CFGA_AUTO 0x01 326*1b8adde7SWilliam Kucharski 327*1b8adde7SWilliam Kucharski /* 328*1b8adde7SWilliam Kucharski * Bits in the CFGB register 329*1b8adde7SWilliam Kucharski */ 330*1b8adde7SWilliam Kucharski 331*1b8adde7SWilliam Kucharski #define CFGB_PD 0x80 332*1b8adde7SWilliam Kucharski #define CFGB_POLEN 0x02 333*1b8adde7SWilliam Kucharski #define CFGB_LNKEN 0x01 334*1b8adde7SWilliam Kucharski 335*1b8adde7SWilliam Kucharski /* 336*1b8adde7SWilliam Kucharski * Bits in the CFGC register 337*1b8adde7SWilliam Kucharski */ 338*1b8adde7SWilliam Kucharski 339*1b8adde7SWilliam Kucharski #define CFGC_M10TIO 0x80 340*1b8adde7SWilliam Kucharski #define CFGC_M10POL 0x40 341*1b8adde7SWilliam Kucharski #define CFGC_PHY1 0x20 342*1b8adde7SWilliam Kucharski #define CFGC_PHY0 0x10 343*1b8adde7SWilliam Kucharski #define CFGC_BTSEL 0x08 344*1b8adde7SWilliam Kucharski #define CFGC_BPS2 0x04 /* bootrom select[2] */ 345*1b8adde7SWilliam Kucharski #define CFGC_BPS1 0x02 /* bootrom select[1] */ 346*1b8adde7SWilliam Kucharski #define CFGC_BPS0 0x01 /* bootrom select[0] */ 347*1b8adde7SWilliam Kucharski 348*1b8adde7SWilliam Kucharski /* 349*1b8adde7SWilliam Kucharski * Bits in the CFGD register 350*1b8adde7SWilliam Kucharski */ 351*1b8adde7SWilliam Kucharski 352*1b8adde7SWilliam Kucharski #define CFGD_GPIOEN 0x80 353*1b8adde7SWilliam Kucharski #define CFGD_DIAG 0x40 354*1b8adde7SWilliam Kucharski #define CFGD_MAGIC 0x10 355*1b8adde7SWilliam Kucharski #define CFGD_CFDX 0x04 356*1b8adde7SWilliam Kucharski #define CFGD_CEREN 0x02 357*1b8adde7SWilliam Kucharski #define CFGD_CETEN 0x01 358*1b8adde7SWilliam Kucharski 359*1b8adde7SWilliam Kucharski /* Bits in RSR */ 360*1b8adde7SWilliam Kucharski #define RSR_RERR 0x00000001 361*1b8adde7SWilliam Kucharski #define RSR_CRC 0x00000002 362*1b8adde7SWilliam Kucharski #define RSR_FAE 0x00000004 363*1b8adde7SWilliam Kucharski #define RSR_FOV 0x00000008 364*1b8adde7SWilliam Kucharski #define RSR_LONG 0x00000010 365*1b8adde7SWilliam Kucharski #define RSR_RUNT 0x00000020 366*1b8adde7SWilliam Kucharski #define RSR_SERR 0x00000040 367*1b8adde7SWilliam Kucharski #define RSR_BUFF 0x00000080 368*1b8adde7SWilliam Kucharski #define RSR_EDP 0x00000100 369*1b8adde7SWilliam Kucharski #define RSR_STP 0x00000200 370*1b8adde7SWilliam Kucharski #define RSR_CHN 0x00000400 371*1b8adde7SWilliam Kucharski #define RSR_PHY 0x00000800 372*1b8adde7SWilliam Kucharski #define RSR_BAR 0x00001000 373*1b8adde7SWilliam Kucharski #define RSR_MAR 0x00002000 374*1b8adde7SWilliam Kucharski #define RSR_RXOK 0x00008000 375*1b8adde7SWilliam Kucharski #define RSR_ABNORMAL RSR_RERR+RSR_LONG+RSR_RUNT 376*1b8adde7SWilliam Kucharski 377*1b8adde7SWilliam Kucharski /* Bits in TSR */ 378*1b8adde7SWilliam Kucharski #define TSR_NCR0 0x00000001 379*1b8adde7SWilliam Kucharski #define TSR_NCR1 0x00000002 380*1b8adde7SWilliam Kucharski #define TSR_NCR2 0x00000004 381*1b8adde7SWilliam Kucharski #define TSR_NCR3 0x00000008 382*1b8adde7SWilliam Kucharski #define TSR_COLS 0x00000010 383*1b8adde7SWilliam Kucharski #define TSR_CDH 0x00000080 384*1b8adde7SWilliam Kucharski #define TSR_ABT 0x00000100 385*1b8adde7SWilliam Kucharski #define TSR_OWC 0x00000200 386*1b8adde7SWilliam Kucharski #define TSR_CRS 0x00000400 387*1b8adde7SWilliam Kucharski #define TSR_UDF 0x00000800 388*1b8adde7SWilliam Kucharski #define TSR_TBUFF 0x00001000 389*1b8adde7SWilliam Kucharski #define TSR_SERR 0x00002000 390*1b8adde7SWilliam Kucharski #define TSR_JAB 0x00004000 391*1b8adde7SWilliam Kucharski #define TSR_TERR 0x00008000 392*1b8adde7SWilliam Kucharski #define TSR_ABNORMAL TSR_TERR+TSR_OWC+TSR_ABT+TSR_JAB+TSR_CRS 393*1b8adde7SWilliam Kucharski #define TSR_OWN_BIT 0x80000000 394*1b8adde7SWilliam Kucharski 395*1b8adde7SWilliam Kucharski #define CB_DELAY_LOOP_WAIT 10 /* 10ms */ 396*1b8adde7SWilliam Kucharski /* enabled mask value of irq */ 397*1b8adde7SWilliam Kucharski 398*1b8adde7SWilliam Kucharski #define W_IMR_MASK_VALUE 0x1BFF /* initial value of IMR */ 399*1b8adde7SWilliam Kucharski 400*1b8adde7SWilliam Kucharski /* Ethernet address filter type */ 401*1b8adde7SWilliam Kucharski #define PKT_TYPE_DIRECTED 0x0001 /* obsolete, directed address is always accepted */ 402*1b8adde7SWilliam Kucharski #define PKT_TYPE_MULTICAST 0x0002 403*1b8adde7SWilliam Kucharski #define PKT_TYPE_ALL_MULTICAST 0x0004 404*1b8adde7SWilliam Kucharski #define PKT_TYPE_BROADCAST 0x0008 405*1b8adde7SWilliam Kucharski #define PKT_TYPE_PROMISCUOUS 0x0020 406*1b8adde7SWilliam Kucharski #define PKT_TYPE_LONG 0x2000 407*1b8adde7SWilliam Kucharski #define PKT_TYPE_RUNT 0x4000 408*1b8adde7SWilliam Kucharski #define PKT_TYPE_ERROR 0x8000 /* accept error packets, e.g. CRC error */ 409*1b8adde7SWilliam Kucharski 410*1b8adde7SWilliam Kucharski /* Loopback mode */ 411*1b8adde7SWilliam Kucharski 412*1b8adde7SWilliam Kucharski #define NIC_LB_NONE 0x00 413*1b8adde7SWilliam Kucharski #define NIC_LB_INTERNAL 0x01 414*1b8adde7SWilliam Kucharski #define NIC_LB_PHY 0x02 /* MII or Internal-10BaseT loopback */ 415*1b8adde7SWilliam Kucharski 416*1b8adde7SWilliam Kucharski #define TX_RING_SIZE 2 417*1b8adde7SWilliam Kucharski #define RX_RING_SIZE 2 418*1b8adde7SWilliam Kucharski #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */ 419*1b8adde7SWilliam Kucharski 420*1b8adde7SWilliam Kucharski /* Transmit and receive descriptors definition */ 421*1b8adde7SWilliam Kucharski 422*1b8adde7SWilliam Kucharski struct rhine_tx_desc 423*1b8adde7SWilliam Kucharski { 424*1b8adde7SWilliam Kucharski union VTC_tx_status_tag 425*1b8adde7SWilliam Kucharski { 426*1b8adde7SWilliam Kucharski struct 427*1b8adde7SWilliam Kucharski { 428*1b8adde7SWilliam Kucharski unsigned long ncro:1; 429*1b8adde7SWilliam Kucharski unsigned long ncr1:1; 430*1b8adde7SWilliam Kucharski unsigned long ncr2:1; 431*1b8adde7SWilliam Kucharski unsigned long ncr3:1; 432*1b8adde7SWilliam Kucharski unsigned long cols:1; 433*1b8adde7SWilliam Kucharski unsigned long reserve_1:2; 434*1b8adde7SWilliam Kucharski unsigned long cdh:1; 435*1b8adde7SWilliam Kucharski unsigned long abt:1; 436*1b8adde7SWilliam Kucharski unsigned long owc:1; 437*1b8adde7SWilliam Kucharski unsigned long crs:1; 438*1b8adde7SWilliam Kucharski unsigned long udf:1; 439*1b8adde7SWilliam Kucharski unsigned long tbuff:1; 440*1b8adde7SWilliam Kucharski unsigned long serr:1; 441*1b8adde7SWilliam Kucharski unsigned long jab:1; 442*1b8adde7SWilliam Kucharski unsigned long terr:1; 443*1b8adde7SWilliam Kucharski unsigned long reserve_2:15; 444*1b8adde7SWilliam Kucharski unsigned long own_bit:1; 445*1b8adde7SWilliam Kucharski } 446*1b8adde7SWilliam Kucharski bits; 447*1b8adde7SWilliam Kucharski unsigned long lw; 448*1b8adde7SWilliam Kucharski } 449*1b8adde7SWilliam Kucharski tx_status; 450*1b8adde7SWilliam Kucharski 451*1b8adde7SWilliam Kucharski union VTC_tx_ctrl_tag 452*1b8adde7SWilliam Kucharski { 453*1b8adde7SWilliam Kucharski struct 454*1b8adde7SWilliam Kucharski { 455*1b8adde7SWilliam Kucharski unsigned long tx_buf_size:11; 456*1b8adde7SWilliam Kucharski unsigned long extend_tx_buf_size:4; 457*1b8adde7SWilliam Kucharski unsigned long chn:1; 458*1b8adde7SWilliam Kucharski unsigned long crc:1; 459*1b8adde7SWilliam Kucharski unsigned long reserve_1:4; 460*1b8adde7SWilliam Kucharski unsigned long stp:1; 461*1b8adde7SWilliam Kucharski unsigned long edp:1; 462*1b8adde7SWilliam Kucharski unsigned long ic:1; 463*1b8adde7SWilliam Kucharski unsigned long reserve_2:8; 464*1b8adde7SWilliam Kucharski } 465*1b8adde7SWilliam Kucharski bits; 466*1b8adde7SWilliam Kucharski unsigned long lw; 467*1b8adde7SWilliam Kucharski } 468*1b8adde7SWilliam Kucharski tx_ctrl; 469*1b8adde7SWilliam Kucharski 470*1b8adde7SWilliam Kucharski unsigned long buf_addr_1:32; 471*1b8adde7SWilliam Kucharski unsigned long buf_addr_2:32; 472*1b8adde7SWilliam Kucharski 473*1b8adde7SWilliam Kucharski }; 474*1b8adde7SWilliam Kucharski 475*1b8adde7SWilliam Kucharski struct rhine_rx_desc 476*1b8adde7SWilliam Kucharski { 477*1b8adde7SWilliam Kucharski union VTC_rx_status_tag 478*1b8adde7SWilliam Kucharski { 479*1b8adde7SWilliam Kucharski struct 480*1b8adde7SWilliam Kucharski { 481*1b8adde7SWilliam Kucharski unsigned long rerr:1; 482*1b8adde7SWilliam Kucharski unsigned long crc_error:1; 483*1b8adde7SWilliam Kucharski unsigned long fae:1; 484*1b8adde7SWilliam Kucharski unsigned long fov:1; 485*1b8adde7SWilliam Kucharski unsigned long toolong:1; 486*1b8adde7SWilliam Kucharski unsigned long runt:1; 487*1b8adde7SWilliam Kucharski unsigned long serr:1; 488*1b8adde7SWilliam Kucharski unsigned long buff:1; 489*1b8adde7SWilliam Kucharski unsigned long edp:1; 490*1b8adde7SWilliam Kucharski unsigned long stp:1; 491*1b8adde7SWilliam Kucharski unsigned long chn:1; 492*1b8adde7SWilliam Kucharski unsigned long phy:1; 493*1b8adde7SWilliam Kucharski unsigned long bar:1; 494*1b8adde7SWilliam Kucharski unsigned long mar:1; 495*1b8adde7SWilliam Kucharski unsigned long reserve_1:1; 496*1b8adde7SWilliam Kucharski unsigned long rxok:1; 497*1b8adde7SWilliam Kucharski unsigned long frame_length:11; 498*1b8adde7SWilliam Kucharski unsigned long reverve_2:4; 499*1b8adde7SWilliam Kucharski unsigned long own_bit:1; 500*1b8adde7SWilliam Kucharski } 501*1b8adde7SWilliam Kucharski bits; 502*1b8adde7SWilliam Kucharski unsigned long lw; 503*1b8adde7SWilliam Kucharski } 504*1b8adde7SWilliam Kucharski rx_status; 505*1b8adde7SWilliam Kucharski 506*1b8adde7SWilliam Kucharski union VTC_rx_ctrl_tag 507*1b8adde7SWilliam Kucharski { 508*1b8adde7SWilliam Kucharski struct 509*1b8adde7SWilliam Kucharski { 510*1b8adde7SWilliam Kucharski unsigned long rx_buf_size:11; 511*1b8adde7SWilliam Kucharski unsigned long extend_rx_buf_size:4; 512*1b8adde7SWilliam Kucharski unsigned long reserved_1:17; 513*1b8adde7SWilliam Kucharski } 514*1b8adde7SWilliam Kucharski bits; 515*1b8adde7SWilliam Kucharski unsigned long lw; 516*1b8adde7SWilliam Kucharski } 517*1b8adde7SWilliam Kucharski rx_ctrl; 518*1b8adde7SWilliam Kucharski 519*1b8adde7SWilliam Kucharski unsigned long buf_addr_1:32; 520*1b8adde7SWilliam Kucharski unsigned long buf_addr_2:32; 521*1b8adde7SWilliam Kucharski 522*1b8adde7SWilliam Kucharski }; 523*1b8adde7SWilliam Kucharski 524*1b8adde7SWilliam Kucharski 525*1b8adde7SWilliam Kucharski /* The I/O extent. */ 526*1b8adde7SWilliam Kucharski #define rhine_TOTAL_SIZE 0x80 527*1b8adde7SWilliam Kucharski 528*1b8adde7SWilliam Kucharski #ifdef HAVE_DEVLIST 529*1b8adde7SWilliam Kucharski struct netdev_entry rhine_drv = 530*1b8adde7SWilliam Kucharski { "rhine", rhine_probe, rhine_TOTAL_SIZE, NULL }; 531*1b8adde7SWilliam Kucharski #endif 532*1b8adde7SWilliam Kucharski 533*1b8adde7SWilliam Kucharski static int rhine_debug = 1; 534*1b8adde7SWilliam Kucharski 535*1b8adde7SWilliam Kucharski /* 536*1b8adde7SWilliam Kucharski Theory of Operation 537*1b8adde7SWilliam Kucharski 538*1b8adde7SWilliam Kucharski I. Board Compatibility 539*1b8adde7SWilliam Kucharski 540*1b8adde7SWilliam Kucharski This driver is designed for the VIA 86c100A Rhine-II PCI Fast Ethernet 541*1b8adde7SWilliam Kucharski controller. 542*1b8adde7SWilliam Kucharski 543*1b8adde7SWilliam Kucharski II. Board-specific settings 544*1b8adde7SWilliam Kucharski 545*1b8adde7SWilliam Kucharski Boards with this chip are functional only in a bus-master PCI slot. 546*1b8adde7SWilliam Kucharski 547*1b8adde7SWilliam Kucharski Many operational settings are loaded from the EEPROM to the Config word at 548*1b8adde7SWilliam Kucharski offset 0x78. This driver assumes that they are correct. 549*1b8adde7SWilliam Kucharski If this driver is compiled to use PCI memory space operations the EEPROM 550*1b8adde7SWilliam Kucharski must be configured to enable memory ops. 551*1b8adde7SWilliam Kucharski 552*1b8adde7SWilliam Kucharski III. Driver operation 553*1b8adde7SWilliam Kucharski 554*1b8adde7SWilliam Kucharski IIIa. Ring buffers 555*1b8adde7SWilliam Kucharski 556*1b8adde7SWilliam Kucharski This driver uses two statically allocated fixed-size descriptor lists 557*1b8adde7SWilliam Kucharski formed into rings by a branch from the final descriptor to the beginning of 558*1b8adde7SWilliam Kucharski the list. The ring sizes are set at compile time by RX/TX_RING_SIZE. 559*1b8adde7SWilliam Kucharski 560*1b8adde7SWilliam Kucharski IIIb/c. Transmit/Receive Structure 561*1b8adde7SWilliam Kucharski 562*1b8adde7SWilliam Kucharski This driver attempts to use a zero-copy receive and transmit scheme. 563*1b8adde7SWilliam Kucharski 564*1b8adde7SWilliam Kucharski Alas, all data buffers are required to start on a 32 bit boundary, so 565*1b8adde7SWilliam Kucharski the driver must often copy transmit packets into bounce buffers. 566*1b8adde7SWilliam Kucharski 567*1b8adde7SWilliam Kucharski The driver allocates full frame size skbuffs for the Rx ring buffers at 568*1b8adde7SWilliam Kucharski open() time and passes the skb->data field to the chip as receive data 569*1b8adde7SWilliam Kucharski buffers. When an incoming frame is less than RX_COPYBREAK bytes long, 570*1b8adde7SWilliam Kucharski a fresh skbuff is allocated and the frame is copied to the new skbuff. 571*1b8adde7SWilliam Kucharski When the incoming frame is larger, the skbuff is passed directly up the 572*1b8adde7SWilliam Kucharski protocol stack. Buffers consumed this way are replaced by newly allocated 573*1b8adde7SWilliam Kucharski skbuffs in the last phase of netdev_rx(). 574*1b8adde7SWilliam Kucharski 575*1b8adde7SWilliam Kucharski The RX_COPYBREAK value is chosen to trade-off the memory wasted by 576*1b8adde7SWilliam Kucharski using a full-sized skbuff for small frames vs. the copying costs of larger 577*1b8adde7SWilliam Kucharski frames. New boards are typically used in generously configured machines 578*1b8adde7SWilliam Kucharski and the underfilled buffers have negligible impact compared to the benefit of 579*1b8adde7SWilliam Kucharski a single allocation size, so the default value of zero results in never 580*1b8adde7SWilliam Kucharski copying packets. When copying is done, the cost is usually mitigated by using 581*1b8adde7SWilliam Kucharski a combined copy/checksum routine. Copying also preloads the cache, which is 582*1b8adde7SWilliam Kucharski most useful with small frames. 583*1b8adde7SWilliam Kucharski 584*1b8adde7SWilliam Kucharski Since the VIA chips are only able to transfer data to buffers on 32 bit 585*1b8adde7SWilliam Kucharski boundaries, the the IP header at offset 14 in an ethernet frame isn't 586*1b8adde7SWilliam Kucharski longword aligned for further processing. Copying these unaligned buffers 587*1b8adde7SWilliam Kucharski has the beneficial effect of 16-byte aligning the IP header. 588*1b8adde7SWilliam Kucharski 589*1b8adde7SWilliam Kucharski IIId. Synchronization 590*1b8adde7SWilliam Kucharski 591*1b8adde7SWilliam Kucharski The driver runs as two independent, single-threaded flows of control. One 592*1b8adde7SWilliam Kucharski is the send-packet routine, which enforces single-threaded use by the 593*1b8adde7SWilliam Kucharski dev->tbusy flag. The other thread is the interrupt handler, which is single 594*1b8adde7SWilliam Kucharski threaded by the hardware and interrupt handling software. 595*1b8adde7SWilliam Kucharski 596*1b8adde7SWilliam Kucharski The send packet thread has partial control over the Tx ring and 'dev->tbusy' 597*1b8adde7SWilliam Kucharski flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next 598*1b8adde7SWilliam Kucharski queue slot is empty, it clears the tbusy flag when finished otherwise it sets 599*1b8adde7SWilliam Kucharski the 'lp->tx_full' flag. 600*1b8adde7SWilliam Kucharski 601*1b8adde7SWilliam Kucharski The interrupt handler has exclusive control over the Rx ring and records stats 602*1b8adde7SWilliam Kucharski from the Tx ring. After reaping the stats, it marks the Tx queue entry as 603*1b8adde7SWilliam Kucharski empty by incrementing the dirty_tx mark. Iff the 'lp->tx_full' flag is set, it 604*1b8adde7SWilliam Kucharski clears both the tx_full and tbusy flags. 605*1b8adde7SWilliam Kucharski 606*1b8adde7SWilliam Kucharski IV. Notes 607*1b8adde7SWilliam Kucharski 608*1b8adde7SWilliam Kucharski IVb. References 609*1b8adde7SWilliam Kucharski 610*1b8adde7SWilliam Kucharski Preliminary VT86C100A manual from http://www.via.com.tw/ 611*1b8adde7SWilliam Kucharski http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html 612*1b8adde7SWilliam Kucharski http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html 613*1b8adde7SWilliam Kucharski 614*1b8adde7SWilliam Kucharski IVc. Errata 615*1b8adde7SWilliam Kucharski 616*1b8adde7SWilliam Kucharski The VT86C100A manual is not reliable information. 617*1b8adde7SWilliam Kucharski The chip does not handle unaligned transmit or receive buffers, resulting 618*1b8adde7SWilliam Kucharski in significant performance degradation for bounce buffer copies on transmit 619*1b8adde7SWilliam Kucharski and unaligned IP headers on receive. 620*1b8adde7SWilliam Kucharski The chip does not pad to minimum transmit length. 621*1b8adde7SWilliam Kucharski 622*1b8adde7SWilliam Kucharski */ 623*1b8adde7SWilliam Kucharski 624*1b8adde7SWilliam Kucharski /* The rest of these values should never change. */ 625*1b8adde7SWilliam Kucharski #define NUM_TX_DESC 2 /* Number of Tx descriptor registers. */ 626*1b8adde7SWilliam Kucharski 627*1b8adde7SWilliam Kucharski static struct rhine_private 628*1b8adde7SWilliam Kucharski { 629*1b8adde7SWilliam Kucharski char devname[8]; /* Used only for kernel debugging. */ 630*1b8adde7SWilliam Kucharski const char *product_name; 631*1b8adde7SWilliam Kucharski struct rhine_rx_desc *rx_ring; 632*1b8adde7SWilliam Kucharski struct rhine_tx_desc *tx_ring; 633*1b8adde7SWilliam Kucharski char *rx_buffs[RX_RING_SIZE]; 634*1b8adde7SWilliam Kucharski char *tx_buffs[TX_RING_SIZE]; 635*1b8adde7SWilliam Kucharski 636*1b8adde7SWilliam Kucharski /* temporary Rx buffers. */ 637*1b8adde7SWilliam Kucharski 638*1b8adde7SWilliam Kucharski int chip_id; 639*1b8adde7SWilliam Kucharski int chip_revision; 640*1b8adde7SWilliam Kucharski unsigned short ioaddr; 641*1b8adde7SWilliam Kucharski unsigned int cur_rx, cur_tx; /* The next free and used entries */ 642*1b8adde7SWilliam Kucharski unsigned int dirty_rx, dirty_tx; 643*1b8adde7SWilliam Kucharski /* The saved address of a sent-in-place packet/buffer, for skfree(). */ 644*1b8adde7SWilliam Kucharski struct sk_buff *tx_skbuff[TX_RING_SIZE]; 645*1b8adde7SWilliam Kucharski unsigned char mc_filter[8]; /* Current multicast filter. */ 646*1b8adde7SWilliam Kucharski char phys[4]; /* MII device addresses. */ 647*1b8adde7SWilliam Kucharski unsigned int tx_full:1; /* The Tx queue is full. */ 648*1b8adde7SWilliam Kucharski unsigned int full_duplex:1; /* Full-duplex operation requested. */ 649*1b8adde7SWilliam Kucharski unsigned int default_port:4; /* Last dev->if_port value. */ 650*1b8adde7SWilliam Kucharski unsigned int media2:4; /* Secondary monitored media port. */ 651*1b8adde7SWilliam Kucharski unsigned int medialock:1; /* Don't sense media type. */ 652*1b8adde7SWilliam Kucharski unsigned int mediasense:1; /* Media sensing in progress. */ 653*1b8adde7SWilliam Kucharski } 654*1b8adde7SWilliam Kucharski rhine; 655*1b8adde7SWilliam Kucharski 656*1b8adde7SWilliam Kucharski static void rhine_probe1 (struct nic *nic, int ioaddr, 657*1b8adde7SWilliam Kucharski int chip_id, int options); 658*1b8adde7SWilliam Kucharski static int QueryAuto (int); 659*1b8adde7SWilliam Kucharski static int ReadMII (int byMIIIndex, int); 660*1b8adde7SWilliam Kucharski static void WriteMII (char, char, char, int); 661*1b8adde7SWilliam Kucharski static void MIIDelay (void); 662*1b8adde7SWilliam Kucharski static void rhine_init_ring (struct nic *dev); 663*1b8adde7SWilliam Kucharski static void rhine_disable (struct dev *dev); 664*1b8adde7SWilliam Kucharski static void rhine_reset (struct nic *nic); 665*1b8adde7SWilliam Kucharski static int rhine_poll (struct nic *nic, int retreive); 666*1b8adde7SWilliam Kucharski static void rhine_transmit (struct nic *nic, const char *d, unsigned int t, 667*1b8adde7SWilliam Kucharski unsigned int s, const char *p); 668*1b8adde7SWilliam Kucharski 669*1b8adde7SWilliam Kucharski /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ 670*1b8adde7SWilliam Kucharski static void 671*1b8adde7SWilliam Kucharski rhine_init_ring (struct nic *nic) 672*1b8adde7SWilliam Kucharski { 673*1b8adde7SWilliam Kucharski struct rhine_private *tp = (struct rhine_private *) nic->priv_data; 674*1b8adde7SWilliam Kucharski int i; 675*1b8adde7SWilliam Kucharski 676*1b8adde7SWilliam Kucharski tp->tx_full = 0; 677*1b8adde7SWilliam Kucharski tp->cur_rx = tp->cur_tx = 0; 678*1b8adde7SWilliam Kucharski tp->dirty_rx = tp->dirty_tx = 0; 679*1b8adde7SWilliam Kucharski 680*1b8adde7SWilliam Kucharski for (i = 0; i < RX_RING_SIZE; i++) 681*1b8adde7SWilliam Kucharski { 682*1b8adde7SWilliam Kucharski 683*1b8adde7SWilliam Kucharski tp->rx_ring[i].rx_status.bits.own_bit = 1; 684*1b8adde7SWilliam Kucharski tp->rx_ring[i].rx_ctrl.bits.rx_buf_size = 1536; 685*1b8adde7SWilliam Kucharski 686*1b8adde7SWilliam Kucharski tp->rx_ring[i].buf_addr_1 = virt_to_bus (tp->rx_buffs[i]); 687*1b8adde7SWilliam Kucharski tp->rx_ring[i].buf_addr_2 = virt_to_bus (&tp->rx_ring[i + 1]); 688*1b8adde7SWilliam Kucharski /* printf("[%d]buf1=%hX,buf2=%hX",i,tp->rx_ring[i].buf_addr_1,tp->rx_ring[i].buf_addr_2); */ 689*1b8adde7SWilliam Kucharski } 690*1b8adde7SWilliam Kucharski /* Mark the last entry as wrapping the ring. */ 691*1b8adde7SWilliam Kucharski /* tp->rx_ring[i-1].rx_ctrl.bits.rx_buf_size =1518; */ 692*1b8adde7SWilliam Kucharski tp->rx_ring[i - 1].buf_addr_2 = virt_to_bus (&tp->rx_ring[0]); 693*1b8adde7SWilliam Kucharski /*printf("[%d]buf1=%hX,buf2=%hX",i-1,tp->rx_ring[i-1].buf_addr_1,tp->rx_ring[i-1].buf_addr_2); */ 694*1b8adde7SWilliam Kucharski 695*1b8adde7SWilliam Kucharski /* The Tx buffer descriptor is filled in as needed, but we 696*1b8adde7SWilliam Kucharski do need to clear the ownership bit. */ 697*1b8adde7SWilliam Kucharski 698*1b8adde7SWilliam Kucharski for (i = 0; i < TX_RING_SIZE; i++) 699*1b8adde7SWilliam Kucharski { 700*1b8adde7SWilliam Kucharski 701*1b8adde7SWilliam Kucharski tp->tx_ring[i].tx_status.lw = 0; 702*1b8adde7SWilliam Kucharski tp->tx_ring[i].tx_ctrl.lw = 0x00e08000; 703*1b8adde7SWilliam Kucharski tp->tx_ring[i].buf_addr_1 = virt_to_bus (tp->tx_buffs[i]); 704*1b8adde7SWilliam Kucharski tp->tx_ring[i].buf_addr_2 = virt_to_bus (&tp->tx_ring[i + 1]); 705*1b8adde7SWilliam Kucharski /* printf("[%d]buf1=%hX,buf2=%hX",i,tp->tx_ring[i].buf_addr_1,tp->tx_ring[i].buf_addr_2); */ 706*1b8adde7SWilliam Kucharski } 707*1b8adde7SWilliam Kucharski 708*1b8adde7SWilliam Kucharski tp->tx_ring[i - 1].buf_addr_2 = virt_to_bus (&tp->tx_ring[0]); 709*1b8adde7SWilliam Kucharski /* printf("[%d]buf1=%hX,buf2=%hX",i,tp->tx_ring[i-1].buf_addr_1,tp->tx_ring[i-1].buf_addr_2); */ 710*1b8adde7SWilliam Kucharski } 711*1b8adde7SWilliam Kucharski 712*1b8adde7SWilliam Kucharski int 713*1b8adde7SWilliam Kucharski QueryAuto (int ioaddr) 714*1b8adde7SWilliam Kucharski { 715*1b8adde7SWilliam Kucharski int byMIIIndex; 716*1b8adde7SWilliam Kucharski int MIIReturn; 717*1b8adde7SWilliam Kucharski 718*1b8adde7SWilliam Kucharski int advertising,mii_reg5; 719*1b8adde7SWilliam Kucharski int negociated; 720*1b8adde7SWilliam Kucharski 721*1b8adde7SWilliam Kucharski byMIIIndex = 0x04; 722*1b8adde7SWilliam Kucharski MIIReturn = ReadMII (byMIIIndex, ioaddr); 723*1b8adde7SWilliam Kucharski advertising=MIIReturn; 724*1b8adde7SWilliam Kucharski 725*1b8adde7SWilliam Kucharski byMIIIndex = 0x05; 726*1b8adde7SWilliam Kucharski MIIReturn = ReadMII (byMIIIndex, ioaddr); 727*1b8adde7SWilliam Kucharski mii_reg5=MIIReturn; 728*1b8adde7SWilliam Kucharski 729*1b8adde7SWilliam Kucharski negociated=mii_reg5 & advertising; 730*1b8adde7SWilliam Kucharski 731*1b8adde7SWilliam Kucharski if ( (negociated & 0x100) || (negociated & 0x1C0) == 0x40 ) 732*1b8adde7SWilliam Kucharski return 1; 733*1b8adde7SWilliam Kucharski else 734*1b8adde7SWilliam Kucharski return 0; 735*1b8adde7SWilliam Kucharski 736*1b8adde7SWilliam Kucharski } 737*1b8adde7SWilliam Kucharski 738*1b8adde7SWilliam Kucharski int 739*1b8adde7SWilliam Kucharski ReadMII (int byMIIIndex, int ioaddr) 740*1b8adde7SWilliam Kucharski { 741*1b8adde7SWilliam Kucharski int ReturnMII; 742*1b8adde7SWilliam Kucharski char byMIIAdrbak; 743*1b8adde7SWilliam Kucharski char byMIICRbak; 744*1b8adde7SWilliam Kucharski char byMIItemp; 745*1b8adde7SWilliam Kucharski 746*1b8adde7SWilliam Kucharski byMIIAdrbak = inb (byMIIAD); 747*1b8adde7SWilliam Kucharski byMIICRbak = inb (byMIICR); 748*1b8adde7SWilliam Kucharski outb (byMIICRbak & 0x7f, byMIICR); 749*1b8adde7SWilliam Kucharski MIIDelay (); 750*1b8adde7SWilliam Kucharski 751*1b8adde7SWilliam Kucharski outb (byMIIIndex, byMIIAD); 752*1b8adde7SWilliam Kucharski MIIDelay (); 753*1b8adde7SWilliam Kucharski 754*1b8adde7SWilliam Kucharski outb (inb (byMIICR) | 0x40, byMIICR); 755*1b8adde7SWilliam Kucharski 756*1b8adde7SWilliam Kucharski byMIItemp = inb (byMIICR); 757*1b8adde7SWilliam Kucharski byMIItemp = byMIItemp & 0x40; 758*1b8adde7SWilliam Kucharski 759*1b8adde7SWilliam Kucharski while (byMIItemp != 0) 760*1b8adde7SWilliam Kucharski { 761*1b8adde7SWilliam Kucharski byMIItemp = inb (byMIICR); 762*1b8adde7SWilliam Kucharski byMIItemp = byMIItemp & 0x40; 763*1b8adde7SWilliam Kucharski } 764*1b8adde7SWilliam Kucharski MIIDelay (); 765*1b8adde7SWilliam Kucharski 766*1b8adde7SWilliam Kucharski ReturnMII = inw (wMIIDATA); 767*1b8adde7SWilliam Kucharski 768*1b8adde7SWilliam Kucharski outb (byMIIAdrbak, byMIIAD); 769*1b8adde7SWilliam Kucharski outb (byMIICRbak, byMIICR); 770*1b8adde7SWilliam Kucharski MIIDelay (); 771*1b8adde7SWilliam Kucharski 772*1b8adde7SWilliam Kucharski return (ReturnMII); 773*1b8adde7SWilliam Kucharski 774*1b8adde7SWilliam Kucharski } 775*1b8adde7SWilliam Kucharski 776*1b8adde7SWilliam Kucharski void 777*1b8adde7SWilliam Kucharski WriteMII (char byMIISetByte, char byMIISetBit, char byMIIOP, int ioaddr) 778*1b8adde7SWilliam Kucharski { 779*1b8adde7SWilliam Kucharski int ReadMIItmp; 780*1b8adde7SWilliam Kucharski int MIIMask; 781*1b8adde7SWilliam Kucharski char byMIIAdrbak; 782*1b8adde7SWilliam Kucharski char byMIICRbak; 783*1b8adde7SWilliam Kucharski char byMIItemp; 784*1b8adde7SWilliam Kucharski 785*1b8adde7SWilliam Kucharski 786*1b8adde7SWilliam Kucharski byMIIAdrbak = inb (byMIIAD); 787*1b8adde7SWilliam Kucharski 788*1b8adde7SWilliam Kucharski byMIICRbak = inb (byMIICR); 789*1b8adde7SWilliam Kucharski outb (byMIICRbak & 0x7f, byMIICR); 790*1b8adde7SWilliam Kucharski MIIDelay (); 791*1b8adde7SWilliam Kucharski outb (byMIISetByte, byMIIAD); 792*1b8adde7SWilliam Kucharski MIIDelay (); 793*1b8adde7SWilliam Kucharski 794*1b8adde7SWilliam Kucharski outb (inb (byMIICR) | 0x40, byMIICR); 795*1b8adde7SWilliam Kucharski 796*1b8adde7SWilliam Kucharski byMIItemp = inb (byMIICR); 797*1b8adde7SWilliam Kucharski byMIItemp = byMIItemp & 0x40; 798*1b8adde7SWilliam Kucharski 799*1b8adde7SWilliam Kucharski while (byMIItemp != 0) 800*1b8adde7SWilliam Kucharski { 801*1b8adde7SWilliam Kucharski byMIItemp = inb (byMIICR); 802*1b8adde7SWilliam Kucharski byMIItemp = byMIItemp & 0x40; 803*1b8adde7SWilliam Kucharski } 804*1b8adde7SWilliam Kucharski MIIDelay (); 805*1b8adde7SWilliam Kucharski 806*1b8adde7SWilliam Kucharski ReadMIItmp = inw (wMIIDATA); 807*1b8adde7SWilliam Kucharski MIIMask = 0x0001; 808*1b8adde7SWilliam Kucharski MIIMask = MIIMask << byMIISetBit; 809*1b8adde7SWilliam Kucharski 810*1b8adde7SWilliam Kucharski 811*1b8adde7SWilliam Kucharski if (byMIIOP == 0) 812*1b8adde7SWilliam Kucharski { 813*1b8adde7SWilliam Kucharski MIIMask = ~MIIMask; 814*1b8adde7SWilliam Kucharski ReadMIItmp = ReadMIItmp & MIIMask; 815*1b8adde7SWilliam Kucharski } 816*1b8adde7SWilliam Kucharski else 817*1b8adde7SWilliam Kucharski { 818*1b8adde7SWilliam Kucharski ReadMIItmp = ReadMIItmp | MIIMask; 819*1b8adde7SWilliam Kucharski 820*1b8adde7SWilliam Kucharski } 821*1b8adde7SWilliam Kucharski outw (ReadMIItmp, wMIIDATA); 822*1b8adde7SWilliam Kucharski MIIDelay (); 823*1b8adde7SWilliam Kucharski 824*1b8adde7SWilliam Kucharski outb (inb (byMIICR) | 0x20, byMIICR); 825*1b8adde7SWilliam Kucharski byMIItemp = inb (byMIICR); 826*1b8adde7SWilliam Kucharski byMIItemp = byMIItemp & 0x20; 827*1b8adde7SWilliam Kucharski 828*1b8adde7SWilliam Kucharski while (byMIItemp != 0) 829*1b8adde7SWilliam Kucharski { 830*1b8adde7SWilliam Kucharski byMIItemp = inb (byMIICR); 831*1b8adde7SWilliam Kucharski byMIItemp = byMIItemp & 0x20; 832*1b8adde7SWilliam Kucharski } 833*1b8adde7SWilliam Kucharski MIIDelay (); 834*1b8adde7SWilliam Kucharski 835*1b8adde7SWilliam Kucharski outb (byMIIAdrbak & 0x7f, byMIIAD); 836*1b8adde7SWilliam Kucharski outb (byMIICRbak, byMIICR); 837*1b8adde7SWilliam Kucharski MIIDelay (); 838*1b8adde7SWilliam Kucharski 839*1b8adde7SWilliam Kucharski } 840*1b8adde7SWilliam Kucharski 841*1b8adde7SWilliam Kucharski void 842*1b8adde7SWilliam Kucharski MIIDelay (void) 843*1b8adde7SWilliam Kucharski { 844*1b8adde7SWilliam Kucharski int i; 845*1b8adde7SWilliam Kucharski for (i = 0; i < 0x7fff; i++) 846*1b8adde7SWilliam Kucharski { 847*1b8adde7SWilliam Kucharski inb (0x61); 848*1b8adde7SWilliam Kucharski inb (0x61); 849*1b8adde7SWilliam Kucharski inb (0x61); 850*1b8adde7SWilliam Kucharski inb (0x61); 851*1b8adde7SWilliam Kucharski } 852*1b8adde7SWilliam Kucharski } 853*1b8adde7SWilliam Kucharski 854*1b8adde7SWilliam Kucharski /* Offsets to the device registers. */ 855*1b8adde7SWilliam Kucharski enum register_offsets { 856*1b8adde7SWilliam Kucharski StationAddr=0x00, RxConfig=0x06, TxConfig=0x07, ChipCmd=0x08, 857*1b8adde7SWilliam Kucharski IntrStatus=0x0C, IntrEnable=0x0E, 858*1b8adde7SWilliam Kucharski MulticastFilter0=0x10, MulticastFilter1=0x14, 859*1b8adde7SWilliam Kucharski RxRingPtr=0x18, TxRingPtr=0x1C, GFIFOTest=0x54, 860*1b8adde7SWilliam Kucharski MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E, 861*1b8adde7SWilliam Kucharski MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, MACRegEEcsr=0x74, 862*1b8adde7SWilliam Kucharski ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B, 863*1b8adde7SWilliam Kucharski RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81, 864*1b8adde7SWilliam Kucharski StickyHW=0x83, IntrStatus2=0x84, WOLcrClr=0xA4, WOLcgClr=0xA7, 865*1b8adde7SWilliam Kucharski PwrcsrClr=0xAC, 866*1b8adde7SWilliam Kucharski }; 867*1b8adde7SWilliam Kucharski 868*1b8adde7SWilliam Kucharski /* Bits in the interrupt status/mask registers. */ 869*1b8adde7SWilliam Kucharski enum intr_status_bits { 870*1b8adde7SWilliam Kucharski IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020, 871*1b8adde7SWilliam Kucharski IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0210, 872*1b8adde7SWilliam Kucharski IntrPCIErr=0x0040, 873*1b8adde7SWilliam Kucharski IntrStatsMax=0x0080, IntrRxEarly=0x0100, 874*1b8adde7SWilliam Kucharski IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000, 875*1b8adde7SWilliam Kucharski IntrTxAborted=0x2000, IntrLinkChange=0x4000, 876*1b8adde7SWilliam Kucharski IntrRxWakeUp=0x8000, 877*1b8adde7SWilliam Kucharski IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260, 878*1b8adde7SWilliam Kucharski IntrTxDescRace=0x080000, /* mapped from IntrStatus2 */ 879*1b8adde7SWilliam Kucharski IntrTxErrSummary=0x082218, 880*1b8adde7SWilliam Kucharski }; 881*1b8adde7SWilliam Kucharski #define DEFAULT_INTR (IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | \ 882*1b8adde7SWilliam Kucharski IntrRxDropped | IntrRxNoBuf) 883*1b8adde7SWilliam Kucharski 884*1b8adde7SWilliam Kucharski /*************************************************************************** 885*1b8adde7SWilliam Kucharski IRQ - PXE IRQ Handler 886*1b8adde7SWilliam Kucharski ***************************************************************************/ 887*1b8adde7SWilliam Kucharski void rhine_irq ( struct nic *nic, irq_action_t action ) { 888*1b8adde7SWilliam Kucharski struct rhine_private *tp = (struct rhine_private *) nic->priv_data; 889*1b8adde7SWilliam Kucharski /* Enable interrupts by setting the interrupt mask. */ 890*1b8adde7SWilliam Kucharski unsigned int intr_status; 891*1b8adde7SWilliam Kucharski 892*1b8adde7SWilliam Kucharski switch ( action ) { 893*1b8adde7SWilliam Kucharski case DISABLE : 894*1b8adde7SWilliam Kucharski case ENABLE : 895*1b8adde7SWilliam Kucharski intr_status = inw(nic->ioaddr + IntrStatus); 896*1b8adde7SWilliam Kucharski /* On Rhine-II, Bit 3 indicates Tx descriptor write-back race. */ 897*1b8adde7SWilliam Kucharski if (tp->chip_id == 0x3065) 898*1b8adde7SWilliam Kucharski intr_status |= inb(nic->ioaddr + IntrStatus2) << 16; 899*1b8adde7SWilliam Kucharski intr_status = (intr_status & ~DEFAULT_INTR); 900*1b8adde7SWilliam Kucharski if ( action == ENABLE ) 901*1b8adde7SWilliam Kucharski intr_status = intr_status | DEFAULT_INTR; 902*1b8adde7SWilliam Kucharski outw(intr_status, nic->ioaddr + IntrEnable); 903*1b8adde7SWilliam Kucharski break; 904*1b8adde7SWilliam Kucharski case FORCE : 905*1b8adde7SWilliam Kucharski outw(0x0010, nic->ioaddr + 0x84); 906*1b8adde7SWilliam Kucharski break; 907*1b8adde7SWilliam Kucharski } 908*1b8adde7SWilliam Kucharski } 909*1b8adde7SWilliam Kucharski 910*1b8adde7SWilliam Kucharski static int 911*1b8adde7SWilliam Kucharski rhine_probe (struct dev *dev, struct pci_device *pci) 912*1b8adde7SWilliam Kucharski { 913*1b8adde7SWilliam Kucharski struct nic *nic = (struct nic *)dev; 914*1b8adde7SWilliam Kucharski struct rhine_private *tp = &rhine; 915*1b8adde7SWilliam Kucharski if (!pci->ioaddr) 916*1b8adde7SWilliam Kucharski return 0; 917*1b8adde7SWilliam Kucharski rhine_probe1 (nic, pci->ioaddr, pci->dev_id, -1); 918*1b8adde7SWilliam Kucharski 919*1b8adde7SWilliam Kucharski adjust_pci_device(pci); 920*1b8adde7SWilliam Kucharski rhine_reset (nic); 921*1b8adde7SWilliam Kucharski 922*1b8adde7SWilliam Kucharski dev->disable = rhine_disable; 923*1b8adde7SWilliam Kucharski nic->poll = rhine_poll; 924*1b8adde7SWilliam Kucharski nic->transmit = rhine_transmit; 925*1b8adde7SWilliam Kucharski nic->irqno = pci->irq; 926*1b8adde7SWilliam Kucharski nic->irq = rhine_irq; 927*1b8adde7SWilliam Kucharski nic->ioaddr = tp->ioaddr; 928*1b8adde7SWilliam Kucharski 929*1b8adde7SWilliam Kucharski 930*1b8adde7SWilliam Kucharski return 1; 931*1b8adde7SWilliam Kucharski } 932*1b8adde7SWilliam Kucharski 933*1b8adde7SWilliam Kucharski static void set_rx_mode(struct nic *nic __unused) { 934*1b8adde7SWilliam Kucharski struct rhine_private *tp = (struct rhine_private *) nic->priv_data; 935*1b8adde7SWilliam Kucharski unsigned char rx_mode; 936*1b8adde7SWilliam Kucharski int ioaddr = tp->ioaddr; 937*1b8adde7SWilliam Kucharski 938*1b8adde7SWilliam Kucharski /* ! IFF_PROMISC */ 939*1b8adde7SWilliam Kucharski outl(0xffffffff, byMAR0); 940*1b8adde7SWilliam Kucharski outl(0xffffffff, byMAR4); 941*1b8adde7SWilliam Kucharski rx_mode = 0x0C; 942*1b8adde7SWilliam Kucharski 943*1b8adde7SWilliam Kucharski outb(0x60 /* thresh */ | rx_mode, byRCR ); 944*1b8adde7SWilliam Kucharski } 945*1b8adde7SWilliam Kucharski 946*1b8adde7SWilliam Kucharski static void 947*1b8adde7SWilliam Kucharski rhine_probe1 (struct nic *nic, int ioaddr, int chip_id, int options) 948*1b8adde7SWilliam Kucharski { 949*1b8adde7SWilliam Kucharski struct rhine_private *tp; 950*1b8adde7SWilliam Kucharski static int did_version = 0; /* Already printed version info. */ 951*1b8adde7SWilliam Kucharski int i; 952*1b8adde7SWilliam Kucharski unsigned int timeout; 953*1b8adde7SWilliam Kucharski int FDXFlag; 954*1b8adde7SWilliam Kucharski int byMIIvalue, LineSpeed, MIICRbak; 955*1b8adde7SWilliam Kucharski 956*1b8adde7SWilliam Kucharski if (rhine_debug > 0 && did_version++ == 0) 957*1b8adde7SWilliam Kucharski printf (version); 958*1b8adde7SWilliam Kucharski 959*1b8adde7SWilliam Kucharski /* D-Link provided reset code (with comment additions) */ 960*1b8adde7SWilliam Kucharski if((chip_id != 0x3043) && (chip_id != 0x6100)) { 961*1b8adde7SWilliam Kucharski unsigned char byOrgValue; 962*1b8adde7SWilliam Kucharski 963*1b8adde7SWilliam Kucharski if(rhine_debug > 0) 964*1b8adde7SWilliam Kucharski printf("Enabling Sticky Bit Workaround for Chip_id: 0x%hX\n" 965*1b8adde7SWilliam Kucharski , chip_id); 966*1b8adde7SWilliam Kucharski /* clear sticky bit before reset & read ethernet address */ 967*1b8adde7SWilliam Kucharski byOrgValue = inb(bySTICKHW); 968*1b8adde7SWilliam Kucharski byOrgValue = byOrgValue & 0xFC; 969*1b8adde7SWilliam Kucharski outb(byOrgValue, bySTICKHW); 970*1b8adde7SWilliam Kucharski 971*1b8adde7SWilliam Kucharski /* (bits written are cleared?) */ 972*1b8adde7SWilliam Kucharski /* disable force PME-enable */ 973*1b8adde7SWilliam Kucharski outb(0x80, byWOLcgClr); 974*1b8adde7SWilliam Kucharski /* disable power-event config bit */ 975*1b8adde7SWilliam Kucharski outb(0xFF, byWOLcrClr); 976*1b8adde7SWilliam Kucharski /* clear power status (undocumented in vt6102 docs?) */ 977*1b8adde7SWilliam Kucharski outb(0xFF, byPwrcsrClr); 978*1b8adde7SWilliam Kucharski 979*1b8adde7SWilliam Kucharski } 980*1b8adde7SWilliam Kucharski 981*1b8adde7SWilliam Kucharski /* Perhaps this should be read from the EEPROM? */ 982*1b8adde7SWilliam Kucharski for (i = 0; i < ETH_ALEN; i++) 983*1b8adde7SWilliam Kucharski nic->node_addr[i] = inb (byPAR0 + i); 984*1b8adde7SWilliam Kucharski printf ("IO address %hX Ethernet Address: %!\n", ioaddr, nic->node_addr); 985*1b8adde7SWilliam Kucharski 986*1b8adde7SWilliam Kucharski /* restart MII auto-negotiation */ 987*1b8adde7SWilliam Kucharski WriteMII (0, 9, 1, ioaddr); 988*1b8adde7SWilliam Kucharski printf ("Analyzing Media type,this will take several seconds........"); 989*1b8adde7SWilliam Kucharski for (i = 0; i < 5; i++) 990*1b8adde7SWilliam Kucharski { 991*1b8adde7SWilliam Kucharski /* need to wait 1 millisecond - we will round it up to 50-100ms */ 992*1b8adde7SWilliam Kucharski timeout = currticks() + 2; 993*1b8adde7SWilliam Kucharski for (timeout = currticks() + 2; currticks() < timeout;) 994*1b8adde7SWilliam Kucharski /* nothing */; 995*1b8adde7SWilliam Kucharski if (ReadMII (1, ioaddr) & 0x0020) 996*1b8adde7SWilliam Kucharski break; 997*1b8adde7SWilliam Kucharski } 998*1b8adde7SWilliam Kucharski printf ("OK\n"); 999*1b8adde7SWilliam Kucharski 1000*1b8adde7SWilliam Kucharski #if 0 1001*1b8adde7SWilliam Kucharski /* JJM : for Debug */ 1002*1b8adde7SWilliam Kucharski printf("MII : Address %hhX ",inb(ioaddr+0x6c)); 1003*1b8adde7SWilliam Kucharski { 1004*1b8adde7SWilliam Kucharski unsigned char st1,st2,adv1,adv2,l1,l2; 1005*1b8adde7SWilliam Kucharski 1006*1b8adde7SWilliam Kucharski st1=ReadMII(1,ioaddr)>>8; 1007*1b8adde7SWilliam Kucharski st2=ReadMII(1,ioaddr)&0xFF; 1008*1b8adde7SWilliam Kucharski adv1=ReadMII(4,ioaddr)>>8; 1009*1b8adde7SWilliam Kucharski adv2=ReadMII(4,ioaddr)&0xFF; 1010*1b8adde7SWilliam Kucharski l1=ReadMII(5,ioaddr)>>8; 1011*1b8adde7SWilliam Kucharski l2=ReadMII(5,ioaddr)&0xFF; 1012*1b8adde7SWilliam Kucharski printf(" status 0x%hhX%hhX, advertising 0x%hhX%hhX, link 0x%hhX%hhX\n", st1,st2,adv1,adv2,l1,l2); 1013*1b8adde7SWilliam Kucharski } 1014*1b8adde7SWilliam Kucharski #endif 1015*1b8adde7SWilliam Kucharski 1016*1b8adde7SWilliam Kucharski 1017*1b8adde7SWilliam Kucharski /* query MII to know LineSpeed,duplex mode */ 1018*1b8adde7SWilliam Kucharski byMIIvalue = inb (ioaddr + 0x6d); 1019*1b8adde7SWilliam Kucharski LineSpeed = byMIIvalue & MIISR_SPEED; 1020*1b8adde7SWilliam Kucharski if (LineSpeed != 0) //JJM 1021*1b8adde7SWilliam Kucharski { 1022*1b8adde7SWilliam Kucharski printf ("Linespeed=10Mbs"); 1023*1b8adde7SWilliam Kucharski } 1024*1b8adde7SWilliam Kucharski else 1025*1b8adde7SWilliam Kucharski { 1026*1b8adde7SWilliam Kucharski printf ("Linespeed=100Mbs"); 1027*1b8adde7SWilliam Kucharski } 1028*1b8adde7SWilliam Kucharski 1029*1b8adde7SWilliam Kucharski FDXFlag = QueryAuto (ioaddr); 1030*1b8adde7SWilliam Kucharski if (FDXFlag == 1) 1031*1b8adde7SWilliam Kucharski { 1032*1b8adde7SWilliam Kucharski printf (" Fullduplex\n"); 1033*1b8adde7SWilliam Kucharski outw (CR_FDX, byCR0); 1034*1b8adde7SWilliam Kucharski } 1035*1b8adde7SWilliam Kucharski else 1036*1b8adde7SWilliam Kucharski { 1037*1b8adde7SWilliam Kucharski printf (" Halfduplex\n"); 1038*1b8adde7SWilliam Kucharski } 1039*1b8adde7SWilliam Kucharski 1040*1b8adde7SWilliam Kucharski 1041*1b8adde7SWilliam Kucharski /* set MII 10 FULL ON */ 1042*1b8adde7SWilliam Kucharski WriteMII (17, 1, 1, ioaddr); 1043*1b8adde7SWilliam Kucharski 1044*1b8adde7SWilliam Kucharski /* turn on MII link change */ 1045*1b8adde7SWilliam Kucharski MIICRbak = inb (byMIICR); 1046*1b8adde7SWilliam Kucharski outb (MIICRbak & 0x7F, byMIICR); 1047*1b8adde7SWilliam Kucharski MIIDelay (); 1048*1b8adde7SWilliam Kucharski outb (0x41, byMIIAD); 1049*1b8adde7SWilliam Kucharski MIIDelay (); 1050*1b8adde7SWilliam Kucharski 1051*1b8adde7SWilliam Kucharski /* while((inb(byMIIAD)&0x20)==0) ; */ 1052*1b8adde7SWilliam Kucharski outb (MIICRbak | 0x80, byMIICR); 1053*1b8adde7SWilliam Kucharski 1054*1b8adde7SWilliam Kucharski nic->priv_data = &rhine; 1055*1b8adde7SWilliam Kucharski tp = &rhine; 1056*1b8adde7SWilliam Kucharski tp->chip_id = chip_id; 1057*1b8adde7SWilliam Kucharski tp->ioaddr = ioaddr; 1058*1b8adde7SWilliam Kucharski tp->phys[0] = -1; 1059*1b8adde7SWilliam Kucharski 1060*1b8adde7SWilliam Kucharski /* The lower four bits are the media type. */ 1061*1b8adde7SWilliam Kucharski if (options > 0) 1062*1b8adde7SWilliam Kucharski { 1063*1b8adde7SWilliam Kucharski tp->full_duplex = (options & 16) ? 1 : 0; 1064*1b8adde7SWilliam Kucharski tp->default_port = options & 15; 1065*1b8adde7SWilliam Kucharski if (tp->default_port) 1066*1b8adde7SWilliam Kucharski tp->medialock = 1; 1067*1b8adde7SWilliam Kucharski } 1068*1b8adde7SWilliam Kucharski return; 1069*1b8adde7SWilliam Kucharski } 1070*1b8adde7SWilliam Kucharski 1071*1b8adde7SWilliam Kucharski static void 1072*1b8adde7SWilliam Kucharski rhine_disable (struct dev *dev) 1073*1b8adde7SWilliam Kucharski { 1074*1b8adde7SWilliam Kucharski struct nic *nic = (struct nic *)dev; 1075*1b8adde7SWilliam Kucharski struct rhine_private *tp = (struct rhine_private *) nic->priv_data; 1076*1b8adde7SWilliam Kucharski int ioaddr = tp->ioaddr; 1077*1b8adde7SWilliam Kucharski 1078*1b8adde7SWilliam Kucharski /* merge reset and disable */ 1079*1b8adde7SWilliam Kucharski rhine_reset(nic); 1080*1b8adde7SWilliam Kucharski 1081*1b8adde7SWilliam Kucharski printf ("rhine disable\n"); 1082*1b8adde7SWilliam Kucharski /* Switch to loopback mode to avoid hardware races. */ 1083*1b8adde7SWilliam Kucharski writeb(0x60 | 0x01, byTCR); 1084*1b8adde7SWilliam Kucharski /* Stop the chip's Tx and Rx processes. */ 1085*1b8adde7SWilliam Kucharski writew(CR_STOP, byCR0); 1086*1b8adde7SWilliam Kucharski } 1087*1b8adde7SWilliam Kucharski 1088*1b8adde7SWilliam Kucharski /************************************************************************** 1089*1b8adde7SWilliam Kucharski ETH_RESET - Reset adapter 1090*1b8adde7SWilliam Kucharski ***************************************************************************/ 1091*1b8adde7SWilliam Kucharski static void 1092*1b8adde7SWilliam Kucharski rhine_reset (struct nic *nic) 1093*1b8adde7SWilliam Kucharski { 1094*1b8adde7SWilliam Kucharski struct rhine_private *tp = (struct rhine_private *) nic->priv_data; 1095*1b8adde7SWilliam Kucharski int ioaddr = tp->ioaddr; 1096*1b8adde7SWilliam Kucharski int i, j; 1097*1b8adde7SWilliam Kucharski int FDXFlag, CRbak; 1098*1b8adde7SWilliam Kucharski int rx_ring_tmp, rx_ring_tmp1; 1099*1b8adde7SWilliam Kucharski int tx_ring_tmp, tx_ring_tmp1; 1100*1b8adde7SWilliam Kucharski int rx_bufs_tmp, rx_bufs_tmp1; 1101*1b8adde7SWilliam Kucharski int tx_bufs_tmp, tx_bufs_tmp1; 1102*1b8adde7SWilliam Kucharski 1103*1b8adde7SWilliam Kucharski static char buf1[RX_RING_SIZE * PKT_BUF_SZ + 32]; 1104*1b8adde7SWilliam Kucharski static char buf2[RX_RING_SIZE * PKT_BUF_SZ + 32]; 1105*1b8adde7SWilliam Kucharski static char desc1[TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32]; 1106*1b8adde7SWilliam Kucharski static char desc2[TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32]; 1107*1b8adde7SWilliam Kucharski 1108*1b8adde7SWilliam Kucharski /* printf ("rhine_reset\n"); */ 1109*1b8adde7SWilliam Kucharski /* Soft reset the chip. */ 1110*1b8adde7SWilliam Kucharski /*outb(CmdReset, ioaddr + ChipCmd); */ 1111*1b8adde7SWilliam Kucharski 1112*1b8adde7SWilliam Kucharski tx_bufs_tmp = (int) buf1; 1113*1b8adde7SWilliam Kucharski tx_ring_tmp = (int) desc1; 1114*1b8adde7SWilliam Kucharski rx_bufs_tmp = (int) buf2; 1115*1b8adde7SWilliam Kucharski rx_ring_tmp = (int) desc2; 1116*1b8adde7SWilliam Kucharski 1117*1b8adde7SWilliam Kucharski /* tune RD TD 32 byte alignment */ 1118*1b8adde7SWilliam Kucharski rx_ring_tmp1 = (int) virt_to_bus ((char *) rx_ring_tmp); 1119*1b8adde7SWilliam Kucharski j = (rx_ring_tmp1 + 32) & (~0x1f); 1120*1b8adde7SWilliam Kucharski /* printf ("txring[%d]", j); */ 1121*1b8adde7SWilliam Kucharski tp->rx_ring = (struct rhine_rx_desc *) bus_to_virt (j); 1122*1b8adde7SWilliam Kucharski 1123*1b8adde7SWilliam Kucharski tx_ring_tmp1 = (int) virt_to_bus ((char *) tx_ring_tmp); 1124*1b8adde7SWilliam Kucharski j = (tx_ring_tmp1 + 32) & (~0x1f); 1125*1b8adde7SWilliam Kucharski tp->tx_ring = (struct rhine_tx_desc *) bus_to_virt (j); 1126*1b8adde7SWilliam Kucharski /* printf ("rxring[%X]", j); */ 1127*1b8adde7SWilliam Kucharski 1128*1b8adde7SWilliam Kucharski 1129*1b8adde7SWilliam Kucharski tx_bufs_tmp1 = (int) virt_to_bus ((char *) tx_bufs_tmp); 1130*1b8adde7SWilliam Kucharski j = (int) (tx_bufs_tmp1 + 32) & (~0x1f); 1131*1b8adde7SWilliam Kucharski tx_bufs_tmp = (int) bus_to_virt (j); 1132*1b8adde7SWilliam Kucharski /* printf ("txb[%X]", j); */ 1133*1b8adde7SWilliam Kucharski 1134*1b8adde7SWilliam Kucharski rx_bufs_tmp1 = (int) virt_to_bus ((char *) rx_bufs_tmp); 1135*1b8adde7SWilliam Kucharski j = (int) (rx_bufs_tmp1 + 32) & (~0x1f); 1136*1b8adde7SWilliam Kucharski rx_bufs_tmp = (int) bus_to_virt (j); 1137*1b8adde7SWilliam Kucharski /* printf ("rxb[%X][%X]", rx_bufs_tmp1, j); */ 1138*1b8adde7SWilliam Kucharski 1139*1b8adde7SWilliam Kucharski for (i = 0; i < RX_RING_SIZE; i++) 1140*1b8adde7SWilliam Kucharski { 1141*1b8adde7SWilliam Kucharski tp->rx_buffs[i] = (char *) rx_bufs_tmp; 1142*1b8adde7SWilliam Kucharski /* printf("r[%X]",tp->rx_buffs[i]); */ 1143*1b8adde7SWilliam Kucharski rx_bufs_tmp += 1536; 1144*1b8adde7SWilliam Kucharski } 1145*1b8adde7SWilliam Kucharski 1146*1b8adde7SWilliam Kucharski for (i = 0; i < TX_RING_SIZE; i++) 1147*1b8adde7SWilliam Kucharski { 1148*1b8adde7SWilliam Kucharski tp->tx_buffs[i] = (char *) tx_bufs_tmp; 1149*1b8adde7SWilliam Kucharski /* printf("t[%X]",tp->tx_buffs[i]); */ 1150*1b8adde7SWilliam Kucharski tx_bufs_tmp += 1536; 1151*1b8adde7SWilliam Kucharski } 1152*1b8adde7SWilliam Kucharski 1153*1b8adde7SWilliam Kucharski /* software reset */ 1154*1b8adde7SWilliam Kucharski outb (CR1_SFRST, byCR1); 1155*1b8adde7SWilliam Kucharski MIIDelay (); 1156*1b8adde7SWilliam Kucharski 1157*1b8adde7SWilliam Kucharski /* printf ("init ring"); */ 1158*1b8adde7SWilliam Kucharski rhine_init_ring (nic); 1159*1b8adde7SWilliam Kucharski /*write TD RD Descriptor to MAC */ 1160*1b8adde7SWilliam Kucharski outl (virt_to_bus (tp->rx_ring), dwCurrentRxDescAddr); 1161*1b8adde7SWilliam Kucharski outl (virt_to_bus (tp->tx_ring), dwCurrentTxDescAddr); 1162*1b8adde7SWilliam Kucharski 1163*1b8adde7SWilliam Kucharski /* Setup Multicast */ 1164*1b8adde7SWilliam Kucharski set_rx_mode(nic); 1165*1b8adde7SWilliam Kucharski 1166*1b8adde7SWilliam Kucharski /* close IMR */ 1167*1b8adde7SWilliam Kucharski outw (0x0000, byIMR0); 1168*1b8adde7SWilliam Kucharski 1169*1b8adde7SWilliam Kucharski /* set TCR RCR threshold */ 1170*1b8adde7SWilliam Kucharski outb (0x06, byBCR0); 1171*1b8adde7SWilliam Kucharski outb (0x00, byBCR1); 1172*1b8adde7SWilliam Kucharski outb (0x2c, byRCR); 1173*1b8adde7SWilliam Kucharski outb (0x60, byTCR); 1174*1b8adde7SWilliam Kucharski /* Set Fulldupex */ 1175*1b8adde7SWilliam Kucharski FDXFlag = QueryAuto (ioaddr); 1176*1b8adde7SWilliam Kucharski if (FDXFlag == 1) 1177*1b8adde7SWilliam Kucharski { 1178*1b8adde7SWilliam Kucharski outb (CFGD_CFDX, byCFGD); 1179*1b8adde7SWilliam Kucharski outw (CR_FDX, byCR0); 1180*1b8adde7SWilliam Kucharski } 1181*1b8adde7SWilliam Kucharski 1182*1b8adde7SWilliam Kucharski /* KICK NIC to WORK */ 1183*1b8adde7SWilliam Kucharski CRbak = inw (byCR0); 1184*1b8adde7SWilliam Kucharski CRbak = CRbak & 0xFFFB; /* not CR_STOP */ 1185*1b8adde7SWilliam Kucharski outw ((CRbak | CR_STRT | CR_TXON | CR_RXON | CR_DPOLL), byCR0); 1186*1b8adde7SWilliam Kucharski 1187*1b8adde7SWilliam Kucharski /*set IMR to work */ 1188*1b8adde7SWilliam Kucharski outw (IMRShadow, byIMR0); 1189*1b8adde7SWilliam Kucharski } 1190*1b8adde7SWilliam Kucharski /* Beware of PCI posted writes */ 1191*1b8adde7SWilliam Kucharski #define IOSYNC do { readb(nic->ioaddr + StationAddr); } while (0) 1192*1b8adde7SWilliam Kucharski 1193*1b8adde7SWilliam Kucharski static int 1194*1b8adde7SWilliam Kucharski rhine_poll (struct nic *nic, int retreive) 1195*1b8adde7SWilliam Kucharski { 1196*1b8adde7SWilliam Kucharski struct rhine_private *tp = (struct rhine_private *) nic->priv_data; 1197*1b8adde7SWilliam Kucharski int rxstatus, good = 0;; 1198*1b8adde7SWilliam Kucharski 1199*1b8adde7SWilliam Kucharski if (tp->rx_ring[tp->cur_rx].rx_status.bits.own_bit == 0) 1200*1b8adde7SWilliam Kucharski { 1201*1b8adde7SWilliam Kucharski unsigned int intr_status; 1202*1b8adde7SWilliam Kucharski /* There is a packet ready */ 1203*1b8adde7SWilliam Kucharski if(!retreive) 1204*1b8adde7SWilliam Kucharski return 1; 1205*1b8adde7SWilliam Kucharski 1206*1b8adde7SWilliam Kucharski intr_status = inw(nic->ioaddr + IntrStatus); 1207*1b8adde7SWilliam Kucharski /* On Rhine-II, Bit 3 indicates Tx descriptor write-back race. */ 1208*1b8adde7SWilliam Kucharski #if 0 1209*1b8adde7SWilliam Kucharski if (tp->chip_id == 0x3065) 1210*1b8adde7SWilliam Kucharski intr_status |= inb(nic->ioaddr + IntrStatus2) << 16; 1211*1b8adde7SWilliam Kucharski #endif 1212*1b8adde7SWilliam Kucharski /* Acknowledge all of the current interrupt sources ASAP. */ 1213*1b8adde7SWilliam Kucharski if (intr_status & IntrTxDescRace) 1214*1b8adde7SWilliam Kucharski outb(0x08, nic->ioaddr + IntrStatus2); 1215*1b8adde7SWilliam Kucharski outw(intr_status & 0xffff, nic->ioaddr + IntrStatus); 1216*1b8adde7SWilliam Kucharski IOSYNC; 1217*1b8adde7SWilliam Kucharski 1218*1b8adde7SWilliam Kucharski rxstatus = tp->rx_ring[tp->cur_rx].rx_status.lw; 1219*1b8adde7SWilliam Kucharski if ((rxstatus & 0x0300) != 0x0300) 1220*1b8adde7SWilliam Kucharski { 1221*1b8adde7SWilliam Kucharski printf("rhine_poll: bad status\n"); 1222*1b8adde7SWilliam Kucharski } 1223*1b8adde7SWilliam Kucharski else if (rxstatus & (RSR_ABNORMAL)) 1224*1b8adde7SWilliam Kucharski { 1225*1b8adde7SWilliam Kucharski printf ("rxerr[%X]\n", rxstatus); 1226*1b8adde7SWilliam Kucharski } 1227*1b8adde7SWilliam Kucharski else 1228*1b8adde7SWilliam Kucharski good = 1; 1229*1b8adde7SWilliam Kucharski 1230*1b8adde7SWilliam Kucharski if (good) 1231*1b8adde7SWilliam Kucharski { 1232*1b8adde7SWilliam Kucharski nic->packetlen = tp->rx_ring[tp->cur_rx].rx_status.bits.frame_length; 1233*1b8adde7SWilliam Kucharski memcpy (nic->packet, tp->rx_buffs[tp->cur_rx], nic->packetlen); 1234*1b8adde7SWilliam Kucharski /* printf ("Packet RXed\n"); */ 1235*1b8adde7SWilliam Kucharski } 1236*1b8adde7SWilliam Kucharski tp->rx_ring[tp->cur_rx].rx_status.bits.own_bit = 1; 1237*1b8adde7SWilliam Kucharski tp->cur_rx++; 1238*1b8adde7SWilliam Kucharski tp->cur_rx = tp->cur_rx % RX_RING_SIZE; 1239*1b8adde7SWilliam Kucharski } 1240*1b8adde7SWilliam Kucharski /* Acknowledge all of the current interrupt sources ASAP. */ 1241*1b8adde7SWilliam Kucharski outw(DEFAULT_INTR & ~IntrRxDone, nic->ioaddr + IntrStatus); 1242*1b8adde7SWilliam Kucharski 1243*1b8adde7SWilliam Kucharski IOSYNC; 1244*1b8adde7SWilliam Kucharski 1245*1b8adde7SWilliam Kucharski return good; 1246*1b8adde7SWilliam Kucharski } 1247*1b8adde7SWilliam Kucharski 1248*1b8adde7SWilliam Kucharski static void 1249*1b8adde7SWilliam Kucharski rhine_transmit (struct nic *nic, 1250*1b8adde7SWilliam Kucharski const char *d, unsigned int t, unsigned int s, const char *p) 1251*1b8adde7SWilliam Kucharski { 1252*1b8adde7SWilliam Kucharski struct rhine_private *tp = (struct rhine_private *) nic->priv_data; 1253*1b8adde7SWilliam Kucharski int ioaddr = tp->ioaddr; 1254*1b8adde7SWilliam Kucharski int entry; 1255*1b8adde7SWilliam Kucharski unsigned char CR1bak; 1256*1b8adde7SWilliam Kucharski 1257*1b8adde7SWilliam Kucharski /*printf ("rhine_transmit\n"); */ 1258*1b8adde7SWilliam Kucharski /* setup ethernet header */ 1259*1b8adde7SWilliam Kucharski 1260*1b8adde7SWilliam Kucharski 1261*1b8adde7SWilliam Kucharski /* Calculate the next Tx descriptor entry. */ 1262*1b8adde7SWilliam Kucharski entry = tp->cur_tx % TX_RING_SIZE; 1263*1b8adde7SWilliam Kucharski 1264*1b8adde7SWilliam Kucharski memcpy (tp->tx_buffs[entry], d, ETH_ALEN); /* dst */ 1265*1b8adde7SWilliam Kucharski memcpy (tp->tx_buffs[entry] + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ 1266*1b8adde7SWilliam Kucharski *((char *) tp->tx_buffs[entry] + 12) = t >> 8; /* type */ 1267*1b8adde7SWilliam Kucharski *((char *) tp->tx_buffs[entry] + 13) = t; 1268*1b8adde7SWilliam Kucharski memcpy (tp->tx_buffs[entry] + ETH_HLEN, p, s); 1269*1b8adde7SWilliam Kucharski s += ETH_HLEN; 1270*1b8adde7SWilliam Kucharski while (s < ETH_ZLEN) 1271*1b8adde7SWilliam Kucharski *((char *) tp->tx_buffs[entry] + ETH_HLEN + (s++)) = 0; 1272*1b8adde7SWilliam Kucharski 1273*1b8adde7SWilliam Kucharski tp->tx_ring[entry].tx_ctrl.bits.tx_buf_size = s; 1274*1b8adde7SWilliam Kucharski 1275*1b8adde7SWilliam Kucharski tp->tx_ring[entry].tx_status.bits.own_bit = 1; 1276*1b8adde7SWilliam Kucharski 1277*1b8adde7SWilliam Kucharski 1278*1b8adde7SWilliam Kucharski CR1bak = inb (byCR1); 1279*1b8adde7SWilliam Kucharski 1280*1b8adde7SWilliam Kucharski CR1bak = CR1bak | CR1_TDMD1; 1281*1b8adde7SWilliam Kucharski /*printf("tdsw=[%X]",tp->tx_ring[entry].tx_status.lw); */ 1282*1b8adde7SWilliam Kucharski /*printf("tdcw=[%X]",tp->tx_ring[entry].tx_ctrl.lw); */ 1283*1b8adde7SWilliam Kucharski /*printf("tdbuf1=[%X]",tp->tx_ring[entry].buf_addr_1); */ 1284*1b8adde7SWilliam Kucharski /*printf("tdbuf2=[%X]",tp->tx_ring[entry].buf_addr_2); */ 1285*1b8adde7SWilliam Kucharski /*printf("td1=[%X]",inl(dwCurrentTDSE0)); */ 1286*1b8adde7SWilliam Kucharski /*printf("td2=[%X]",inl(dwCurrentTDSE1)); */ 1287*1b8adde7SWilliam Kucharski /*printf("td3=[%X]",inl(dwCurrentTDSE2)); */ 1288*1b8adde7SWilliam Kucharski /*printf("td4=[%X]",inl(dwCurrentTDSE3)); */ 1289*1b8adde7SWilliam Kucharski 1290*1b8adde7SWilliam Kucharski outb (CR1bak, byCR1); 1291*1b8adde7SWilliam Kucharski /* Wait until transmit is finished */ 1292*1b8adde7SWilliam Kucharski while (tp->tx_ring[entry].tx_status.bits.own_bit != 0) 1293*1b8adde7SWilliam Kucharski ; 1294*1b8adde7SWilliam Kucharski tp->cur_tx++; 1295*1b8adde7SWilliam Kucharski 1296*1b8adde7SWilliam Kucharski /*outw(IMRShadow,byIMR0); */ 1297*1b8adde7SWilliam Kucharski /*dev_kfree_skb(tp->tx_skbuff[entry], FREE_WRITE); */ 1298*1b8adde7SWilliam Kucharski /*tp->tx_skbuff[entry] = 0; */ 1299*1b8adde7SWilliam Kucharski } 1300*1b8adde7SWilliam Kucharski 1301*1b8adde7SWilliam Kucharski static struct pci_id rhine_nics[] = { 1302*1b8adde7SWilliam Kucharski PCI_ROM(0x1106, 0x3065, "dlink-530tx", "VIA 6102"), 1303*1b8adde7SWilliam Kucharski PCI_ROM(0x1106, 0x3106, "via-rhine-6105", "VIA 6105"), 1304*1b8adde7SWilliam Kucharski PCI_ROM(0x1106, 0x3043, "dlink-530tx-old", "VIA 3043"), /* Rhine-I 86c100a */ 1305*1b8adde7SWilliam Kucharski PCI_ROM(0x1106, 0x3053, "via6105m", "VIA 6105M"), 1306*1b8adde7SWilliam Kucharski PCI_ROM(0x1106, 0x6100, "via-rhine-old", "VIA 86C100A"), /* Rhine-II */ 1307*1b8adde7SWilliam Kucharski }; 1308*1b8adde7SWilliam Kucharski 1309*1b8adde7SWilliam Kucharski struct pci_driver rhine_driver = { 1310*1b8adde7SWilliam Kucharski .type = NIC_DRIVER, 1311*1b8adde7SWilliam Kucharski .name = "VIA 86C100", 1312*1b8adde7SWilliam Kucharski .probe = rhine_probe, 1313*1b8adde7SWilliam Kucharski .ids = rhine_nics, 1314*1b8adde7SWilliam Kucharski .id_count = sizeof(rhine_nics)/sizeof(rhine_nics[0]), 1315*1b8adde7SWilliam Kucharski .class = 0, 1316*1b8adde7SWilliam Kucharski }; 1317*1b8adde7SWilliam Kucharski 1318*1b8adde7SWilliam Kucharski /* EOF via-rhine.c */ 1319