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
rhine_init_ring(struct nic * nic)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
QueryAuto(int ioaddr)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
ReadMII(int byMIIIndex,int ioaddr)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
WriteMII(char byMIISetByte,char byMIISetBit,char byMIIOP,int ioaddr)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
MIIDelay(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 ***************************************************************************/
rhine_irq(struct nic * nic,irq_action_t action)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
rhine_probe(struct dev * dev,struct pci_device * pci)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
set_rx_mode(struct nic * nic __unused)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
rhine_probe1(struct nic * nic,int ioaddr,int chip_id,int options)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
rhine_disable(struct dev * dev)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
rhine_reset(struct nic * nic)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
rhine_poll(struct nic * nic,int retreive)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
rhine_transmit(struct nic * nic,const char * d,unsigned int t,unsigned int s,const char * p)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