xref: /titanic_52/usr/src/grub/grub-0.97/netboot/via-rhine.c (revision 1b8adde7ba7d5e04395c141c5400dc2cffd7d809)
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