Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
629 | giacomo | 1 | /* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */ |
2 | /* |
||
3 | Written 1997-1999 by Donald Becker. |
||
4 | |||
5 | This software may be used and distributed according to the terms |
||
6 | of the GNU Public License, incorporated herein by reference. |
||
7 | All other rights reserved. |
||
8 | |||
9 | This driver is for boards based on the RTL8129 and RTL8139 PCI ethernet |
||
10 | chips. |
||
11 | |||
12 | The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O |
||
13 | Center of Excellence in Space Data and Information Sciences |
||
14 | Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 |
||
15 | |||
16 | Support and updates available at |
||
17 | http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html |
||
18 | |||
19 | Twister-tuning table provided by Kinston <shangh@realtek.com.tw>. |
||
20 | */ |
||
21 | |||
22 | static const char *version = |
||
23 | "rtl8139.c:v1.07 5/6/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n"; |
||
24 | |||
25 | /* A few user-configurable values. */ |
||
26 | /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ |
||
27 | static int max_interrupt_work = 20; |
||
28 | //#define rtl8129_debug debug |
||
29 | static int rtl8129_debug = 0; |
||
30 | |||
31 | /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). |
||
32 | The RTL chips use a 64 element hash table based on the Ethernet CRC. */ |
||
33 | static int multicast_filter_limit = 32; |
||
34 | |||
35 | /* Used to pass the full-duplex flag, etc. */ |
||
36 | #define MAX_UNITS 8 /* More are supported, limit only on options */ |
||
37 | static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; |
||
38 | static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; |
||
39 | |||
40 | /* Size of the in-memory receive ring. */ |
||
41 | #define RX_BUF_LEN_IDX 3 /* 0==8K, 1==16K, 2==32K, 3==64K */ |
||
42 | #define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) |
||
43 | /* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ |
||
44 | #define TX_BUF_SIZE 1536 |
||
45 | |||
46 | /* PCI Tuning Parameters |
||
47 | Threshold is bytes transferred to chip before transmission starts. */ |
||
48 | #define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ |
||
49 | |||
50 | /* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. */ |
||
51 | #define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */ |
||
52 | #define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */ |
||
53 | #define TX_DMA_BURST 4 /* Calculate as 16<<val. */ |
||
54 | |||
55 | /* Operational parameters that usually are not changed. */ |
||
56 | /* Time in jiffies before concluding the transmitter is hung. */ |
||
57 | #define TX_TIMEOUT (4*HZ) |
||
58 | |||
59 | #include <linux/module.h> |
||
60 | #include <linux/version.h> |
||
61 | #include <linux/kernel.h> |
||
62 | #include <linux/sched.h> |
||
63 | #include <linux/string.h> |
||
64 | #include <linux/timer.h> |
||
65 | #include <linux/errno.h> |
||
66 | #include <linux/ioport.h> |
||
67 | #include <linux/malloc.h> |
||
68 | #include <linux/interrupt.h> |
||
69 | #include <linux/pci.h> |
||
70 | #include <linux/netdevice.h> |
||
71 | #include <linux/etherdevice.h> |
||
72 | #include <linux/skbuff.h> |
||
73 | #include <asm/processor.h> /* Processor type for cache alignment. */ |
||
74 | #include <asm/bitops.h> |
||
75 | #include <asm/io.h> |
||
76 | |||
77 | /* Kernel compatibility defines, some common to David Hind's PCMCIA package. |
||
78 | This is only in the support-all-kernels source code. */ |
||
79 | |||
80 | #define RUN_AT(x) (jiffies + (x)) |
||
81 | |||
82 | #include <linux/delay.h> |
||
83 | |||
84 | #if LINUX_VERSION_CODE < 0x20123 |
||
85 | #define test_and_set_bit(val, addr) set_bit(val, addr) |
||
86 | #endif |
||
87 | #if LINUX_VERSION_CODE <= 0x20139 |
||
88 | #define net_device_stats enet_statistics |
||
89 | #else |
||
90 | #define NETSTATS_VER2 |
||
91 | #endif |
||
92 | #if LINUX_VERSION_CODE < 0x20155 || defined(CARDBUS) |
||
93 | /* Grrrr, the PCI code changed, but did not consider CardBus... */ |
||
94 | #include <linux/bios32.h> |
||
95 | #define PCI_SUPPORT_VER1 |
||
96 | #else |
||
97 | #define PCI_SUPPORT_VER2 |
||
98 | #endif |
||
99 | #if LINUX_VERSION_CODE < 0x20159 |
||
100 | #define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE); |
||
101 | #else |
||
102 | #define dev_free_skb(skb) dev_kfree_skb(skb); |
||
103 | #endif |
||
104 | |||
105 | /* The I/O extent. */ |
||
106 | #define RTL8129_TOTAL_SIZE 0x80 |
||
107 | |||
108 | /* |
||
109 | Theory of Operation |
||
110 | |||
111 | I. Board Compatibility |
||
112 | |||
113 | This device driver is designed for the RealTek RTL8129, the RealTek Fast |
||
114 | Ethernet controllers for PCI. This chip is used on a few clone boards. |
||
115 | |||
116 | |||
117 | II. Board-specific settings |
||
118 | |||
119 | PCI bus devices are configured by the system at boot time, so no jumpers |
||
120 | need to be set on the board. The system BIOS will assign the |
||
121 | PCI INTA signal to a (preferably otherwise unused) system IRQ line. |
||
122 | Note: Kernel versions earlier than 1.3.73 do not support shared PCI |
||
123 | interrupt lines. |
||
124 | |||
125 | III. Driver operation |
||
126 | |||
127 | IIIa. Rx Ring buffers |
||
128 | |||
129 | The receive unit uses a single linear ring buffer rather than the more |
||
130 | common (and more efficient) descriptor-based architecture. Incoming frames |
||
131 | are sequentially stored into the Rx region, and the host copies them into |
||
132 | skbuffs. |
||
133 | |||
134 | Comment: While it is theoretically possible to process many frames in place, |
||
135 | any delay in Rx processing would cause us to drop frames. More importantly, |
||
136 | the Linux protocol stack is not designed to operate in this manner. |
||
137 | |||
138 | IIIb. Tx operation |
||
139 | |||
140 | The RTL8129 uses a fixed set of four Tx descriptors in register space. |
||
141 | In a stunningly bad design choice, Tx frames must be 32 bit aligned. Linux |
||
142 | aligns the IP header on word boundaries, and 14 byte ethernet header means |
||
143 | that almost all frames will need to be copied to an alignment buffer. |
||
144 | |||
145 | IVb. References |
||
146 | |||
147 | http://www.realtek.com.tw/cn/cn.html |
||
148 | http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html |
||
149 | |||
150 | IVc. Errata |
||
151 | |||
152 | */ |
||
153 | |||
154 | /* Added by Nino - Begin */ |
||
155 | extern int pci20to26_find_class(unsigned int class_code, int index, BYTE *bus, BYTE *dev); |
||
156 | extern int pci20to26_read_config_byte(unsigned int bus, unsigned int dev, int where, u8 *val); |
||
157 | extern int pci20to26_read_config_word(unsigned int bus, unsigned int dev, int where, u16 *val); |
||
158 | extern int pci20to26_read_config_dword(unsigned int bus, unsigned int dev, int where, u32 *val); |
||
159 | extern int pci20to26_write_config_byte(unsigned int bus, unsigned int dev, int where, u8 val); |
||
160 | extern int pci20to26_write_config_word(unsigned int bus, unsigned int dev, int where, u16 val); |
||
161 | extern int pci20to26_write_config_dword(unsigned int bus, unsigned int dev, int where, u32 val); |
||
162 | /* Added by Nino - End */ |
||
163 | |||
164 | /* This table drives the PCI probe routines. It's mostly boilerplate in all |
||
165 | of the drivers, and will likely be provided by some future kernel. |
||
166 | Note the matching code -- the first table entry matchs all 56** cards but |
||
167 | second only the 1234 card. |
||
168 | */ |
||
169 | enum pci_flags_bit { |
||
170 | PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, |
||
171 | PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, |
||
172 | }; |
||
173 | struct pci_id_info { |
||
174 | const char *name; |
||
175 | u16 vendor_id, device_id, device_id_mask, flags; |
||
176 | int io_size; |
||
177 | struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev, |
||
178 | long ioaddr, int irq, int chip_idx, int fnd_cnt); |
||
179 | }; |
||
180 | |||
181 | static struct device * rtl8129_probe1(int pci_bus, int pci_devfn, |
||
182 | struct device *dev, long ioaddr, |
||
183 | int irq, int chp_idx, int fnd_cnt); |
||
184 | |||
185 | static struct pci_id_info pci_tbl[] = |
||
186 | {{ "RealTek RTL8129 Fast Ethernet", |
||
187 | 0x10ec, 0x8129, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, |
||
188 | { "RealTek RTL8139 Fast Ethernet", |
||
189 | 0x10ec, 0x8139, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, |
||
190 | { "SMC1211TX EZCard 10/100 (RealTek RTL8139)", |
||
191 | 0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, |
||
192 | { "Accton MPX5030 (RealTek RTL8139)", |
||
193 | 0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, |
||
194 | {0,}, /* 0 terminated list. */ |
||
195 | }; |
||
196 | |||
197 | /* The capability table matches the chip table above. */ |
||
198 | enum {HAS_MII_XCVR=0x01, HAS_CHIP_XCVR=0x02, HAS_LNK_CHNG=0x04}; |
||
199 | static int rtl_cap_tbl[] = { |
||
200 | HAS_MII_XCVR, HAS_CHIP_XCVR|HAS_LNK_CHNG, HAS_CHIP_XCVR|HAS_LNK_CHNG, |
||
201 | }; |
||
202 | |||
203 | |||
204 | /* The rest of these values should never change. */ |
||
205 | #define NUM_TX_DESC 4 /* Number of Tx descriptor registers. */ |
||
206 | |||
207 | /* Symbolic offsets to registers. */ |
||
208 | enum RTL8129_registers { |
||
209 | MAC0=0, /* Ethernet hardware address. */ |
||
210 | MAR0=8, /* Multicast filter. */ |
||
211 | TxStatus0=0x10, /* Transmit status (Four 32bit registers). */ |
||
212 | TxAddr0=0x20, /* Tx descriptors (also four 32bit). */ |
||
213 | RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36, |
||
214 | ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A, |
||
215 | IntrMask=0x3C, IntrStatus=0x3E, |
||
216 | TxConfig=0x40, RxConfig=0x44, |
||
217 | Timer=0x48, /* A general-purpose counter. */ |
||
218 | RxMissed=0x4C, /* 24 bits valid, write clears. */ |
||
219 | Cfg9346=0x50, Config0=0x51, Config1=0x52, |
||
220 | FlashReg=0x54, GPPinData=0x58, GPPinDir=0x59, MII_SMI=0x5A, HltClk=0x5B, |
||
221 | MultiIntr=0x5C, TxSummary=0x60, |
||
222 | MII_BMCR=0x62, MII_BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68, |
||
223 | NWayExpansion=0x6A, |
||
224 | /* Undocumented registers, but required for proper operation. */ |
||
225 | FIFOTMS=0x70, /* FIFO Test Mode Select */ |
||
226 | CSCR=0x74, /* Chip Status and Configuration Register. */ |
||
227 | PARA78=0x78, PARA7c=0x7c, /* Magic transceiver parameter register. */ |
||
228 | }; |
||
229 | |||
230 | enum ChipCmdBits { |
||
231 | CmdReset=0x10, CmdRxEnb=0x08, CmdTxEnb=0x04, RxBufEmpty=0x01, }; |
||
232 | |||
233 | /* Interrupt register bits, using my own meaningful names. */ |
||
234 | enum IntrStatusBits { |
||
235 | PCIErr=0x8000, PCSTimeout=0x4000, |
||
236 | RxFIFOOver=0x40, RxUnderrun=0x20, RxOverflow=0x10, |
||
237 | TxErr=0x08, TxOK=0x04, RxErr=0x02, RxOK=0x01, |
||
238 | }; |
||
239 | enum TxStatusBits { |
||
240 | TxHostOwns=0x2000, TxUnderrun=0x4000, TxStatOK=0x8000, |
||
241 | TxOutOfWindow=0x20000000, TxAborted=0x40000000, TxCarrierLost=0x80000000, |
||
242 | }; |
||
243 | enum RxStatusBits { |
||
244 | RxMulticast=0x8000, RxPhysical=0x4000, RxBroadcast=0x2000, |
||
245 | RxBadSymbol=0x0020, RxRunt=0x0010, RxTooLong=0x0008, RxCRCErr=0x0004, |
||
246 | RxBadAlign=0x0002, RxStatusOK=0x0001, |
||
247 | }; |
||
248 | |||
249 | /* Twister tuning parameters from RealTek. |
||
250 | Completely undocumented, but required to tune bad links. */ |
||
251 | enum CSCRBits { |
||
252 | CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800, |
||
253 | CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0, |
||
254 | CSCR_LinkDownCmd=0x0f3c0, |
||
255 | }; |
||
256 | unsigned long param[4][4]={ |
||
257 | {0x0cb39de43,0x0cb39ce43,0x0fb38de03,0x0cb38de43}, |
||
258 | {0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83}, |
||
259 | {0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83}, |
||
260 | {0x0bb39de43,0x0bb39ce43,0x0bb39ce83,0x0bb39ce83} |
||
261 | }; |
||
262 | |||
263 | struct rtl8129_private { |
||
264 | char devname[8]; /* Used only for kernel debugging. */ |
||
265 | const char *product_name; |
||
266 | struct device *next_module; |
||
267 | int chip_id; |
||
268 | int chip_revision; |
||
269 | unsigned char pci_bus, pci_devfn; |
||
270 | #if LINUX_VERSION_CODE > 0x20139 |
||
271 | struct net_device_stats stats; |
||
272 | #else |
||
273 | struct enet_statistics stats; |
||
274 | #endif |
||
275 | struct timer_list timer; /* Media selection timer. */ |
||
276 | unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ |
||
277 | unsigned int cur_tx, dirty_tx, tx_flag; |
||
278 | /* The saved address of a sent-in-place packet/buffer, for skfree(). */ |
||
279 | struct sk_buff* tx_skbuff[NUM_TX_DESC]; |
||
280 | unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ |
||
281 | unsigned char *rx_ring; |
||
282 | unsigned char *tx_bufs; /* Tx bounce buffer region. */ |
||
283 | char phys[4]; /* MII device addresses. */ |
||
284 | char twistie, twist_cnt; /* Twister tune state. */ |
||
285 | unsigned int tx_full:1; /* The Tx queue is full. */ |
||
286 | unsigned int full_duplex:1; /* Full-duplex operation requested. */ |
||
287 | unsigned int duplex_lock:1; |
||
288 | unsigned int default_port:4; /* Last dev->if_port value. */ |
||
289 | unsigned int media2:4; /* Secondary monitored media port. */ |
||
290 | unsigned int medialock:1; /* Don't sense media type. */ |
||
291 | unsigned int mediasense:1; /* Media sensing in progress. */ |
||
292 | }; |
||
293 | |||
294 | #ifdef MODULE |
||
295 | #if LINUX_VERSION_CODE > 0x20115 |
||
296 | MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>"); |
||
297 | MODULE_DESCRIPTION("RealTek RTL8129/8139 Fast Ethernet driver"); |
||
298 | MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); |
||
299 | MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); |
||
300 | MODULE_PARM(multicast_filter_limit, "i"); |
||
301 | MODULE_PARM(max_interrupt_work, "i"); |
||
302 | MODULE_PARM(debug, "i"); |
||
303 | #endif |
||
304 | #endif |
||
305 | |||
306 | static int rtl8129_open(struct device *dev); |
||
307 | static int read_eeprom(long ioaddr, int location); |
||
308 | static int mdio_read(struct device *dev, int phy_id, int location); |
||
309 | static void mdio_write(struct device *dev, int phy_id, int location, int val); |
||
310 | static void rtl8129_timer(unsigned long data); |
||
311 | static void rtl8129_tx_timeout(struct device *dev); |
||
312 | static void rtl8129_init_ring(struct device *dev); |
||
313 | static int rtl8129_start_xmit(struct sk_buff *skb, struct device *dev); |
||
314 | static int rtl8129_rx(struct device *dev); |
||
315 | static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs); |
||
316 | static int rtl8129_close(struct device *dev); |
||
317 | static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd); |
||
318 | static struct enet_statistics *rtl8129_get_stats(struct device *dev); |
||
319 | static inline u32 ether_crc(int length, unsigned char *data); |
||
320 | static void set_rx_mode(struct device *dev); |
||
321 | |||
322 | |||
323 | /* A list of all installed RTL8129 devices, for removing the driver module. */ |
||
324 | static struct device *root_rtl8129_dev = NULL; |
||
325 | |||
326 | /* Ideally we would detect all network cards in slot order. That would |
||
327 | be best done a central PCI probe dispatch, which wouldn't work |
||
328 | well when dynamically adding drivers. So instead we detect just the |
||
329 | Rtl81*9 cards in slot order. */ |
||
330 | |||
331 | int rtl8139_probe(struct device *dev) |
||
332 | { |
||
333 | int cards_found = 0; |
||
334 | int pci_index = 0; |
||
335 | unsigned char pci_bus, pci_device_fn; |
||
336 | |||
337 | if ( ! pcibios_present()) |
||
338 | return -ENODEV; |
||
339 | |||
340 | for (; pci_index < 0x0f; pci_index++) { // 0x0f was 0xff |
||
341 | u16 vendor, device, pci_command, new_command; |
||
342 | int chip_idx, irq; |
||
343 | long ioaddr; |
||
344 | |||
345 | if (pci20to26_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index, |
||
346 | &pci_bus, &pci_device_fn) |
||
347 | != PCIBIOS_SUCCESSFUL) |
||
348 | break; |
||
349 | pci20to26_read_config_word(pci_bus, pci_device_fn, |
||
350 | PCI_VENDOR_ID, &vendor); |
||
351 | pci20to26_read_config_word(pci_bus, pci_device_fn, |
||
352 | PCI_DEVICE_ID, &device); |
||
353 | |||
354 | for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) |
||
355 | if (vendor == pci_tbl[chip_idx].vendor_id |
||
356 | && (device & pci_tbl[chip_idx].device_id_mask) == |
||
357 | pci_tbl[chip_idx].device_id) |
||
358 | break; |
||
359 | if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */ |
||
360 | continue; |
||
361 | |||
362 | { |
||
363 | #if 0 //defined(PCI_SUPPORT_VER2) |
||
364 | struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); |
||
365 | ioaddr = pdev->base_address[0] & ~3; |
||
366 | irq = pdev->irq; |
||
367 | #else |
||
368 | u32 pci_ioaddr; |
||
369 | u8 pci_irq_line; |
||
370 | pci20to26_read_config_byte(pci_bus, pci_device_fn, |
||
371 | PCI_INTERRUPT_LINE, &pci_irq_line); |
||
372 | pci20to26_read_config_dword(pci_bus, pci_device_fn, |
||
373 | PCI_BASE_ADDRESS_0, &pci_ioaddr); |
||
374 | ioaddr = pci_ioaddr & ~3; |
||
375 | irq = pci_irq_line; |
||
376 | #endif |
||
377 | } |
||
378 | |||
379 | if ((pci_tbl[chip_idx].flags & PCI_USES_IO) && |
||
380 | check_region(ioaddr, pci_tbl[chip_idx].io_size)) |
||
381 | continue; |
||
382 | |||
383 | /* Activate the card: fix for brain-damaged Win98 BIOSes. */ |
||
384 | pci20to26_read_config_word(pci_bus, pci_device_fn, |
||
385 | PCI_COMMAND, &pci_command); |
||
386 | new_command = pci_command | (pci_tbl[chip_idx].flags & 7); |
||
387 | if (pci_command != new_command) { |
||
388 | printk(KERN_INFO " The PCI BIOS has not enabled the" |
||
389 | " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n", |
||
390 | pci_bus, pci_device_fn, pci_command, new_command); |
||
391 | pci20to26_write_config_word(pci_bus, pci_device_fn, |
||
392 | PCI_COMMAND, new_command); |
||
393 | } |
||
394 | |||
395 | dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr, |
||
396 | irq, chip_idx, cards_found); |
||
397 | |||
398 | if (dev && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) { |
||
399 | u8 pci_latency; |
||
400 | pci20to26_read_config_byte(pci_bus, pci_device_fn, |
||
401 | PCI_LATENCY_TIMER, &pci_latency); |
||
402 | if (pci_latency < 32) { |
||
403 | printk(KERN_NOTICE " PCI latency timer (CFLT) is " |
||
404 | "unreasonably low at %d. Setting to 64 clocks.\n", |
||
405 | pci_latency); |
||
406 | pci20to26_write_config_byte(pci_bus, pci_device_fn, |
||
407 | PCI_LATENCY_TIMER, 64); |
||
408 | } |
||
409 | } |
||
410 | dev = 0; |
||
411 | cards_found++; |
||
412 | } |
||
413 | |||
414 | return cards_found ? 0 : -ENODEV; |
||
415 | } |
||
416 | |||
417 | static struct device *rtl8129_probe1(int pci_bus, int pci_devfn, |
||
418 | struct device *dev, long ioaddr, |
||
419 | int irq, int chip_idx, int found_cnt) |
||
420 | { |
||
421 | static int did_version = 0; /* Already printed version info. */ |
||
422 | struct rtl8129_private *tp; |
||
423 | int i, option = found_cnt < MAX_UNITS ? options[found_cnt] : 0; |
||
424 | |||
425 | if (rtl8129_debug > 0 && did_version++ == 0) |
||
426 | printk(KERN_INFO "%s", version); |
||
427 | |||
428 | dev = init_etherdev(dev, 0); |
||
429 | |||
430 | printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", |
||
431 | dev->name, pci_tbl[chip_idx].name, ioaddr, irq); |
||
432 | |||
433 | /* Bring the chip out of low-power mode. */ |
||
434 | outb(0x00, ioaddr + Config1); |
||
435 | |||
436 | if (read_eeprom(ioaddr, 0) != 0xffff) { |
||
437 | for (i = 0; i < 3; i++) { |
||
438 | ((u16 *)(dev->dev_addr))[i] = |
||
439 | le16_to_cpu(read_eeprom(ioaddr, i + 7)); |
||
440 | } |
||
441 | } else { |
||
442 | for (i = 0; i < 6; i++) |
||
443 | dev->dev_addr[i] = inb(ioaddr + MAC0 + i); |
||
444 | } |
||
445 | for (i = 0; i < 5; i++) |
||
446 | printk("%2.2x:", dev->dev_addr[i]); |
||
447 | printk("%2.2x.\n", dev->dev_addr[i]); |
||
448 | |||
449 | /* We do a request_region() to register /proc/ioports info. */ |
||
450 | request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name); |
||
451 | |||
452 | dev->base_addr = ioaddr; |
||
453 | dev->irq = irq; |
||
454 | |||
455 | /* Some data structures must be quadword aligned. */ |
||
456 | tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA); |
||
457 | memset(tp, 0, sizeof(*tp)); |
||
458 | dev->priv = tp; |
||
459 | |||
460 | tp->next_module = root_rtl8129_dev; |
||
461 | root_rtl8129_dev = dev; |
||
462 | |||
463 | tp->chip_id = chip_idx; |
||
464 | tp->pci_bus = pci_bus; |
||
465 | tp->pci_devfn = pci_devfn; |
||
466 | |||
467 | /* Find the connected MII xcvrs. |
||
468 | Doing this in open() would allow detecting external xcvrs later, but |
||
469 | takes too much time. */ |
||
470 | if (rtl_cap_tbl[chip_idx] & HAS_MII_XCVR) { |
||
471 | int phy, phy_idx; |
||
472 | for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys); |
||
473 | phy++) { |
||
474 | int mii_status = mdio_read(dev, phy, 1); |
||
475 | if (mii_status != 0xffff && mii_status != 0x0000) { |
||
476 | tp->phys[phy_idx++] = phy; |
||
477 | printk(KERN_INFO "%s: MII transceiver found at address %d.\n", |
||
478 | dev->name, phy); |
||
479 | } |
||
480 | } |
||
481 | if (phy_idx == 0) { |
||
482 | printk(KERN_INFO "%s: No MII transceivers found! Assuming SYM " |
||
483 | "transceiver.\n", |
||
484 | dev->name); |
||
485 | tp->phys[0] = -1; |
||
486 | } |
||
487 | } else |
||
488 | tp->phys[0] = 32; |
||
489 | |||
490 | /* Put the chip into low-power mode. */ |
||
491 | outb(0xC0, ioaddr + Cfg9346); |
||
492 | outb(0x03, ioaddr + Config1); |
||
493 | outb('H', ioaddr + HltClk); /* 'R' would leave the clock running. */ |
||
494 | |||
495 | /* The lower four bits are the media type. */ |
||
496 | if (option > 0) { |
||
497 | tp->full_duplex = (option & 0x200) ? 1 : 0; |
||
498 | tp->default_port = option & 15; |
||
499 | if (tp->default_port) |
||
500 | tp->medialock = 1; |
||
501 | } |
||
502 | |||
503 | if (found_cnt < MAX_UNITS && full_duplex[found_cnt] > 0) |
||
504 | tp->full_duplex = full_duplex[found_cnt]; |
||
505 | |||
506 | if (tp->full_duplex) { |
||
507 | printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); |
||
508 | mdio_write(dev, tp->phys[0], 4, 0x141); |
||
509 | tp->duplex_lock = 1; |
||
510 | } |
||
511 | |||
512 | /* The Rtl8129-specific entries in the device structure. */ |
||
513 | dev->open = &rtl8129_open; |
||
514 | dev->hard_start_xmit = &rtl8129_start_xmit; |
||
515 | dev->stop = &rtl8129_close; |
||
516 | dev->get_stats = &rtl8129_get_stats; |
||
517 | dev->set_multicast_list = &set_rx_mode; |
||
518 | dev->do_ioctl = &mii_ioctl; |
||
519 | |||
520 | return dev; |
||
521 | } |
||
522 | |||
523 | /* Serial EEPROM section. */ |
||
524 | |||
525 | /* EEPROM_Ctrl bits. */ |
||
526 | #define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ |
||
527 | #define EE_CS 0x08 /* EEPROM chip select. */ |
||
528 | #define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ |
||
529 | #define EE_WRITE_0 0x00 |
||
530 | #define EE_WRITE_1 0x02 |
||
531 | #define EE_DATA_READ 0x01 /* EEPROM chip data out. */ |
||
532 | #define EE_ENB (0x80 | EE_CS) |
||
533 | |||
534 | /* Delay between EEPROM clock transitions. |
||
535 | No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. |
||
536 | */ |
||
537 | |||
538 | #define eeprom_delay() inl(ee_addr) |
||
539 | |||
540 | /* The EEPROM commands include the alway-set leading bit. */ |
||
541 | #define EE_WRITE_CMD (5 << 6) |
||
542 | #define EE_READ_CMD (6 << 6) |
||
543 | #define EE_ERASE_CMD (7 << 6) |
||
544 | |||
545 | static int read_eeprom(long ioaddr, int location) |
||
546 | { |
||
547 | int i; |
||
548 | unsigned retval = 0; |
||
549 | long ee_addr = ioaddr + Cfg9346; |
||
550 | int read_cmd = location | EE_READ_CMD; |
||
551 | |||
552 | outb(EE_ENB & ~EE_CS, ee_addr); |
||
553 | outb(EE_ENB, ee_addr); |
||
554 | |||
555 | /* Shift the read command bits out. */ |
||
556 | for (i = 10; i >= 0; i--) { |
||
557 | int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; |
||
558 | outb(EE_ENB | dataval, ee_addr); |
||
559 | eeprom_delay(); |
||
560 | outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); |
||
561 | eeprom_delay(); |
||
562 | } |
||
563 | outb(EE_ENB, ee_addr); |
||
564 | eeprom_delay(); |
||
565 | |||
566 | for (i = 16; i > 0; i--) { |
||
567 | outb(EE_ENB | EE_SHIFT_CLK, ee_addr); |
||
568 | eeprom_delay(); |
||
569 | retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0); |
||
570 | outb(EE_ENB, ee_addr); |
||
571 | eeprom_delay(); |
||
572 | } |
||
573 | |||
574 | /* Terminate the EEPROM access. */ |
||
575 | outb(~EE_CS, ee_addr); |
||
576 | return retval; |
||
577 | } |
||
578 | |||
579 | /* MII serial management: mostly bogus for now. */ |
||
580 | /* Read and write the MII management registers using software-generated |
||
581 | serial MDIO protocol. |
||
582 | The maximum data clock rate is 2.5 Mhz. The minimum timing is usually |
||
583 | met by back-to-back PCI I/O cycles, but we insert a delay to avoid |
||
584 | "overclocking" issues. */ |
||
585 | #define MDIO_DIR 0x80 |
||
586 | #define MDIO_DATA_OUT 0x04 |
||
587 | #define MDIO_DATA_IN 0x02 |
||
588 | #define MDIO_CLK 0x01 |
||
589 | #define MDIO_WRITE0 (MDIO_DIR) |
||
590 | #define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) |
||
591 | |||
592 | #define mdio_delay() inb(mdio_addr) |
||
593 | |||
594 | static char mii_2_8139_map[8] = {MII_BMCR, MII_BMSR, 0, 0, NWayAdvert, |
||
595 | NWayLPAR, NWayExpansion, 0 }; |
||
596 | |||
597 | /* Syncronize the MII management interface by shifting 32 one bits out. */ |
||
598 | static void mdio_sync(long mdio_addr) |
||
599 | { |
||
600 | int i; |
||
601 | |||
602 | for (i = 32; i >= 0; i--) { |
||
603 | outb(MDIO_WRITE1, mdio_addr); |
||
604 | mdio_delay(); |
||
605 | outb(MDIO_WRITE1 | MDIO_CLK, mdio_addr); |
||
606 | mdio_delay(); |
||
607 | } |
||
608 | return; |
||
609 | } |
||
610 | static int mdio_read(struct device *dev, int phy_id, int location) |
||
611 | { |
||
612 | long mdio_addr = dev->base_addr + MII_SMI; |
||
613 | int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; |
||
614 | int retval = 0; |
||
615 | int i; |
||
616 | |||
617 | if (phy_id > 31) { /* Really a 8139. Use internal registers. */ |
||
618 | return location < 8 && mii_2_8139_map[location] ? |
||
619 | inw(dev->base_addr + mii_2_8139_map[location]) : 0; |
||
620 | } |
||
621 | mdio_sync(mdio_addr); |
||
622 | /* Shift the read command bits out. */ |
||
623 | for (i = 15; i >= 0; i--) { |
||
624 | int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; |
||
625 | |||
626 | outb(MDIO_DIR | dataval, mdio_addr); |
||
627 | mdio_delay(); |
||
628 | outb(MDIO_DIR | dataval | MDIO_CLK, mdio_addr); |
||
629 | mdio_delay(); |
||
630 | } |
||
631 | |||
632 | /* Read the two transition, 16 data, and wire-idle bits. */ |
||
633 | for (i = 19; i > 0; i--) { |
||
634 | outb(0, mdio_addr); |
||
635 | mdio_delay(); |
||
636 | retval = (retval << 1) | ((inb(mdio_addr) & MDIO_DATA_IN) ? 1 : 0); |
||
637 | outb(MDIO_CLK, mdio_addr); |
||
638 | mdio_delay(); |
||
639 | } |
||
640 | return (retval>>1) & 0xffff; |
||
641 | } |
||
642 | |||
643 | static void mdio_write(struct device *dev, int phy_id, int location, int value) |
||
644 | { |
||
645 | long mdio_addr = dev->base_addr + MII_SMI; |
||
646 | int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value; |
||
647 | int i; |
||
648 | |||
649 | if (phy_id > 31) { /* Really a 8139. Use internal registers. */ |
||
650 | if (location < 8 && mii_2_8139_map[location]) |
||
651 | outw(value, dev->base_addr + mii_2_8139_map[location]); |
||
652 | return; |
||
653 | } |
||
654 | mdio_sync(mdio_addr); |
||
655 | |||
656 | /* Shift the command bits out. */ |
||
657 | for (i = 31; i >= 0; i--) { |
||
658 | int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; |
||
659 | outb(dataval, mdio_addr); |
||
660 | mdio_delay(); |
||
661 | outb(dataval | MDIO_CLK, mdio_addr); |
||
662 | mdio_delay(); |
||
663 | } |
||
664 | /* Clear out extra bits. */ |
||
665 | for (i = 2; i > 0; i--) { |
||
666 | outb(0, mdio_addr); |
||
667 | mdio_delay(); |
||
668 | outb(MDIO_CLK, mdio_addr); |
||
669 | mdio_delay(); |
||
670 | } |
||
671 | return; |
||
672 | } |
||
673 | |||
674 | |||
675 | static int |
||
676 | rtl8129_open(struct device *dev) |
||
677 | { |
||
678 | struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; |
||
679 | long ioaddr = dev->base_addr; |
||
680 | int i; |
||
681 | |||
682 | /* Soft reset the chip. */ |
||
683 | outb(CmdReset, ioaddr + ChipCmd); |
||
684 | |||
685 | if (request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ, dev->name, dev)) { |
||
686 | return -EAGAIN; |
||
687 | } |
||
688 | |||
689 | MOD_INC_USE_COUNT; |
||
690 | |||
691 | tp->tx_bufs = kmalloc(TX_BUF_SIZE * NUM_TX_DESC, GFP_KERNEL); |
||
692 | tp->rx_ring = kmalloc(RX_BUF_LEN + 16, GFP_KERNEL); |
||
693 | if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { |
||
694 | free_irq(dev->irq, dev); |
||
695 | if (tp->tx_bufs) |
||
696 | kfree(tp->tx_bufs); |
||
697 | if (rtl8129_debug > 0) |
||
698 | printk(KERN_ERR "%s: Couldn't allocate a %d byte receive ring.\n", |
||
699 | dev->name, RX_BUF_LEN); |
||
700 | return -ENOMEM; |
||
701 | } |
||
702 | rtl8129_init_ring(dev); |
||
703 | |||
704 | /* Check that the chip has finished the reset. */ |
||
705 | for (i = 1000; i > 0; i--) |
||
706 | if ((inb(ioaddr + ChipCmd) & CmdReset) == 0) |
||
707 | break; |
||
708 | |||
709 | for (i = 0; i < 6; i++) |
||
710 | outb(dev->dev_addr[i], ioaddr + MAC0 + i); |
||
711 | |||
712 | /* Must enable Tx/Rx before setting transfer thresholds! */ |
||
713 | outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); |
||
714 | outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8), |
||
715 | ioaddr + RxConfig); |
||
716 | outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig); |
||
717 | tp->tx_flag = (TX_FIFO_THRESH<<11) & 0x003f0000; |
||
718 | |||
719 | tp->full_duplex = tp->duplex_lock; |
||
720 | if (tp->phys[0] >= 0 || (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR)) { |
||
721 | u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5); |
||
722 | if (mii_reg5 == 0xffff) |
||
723 | ; /* Not there */ |
||
724 | else if ((mii_reg5 & 0x0100) == 0x0100 |
||
725 | || (mii_reg5 & 0x00C0) == 0x0040) |
||
726 | tp->full_duplex = 1; |
||
727 | if (rtl8129_debug > 1) |
||
728 | printk(KERN_INFO"%s: Setting %s%s-duplex based on" |
||
729 | " auto-negotiated partner ability %4.4x.\n", dev->name, |
||
730 | mii_reg5 == 0 ? "" : |
||
731 | (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ", |
||
732 | tp->full_duplex ? "full" : "half", mii_reg5); |
||
733 | } |
||
734 | |||
735 | outb(0xC0, ioaddr + Cfg9346); |
||
736 | outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1); |
||
737 | outb(0x00, ioaddr + Cfg9346); |
||
738 | |||
739 | outl(virt_to_bus(tp->rx_ring), ioaddr + RxBuf); |
||
740 | |||
741 | /* Start the chip's Tx and Rx process. */ |
||
742 | outl(0, ioaddr + RxMissed); |
||
743 | set_rx_mode(dev); |
||
744 | |||
745 | outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); |
||
746 | |||
747 | dev->tbusy = 0; |
||
748 | dev->interrupt = 0; |
||
749 | dev->start = 1; |
||
750 | |||
751 | /* Enable all known interrupts by setting the interrupt mask. */ |
||
752 | outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |
||
753 | | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask); |
||
754 | |||
755 | if (rtl8129_debug > 1) |
||
756 | printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %#lx IRQ %d" |
||
757 | " GP Pins %2.2x %s-duplex.\n", |
||
758 | dev->name, ioaddr, dev->irq, inb(ioaddr + GPPinData), |
||
759 | tp->full_duplex ? "full" : "half"); |
||
760 | |||
761 | /* Set the timer to switch to check for link beat and perhaps switch |
||
762 | to an alternate media type. */ |
||
763 | init_timer(&tp->timer); |
||
764 | tp->timer.expires = RUN_AT((24*HZ)/10); // 2.4 sec. |
||
765 | tp->timer.data = (unsigned long)dev; |
||
766 | tp->timer.function = &rtl8129_timer; |
||
767 | add_timer(&tp->timer); |
||
768 | |||
769 | return 0; |
||
770 | } |
||
771 | |||
772 | static void rtl8129_timer(unsigned long data) |
||
773 | { |
||
774 | struct device *dev = (struct device *)data; |
||
775 | struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; |
||
776 | long ioaddr = dev->base_addr; |
||
777 | int next_tick = 60*HZ; |
||
778 | int mii_reg5 = mdio_read(dev, tp->phys[0], 5); |
||
779 | |||
780 | if (! tp->duplex_lock && mii_reg5 != 0xffff) { |
||
781 | int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040; |
||
782 | if (tp->full_duplex != duplex) { |
||
783 | tp->full_duplex = duplex; |
||
784 | printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link" |
||
785 | " partner ability of %4.4x.\n", dev->name, |
||
786 | tp->full_duplex ? "full" : "half", tp->phys[0], mii_reg5); |
||
787 | outb(0xC0, ioaddr + Cfg9346); |
||
788 | outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1); |
||
789 | outb(0x00, ioaddr + Cfg9346); |
||
790 | } |
||
791 | } |
||
792 | /* Check for bogusness. */ |
||
793 | if (inw(ioaddr + IntrStatus) & (TxOK | RxOK)) { |
||
794 | int status = inw(ioaddr + IntrStatus); |
||
795 | if (status & (TxOK | RxOK)) { /* Double check */ |
||
796 | printk(KERN_ERR "%s: RTL8139 Interrupt line blocked, status %x.\n", |
||
797 | dev->name, status); |
||
798 | rtl8129_interrupt(dev->irq, dev, 0); |
||
799 | } |
||
800 | } |
||
801 | if (dev->tbusy && jiffies - dev->trans_start >= 2*TX_TIMEOUT) |
||
802 | rtl8129_tx_timeout(dev); |
||
803 | |||
804 | #if 0 |
||
805 | if (tp->twistie) { |
||
806 | unsigned int CSCRval = inw(ioaddr + CSCR); /* Read link status. */ |
||
807 | if (tp->twistie == 1) { |
||
808 | if (CSCRval & CSCR_LinkOKBit) { |
||
809 | outw(CSCR_LinkDownOffCmd, ioaddr + CSCR); |
||
810 | tp->twistie = 2; |
||
811 | next_tick = HZ/10; |
||
812 | } else { |
||
813 | outw(CSCR_LinkDownCmd, ioaddr + CSCR); |
||
814 | outl(FIFOTMS_default,ioaddr + FIFOTMS); |
||
815 | outl(PARA78_default ,ioaddr + PARA78); |
||
816 | outl(PARA7c_default ,ioaddr + PARA7c); |
||
817 | tp->twistie = 0; |
||
818 | } |
||
819 | } else if (tp->twistie == 2) { |
||
820 | int linkcase = (CSCRval & CSCR_LinkStatusBits) >> 12; |
||
821 | int row; |
||
822 | if (linkcase >= 0x7000) row = 3; |
||
823 | else if (linkcase >= 0x3000) row = 2; |
||
824 | else if (linkcase >= 0x1000) row = 1; |
||
825 | else row = 0; |
||
826 | tp->twistie == row + 3; |
||
827 | outw(0,ioaddr+FIFOTMS); |
||
828 | outl(param[row][0], ioaddr+PARA7c); |
||
829 | tp->twist_cnt = 1; |
||
830 | } else { |
||
831 | outl(param[tp->twistie-3][tp->twist_cnt], ioaddr+PARA7c); |
||
832 | if (++tp->twist_cnt < 4) { |
||
833 | next_tick = HZ/10; |
||
834 | } else if (tp->twistie-3 == 3) { |
||
835 | if ((CSCRval & CSCR_LinkStatusBits) != 0x7000) { |
||
836 | outl(PARA7c_xxx, ioaddr+PARA7c); |
||
837 | next_tick = HZ/10; /* 100ms. */ |
||
838 | outl(FIFOTMS_default, ioaddr+FIFOTMS); |
||
839 | outl(PARA78_default, ioaddr+PARA78); |
||
840 | outl(PARA7c_default, ioaddr+PARA7c); |
||
841 | tp->twistie == 3 + 3; |
||
842 | outw(0,ioaddr+FIFOTMS); |
||
843 | outl(param[3][0], ioaddr+PARA7c); |
||
844 | tp->twist_cnt = 1; |
||
845 | } |
||
846 | } |
||
847 | } |
||
848 | } |
||
849 | #endif |
||
850 | |||
851 | if (rtl8129_debug > 2) { |
||
852 | if (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR) |
||
853 | printk(KERN_DEBUG"%s: Media selection tick, GP pins %2.2x.\n", |
||
854 | dev->name, inb(ioaddr + GPPinData)); |
||
855 | else |
||
856 | printk(KERN_DEBUG"%s: Media selection tick, Link partner %4.4x.\n", |
||
857 | dev->name, inw(ioaddr + NWayLPAR)); |
||
858 | printk(KERN_DEBUG"%s: Other registers are IntMask %4.4x IntStatus %4.4x" |
||
859 | " RxStatus %4.4x.\n", |
||
860 | dev->name, inw(ioaddr + IntrMask), inw(ioaddr + IntrStatus), |
||
861 | inl(ioaddr + RxEarlyStatus)); |
||
862 | printk(KERN_DEBUG"%s: Chip config %2.2x %2.2x.\n", |
||
863 | dev->name, inb(ioaddr + Config0), inb(ioaddr + Config1)); |
||
864 | } |
||
865 | |||
866 | tp->timer.expires = RUN_AT(next_tick); |
||
867 | add_timer(&tp->timer); |
||
868 | } |
||
869 | |||
870 | static void rtl8129_tx_timeout(struct device *dev) |
||
871 | { |
||
872 | struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; |
||
873 | long ioaddr = dev->base_addr; |
||
874 | int mii_reg, i; |
||
875 | |||
876 | if (rtl8129_debug > 0) |
||
877 | printk(KERN_WARNING "%s: Transmit timeout, status %2.2x %4.4x " |
||
878 | "media %2.2x.\n", |
||
879 | dev->name, inb(ioaddr + ChipCmd), inw(ioaddr + IntrStatus), |
||
880 | inb(ioaddr + GPPinData)); |
||
881 | |||
882 | /* Disable interrupts by clearing the interrupt mask. */ |
||
883 | outw(0x0000, ioaddr + IntrMask); |
||
884 | /* Emit info to figure out what went wrong. */ |
||
885 | printk("%s: Tx queue start entry %d dirty entry %d.\n", |
||
886 | dev->name, tp->cur_tx, tp->dirty_tx); |
||
887 | for (i = 0; i < NUM_TX_DESC; i++) |
||
888 | printk(KERN_DEBUG"%s: Tx descriptor %d is %8.8x.%s\n", |
||
889 | dev->name, i, inl(ioaddr + TxStatus0 + i*4), |
||
890 | i == tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : ""); |
||
891 | printk(KERN_DEBUG"%s: MII #%d registers are:", dev->name, tp->phys[0]); |
||
892 | for (mii_reg = 0; mii_reg < 8; mii_reg++) |
||
893 | printk(" %4.4x", mdio_read(dev, tp->phys[0], mii_reg)); |
||
894 | printk(".\n"); |
||
895 | |||
896 | /* Soft reset the chip. */ |
||
897 | outb(CmdReset, ioaddr + ChipCmd); |
||
898 | /* Check that the chip has finished the reset. */ |
||
899 | for (i = 1000; i > 0; i--) |
||
900 | if ((inb(ioaddr + ChipCmd) & CmdReset) == 0) |
||
901 | break; |
||
902 | for (i = 0; i < 6; i++) |
||
903 | outb(dev->dev_addr[i], ioaddr + MAC0 + i); |
||
904 | |||
905 | outb(0x00, ioaddr + Cfg9346); |
||
906 | tp->cur_rx = 0; |
||
907 | /* Must enable Tx/Rx before setting transfer thresholds! */ |
||
908 | outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); |
||
909 | outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8), |
||
910 | ioaddr + RxConfig); |
||
911 | outl((TX_DMA_BURST<<8), ioaddr + TxConfig); |
||
912 | set_rx_mode(dev); |
||
913 | { /* Save the unsent Tx packets. */ |
||
914 | struct sk_buff *saved_skb[NUM_TX_DESC], *skb; |
||
915 | int j; |
||
916 | for (j = 0; tp->cur_tx - tp->dirty_tx > 0 ; j++, tp->dirty_tx++) |
||
917 | saved_skb[j] = tp->tx_skbuff[tp->dirty_tx % NUM_TX_DESC]; |
||
918 | tp->dirty_tx = tp->cur_tx = 0; |
||
919 | |||
920 | for (i = 0; i < j; i++) { |
||
921 | skb = tp->tx_skbuff[i] = saved_skb[i]; |
||
922 | if ((long)skb->data & 3) { /* Must use alignment buffer. */ |
||
923 | memcpy(tp->tx_buf[i], skb->data, skb->len); |
||
924 | outl(virt_to_bus(tp->tx_buf[i]), ioaddr + TxAddr0 + i*4); |
||
925 | } else |
||
926 | outl(virt_to_bus(skb->data), ioaddr + TxAddr0 + i*4); |
||
927 | /* Note: the chip doesn't have auto-pad! */ |
||
928 | outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN), |
||
929 | ioaddr + TxStatus0 + i*4); |
||
930 | } |
||
931 | tp->cur_tx = i; |
||
932 | while (i < NUM_TX_DESC) |
||
933 | tp->tx_skbuff[i++] = 0; |
||
934 | if (tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */ |
||
935 | dev->tbusy = 0; |
||
936 | tp->tx_full = 0; |
||
937 | } else { |
||
938 | tp->tx_full = 1; |
||
939 | } |
||
940 | } |
||
941 | |||
942 | dev->trans_start = jiffies; |
||
943 | tp->stats.tx_errors++; |
||
944 | /* Enable all known interrupts by setting the interrupt mask. */ |
||
945 | outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |
||
946 | | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask); |
||
947 | return; |
||
948 | } |
||
949 | |||
950 | |||
951 | /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ |
||
952 | static void |
||
953 | rtl8129_init_ring(struct device *dev) |
||
954 | { |
||
955 | struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; |
||
956 | int i; |
||
957 | |||
958 | tp->tx_full = 0; |
||
959 | tp->cur_rx = 0; |
||
960 | tp->dirty_tx = tp->cur_tx = 0; |
||
961 | |||
962 | for (i = 0; i < NUM_TX_DESC; i++) { |
||
963 | tp->tx_skbuff[i] = 0; |
||
964 | tp->tx_buf[i] = &tp->tx_bufs[i*TX_BUF_SIZE]; |
||
965 | } |
||
966 | } |
||
967 | |||
968 | static int |
||
969 | rtl8129_start_xmit(struct sk_buff *skb, struct device *dev) |
||
970 | { |
||
971 | struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; |
||
972 | long ioaddr = dev->base_addr; |
||
973 | int entry; |
||
974 | |||
975 | /* Block a timer-based transmit from overlapping. This could better be |
||
976 | done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ |
||
977 | if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { |
||
978 | if (jiffies - dev->trans_start >= TX_TIMEOUT) |
||
979 | rtl8129_tx_timeout(dev); |
||
980 | return 1; |
||
981 | } |
||
982 | |||
983 | /* Calculate the next Tx descriptor entry. */ |
||
984 | entry = tp->cur_tx % NUM_TX_DESC; |
||
985 | |||
986 | tp->tx_skbuff[entry] = skb; |
||
987 | if ((long)skb->data & 3) { /* Must use alignment buffer. */ |
||
988 | memcpy(tp->tx_buf[entry], skb->data, skb->len); |
||
989 | outl(virt_to_bus(tp->tx_buf[entry]), ioaddr + TxAddr0 + entry*4); |
||
990 | } else |
||
991 | outl(virt_to_bus(skb->data), ioaddr + TxAddr0 + entry*4); |
||
992 | /* Note: the chip doesn't have auto-pad! */ |
||
993 | outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN), |
||
994 | ioaddr + TxStatus0 + entry*4); |
||
995 | |||
996 | if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) { /* Typical path */ |
||
997 | clear_bit(0, (void*)&dev->tbusy); |
||
998 | } else { |
||
999 | tp->tx_full = 1; |
||
1000 | } |
||
1001 | |||
1002 | dev->trans_start = jiffies; |
||
1003 | if (rtl8129_debug > 4) |
||
1004 | printk(KERN_DEBUG"%s: Queued Tx packet at %p size %d to slot %d.\n", |
||
1005 | dev->name, skb->data, (int)skb->len, entry); |
||
1006 | |||
1007 | return 0; |
||
1008 | } |
||
1009 | |||
1010 | /* The interrupt handler does all of the Rx thread work and cleans up |
||
1011 | after the Tx thread. */ |
||
1012 | static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs) |
||
1013 | { |
||
1014 | struct device *dev = (struct device *)dev_instance; |
||
1015 | struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; |
||
1016 | int boguscnt = max_interrupt_work; |
||
1017 | int status, link_changed = 0; |
||
1018 | long ioaddr = dev->base_addr; |
||
1019 | |||
1020 | #if defined(__i386__) |
||
1021 | /* A lock to prevent simultaneous entry bug on Intel SMP machines. */ |
||
1022 | if (test_and_set_bit(0, (void*)&dev->interrupt)) { |
||
1023 | printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n", |
||
1024 | dev->name); |
||
1025 | dev->interrupt = 0; /* Avoid halting machine. */ |
||
1026 | return; |
||
1027 | } |
||
1028 | #else |
||
1029 | if (dev->interrupt) { |
||
1030 | printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); |
||
1031 | return; |
||
1032 | } |
||
1033 | dev->interrupt = 1; |
||
1034 | #endif |
||
1035 | |||
1036 | do { |
||
1037 | status = inw(ioaddr + IntrStatus); |
||
1038 | /* Acknowledge all of the current interrupt sources ASAP, but |
||
1039 | an first get an additional status bit from CSCR. */ |
||
1040 | if ((status & RxUnderrun) && inw(ioaddr+CSCR) & CSCR_LinkChangeBit) |
||
1041 | link_changed = 1; |
||
1042 | outw(status, ioaddr + IntrStatus); |
||
1043 | |||
1044 | if (rtl8129_debug > 4) |
||
1045 | printk(KERN_DEBUG"%s: interrupt status=%#4.4x new intstat=%#4.4x.\n", |
||
1046 | dev->name, status, inw(ioaddr + IntrStatus)); |
||
1047 | |||
1048 | if ((status & (PCIErr|PCSTimeout|RxUnderrun|RxOverflow|RxFIFOOver |
||
1049 | |TxErr|TxOK|RxErr|RxOK)) == 0) |
||
1050 | break; |
||
1051 | |||
1052 | if (status & (RxOK|RxUnderrun|RxOverflow|RxFIFOOver))/* Rx interrupt */ |
||
1053 | rtl8129_rx(dev); |
||
1054 | |||
1055 | if (status & (TxOK | TxErr)) { |
||
1056 | unsigned int dirty_tx; |
||
1057 | |||
1058 | for (dirty_tx = tp->dirty_tx; dirty_tx < tp->cur_tx; dirty_tx++) { |
||
1059 | int entry = dirty_tx % NUM_TX_DESC; |
||
1060 | int txstatus = inl(ioaddr + TxStatus0 + entry*4); |
||
1061 | |||
1062 | if ( ! (txstatus & (TxStatOK | TxUnderrun | TxAborted))) |
||
1063 | break; /* It still hasn't been Txed */ |
||
1064 | |||
1065 | /* Note: TxCarrierLost is always asserted at 100mbps. */ |
||
1066 | if (txstatus & (TxOutOfWindow | TxAborted)) { |
||
1067 | /* There was an major error, log it. */ |
||
1068 | if (rtl8129_debug > 1) |
||
1069 | printk(KERN_NOTICE"%s: Transmit error, Tx status %8.8x.\n", |
||
1070 | dev->name, txstatus); |
||
1071 | tp->stats.tx_errors++; |
||
1072 | if (txstatus&TxAborted) { |
||
1073 | tp->stats.tx_aborted_errors++; |
||
1074 | outl((TX_DMA_BURST<<8)|0x03000001, ioaddr + TxConfig); |
||
1075 | } |
||
1076 | if (txstatus&TxCarrierLost) tp->stats.tx_carrier_errors++; |
||
1077 | if (txstatus&TxOutOfWindow) tp->stats.tx_window_errors++; |
||
1078 | #ifdef ETHER_STATS |
||
1079 | if ((txstatus & 0x0f000000) == 0x0f000000) |
||
1080 | tp->stats.collisions16++; |
||
1081 | #endif |
||
1082 | } else { |
||
1083 | if (txstatus & TxUnderrun) { |
||
1084 | /* Add 64 to the Tx FIFO threshold. */ |
||
1085 | if (tp->tx_flag < 0x00300000) |
||
1086 | tp->tx_flag += 0x00020000; |
||
1087 | tp->stats.tx_fifo_errors++; |
||
1088 | } |
||
1089 | tp->stats.collisions += (txstatus >> 24) & 15; |
||
1090 | #if LINUX_VERSION_CODE > 0x20119 |
||
1091 | tp->stats.tx_bytes += txstatus & 0x7ff; |
||
1092 | #endif |
||
1093 | tp->stats.tx_packets++; |
||
1094 | } |
||
1095 | |||
1096 | /* Free the original skb. */ |
||
1097 | dev_free_skb(tp->tx_skbuff[entry]); |
||
1098 | tp->tx_skbuff[entry] = 0; |
||
1099 | if (tp->tx_full) { |
||
1100 | /* The ring is no longer full, clear tbusy. */ |
||
1101 | tp->tx_full = 0; |
||
1102 | clear_bit(0, (void*)&dev->tbusy); |
||
1103 | mark_bh(NET_BH); |
||
1104 | } |
||
1105 | } |
||
1106 | |||
1107 | #ifndef final_version |
||
1108 | if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { |
||
1109 | printk(KERN_ERR"%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", |
||
1110 | dev->name, dirty_tx, tp->cur_tx, tp->tx_full); |
||
1111 | dirty_tx += NUM_TX_DESC; |
||
1112 | } |
||
1113 | #endif |
||
1114 | tp->dirty_tx = dirty_tx; |
||
1115 | } |
||
1116 | |||
1117 | /* Check uncommon events with one test. */ |
||
1118 | if (status & (PCIErr|PCSTimeout |RxUnderrun|RxOverflow|RxFIFOOver |
||
1119 | |TxErr|RxErr)) { |
||
1120 | if (rtl8129_debug > 2) |
||
1121 | printk(KERN_NOTICE"%s: Abnormal interrupt, status %8.8x.\n", |
||
1122 | dev->name, status); |
||
1123 | |||
1124 | if (status == 0xffffffff) |
||
1125 | break; |
||
1126 | /* Update the error count. */ |
||
1127 | tp->stats.rx_missed_errors += inl(ioaddr + RxMissed); |
||
1128 | outl(0, ioaddr + RxMissed); |
||
1129 | |||
1130 | if ((status & RxUnderrun) && link_changed && |
||
1131 | (rtl_cap_tbl[tp->chip_id] & HAS_LNK_CHNG)) { |
||
1132 | /* Really link-change on new chips. */ |
||
1133 | int lpar = inw(ioaddr + NWayLPAR); |
||
1134 | int duplex = (lpar&0x0100)||(lpar & 0x01C0) == 0x0040; |
||
1135 | if (tp->full_duplex != duplex) { |
||
1136 | tp->full_duplex = duplex; |
||
1137 | outb(0xC0, ioaddr + Cfg9346); |
||
1138 | outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1); |
||
1139 | outb(0x00, ioaddr + Cfg9346); |
||
1140 | } |
||
1141 | status &= ~RxUnderrun; |
||
1142 | } |
||
1143 | if (status & (RxUnderrun | RxOverflow | RxErr | RxFIFOOver)) |
||
1144 | tp->stats.rx_errors++; |
||
1145 | |||
1146 | if (status & (PCSTimeout)) tp->stats.rx_length_errors++; |
||
1147 | if (status & (RxUnderrun|RxFIFOOver)) tp->stats.rx_fifo_errors++; |
||
1148 | |||
1149 | if (status & RxFIFOOver) { |
||
1150 | tp->cur_rx = 0; |
||
1151 | outb(CmdTxEnb, ioaddr + ChipCmd); |
||
1152 | outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); |
||
1153 | outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | |
||
1154 | (RX_DMA_BURST<<8), ioaddr + RxConfig); |
||
1155 | } |
||
1156 | |||
1157 | if (status & RxOverflow) { |
||
1158 | tp->stats.rx_over_errors++; |
||
1159 | tp->cur_rx = inw(ioaddr + RxBufAddr) % RX_BUF_LEN; |
||
1160 | outw(tp->cur_rx - 16, ioaddr + RxBufPtr); |
||
1161 | } |
||
1162 | if (status & PCIErr) { |
||
1163 | u32 pci_cmd_status; |
||
1164 | pci20to26_read_config_dword(tp->pci_bus, tp->pci_devfn, |
||
1165 | PCI_COMMAND, &pci_cmd_status); |
||
1166 | |||
1167 | printk(KERN_ERR "%s: PCI Bus error %4.4x.\n", |
||
1168 | dev->name, pci_cmd_status); |
||
1169 | } |
||
1170 | } |
||
1171 | if (--boguscnt < 0) { |
||
1172 | printk(KERN_WARNING"%s: Too much work at interrupt, " |
||
1173 | "IntrStatus=0x%4.4x.\n", |
||
1174 | dev->name, status); |
||
1175 | /* Clear all interrupt sources. */ |
||
1176 | outw(0xffff, ioaddr + IntrStatus); |
||
1177 | break; |
||
1178 | } |
||
1179 | } while (1); |
||
1180 | |||
1181 | if (rtl8129_debug > 3) |
||
1182 | printk(KERN_DEBUG"%s: exiting interrupt, intr_status=%#4.4x.\n", |
||
1183 | dev->name, inl(ioaddr + IntrStatus)); |
||
1184 | |||
1185 | #if defined(__i386__) |
||
1186 | clear_bit(0, (void*)&dev->interrupt); |
||
1187 | #else |
||
1188 | dev->interrupt = 0; |
||
1189 | #endif |
||
1190 | return; |
||
1191 | } |
||
1192 | |||
1193 | /* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the |
||
1194 | field alignments and semantics. */ |
||
1195 | static int rtl8129_rx(struct device *dev) |
||
1196 | { |
||
1197 | struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; |
||
1198 | long ioaddr = dev->base_addr; |
||
1199 | unsigned char *rx_ring = tp->rx_ring; |
||
1200 | u16 cur_rx = tp->cur_rx; |
||
1201 | |||
1202 | if (rtl8129_debug > 4) |
||
1203 | printk(KERN_DEBUG"%s: In rtl8129_rx(), current %4.4x BufAddr %4.4x," |
||
1204 | " free to %4.4x, Cmd %2.2x.\n", |
||
1205 | dev->name, cur_rx, inw(ioaddr + RxBufAddr), |
||
1206 | inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd)); |
||
1207 | |||
1208 | while ((inb(ioaddr + ChipCmd) & 1) == 0) { |
||
1209 | int ring_offset = cur_rx % RX_BUF_LEN; |
||
1210 | u32 rx_status = le32_to_cpu(*(u32*)(rx_ring + ring_offset)); |
||
1211 | int rx_size = rx_status >> 16; |
||
1212 | |||
1213 | if (rtl8129_debug > 4) { |
||
1214 | int i; |
||
1215 | printk(KERN_DEBUG"%s: rtl8129_rx() status %4.4x, size %4.4x, cur %4.4x.\n", |
||
1216 | dev->name, rx_status, rx_size, cur_rx); |
||
1217 | printk(KERN_DEBUG"%s: Frame contents ", dev->name); |
||
1218 | for (i = 0; i < 70; i++) |
||
1219 | printk(" %2.2x", le32_to_cpu(rx_ring[ring_offset + i])); |
||
1220 | printk(".\n"); |
||
1221 | } |
||
1222 | if (rx_status & RxTooLong) { |
||
1223 | if (rtl8129_debug > 0) |
||
1224 | printk(KERN_NOTICE"%s: Oversized Ethernet frame, status %4.4x!\n", |
||
1225 | dev->name, rx_status); |
||
1226 | tp->stats.rx_length_errors++; |
||
1227 | } else if (rx_status & |
||
1228 | (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)) { |
||
1229 | if (rtl8129_debug > 1) |
||
1230 | printk(KERN_DEBUG"%s: Ethernet frame had errors," |
||
1231 | " status %4.4x.\n", dev->name, rx_status); |
||
1232 | tp->stats.rx_errors++; |
||
1233 | if (rx_status & (RxBadSymbol|RxBadAlign)) |
||
1234 | tp->stats.rx_frame_errors++; |
||
1235 | if (rx_status & (RxRunt|RxTooLong)) tp->stats.rx_length_errors++; |
||
1236 | if (rx_status & RxCRCErr) tp->stats.rx_crc_errors++; |
||
1237 | /* Reset the receiver, based on RealTek recommendation. (Bug?) */ |
||
1238 | tp->cur_rx = 0; |
||
1239 | outb(CmdTxEnb, ioaddr + ChipCmd); |
||
1240 | outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); |
||
1241 | outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | |
||
1242 | (RX_DMA_BURST<<8), ioaddr + RxConfig); |
||
1243 | } else { |
||
1244 | /* Malloc up new buffer, compatible with net-2e. */ |
||
1245 | /* Omit the four octet CRC from the length. */ |
||
1246 | struct sk_buff *skb; |
||
1247 | |||
1248 | skb = dev_alloc_skb(rx_size + 2); |
||
1249 | if (skb == NULL) { |
||
1250 | printk(KERN_WARNING"%s: Memory squeeze, deferring packet.\n", |
||
1251 | dev->name); |
||
1252 | /* We should check that some rx space is free. |
||
1253 | If not, free one and mark stats->rx_dropped++. */ |
||
1254 | tp->stats.rx_dropped++; |
||
1255 | break; |
||
1256 | } |
||
1257 | skb->dev = dev; |
||
1258 | skb_reserve(skb, 2); /* 16 byte align the IP fields. */ |
||
1259 | if (ring_offset+rx_size+4 > RX_BUF_LEN) { |
||
1260 | int semi_count = RX_BUF_LEN - ring_offset - 4; |
||
1261 | memcpy(skb_put(skb, semi_count), &rx_ring[ring_offset + 4], |
||
1262 | semi_count); |
||
1263 | memcpy(skb_put(skb, rx_size-semi_count), rx_ring, |
||
1264 | rx_size-semi_count); |
||
1265 | if (rtl8129_debug > 4) { |
||
1266 | int i; |
||
1267 | printk(KERN_DEBUG"%s: Frame wrap @%d", |
||
1268 | dev->name, semi_count); |
||
1269 | for (i = 0; i < 16; i++) |
||
1270 | printk(" %2.2x", le32_to_cpu(rx_ring[i])); |
||
1271 | printk(".\n"); |
||
1272 | memset(rx_ring, 0xcc, 16); |
||
1273 | } |
||
1274 | } else { |
||
1275 | #if 0 /* USE_IP_COPYSUM */ |
||
1276 | eth_copy_and_sum(skb, &rx_ring[ring_offset + 4], |
||
1277 | rx_size, 0); |
||
1278 | skb_put(skb, rx_size); |
||
1279 | #else |
||
1280 | memcpy(skb_put(skb, rx_size), &rx_ring[ring_offset + 4], |
||
1281 | rx_size); |
||
1282 | #endif |
||
1283 | } |
||
1284 | skb->protocol = eth_type_trans(skb, dev); |
||
1285 | netif_rx(skb); |
||
1286 | #if LINUX_VERSION_CODE > 0x20119 |
||
1287 | tp->stats.rx_bytes += rx_size; |
||
1288 | #endif |
||
1289 | tp->stats.rx_packets++; |
||
1290 | } |
||
1291 | |||
1292 | cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; |
||
1293 | outw(cur_rx - 16, ioaddr + RxBufPtr); |
||
1294 | } |
||
1295 | if (rtl8129_debug > 4) |
||
1296 | printk(KERN_DEBUG"%s: Done rtl8129_rx(), current %4.4x BufAddr %4.4x," |
||
1297 | " free to %4.4x, Cmd %2.2x.\n", |
||
1298 | dev->name, cur_rx, inw(ioaddr + RxBufAddr), |
||
1299 | inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd)); |
||
1300 | tp->cur_rx = cur_rx; |
||
1301 | return 0; |
||
1302 | } |
||
1303 | |||
1304 | static int |
||
1305 | rtl8129_close(struct device *dev) |
||
1306 | { |
||
1307 | long ioaddr = dev->base_addr; |
||
1308 | struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; |
||
1309 | int i; |
||
1310 | |||
1311 | dev->start = 0; |
||
1312 | dev->tbusy = 1; |
||
1313 | |||
1314 | if (rtl8129_debug > 1) |
||
1315 | printk(KERN_DEBUG"%s: Shutting down ethercard, status was 0x%4.4x.\n", |
||
1316 | dev->name, inw(ioaddr + IntrStatus)); |
||
1317 | |||
1318 | /* Disable interrupts by clearing the interrupt mask. */ |
||
1319 | outw(0x0000, ioaddr + IntrMask); |
||
1320 | |||
1321 | /* Stop the chip's Tx and Rx DMA processes. */ |
||
1322 | outb(0x00, ioaddr + ChipCmd); |
||
1323 | |||
1324 | /* Update the error counts. */ |
||
1325 | tp->stats.rx_missed_errors += inl(ioaddr + RxMissed); |
||
1326 | outl(0, ioaddr + RxMissed); |
||
1327 | |||
1328 | del_timer(&tp->timer); |
||
1329 | |||
1330 | free_irq(dev->irq, dev); |
||
1331 | |||
1332 | for (i = 0; i < NUM_TX_DESC; i++) { |
||
1333 | if (tp->tx_skbuff[i]) |
||
1334 | dev_free_skb(tp->tx_skbuff[i]); |
||
1335 | tp->tx_skbuff[i] = 0; |
||
1336 | } |
||
1337 | kfree(tp->rx_ring); |
||
1338 | kfree(tp->tx_bufs); |
||
1339 | |||
1340 | /* Green! Put the chip in low-power mode. */ |
||
1341 | outb(0xC0, ioaddr + Cfg9346); |
||
1342 | outb(0x03, ioaddr + Config1); |
||
1343 | outb('H', ioaddr + HltClk); /* 'R' would leave the clock running. */ |
||
1344 | |||
1345 | MOD_DEC_USE_COUNT; |
||
1346 | |||
1347 | return 0; |
||
1348 | } |
||
1349 | |||
1350 | static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd) |
||
1351 | { |
||
1352 | struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; |
||
1353 | u16 *data = (u16 *)&rq->ifr_data; |
||
1354 | |||
1355 | switch(cmd) { |
||
1356 | case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ |
||
1357 | data[0] = tp->phys[0] & 0x3f; |
||
1358 | /* Fall Through */ |
||
1359 | case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ |
||
1360 | data[3] = mdio_read(dev, data[0], data[1] & 0x1f); |
||
1361 | return 0; |
||
1362 | case SIOCDEVPRIVATE+2: /* Write the specified MII register */ |
||
1363 | if (!capable(CAP_NET_ADMIN)) |
||
1364 | return -EPERM; |
||
1365 | mdio_write(dev, data[0], data[1] & 0x1f, data[2]); |
||
1366 | return 0; |
||
1367 | default: |
||
1368 | return -EOPNOTSUPP; |
||
1369 | } |
||
1370 | } |
||
1371 | |||
1372 | static struct enet_statistics * |
||
1373 | rtl8129_get_stats(struct device *dev) |
||
1374 | { |
||
1375 | struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; |
||
1376 | long ioaddr = dev->base_addr; |
||
1377 | |||
1378 | if (dev->start) { |
||
1379 | tp->stats.rx_missed_errors += inl(ioaddr + RxMissed); |
||
1380 | outl(0, ioaddr + RxMissed); |
||
1381 | } |
||
1382 | |||
1383 | return &tp->stats; |
||
1384 | } |
||
1385 | |||
1386 | /* Set or clear the multicast filter for this adaptor. |
||
1387 | This routine is not state sensitive and need not be SMP locked. */ |
||
1388 | |||
1389 | static unsigned const ethernet_polynomial = 0x04c11db7U; |
||
1390 | static inline u32 ether_crc(int length, unsigned char *data) |
||
1391 | { |
||
1392 | int crc = -1; |
||
1393 | |||
1394 | while (--length >= 0) { |
||
1395 | unsigned char current_octet = *data++; |
||
1396 | int bit; |
||
1397 | for (bit = 0; bit < 8; bit++, current_octet >>= 1) |
||
1398 | crc = (crc << 1) ^ |
||
1399 | ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); |
||
1400 | } |
||
1401 | return crc; |
||
1402 | } |
||
1403 | |||
1404 | /* Bits in RxConfig. */ |
||
1405 | enum rx_mode_bits { |
||
1406 | AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08, |
||
1407 | AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01, |
||
1408 | }; |
||
1409 | |||
1410 | static void set_rx_mode(struct device *dev) |
||
1411 | { |
||
1412 | long ioaddr = dev->base_addr; |
||
1413 | u32 mc_filter[2]; /* Multicast hash filter */ |
||
1414 | int i, rx_mode; |
||
1415 | |||
1416 | if (rtl8129_debug > 3) |
||
1417 | printk(KERN_DEBUG"%s: set_rx_mode(%4.4x) done -- Rx config %8.8x.\n", |
||
1418 | dev->name, dev->flags, inl(ioaddr + RxConfig)); |
||
1419 | |||
1420 | /* Note: do not reorder, GCC is clever about common statements. */ |
||
1421 | if (dev->flags & IFF_PROMISC) { |
||
1422 | /* Unconditionally log net taps. */ |
||
1423 | printk(KERN_NOTICE"%s: Promiscuous mode enabled.\n", dev->name); |
||
1424 | rx_mode = AcceptBroadcast|AcceptMulticast|AcceptMyPhys|AcceptAllPhys; |
||
1425 | mc_filter[1] = mc_filter[0] = 0xffffffff; |
||
1426 | } else if ((dev->mc_count > multicast_filter_limit) |
||
1427 | || (dev->flags & IFF_ALLMULTI)) { |
||
1428 | /* Too many to filter perfectly -- accept all multicasts. */ |
||
1429 | rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; |
||
1430 | mc_filter[1] = mc_filter[0] = 0xffffffff; |
||
1431 | } else { |
||
1432 | struct dev_mc_list *mclist; |
||
1433 | rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; |
||
1434 | mc_filter[1] = mc_filter[0] = 0; |
||
1435 | for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; |
||
1436 | i++, mclist = mclist->next) |
||
1437 | set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26, mc_filter); |
||
1438 | } |
||
1439 | /* We can safely update without stopping the chip. */ |
||
1440 | outb(rx_mode, ioaddr + RxConfig); |
||
1441 | outl(mc_filter[0], ioaddr + MAR0 + 0); |
||
1442 | outl(mc_filter[1], ioaddr + MAR0 + 4); |
||
1443 | return; |
||
1444 | } |
||
1445 | |||
1446 | #ifdef MODULE |
||
1447 | int init_module(void) |
||
1448 | { |
||
1449 | return rtl8139_probe(0); |
||
1450 | } |
||
1451 | |||
1452 | void |
||
1453 | cleanup_module(void) |
||
1454 | { |
||
1455 | struct device *next_dev; |
||
1456 | |||
1457 | /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ |
||
1458 | while (root_rtl8129_dev) { |
||
1459 | struct rtl8129_private *tp = |
||
1460 | (struct rtl8129_private *)root_rtl8129_dev->priv; |
||
1461 | next_dev = tp->next_module; |
||
1462 | unregister_netdev(root_rtl8129_dev); |
||
1463 | release_region(root_rtl8129_dev->base_addr, |
||
1464 | pci_tbl[tp->chip_id].io_size); |
||
1465 | kfree(tp); |
||
1466 | kfree(root_rtl8129_dev); |
||
1467 | root_rtl8129_dev = next_dev; |
||
1468 | } |
||
1469 | } |
||
1470 | |||
1471 | #endif /* MODULE */ |
||
1472 | |||
1473 | /* |
||
1474 | * Local variables: |
||
1475 | * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" |
||
1476 | * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" |
||
1477 | * c-indent-level: 4 |
||
1478 | * c-basic-offset: 4 |
||
1479 | * tab-width: 4 |
||
1480 | * End: |
||
1481 | */ |