1 | /**************************************************************************
|
---|
2 | * r8169.c: Etherboot device driver for the RealTek RTL-8169 Gigabit
|
---|
3 | * Written 2003 by Timothy Legge <[email protected]>
|
---|
4 | *
|
---|
5 | * This program is free software; you can redistribute it and/or modify
|
---|
6 | * it under the terms of the GNU General Public License as published by
|
---|
7 | * the Free Software Foundation; either version 2 of the License, or
|
---|
8 | * (at your option) any later version.
|
---|
9 | *
|
---|
10 | * This program is distributed in the hope that it will be useful,
|
---|
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
13 | * GNU General Public License for more details.
|
---|
14 | *
|
---|
15 | * You should have received a copy of the GNU General Public License
|
---|
16 | * along with this program; if not, write to the Free Software
|
---|
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
18 | *
|
---|
19 | * Portions of this code based on:
|
---|
20 | * r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver
|
---|
21 | * for Linux kernel 2.4.x.
|
---|
22 | *
|
---|
23 | * Written 2002 ShuChen <[email protected]>
|
---|
24 | * See Linux Driver for full information
|
---|
25 | *
|
---|
26 | * Linux Driver Versions:
|
---|
27 | * 1.27a, 10.02.2002
|
---|
28 | * RTL8169_VERSION "2.2" <2004/08/09>
|
---|
29 | *
|
---|
30 | * Thanks to:
|
---|
31 | * Jean Chen of RealTek Semiconductor Corp. for
|
---|
32 | * providing the evaluation NIC used to develop
|
---|
33 | * this driver. RealTek's support for Etherboot
|
---|
34 | * is appreciated.
|
---|
35 | *
|
---|
36 | * REVISION HISTORY:
|
---|
37 | * ================
|
---|
38 | *
|
---|
39 | * v1.0 11-26-2003 timlegge Initial port of Linux driver
|
---|
40 | * v1.5 01-17-2004 timlegge Initial driver output cleanup
|
---|
41 | * v1.6 03-27-2004 timlegge Additional Cleanup
|
---|
42 | * v1.7 11-22-2005 timlegge Update to RealTek Driver Version 2.2
|
---|
43 | *
|
---|
44 | * Indent Options: indent -kr -i8
|
---|
45 | ***************************************************************************/
|
---|
46 |
|
---|
47 | /* to get some global routines like printf */
|
---|
48 | #include "etherboot.h"
|
---|
49 | /* to get the interface to the body of the program */
|
---|
50 | #include "nic.h"
|
---|
51 | /* to get the PCI support functions, if this is a PCI NIC */
|
---|
52 | #include "pci.h"
|
---|
53 | #include "timer.h"
|
---|
54 |
|
---|
55 | #define drv_version "v1.6"
|
---|
56 | #define drv_date "03-27-2004"
|
---|
57 |
|
---|
58 | #define HZ 1000
|
---|
59 |
|
---|
60 | static u32 ioaddr;
|
---|
61 |
|
---|
62 | #ifdef EDEBUG
|
---|
63 | #define dprintf(x) printf x
|
---|
64 | #else
|
---|
65 | #define dprintf(x)
|
---|
66 | #endif
|
---|
67 |
|
---|
68 | /* Condensed operations for readability. */
|
---|
69 | #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
|
---|
70 | #define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
|
---|
71 |
|
---|
72 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
---|
73 |
|
---|
74 | #undef RTL8169_DEBUG
|
---|
75 | #undef RTL8169_JUMBO_FRAME_SUPPORT
|
---|
76 | #undef RTL8169_HW_FLOW_CONTROL_SUPPORT
|
---|
77 |
|
---|
78 |
|
---|
79 | #undef RTL8169_IOCTL_SUPPORT
|
---|
80 | #undef RTL8169_DYNAMIC_CONTROL
|
---|
81 | #define RTL8169_USE_IO
|
---|
82 |
|
---|
83 |
|
---|
84 | #ifdef RTL8169_DEBUG
|
---|
85 | #define assert(expr) \
|
---|
86 | if(!(expr)) { printk( "Assertion failed! %s,%s,%s,line=%d\n", #expr,__FILE__,__FUNCTION__,__LINE__); }
|
---|
87 | #define DBG_PRINT( fmt, args...) printk("r8169: " fmt, ## args);
|
---|
88 | #else
|
---|
89 | #define assert(expr) do {} while (0)
|
---|
90 | #define DBG_PRINT( fmt, args...) ;
|
---|
91 | #endif // end of #ifdef RTL8169_DEBUG
|
---|
92 |
|
---|
93 | /* media options
|
---|
94 | _10_Half = 0x01,
|
---|
95 | _10_Full = 0x02,
|
---|
96 | _100_Half = 0x04,
|
---|
97 | _100_Full = 0x08,
|
---|
98 | _1000_Full = 0x10,
|
---|
99 | */
|
---|
100 | static int media = -1;
|
---|
101 |
|
---|
102 | #if 0
|
---|
103 | /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
|
---|
104 | static int max_interrupt_work = 20;
|
---|
105 | #endif
|
---|
106 |
|
---|
107 | #if 0
|
---|
108 | /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
|
---|
109 | The RTL chips use a 64 element hash table based on the Ethernet CRC. */
|
---|
110 | static int multicast_filter_limit = 32;
|
---|
111 | #endif
|
---|
112 |
|
---|
113 | /* MAC address length*/
|
---|
114 | #define MAC_ADDR_LEN 6
|
---|
115 |
|
---|
116 | /* max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4).*/
|
---|
117 | #define MAX_ETH_FRAME_SIZE 1536
|
---|
118 |
|
---|
119 | #define TX_FIFO_THRESH 256 /* In bytes */
|
---|
120 |
|
---|
121 | #define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */
|
---|
122 | #define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */
|
---|
123 | #define TX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */
|
---|
124 | #define ETTh 0x3F /* 0x3F means NO threshold */
|
---|
125 |
|
---|
126 | #define EarlyTxThld 0x3F /* 0x3F means NO early transmit */
|
---|
127 | #define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */
|
---|
128 | #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
|
---|
129 |
|
---|
130 | #define NUM_TX_DESC 1 /* Number of Tx descriptor registers */
|
---|
131 | #define NUM_RX_DESC 4 /* Number of Rx descriptor registers */
|
---|
132 | #define RX_BUF_SIZE 1536 /* Rx Buffer size */
|
---|
133 |
|
---|
134 | #define RTL_MIN_IO_SIZE 0x80
|
---|
135 | #define TX_TIMEOUT (6*HZ)
|
---|
136 |
|
---|
137 | #define RTL8169_TIMER_EXPIRE_TIME 100 //100
|
---|
138 |
|
---|
139 | #define ETH_HDR_LEN 14
|
---|
140 | #define DEFAULT_MTU 1500
|
---|
141 | #define DEFAULT_RX_BUF_LEN 1536
|
---|
142 |
|
---|
143 |
|
---|
144 | #ifdef RTL8169_JUMBO_FRAME_SUPPORT
|
---|
145 | #define MAX_JUMBO_FRAME_MTU ( 10000 )
|
---|
146 | #define MAX_RX_SKBDATA_SIZE ( MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN )
|
---|
147 | #else
|
---|
148 | #define MAX_RX_SKBDATA_SIZE 1600
|
---|
149 | #endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT
|
---|
150 |
|
---|
151 | #ifdef RTL8169_USE_IO
|
---|
152 | #define RTL_W8(reg, val8) outb ((val8), ioaddr + (reg))
|
---|
153 | #define RTL_W16(reg, val16) outw ((val16), ioaddr + (reg))
|
---|
154 | #define RTL_W32(reg, val32) outl ((val32), ioaddr + (reg))
|
---|
155 | #define RTL_R8(reg) inb (ioaddr + (reg))
|
---|
156 | #define RTL_R16(reg) inw (ioaddr + (reg))
|
---|
157 | #define RTL_R32(reg) ((unsigned long) inl (ioaddr + (reg)))
|
---|
158 | #else
|
---|
159 | /* write/read MMIO register */
|
---|
160 | #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
|
---|
161 | #define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
|
---|
162 | #define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
|
---|
163 | #define RTL_R8(reg) readb (ioaddr + (reg))
|
---|
164 | #define RTL_R16(reg) readw (ioaddr + (reg))
|
---|
165 | #define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
|
---|
166 | #endif
|
---|
167 |
|
---|
168 | #define MCFG_METHOD_1 0x01
|
---|
169 | #define MCFG_METHOD_2 0x02
|
---|
170 | #define MCFG_METHOD_3 0x03
|
---|
171 | #define MCFG_METHOD_4 0x04
|
---|
172 |
|
---|
173 | #define PCFG_METHOD_1 0x01 //PHY Reg 0x03 bit0-3 == 0x0000
|
---|
174 | #define PCFG_METHOD_2 0x02 //PHY Reg 0x03 bit0-3 == 0x0001
|
---|
175 | #define PCFG_METHOD_3 0x03 //PHY Reg 0x03 bit0-3 == 0x0002
|
---|
176 |
|
---|
177 | static struct {
|
---|
178 | const char *name;
|
---|
179 | u8 mcfg; /* depend on RTL8169 docs */
|
---|
180 | u32 RxConfigMask; /* should clear the bits supported by this chip */
|
---|
181 | } rtl_chip_info[] = {
|
---|
182 | {
|
---|
183 | "RTL-8169", MCFG_METHOD_1, 0xff7e1880,}, {
|
---|
184 | "RTL8169s/8110s", MCFG_METHOD_2, 0xff7e1880}, {
|
---|
185 | "RTL8169s/8110s", MCFG_METHOD_3, 0xff7e1880},};
|
---|
186 |
|
---|
187 | enum RTL8169_registers {
|
---|
188 | MAC0 = 0x0, /* Ethernet hardware address. */
|
---|
189 | MAR0 = 0x8, /* Multicast filter. */
|
---|
190 | TxDescStartAddr = 0x20,
|
---|
191 | TxHDescStartAddr = 0x28,
|
---|
192 | FLASH = 0x30,
|
---|
193 | ERSR = 0x36,
|
---|
194 | ChipCmd = 0x37,
|
---|
195 | TxPoll = 0x38,
|
---|
196 | IntrMask = 0x3C,
|
---|
197 | IntrStatus = 0x3E,
|
---|
198 | TxConfig = 0x40,
|
---|
199 | RxConfig = 0x44,
|
---|
200 | RxMissed = 0x4C,
|
---|
201 | Cfg9346 = 0x50,
|
---|
202 | Config0 = 0x51,
|
---|
203 | Config1 = 0x52,
|
---|
204 | Config2 = 0x53,
|
---|
205 | Config3 = 0x54,
|
---|
206 | Config4 = 0x55,
|
---|
207 | Config5 = 0x56,
|
---|
208 | MultiIntr = 0x5C,
|
---|
209 | PHYAR = 0x60,
|
---|
210 | TBICSR = 0x64,
|
---|
211 | TBI_ANAR = 0x68,
|
---|
212 | TBI_LPAR = 0x6A,
|
---|
213 | PHYstatus = 0x6C,
|
---|
214 | RxMaxSize = 0xDA,
|
---|
215 | CPlusCmd = 0xE0,
|
---|
216 | RxDescStartAddr = 0xE4,
|
---|
217 | ETThReg = 0xEC,
|
---|
218 | FuncEvent = 0xF0,
|
---|
219 | FuncEventMask = 0xF4,
|
---|
220 | FuncPresetState = 0xF8,
|
---|
221 | FuncForceEvent = 0xFC,
|
---|
222 | };
|
---|
223 |
|
---|
224 | enum RTL8169_register_content {
|
---|
225 | /*InterruptStatusBits */
|
---|
226 | SYSErr = 0x8000,
|
---|
227 | PCSTimeout = 0x4000,
|
---|
228 | SWInt = 0x0100,
|
---|
229 | TxDescUnavail = 0x80,
|
---|
230 | RxFIFOOver = 0x40,
|
---|
231 | LinkChg = 0x20,
|
---|
232 | RxOverflow = 0x10,
|
---|
233 | TxErr = 0x08,
|
---|
234 | TxOK = 0x04,
|
---|
235 | RxErr = 0x02,
|
---|
236 | RxOK = 0x01,
|
---|
237 |
|
---|
238 | /*RxStatusDesc */
|
---|
239 | RxRES = 0x00200000,
|
---|
240 | RxCRC = 0x00080000,
|
---|
241 | RxRUNT = 0x00100000,
|
---|
242 | RxRWT = 0x00400000,
|
---|
243 |
|
---|
244 | /*ChipCmdBits */
|
---|
245 | CmdReset = 0x10,
|
---|
246 | CmdRxEnb = 0x08,
|
---|
247 | CmdTxEnb = 0x04,
|
---|
248 | RxBufEmpty = 0x01,
|
---|
249 |
|
---|
250 | /*Cfg9346Bits */
|
---|
251 | Cfg9346_Lock = 0x00,
|
---|
252 | Cfg9346_Unlock = 0xC0,
|
---|
253 |
|
---|
254 | /*rx_mode_bits */
|
---|
255 | AcceptErr = 0x20,
|
---|
256 | AcceptRunt = 0x10,
|
---|
257 | AcceptBroadcast = 0x08,
|
---|
258 | AcceptMulticast = 0x04,
|
---|
259 | AcceptMyPhys = 0x02,
|
---|
260 | AcceptAllPhys = 0x01,
|
---|
261 |
|
---|
262 | /*RxConfigBits */
|
---|
263 | RxCfgFIFOShift = 13,
|
---|
264 | RxCfgDMAShift = 8,
|
---|
265 |
|
---|
266 | /*TxConfigBits */
|
---|
267 | TxInterFrameGapShift = 24,
|
---|
268 | TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
|
---|
269 |
|
---|
270 | /*rtl8169_PHYstatus */
|
---|
271 | TBI_Enable = 0x80,
|
---|
272 | TxFlowCtrl = 0x40,
|
---|
273 | RxFlowCtrl = 0x20,
|
---|
274 | _1000bpsF = 0x10,
|
---|
275 | _100bps = 0x08,
|
---|
276 | _10bps = 0x04,
|
---|
277 | LinkStatus = 0x02,
|
---|
278 | FullDup = 0x01,
|
---|
279 |
|
---|
280 | /*GIGABIT_PHY_registers */
|
---|
281 | PHY_CTRL_REG = 0,
|
---|
282 | PHY_STAT_REG = 1,
|
---|
283 | PHY_AUTO_NEGO_REG = 4,
|
---|
284 | PHY_1000_CTRL_REG = 9,
|
---|
285 |
|
---|
286 | /*GIGABIT_PHY_REG_BIT */
|
---|
287 | PHY_Restart_Auto_Nego = 0x0200,
|
---|
288 | PHY_Enable_Auto_Nego = 0x1000,
|
---|
289 |
|
---|
290 | /* PHY_STAT_REG = 1; */
|
---|
291 | PHY_Auto_Neco_Comp = 0x0020,
|
---|
292 |
|
---|
293 | /* PHY_AUTO_NEGO_REG = 4; */
|
---|
294 | PHY_Cap_10_Half = 0x0020,
|
---|
295 | PHY_Cap_10_Full = 0x0040,
|
---|
296 | PHY_Cap_100_Half = 0x0080,
|
---|
297 | PHY_Cap_100_Full = 0x0100,
|
---|
298 |
|
---|
299 | /* PHY_1000_CTRL_REG = 9; */
|
---|
300 | PHY_Cap_1000_Full = 0x0200,
|
---|
301 | PHY_Cap_1000_Half = 0x0100,
|
---|
302 |
|
---|
303 | PHY_Cap_PAUSE = 0x0400,
|
---|
304 | PHY_Cap_ASYM_PAUSE = 0x0800,
|
---|
305 |
|
---|
306 | PHY_Cap_Null = 0x0,
|
---|
307 |
|
---|
308 | /*_MediaType*/
|
---|
309 | _10_Half = 0x01,
|
---|
310 | _10_Full = 0x02,
|
---|
311 | _100_Half = 0x04,
|
---|
312 | _100_Full = 0x08,
|
---|
313 | _1000_Full = 0x10,
|
---|
314 |
|
---|
315 | /*_TBICSRBit*/
|
---|
316 | TBILinkOK = 0x02000000,
|
---|
317 | };
|
---|
318 |
|
---|
319 | enum _DescStatusBit {
|
---|
320 | OWNbit = 0x80000000,
|
---|
321 | EORbit = 0x40000000,
|
---|
322 | FSbit = 0x20000000,
|
---|
323 | LSbit = 0x10000000,
|
---|
324 | };
|
---|
325 |
|
---|
326 | struct TxDesc {
|
---|
327 | u32 status;
|
---|
328 | u32 vlan_tag;
|
---|
329 | u32 buf_addr;
|
---|
330 | u32 buf_Haddr;
|
---|
331 | };
|
---|
332 |
|
---|
333 | struct RxDesc {
|
---|
334 | u32 status;
|
---|
335 | u32 vlan_tag;
|
---|
336 | u32 buf_addr;
|
---|
337 | u32 buf_Haddr;
|
---|
338 | };
|
---|
339 |
|
---|
340 | /* The descriptors for this card are required to be aligned on
|
---|
341 | 256 byte boundaries. As the align attribute does not do more than
|
---|
342 | 16 bytes of alignment it requires some extra steps. Add 256 to the
|
---|
343 | size of the array and the init_ring adjusts the alignment */
|
---|
344 |
|
---|
345 | /* Define the TX Descriptor */
|
---|
346 | static u8 tx_ring[NUM_TX_DESC * sizeof(struct TxDesc) + 256];
|
---|
347 |
|
---|
348 | /* Create a static buffer of size RX_BUF_SZ for each
|
---|
349 | TX Descriptor. All descriptors point to a
|
---|
350 | part of this buffer */
|
---|
351 | static unsigned char txb[NUM_TX_DESC * RX_BUF_SIZE];
|
---|
352 |
|
---|
353 | /* Define the RX Descriptor */
|
---|
354 | static u8 rx_ring[NUM_RX_DESC * sizeof(struct TxDesc) + 256];
|
---|
355 |
|
---|
356 | /* Create a static buffer of size RX_BUF_SZ for each
|
---|
357 | RX Descriptor All descriptors point to a
|
---|
358 | part of this buffer */
|
---|
359 | static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
|
---|
360 |
|
---|
361 | struct rtl8169_private {
|
---|
362 | void *mmio_addr; /* memory map physical address */
|
---|
363 | int chipset;
|
---|
364 | int pcfg;
|
---|
365 | int mcfg;
|
---|
366 | unsigned long cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
|
---|
367 | unsigned long cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
|
---|
368 | unsigned char *TxDescArrays; /* Index of Tx Descriptor buffer */
|
---|
369 | unsigned char *RxDescArrays; /* Index of Rx Descriptor buffer */
|
---|
370 | struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */
|
---|
371 | struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */
|
---|
372 | unsigned char *RxBufferRing[NUM_RX_DESC]; /* Index of Rx Buffer array */
|
---|
373 | unsigned char *Tx_skbuff[NUM_TX_DESC];
|
---|
374 | } tpx;
|
---|
375 |
|
---|
376 | static struct rtl8169_private *tpc;
|
---|
377 |
|
---|
378 | static const u16 rtl8169_intr_mask =
|
---|
379 | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
|
---|
380 | static const unsigned int rtl8169_rx_config =
|
---|
381 | (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift) |
|
---|
382 | 0x0000000E;
|
---|
383 |
|
---|
384 | static void rtl8169_hw_PHY_config(struct nic *nic __unused);
|
---|
385 | //static void rtl8169_hw_PHY_reset(struct net_device *dev);
|
---|
386 |
|
---|
387 | #define RTL8169_WRITE_GMII_REG_BIT( ioaddr, reg, bitnum, bitval )\
|
---|
388 | { \
|
---|
389 | int val; \
|
---|
390 | if( bitval == 1 ){ val = ( RTL8169_READ_GMII_REG( ioaddr, reg ) | (bitval<<bitnum) ) & 0xffff ; } \
|
---|
391 | else{ val = ( RTL8169_READ_GMII_REG( ioaddr, reg ) & (~(0x0001<<bitnum)) ) & 0xffff ; } \
|
---|
392 | RTL8169_WRITE_GMII_REG( ioaddr, reg, val ); \
|
---|
393 | }
|
---|
394 |
|
---|
395 | //=================================================================
|
---|
396 | // PHYAR
|
---|
397 | // bit Symbol
|
---|
398 | // 31 Flag
|
---|
399 | // 30-21 reserved
|
---|
400 | // 20-16 5-bit GMII/MII register address
|
---|
401 | // 15-0 16-bit GMII/MII register data
|
---|
402 | //=================================================================
|
---|
403 | void RTL8169_WRITE_GMII_REG(unsigned long ioaddr, int RegAddr, int value)
|
---|
404 | {
|
---|
405 | int i;
|
---|
406 |
|
---|
407 | RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
|
---|
408 | udelay(1000);
|
---|
409 |
|
---|
410 | for (i = 2000; i > 0; i--) {
|
---|
411 | // Check if the RTL8169 has completed writing to the specified MII register
|
---|
412 | if (!(RTL_R32(PHYAR) & 0x80000000)) {
|
---|
413 | break;
|
---|
414 | } else {
|
---|
415 | udelay(100);
|
---|
416 | } // end of if( ! (RTL_R32(PHYAR)&0x80000000) )
|
---|
417 | } // end of for() loop
|
---|
418 | }
|
---|
419 |
|
---|
420 | //=================================================================
|
---|
421 | int RTL8169_READ_GMII_REG(unsigned long ioaddr, int RegAddr)
|
---|
422 | {
|
---|
423 | int i, value = -1;
|
---|
424 |
|
---|
425 | RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
|
---|
426 | udelay(1000);
|
---|
427 |
|
---|
428 | for (i = 2000; i > 0; i--) {
|
---|
429 | // Check if the RTL8169 has completed retrieving data from the specified MII register
|
---|
430 | if (RTL_R32(PHYAR) & 0x80000000) {
|
---|
431 | value = (int) (RTL_R32(PHYAR) & 0xFFFF);
|
---|
432 | break;
|
---|
433 | } else {
|
---|
434 | udelay(100);
|
---|
435 | } // end of if( RTL_R32(PHYAR) & 0x80000000 )
|
---|
436 | } // end of for() loop
|
---|
437 | return value;
|
---|
438 | }
|
---|
439 |
|
---|
440 |
|
---|
441 | void mdio_write(int RegAddr, int value)
|
---|
442 | {
|
---|
443 | int i;
|
---|
444 |
|
---|
445 | RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
|
---|
446 | udelay(1000);
|
---|
447 |
|
---|
448 | for (i = 2000; i > 0; i--) {
|
---|
449 | /* Check if the RTL8169 has completed writing to the specified MII register */
|
---|
450 | if (!(RTL_R32(PHYAR) & 0x80000000)) {
|
---|
451 | break;
|
---|
452 | } else {
|
---|
453 | udelay(100);
|
---|
454 | }
|
---|
455 | }
|
---|
456 | }
|
---|
457 |
|
---|
458 | int mdio_read(int RegAddr)
|
---|
459 | {
|
---|
460 | int i, value = -1;
|
---|
461 |
|
---|
462 | RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
|
---|
463 | udelay(1000);
|
---|
464 |
|
---|
465 | for (i = 2000; i > 0; i--) {
|
---|
466 | /* Check if the RTL8169 has completed retrieving data from the specified MII register */
|
---|
467 | if (RTL_R32(PHYAR) & 0x80000000) {
|
---|
468 | value = (int) (RTL_R32(PHYAR) & 0xFFFF);
|
---|
469 | break;
|
---|
470 | } else {
|
---|
471 | udelay(100);
|
---|
472 | }
|
---|
473 | }
|
---|
474 | return value;
|
---|
475 | }
|
---|
476 |
|
---|
477 | #define IORESOURCE_MEM 0x00000200
|
---|
478 |
|
---|
479 | static int rtl8169_init_board(struct pci_device *pdev)
|
---|
480 | {
|
---|
481 | int i;
|
---|
482 | unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
|
---|
483 |
|
---|
484 | adjust_pci_device(pdev);
|
---|
485 |
|
---|
486 | mmio_start = pci_bar_start(pdev, PCI_BASE_ADDRESS_1);
|
---|
487 | // mmio_end = pci_resource_end (pdev, 1);
|
---|
488 | // mmio_flags = pci_resource_flags (pdev, PCI_BASE_ADDRESS_1);
|
---|
489 | mmio_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_1);
|
---|
490 |
|
---|
491 | // make sure PCI base addr 1 is MMIO
|
---|
492 | // if (!(mmio_flags & IORESOURCE_MEM)) {
|
---|
493 | // printf ("region #1 not an MMIO resource, aborting\n");
|
---|
494 | // return 0;
|
---|
495 | // }
|
---|
496 |
|
---|
497 | // check for weird/broken PCI region reporting
|
---|
498 | if (mmio_len < RTL_MIN_IO_SIZE) {
|
---|
499 | printf("Invalid PCI region size(s), aborting\n");
|
---|
500 | return 0;
|
---|
501 | }
|
---|
502 | #ifdef RTL8169_USE_IO
|
---|
503 | ioaddr = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
|
---|
504 | #else
|
---|
505 | // ioremap MMIO region
|
---|
506 | ioaddr = (unsigned long) ioremap(mmio_start, mmio_len);
|
---|
507 | if (ioaddr == 0) {
|
---|
508 | printk("cannot remap MMIO, aborting\n");
|
---|
509 | return 0;
|
---|
510 | }
|
---|
511 | #endif
|
---|
512 |
|
---|
513 | tpc->mmio_addr = &ioaddr;
|
---|
514 | /* Soft reset the chip. */
|
---|
515 | RTL_W8(ChipCmd, CmdReset);
|
---|
516 |
|
---|
517 | /* Check that the chip has finished the reset. */
|
---|
518 | for (i = 1000; i > 0; i--)
|
---|
519 | if ((RTL_R8(ChipCmd) & CmdReset) == 0)
|
---|
520 | break;
|
---|
521 | else
|
---|
522 | udelay(10);
|
---|
523 | // identify config method
|
---|
524 | {
|
---|
525 | unsigned long val32 = (RTL_R32(TxConfig) & 0x7c800000);
|
---|
526 | if (val32 == (0x1 << 28)) {
|
---|
527 | tpc->mcfg = MCFG_METHOD_4;
|
---|
528 | } else if (val32 == (0x1 << 26)) {
|
---|
529 | tpc->mcfg = MCFG_METHOD_3;
|
---|
530 | } else if (val32 == (0x1 << 23)) {
|
---|
531 | tpc->mcfg = MCFG_METHOD_2;
|
---|
532 | } else if (val32 == 0x00000000) {
|
---|
533 | tpc->mcfg = MCFG_METHOD_1;
|
---|
534 | } else {
|
---|
535 | tpc->mcfg = MCFG_METHOD_1;
|
---|
536 | }
|
---|
537 | }
|
---|
538 | {
|
---|
539 | unsigned char val8 =
|
---|
540 | (unsigned char) (RTL8169_READ_GMII_REG(ioaddr, 3) &
|
---|
541 | 0x000f);
|
---|
542 | if (val8 == 0x00) {
|
---|
543 | tpc->pcfg = PCFG_METHOD_1;
|
---|
544 | } else if (val8 == 0x01) {
|
---|
545 | tpc->pcfg = PCFG_METHOD_2;
|
---|
546 | } else if (val8 == 0x02) {
|
---|
547 | tpc->pcfg = PCFG_METHOD_3;
|
---|
548 | } else {
|
---|
549 | tpc->pcfg = PCFG_METHOD_3;
|
---|
550 | }
|
---|
551 | }
|
---|
552 |
|
---|
553 | /* identify chip attached to board */
|
---|
554 |
|
---|
555 | for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--)
|
---|
556 | if (tpc->mcfg == rtl_chip_info[i].mcfg) {
|
---|
557 | tpc->chipset = i;
|
---|
558 | goto match;
|
---|
559 | }
|
---|
560 | /* if unknown chip, assume array element #0, original RTL-8169 in this case */
|
---|
561 | dprintf(("PCI device: unknown chip version, assuming RTL-8169\n"));
|
---|
562 | dprintf(("PCI device: TxConfig = 0x%hX\n",
|
---|
563 | (unsigned long) RTL_R32(TxConfig)));
|
---|
564 |
|
---|
565 | tpc->chipset = 0;
|
---|
566 | return 1;
|
---|
567 |
|
---|
568 | match:
|
---|
569 | return 0;
|
---|
570 |
|
---|
571 | }
|
---|
572 |
|
---|
573 | /**************************************************************************
|
---|
574 | IRQ - Wait for a frame
|
---|
575 | ***************************************************************************/
|
---|
576 | void r8169_irq(struct nic *nic __unused, irq_action_t action)
|
---|
577 | {
|
---|
578 | int intr_status = 0;
|
---|
579 | int interested = RxOverflow | RxFIFOOver | RxErr | RxOK;
|
---|
580 |
|
---|
581 | switch (action) {
|
---|
582 | case DISABLE:
|
---|
583 | case ENABLE:
|
---|
584 | intr_status = RTL_R16(IntrStatus);
|
---|
585 | /* h/w no longer present (hotplug?) or major error,
|
---|
586 | bail */
|
---|
587 | if (intr_status == 0xFFFF)
|
---|
588 | break;
|
---|
589 |
|
---|
590 | intr_status = intr_status & ~interested;
|
---|
591 | if (action == ENABLE)
|
---|
592 | intr_status = intr_status | interested;
|
---|
593 | RTL_W16(IntrMask, intr_status);
|
---|
594 | break;
|
---|
595 | case FORCE:
|
---|
596 | RTL_W8(TxPoll, (RTL_R8(TxPoll) | 0x01));
|
---|
597 | break;
|
---|
598 | }
|
---|
599 | }
|
---|
600 |
|
---|
601 | /**************************************************************************
|
---|
602 | POLL - Wait for a frame
|
---|
603 | ***************************************************************************/
|
---|
604 | static int r8169_poll(struct nic *nic, int retreive)
|
---|
605 | {
|
---|
606 | /* return true if there's an ethernet packet ready to read */
|
---|
607 | /* nic->packet should contain data on return */
|
---|
608 | /* nic->packetlen should contain length of data */
|
---|
609 | int cur_rx;
|
---|
610 | unsigned int intr_status = 0;
|
---|
611 | cur_rx = tpc->cur_rx;
|
---|
612 | if ((tpc->RxDescArray[cur_rx].status & OWNbit) == 0) {
|
---|
613 | /* There is a packet ready */
|
---|
614 | if (!retreive)
|
---|
615 | return 1;
|
---|
616 | intr_status = RTL_R16(IntrStatus);
|
---|
617 | /* h/w no longer present (hotplug?) or major error,
|
---|
618 | bail */
|
---|
619 | if (intr_status == 0xFFFF)
|
---|
620 | return 0;
|
---|
621 | RTL_W16(IntrStatus, intr_status &
|
---|
622 | ~(RxFIFOOver | RxOverflow | RxOK));
|
---|
623 |
|
---|
624 | if (!(tpc->RxDescArray[cur_rx].status & RxRES)) {
|
---|
625 | nic->packetlen = (int) (tpc->RxDescArray[cur_rx].
|
---|
626 | status & 0x00001FFF) - 4;
|
---|
627 | memcpy(nic->packet, tpc->RxBufferRing[cur_rx],
|
---|
628 | nic->packetlen);
|
---|
629 | if (cur_rx == NUM_RX_DESC - 1)
|
---|
630 | tpc->RxDescArray[cur_rx].status =
|
---|
631 | (OWNbit | EORbit) + RX_BUF_SIZE;
|
---|
632 | else
|
---|
633 | tpc->RxDescArray[cur_rx].status =
|
---|
634 | OWNbit + RX_BUF_SIZE;
|
---|
635 | tpc->RxDescArray[cur_rx].buf_addr =
|
---|
636 | virt_to_bus(tpc->RxBufferRing[cur_rx]);
|
---|
637 | } else
|
---|
638 | printf("Error Rx");
|
---|
639 | /* FIXME: shouldn't I reset the status on an error */
|
---|
640 | cur_rx = (cur_rx + 1) % NUM_RX_DESC;
|
---|
641 | tpc->cur_rx = cur_rx;
|
---|
642 | RTL_W16(IntrStatus, intr_status &
|
---|
643 | (RxFIFOOver | RxOverflow | RxOK));
|
---|
644 |
|
---|
645 | return 1;
|
---|
646 |
|
---|
647 | }
|
---|
648 | tpc->cur_rx = cur_rx;
|
---|
649 | /* FIXME: There is no reason to do this as cur_rx did not change */
|
---|
650 |
|
---|
651 | return (0); /* initially as this is called to flush the input */
|
---|
652 |
|
---|
653 | }
|
---|
654 |
|
---|
655 | /**************************************************************************
|
---|
656 | TRANSMIT - Transmit a frame
|
---|
657 | ***************************************************************************/
|
---|
658 | static void r8169_transmit(struct nic *nic, const char *d, /* Destination */
|
---|
659 | unsigned int t, /* Type */
|
---|
660 | unsigned int s, /* size */
|
---|
661 | const char *p)
|
---|
662 | { /* Packet */
|
---|
663 | /* send the packet to destination */
|
---|
664 |
|
---|
665 | u16 nstype;
|
---|
666 | u32 to;
|
---|
667 | u8 *ptxb;
|
---|
668 | int entry = tpc->cur_tx % NUM_TX_DESC;
|
---|
669 |
|
---|
670 | /* point to the current txb incase multiple tx_rings are used */
|
---|
671 | ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE];
|
---|
672 | memcpy(ptxb, d, ETH_ALEN);
|
---|
673 | memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN);
|
---|
674 | nstype = htons((u16) t);
|
---|
675 | memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2);
|
---|
676 | memcpy(ptxb + ETH_HLEN, p, s);
|
---|
677 | s += ETH_HLEN;
|
---|
678 | s &= 0x0FFF;
|
---|
679 | while (s < ETH_ZLEN)
|
---|
680 | ptxb[s++] = '\0';
|
---|
681 |
|
---|
682 | tpc->TxDescArray[entry].buf_addr = virt_to_bus(ptxb);
|
---|
683 | if (entry != (NUM_TX_DESC - 1))
|
---|
684 | tpc->TxDescArray[entry].status =
|
---|
685 | (OWNbit | FSbit | LSbit) | ((s > ETH_ZLEN) ? s :
|
---|
686 | ETH_ZLEN);
|
---|
687 | else
|
---|
688 | tpc->TxDescArray[entry].status =
|
---|
689 | (OWNbit | EORbit | FSbit | LSbit) | ((s > ETH_ZLEN) ? s
|
---|
690 | : ETH_ZLEN);
|
---|
691 | RTL_W8(TxPoll, 0x40); /* set polling bit */
|
---|
692 |
|
---|
693 | tpc->cur_tx++;
|
---|
694 | to = currticks() + TX_TIMEOUT;
|
---|
695 | while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */
|
---|
696 |
|
---|
697 | if (currticks() >= to) {
|
---|
698 | printf("TX Time Out");
|
---|
699 | }
|
---|
700 | }
|
---|
701 |
|
---|
702 | static void rtl8169_set_rx_mode(struct nic *nic __unused)
|
---|
703 | {
|
---|
704 | u32 mc_filter[2]; /* Multicast hash filter */
|
---|
705 | int rx_mode;
|
---|
706 | u32 tmp = 0;
|
---|
707 |
|
---|
708 | /* IFF_ALLMULTI */
|
---|
709 | /* Too many to filter perfectly -- accept all multicasts. */
|
---|
710 | rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
|
---|
711 | mc_filter[1] = mc_filter[0] = 0xffffffff;
|
---|
712 |
|
---|
713 | tmp =
|
---|
714 | rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) &
|
---|
715 | rtl_chip_info[tpc->chipset].
|
---|
716 | RxConfigMask);
|
---|
717 |
|
---|
718 | RTL_W32(RxConfig, tmp);
|
---|
719 | RTL_W32(MAR0 + 0, mc_filter[0]);
|
---|
720 | RTL_W32(MAR0 + 4, mc_filter[1]);
|
---|
721 | }
|
---|
722 | static void rtl8169_hw_start(struct nic *nic)
|
---|
723 | {
|
---|
724 | u32 i;
|
---|
725 |
|
---|
726 | /* Soft reset the chip. */
|
---|
727 | RTL_W8(ChipCmd, CmdReset);
|
---|
728 |
|
---|
729 | /* Check that the chip has finished the reset. */
|
---|
730 | for (i = 1000; i > 0; i--) {
|
---|
731 | if ((RTL_R8(ChipCmd) & CmdReset) == 0)
|
---|
732 | break;
|
---|
733 | else
|
---|
734 | udelay(10);
|
---|
735 | }
|
---|
736 |
|
---|
737 | RTL_W8(Cfg9346, Cfg9346_Unlock);
|
---|
738 | RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
|
---|
739 | RTL_W8(ETThReg, ETTh);
|
---|
740 |
|
---|
741 | /* For gigabit rtl8169 */
|
---|
742 | RTL_W16(RxMaxSize, RxPacketMaxSize);
|
---|
743 |
|
---|
744 | /* Set Rx Config register */
|
---|
745 | i = rtl8169_rx_config | (RTL_R32(RxConfig) &
|
---|
746 | rtl_chip_info[tpc->chipset].RxConfigMask);
|
---|
747 | RTL_W32(RxConfig, i);
|
---|
748 |
|
---|
749 | /* Set DMA burst size and Interframe Gap Time */
|
---|
750 | RTL_W32(TxConfig,
|
---|
751 | (TX_DMA_BURST << TxDMAShift) | (InterFrameGap <<
|
---|
752 | TxInterFrameGapShift));
|
---|
753 |
|
---|
754 |
|
---|
755 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd));
|
---|
756 |
|
---|
757 | if (tpc->mcfg == MCFG_METHOD_2 || tpc->mcfg == MCFG_METHOD_3) {
|
---|
758 | RTL_W16(CPlusCmd,
|
---|
759 | (RTL_R16(CPlusCmd) | (1 << 14) | (1 << 3)));
|
---|
760 | DBG_PRINT
|
---|
761 | ("Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n");
|
---|
762 | } else {
|
---|
763 | RTL_W16(CPlusCmd, (RTL_R16(CPlusCmd) | (1 << 3)));
|
---|
764 | DBG_PRINT("Set MAC Reg C+CR Offset 0xE0: bit-3.\n");
|
---|
765 | }
|
---|
766 |
|
---|
767 | {
|
---|
768 | //RTL_W16(0xE2, 0x1517);
|
---|
769 | //RTL_W16(0xE2, 0x152a);
|
---|
770 | //RTL_W16(0xE2, 0x282a);
|
---|
771 | RTL_W16(0xE2, 0x0000);
|
---|
772 | }
|
---|
773 |
|
---|
774 |
|
---|
775 |
|
---|
776 | tpc->cur_rx = 0;
|
---|
777 |
|
---|
778 | RTL_W32(TxDescStartAddr, virt_to_le32desc(tpc->TxDescArray));
|
---|
779 | RTL_W32(RxDescStartAddr, virt_to_le32desc(tpc->RxDescArray));
|
---|
780 | RTL_W8(Cfg9346, Cfg9346_Lock);
|
---|
781 | udelay(10);
|
---|
782 |
|
---|
783 | RTL_W32(RxMissed, 0);
|
---|
784 |
|
---|
785 | rtl8169_set_rx_mode(nic);
|
---|
786 |
|
---|
787 | /* no early-rx interrupts */
|
---|
788 | RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
|
---|
789 |
|
---|
790 | RTL_W16(IntrMask, rtl8169_intr_mask);
|
---|
791 |
|
---|
792 | }
|
---|
793 |
|
---|
794 | static void rtl8169_init_ring(struct nic *nic __unused)
|
---|
795 | {
|
---|
796 | int i;
|
---|
797 |
|
---|
798 | tpc->cur_rx = 0;
|
---|
799 | tpc->cur_tx = 0;
|
---|
800 | memset(tpc->TxDescArray, 0x0, NUM_TX_DESC * sizeof(struct TxDesc));
|
---|
801 | memset(tpc->RxDescArray, 0x0, NUM_RX_DESC * sizeof(struct RxDesc));
|
---|
802 |
|
---|
803 | for (i = 0; i < NUM_TX_DESC; i++) {
|
---|
804 | tpc->Tx_skbuff[i] = &txb[i];
|
---|
805 | }
|
---|
806 |
|
---|
807 | for (i = 0; i < NUM_RX_DESC; i++) {
|
---|
808 | if (i == (NUM_RX_DESC - 1))
|
---|
809 | tpc->RxDescArray[i].status =
|
---|
810 | (OWNbit | EORbit) | RX_BUF_SIZE;
|
---|
811 | else
|
---|
812 | tpc->RxDescArray[i].status = OWNbit | RX_BUF_SIZE;
|
---|
813 |
|
---|
814 | tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE];
|
---|
815 | tpc->RxDescArray[i].buf_addr =
|
---|
816 | virt_to_bus(tpc->RxBufferRing[i]);
|
---|
817 | }
|
---|
818 | }
|
---|
819 |
|
---|
820 | /**************************************************************************
|
---|
821 | RESET - Finish setting up the ethernet interface
|
---|
822 | ***************************************************************************/
|
---|
823 | static void r8169_reset(struct nic *nic)
|
---|
824 | {
|
---|
825 | int i;
|
---|
826 | u8 diff;
|
---|
827 | u32 TxPhyAddr, RxPhyAddr;
|
---|
828 |
|
---|
829 | tpc->TxDescArrays = tx_ring;
|
---|
830 | if (tpc->TxDescArrays == 0)
|
---|
831 | printf("Allot Error");
|
---|
832 | /* Tx Desscriptor needs 256 bytes alignment; */
|
---|
833 | TxPhyAddr = virt_to_bus(tpc->TxDescArrays);
|
---|
834 | diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8));
|
---|
835 | TxPhyAddr += diff;
|
---|
836 | tpc->TxDescArray = (struct TxDesc *) (tpc->TxDescArrays + diff);
|
---|
837 |
|
---|
838 | tpc->RxDescArrays = rx_ring;
|
---|
839 | /* Rx Desscriptor needs 256 bytes alignment; */
|
---|
840 | RxPhyAddr = virt_to_bus(tpc->RxDescArrays);
|
---|
841 | diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8));
|
---|
842 | RxPhyAddr += diff;
|
---|
843 | tpc->RxDescArray = (struct RxDesc *) (tpc->RxDescArrays + diff);
|
---|
844 |
|
---|
845 | if (tpc->TxDescArrays == NULL || tpc->RxDescArrays == NULL) {
|
---|
846 | printf("Allocate RxDescArray or TxDescArray failed\n");
|
---|
847 | return;
|
---|
848 | }
|
---|
849 |
|
---|
850 | rtl8169_init_ring(nic);
|
---|
851 | rtl8169_hw_start(nic);
|
---|
852 | /* Construct a perfect filter frame with the mac address as first match
|
---|
853 | * and broadcast for all others */
|
---|
854 | for (i = 0; i < 192; i++)
|
---|
855 | txb[i] = 0xFF;
|
---|
856 |
|
---|
857 | txb[0] = nic->node_addr[0];
|
---|
858 | txb[1] = nic->node_addr[1];
|
---|
859 | txb[2] = nic->node_addr[2];
|
---|
860 | txb[3] = nic->node_addr[3];
|
---|
861 | txb[4] = nic->node_addr[4];
|
---|
862 | txb[5] = nic->node_addr[5];
|
---|
863 | }
|
---|
864 |
|
---|
865 | /**************************************************************************
|
---|
866 | DISABLE - Turn off ethernet interface
|
---|
867 | ***************************************************************************/
|
---|
868 | static void r8169_disable(struct dev *dev __unused)
|
---|
869 | {
|
---|
870 | int i;
|
---|
871 | /* Stop the chip's Tx and Rx DMA processes. */
|
---|
872 | RTL_W8(ChipCmd, 0x00);
|
---|
873 |
|
---|
874 | /* Disable interrupts by clearing the interrupt mask. */
|
---|
875 | RTL_W16(IntrMask, 0x0000);
|
---|
876 |
|
---|
877 | RTL_W32(RxMissed, 0);
|
---|
878 |
|
---|
879 | tpc->TxDescArrays = NULL;
|
---|
880 | tpc->RxDescArrays = NULL;
|
---|
881 | tpc->TxDescArray = NULL;
|
---|
882 | tpc->RxDescArray = NULL;
|
---|
883 | for (i = 0; i < NUM_RX_DESC; i++) {
|
---|
884 | tpc->RxBufferRing[i] = NULL;
|
---|
885 | }
|
---|
886 | }
|
---|
887 |
|
---|
888 | /**************************************************************************
|
---|
889 | PROBE - Look for an adapter, this routine's visible to the outside
|
---|
890 | ***************************************************************************/
|
---|
891 |
|
---|
892 | #define board_found 1
|
---|
893 | #define valid_link 0
|
---|
894 | static int r8169_probe(struct dev *dev, struct pci_device *pci)
|
---|
895 | {
|
---|
896 | struct nic *nic = (struct nic *) dev;
|
---|
897 | static int board_idx = -1;
|
---|
898 | static int printed_version = 0;
|
---|
899 | int i, rc;
|
---|
900 | int option = -1, Cap10_100 = 0, Cap1000 = 0;
|
---|
901 |
|
---|
902 | printf("r8169.c: Found %s, Vendor=%hX Device=%hX\n",
|
---|
903 | pci->name, pci->vendor, pci->dev_id);
|
---|
904 |
|
---|
905 | board_idx++;
|
---|
906 |
|
---|
907 | printed_version = 1;
|
---|
908 |
|
---|
909 | /* point to private storage */
|
---|
910 | tpc = &tpx;
|
---|
911 |
|
---|
912 | rc = rtl8169_init_board(pci); /* Return code is meaningless */
|
---|
913 |
|
---|
914 | /* Get MAC address. FIXME: read EEPROM */
|
---|
915 | for (i = 0; i < MAC_ADDR_LEN; i++)
|
---|
916 | nic->node_addr[i] = RTL_R8(MAC0 + i);
|
---|
917 |
|
---|
918 | dprintf(("%s: Identified chip type is '%s'.\n", pci->name,
|
---|
919 | rtl_chip_info[tpc->chipset].name));
|
---|
920 | /* Print out some hardware info */
|
---|
921 | printf("%s: %! at ioaddr %hX, ", pci->name, nic->node_addr,
|
---|
922 | ioaddr);
|
---|
923 |
|
---|
924 | // Config PHY
|
---|
925 | rtl8169_hw_PHY_config(nic);
|
---|
926 |
|
---|
927 | DBG_PRINT("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
|
---|
928 | RTL_W8(0x82, 0x01);
|
---|
929 |
|
---|
930 | if (tpc->mcfg < MCFG_METHOD_3) {
|
---|
931 | DBG_PRINT("Set PCI Latency=0x40\n");
|
---|
932 | pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0x40);
|
---|
933 | }
|
---|
934 |
|
---|
935 | if (tpc->mcfg == MCFG_METHOD_2) {
|
---|
936 | DBG_PRINT("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
|
---|
937 | RTL_W8(0x82, 0x01);
|
---|
938 | DBG_PRINT("Set PHY Reg 0x0bh = 0x00h\n");
|
---|
939 | RTL8169_WRITE_GMII_REG(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
|
---|
940 | }
|
---|
941 |
|
---|
942 | /* if TBI is not endbled */
|
---|
943 | if (!(RTL_R8(PHYstatus) & TBI_Enable)) {
|
---|
944 | int val = RTL8169_READ_GMII_REG(ioaddr, PHY_AUTO_NEGO_REG);
|
---|
945 |
|
---|
946 | #ifdef RTL8169_HW_FLOW_CONTROL_SUPPORT
|
---|
947 | val |= PHY_Cap_PAUSE | PHY_Cap_ASYM_PAUSE;
|
---|
948 | #endif //end #define RTL8169_HW_FLOW_CONTROL_SUPPORT
|
---|
949 |
|
---|
950 | option = media;
|
---|
951 | /* Force RTL8169 in 10/100/1000 Full/Half mode. */
|
---|
952 | if (option > 0) {
|
---|
953 | printf(" Force-mode Enabled.\n");
|
---|
954 | Cap10_100 = 0, Cap1000 = 0;
|
---|
955 | switch (option) {
|
---|
956 | case _10_Half:
|
---|
957 | Cap10_100 = PHY_Cap_10_Half;
|
---|
958 | Cap1000 = PHY_Cap_Null;
|
---|
959 | break;
|
---|
960 | case _10_Full:
|
---|
961 | Cap10_100 = PHY_Cap_10_Full;
|
---|
962 | Cap1000 = PHY_Cap_Null;
|
---|
963 | break;
|
---|
964 | case _100_Half:
|
---|
965 | Cap10_100 = PHY_Cap_100_Half;
|
---|
966 | Cap1000 = PHY_Cap_Null;
|
---|
967 | break;
|
---|
968 | case _100_Full:
|
---|
969 | Cap10_100 = PHY_Cap_100_Full;
|
---|
970 | Cap1000 = PHY_Cap_Null;
|
---|
971 | break;
|
---|
972 | case _1000_Full:
|
---|
973 | Cap10_100 = PHY_Cap_Null;
|
---|
974 | Cap1000 = PHY_Cap_1000_Full;
|
---|
975 | break;
|
---|
976 | default:
|
---|
977 | break;
|
---|
978 | }
|
---|
979 | RTL8169_WRITE_GMII_REG(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0xC1F)); //leave PHY_AUTO_NEGO_REG bit4:0 unchanged
|
---|
980 | RTL8169_WRITE_GMII_REG(ioaddr, PHY_1000_CTRL_REG,
|
---|
981 | Cap1000);
|
---|
982 | } else {
|
---|
983 | dprintf(("Auto-negotiation Enabled.\n",
|
---|
984 | pci->name));
|
---|
985 |
|
---|
986 | // enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
|
---|
987 | RTL8169_WRITE_GMII_REG(ioaddr, PHY_AUTO_NEGO_REG,
|
---|
988 | PHY_Cap_10_Half |
|
---|
989 | PHY_Cap_10_Full |
|
---|
990 | PHY_Cap_100_Half |
|
---|
991 | PHY_Cap_100_Full | (val &
|
---|
992 | 0xC1F));
|
---|
993 |
|
---|
994 | // enable 1000 Full Mode
|
---|
995 | // RTL8169_WRITE_GMII_REG( ioaddr, PHY_1000_CTRL_REG, PHY_Cap_1000_Full );
|
---|
996 | RTL8169_WRITE_GMII_REG(ioaddr, PHY_1000_CTRL_REG, PHY_Cap_1000_Full | PHY_Cap_1000_Half); //rtl8168
|
---|
997 |
|
---|
998 | } // end of if( option > 0 )
|
---|
999 |
|
---|
1000 | // Enable auto-negotiation and restart auto-nigotiation
|
---|
1001 | RTL8169_WRITE_GMII_REG(ioaddr, PHY_CTRL_REG,
|
---|
1002 | PHY_Enable_Auto_Nego |
|
---|
1003 | PHY_Restart_Auto_Nego);
|
---|
1004 | udelay(100);
|
---|
1005 |
|
---|
1006 | // wait for auto-negotiation process
|
---|
1007 | for (i = 10000; i > 0; i--) {
|
---|
1008 | //check if auto-negotiation complete
|
---|
1009 | if (RTL8169_READ_GMII_REG(ioaddr, PHY_STAT_REG) &
|
---|
1010 | PHY_Auto_Neco_Comp) {
|
---|
1011 | udelay(100);
|
---|
1012 | option = RTL_R8(PHYstatus);
|
---|
1013 | if (option & _1000bpsF) {
|
---|
1014 | printf
|
---|
1015 | ("1000Mbps Full-duplex operation.\n");
|
---|
1016 | } else {
|
---|
1017 | printf
|
---|
1018 | ("%sMbps %s-duplex operation.\n",
|
---|
1019 | (option & _100bps) ? "100" :
|
---|
1020 | "10",
|
---|
1021 | (option & FullDup) ? "Full" :
|
---|
1022 | "Half");
|
---|
1023 | }
|
---|
1024 | break;
|
---|
1025 | } else {
|
---|
1026 | udelay(100);
|
---|
1027 | } // end of if( RTL8169_READ_GMII_REG(ioaddr, 1) & 0x20 )
|
---|
1028 | } // end for-loop to wait for auto-negotiation process
|
---|
1029 |
|
---|
1030 |
|
---|
1031 | } else {
|
---|
1032 | udelay(100);
|
---|
1033 | printf
|
---|
1034 | ("%s: 1000Mbps Full-duplex operation, TBI Link %s!\n",
|
---|
1035 | pci->name,
|
---|
1036 | (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed");
|
---|
1037 |
|
---|
1038 | }
|
---|
1039 |
|
---|
1040 | r8169_reset(nic);
|
---|
1041 | /* point to NIC specific routines */
|
---|
1042 | dev->disable = r8169_disable;
|
---|
1043 | nic->poll = r8169_poll;
|
---|
1044 | nic->transmit = r8169_transmit;
|
---|
1045 | nic->irqno = pci->irq;
|
---|
1046 | nic->irq = r8169_irq;
|
---|
1047 | nic->ioaddr = ioaddr;
|
---|
1048 | return 1;
|
---|
1049 |
|
---|
1050 | }
|
---|
1051 |
|
---|
1052 | //======================================================================================================
|
---|
1053 | /*
|
---|
1054 | static void rtl8169_hw_PHY_reset(struct nic *nic __unused)
|
---|
1055 | {
|
---|
1056 | int val, phy_reset_expiretime = 50;
|
---|
1057 | struct rtl8169_private *priv = dev->priv;
|
---|
1058 | unsigned long ioaddr = priv->ioaddr;
|
---|
1059 |
|
---|
1060 | DBG_PRINT("%s: Reset RTL8169s PHY\n", dev->name);
|
---|
1061 |
|
---|
1062 | val = ( RTL8169_READ_GMII_REG( ioaddr, 0 ) | 0x8000 ) & 0xffff;
|
---|
1063 | RTL8169_WRITE_GMII_REG( ioaddr, 0, val );
|
---|
1064 |
|
---|
1065 | do //waiting for phy reset
|
---|
1066 | {
|
---|
1067 | if( RTL8169_READ_GMII_REG( ioaddr, 0 ) & 0x8000 ){
|
---|
1068 | phy_reset_expiretime --;
|
---|
1069 | udelay(100);
|
---|
1070 | }
|
---|
1071 | else{
|
---|
1072 | break;
|
---|
1073 | }
|
---|
1074 | }while( phy_reset_expiretime >= 0 );
|
---|
1075 |
|
---|
1076 | assert( phy_reset_expiretime > 0 );
|
---|
1077 | }
|
---|
1078 |
|
---|
1079 | */
|
---|
1080 |
|
---|
1081 | //======================================================================================================
|
---|
1082 | static void rtl8169_hw_PHY_config(struct nic *nic __unused)
|
---|
1083 | {
|
---|
1084 |
|
---|
1085 | DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n", tpc->mcfg, tpc->pcfg);
|
---|
1086 |
|
---|
1087 | if (tpc->mcfg == MCFG_METHOD_4) {
|
---|
1088 | /*
|
---|
1089 | RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1F, 0x0001 );
|
---|
1090 | RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1b, 0x841e );
|
---|
1091 | RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x0e, 0x7bfb );
|
---|
1092 | RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x09, 0x273a );
|
---|
1093 | */
|
---|
1094 |
|
---|
1095 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x1F,
|
---|
1096 | 0x0002);
|
---|
1097 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01,
|
---|
1098 | 0x90D0);
|
---|
1099 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x1F,
|
---|
1100 | 0x0000);
|
---|
1101 | } else if ((tpc->mcfg == MCFG_METHOD_2)
|
---|
1102 | || (tpc->mcfg == MCFG_METHOD_3)) {
|
---|
1103 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x1F,
|
---|
1104 | 0x0001);
|
---|
1105 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x15,
|
---|
1106 | 0x1000);
|
---|
1107 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x18,
|
---|
1108 | 0x65C7);
|
---|
1109 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1110 | 0x0000);
|
---|
1111 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x03,
|
---|
1112 | 0x00A1);
|
---|
1113 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x02,
|
---|
1114 | 0x0008);
|
---|
1115 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01,
|
---|
1116 | 0x1020);
|
---|
1117 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x00,
|
---|
1118 | 0x1000);
|
---|
1119 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1120 | 0x0800);
|
---|
1121 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1122 | 0x0000);
|
---|
1123 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1124 | 0x7000);
|
---|
1125 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x03,
|
---|
1126 | 0xFF41);
|
---|
1127 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x02,
|
---|
1128 | 0xDE60);
|
---|
1129 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01,
|
---|
1130 | 0x0140);
|
---|
1131 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x00,
|
---|
1132 | 0x0077);
|
---|
1133 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1134 | 0x7800);
|
---|
1135 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1136 | 0x7000);
|
---|
1137 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1138 | 0xA000);
|
---|
1139 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x03,
|
---|
1140 | 0xDF01);
|
---|
1141 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x02,
|
---|
1142 | 0xDF20);
|
---|
1143 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01,
|
---|
1144 | 0xFF95);
|
---|
1145 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x00,
|
---|
1146 | 0xFA00);
|
---|
1147 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1148 | 0xA800);
|
---|
1149 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1150 | 0xA000);
|
---|
1151 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1152 | 0xB000);
|
---|
1153 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x03,
|
---|
1154 | 0xFF41);
|
---|
1155 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x02,
|
---|
1156 | 0xDE20);
|
---|
1157 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01,
|
---|
1158 | 0x0140);
|
---|
1159 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x00,
|
---|
1160 | 0x00BB);
|
---|
1161 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1162 | 0xB800);
|
---|
1163 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1164 | 0xB000);
|
---|
1165 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1166 | 0xF000);
|
---|
1167 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x03,
|
---|
1168 | 0xDF01);
|
---|
1169 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x02,
|
---|
1170 | 0xDF20);
|
---|
1171 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01,
|
---|
1172 | 0xFF95);
|
---|
1173 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x00,
|
---|
1174 | 0xBF00);
|
---|
1175 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1176 | 0xF800);
|
---|
1177 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1178 | 0xF000);
|
---|
1179 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04,
|
---|
1180 | 0x0000);
|
---|
1181 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x1F,
|
---|
1182 | 0x0000);
|
---|
1183 | RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x0B,
|
---|
1184 | 0x0000);
|
---|
1185 | } else {
|
---|
1186 | DBG_PRINT("tpc->mcfg=%d. Discard hw PHY config.\n",
|
---|
1187 | tpc->mcfg);
|
---|
1188 | }
|
---|
1189 | }
|
---|
1190 |
|
---|
1191 |
|
---|
1192 | static struct pci_id r8169_nics[] = {
|
---|
1193 | PCI_ROM(0x10ec, 0x8169, "r8169", "RealTek RTL8169 Gigabit Ethernet"),
|
---|
1194 | PCI_ROM(0x16ec, 0x0116, "usr-r8169", "US Robotics RTL8169 Gigabit Ethernet"),
|
---|
1195 | PCI_ROM(0x1186, 0x4300, "dlink-r8169", "D-Link RTL8169 Gigabit Ethernet"),
|
---|
1196 | };
|
---|
1197 |
|
---|
1198 | static struct pci_driver r8169_driver __pci_driver = {
|
---|
1199 | .type = NIC_DRIVER,
|
---|
1200 | .name = "r8169/PCI",
|
---|
1201 | .probe = r8169_probe,
|
---|
1202 | .ids = r8169_nics,
|
---|
1203 | .id_count = sizeof(r8169_nics) / sizeof(r8169_nics[0]),
|
---|
1204 | .class = 0,
|
---|
1205 | };
|
---|