get rid of $Id$ - it has never helped us and it has broken too many patches ;)
[oweals/openwrt.git] / package / broadcom-57xx / src / b57um.c
1 /******************************************************************************/
2 /*                                                                            */
3 /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2005 Broadcom  */
4 /* Corporation.                                                               */
5 /* All rights reserved.                                                       */
6 /*                                                                            */
7 /* This program is free software; you can redistribute it and/or modify       */
8 /* it under the terms of the GNU General Public License as published by       */
9 /* the Free Software Foundation, located in the file LICENSE.                 */
10 /*                                                                            */
11 /******************************************************************************/
12
13
14 char bcm5700_driver[] = "bcm57xx";
15 char bcm5700_version[] = "8.3.14";
16 char bcm5700_date[] = "(11/2/05)";
17
18 #define B57UM
19 #include "mm.h"
20 #include "linux/mii.h" //@.@jack add it 2006/06/28.
21 #include "typedefs.h"
22 #include "osl.h"
23 #include "bcmdefs.h"
24 #include "bcmdevs.h"
25 #include "sbconfig.h"
26 #include "sbutils.h"
27 #include "hndgige.h"
28 #include "bcmrobo.h"
29 #include "robo_register.c"
30
31 #include "bcmendian.h"
32 #include "bcmnvram.h"
33 #include "proto/ethernet.h"
34 #include "proto/vlan.h"
35 #include "proto/bcmtcp.h"
36 #include "proto/bcmip.h"
37 #define PKTDATA(osh, skb)               (((struct sk_buff*)(skb))->data)
38
39 /* this is needed to get good and stable performances */
40 #define EXTRA_HDR BCMEXTRAHDROOM
41
42 #define SIOCGREG_STATUS  0x8996          /* Read Switch register (for debug)*/
43 #define SIOCSREG_STATUS  0x8997          /* Write Switch register(for debug)*/
44
45 /* This structure is used in SIOCXREG_STATUS ioctl calls*/
46 struct reg_ioctl_data {
47         u16             page_num;
48         u16             addr_num;
49         u16             len;
50         u16             val_in[4];
51         u16             val_out[4];
52 };
53
54 /* A few user-configurable values. */
55
56 #define MAX_UNITS 16
57 /* Used to pass the full-duplex flag, etc. */
58 static int line_speed[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
59 static int auto_speed[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
60 static int full_duplex[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
61 static int rx_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
62 static int tx_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
63 static int auto_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
64 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
65 static int mtu[MAX_UNITS] = {1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500};  /* Jumbo MTU for interfaces. */
66 #endif
67 static int tx_checksum[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
68 static int rx_checksum[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
69 static int scatter_gather[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
70 static int activate_gpio = -1;
71
72 #define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT
73 static unsigned int tx_pkt_desc_cnt[MAX_UNITS] =
74         {TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
75         TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
76         TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
77         TX_DESC_CNT};
78
79 #define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT
80 static unsigned int rx_std_desc_cnt[MAX_UNITS] =
81         {RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
82         RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
83         RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
84         RX_DESC_CNT };
85
86 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
87 #define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT
88 static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] =
89         {JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,
90         JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,
91         JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,
92         JBO_DESC_CNT };
93 #endif
94
95 #ifdef BCM_INT_COAL
96 #ifdef BCM_NAPI_RXPOLL
97 static unsigned int adaptive_coalesce[MAX_UNITS] =
98         {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
99 #else
100 static unsigned int adaptive_coalesce[MAX_UNITS] =
101         {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
102 #endif
103
104 #define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS
105 static unsigned int rx_coalesce_ticks[MAX_UNITS] =
106         {RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,
107         RX_COAL_TK, RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,
108         RX_COAL_TK,RX_COAL_TK, RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,
109         RX_COAL_TK};
110
111 #define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES
112 static unsigned int rx_max_coalesce_frames[MAX_UNITS] =
113         {RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,
114         RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,
115         RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,
116         RX_COAL_FM};
117
118 #define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS
119 static unsigned int tx_coalesce_ticks[MAX_UNITS] =
120         {TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,
121         TX_COAL_TK, TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,
122         TX_COAL_TK,TX_COAL_TK, TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,
123         TX_COAL_TK};
124
125 #define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES
126 static unsigned int tx_max_coalesce_frames[MAX_UNITS] =
127         {TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,
128         TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,
129         TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,
130         TX_COAL_FM};
131
132 #define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS
133 static unsigned int stats_coalesce_ticks[MAX_UNITS] =
134         {ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,
135         ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,
136         ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,
137         ST_COAL_TK,};
138
139 #endif
140 #ifdef BCM_WOL
141 static int enable_wol[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
142 #endif
143 #ifdef BCM_TSO
144 static int enable_tso[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
145 #endif
146 #ifdef BCM_NIC_SEND_BD
147 static int nic_tx_bd[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
148 #endif
149 #ifdef BCM_ASF
150 static int vlan_tag_mode[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
151 #endif
152 static int delay_link[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
153 static int disable_d3hot[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
154
155 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
156 static int disable_msi[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
157 static int bcm_msi_chipset_bug = 0;
158 #endif
159
160 #define BCM_TIMER_GRANULARITY  (1000000 / HZ)
161
162 /* Hack to hook the data path to the BCM WL dirver */
163 #ifdef BCM_WL_EMULATOR
164 #include "bcmnvram.h"
165 #include "wl_bcm57emu.h" 
166 #ifdef SKB_MANAGER
167 int skb_old_alloc = 0;
168 #endif
169 #endif /* BCM_WL_EMULATOR */
170
171 /* Operational parameters that usually are not changed. */
172 /* Time in jiffies before concluding the transmitter is hung. */
173 #define TX_TIMEOUT  (2*HZ)
174
175 #if (LINUX_VERSION_CODE < 0x02030d)
176 #define pci_resource_start(dev, bar)    (dev->base_address[bar] & PCI_BASE_ADDRESS_MEM_MASK)
177 #elif (LINUX_VERSION_CODE < 0x02032b)
178 #define pci_resource_start(dev, bar)    (dev->resource[bar] & PCI_BASE_ADDRESS_MEM_MASK)
179 #endif
180
181 #if (LINUX_VERSION_CODE < 0x02032b)
182 #define dev_kfree_skb_irq(skb)  dev_kfree_skb(skb)
183 #define netif_wake_queue(dev)   clear_bit(0, &dev->tbusy); mark_bh(NET_BH)
184 #define netif_stop_queue(dev)   set_bit(0, &dev->tbusy)
185
186 static inline void netif_start_queue(struct net_device *dev)
187 {
188         dev->tbusy = 0;
189         dev->interrupt = 0;
190         dev->start = 1;
191 }
192
193 #define netif_queue_stopped(dev)        dev->tbusy
194 #define netif_running(dev)              dev->start
195
196 static inline void tasklet_schedule(struct tasklet_struct *tasklet)
197 {
198         queue_task(tasklet, &tq_immediate);
199         mark_bh(IMMEDIATE_BH);
200 }
201
202 static inline void tasklet_init(struct tasklet_struct *tasklet,
203                                 void (*func)(unsigned long),
204                                 unsigned long data)
205 {
206                 tasklet->next = NULL;
207                 tasklet->sync = 0;
208                 tasklet->routine = (void (*)(void *))func;
209                 tasklet->data = (void *)data;
210 }
211
212 #define tasklet_kill(tasklet)
213
214 #endif
215
216 #if (LINUX_VERSION_CODE < 0x020300)
217 struct pci_device_id {
218         unsigned int vendor, device;            /* Vendor and device ID or PCI_ANY_ID */
219         unsigned int subvendor, subdevice;      /* Subsystem ID's or PCI_ANY_ID */
220         unsigned int class, class_mask;         /* (class,subclass,prog-if) triplet */
221         unsigned long driver_data;              /* Data private to the driver */
222 };
223
224 #define PCI_ANY_ID              0
225
226 #define pci_set_drvdata(pdev, dev)
227 #define pci_get_drvdata(pdev) 0
228
229 #define pci_enable_device(pdev) 0
230
231 #define __devinit               __init
232 #define __devinitdata           __initdata
233 #define __devexit
234
235 #define SET_MODULE_OWNER(dev)
236 #define MODULE_DEVICE_TABLE(pci, pci_tbl)
237
238 #endif
239
240 #if (LINUX_VERSION_CODE < 0x020411)
241 #ifndef __devexit_p
242 #define __devexit_p(x)  x
243 #endif
244 #endif
245
246 #ifndef MODULE_LICENSE
247 #define MODULE_LICENSE(license)
248 #endif
249
250 #ifndef IRQ_RETVAL
251 typedef void irqreturn_t;
252 #define IRQ_RETVAL(x)
253 #endif
254
255 #if (LINUX_VERSION_CODE < 0x02032a)
256 static inline void *pci_alloc_consistent(struct pci_dev *pdev, size_t size,
257                                          dma_addr_t *dma_handle)
258 {
259         void *virt_ptr;
260
261         /* Maximum in slab.c */
262         if (size > 131072)
263                 return 0;
264
265         virt_ptr = kmalloc(size, GFP_KERNEL);
266         *dma_handle = virt_to_bus(virt_ptr);
267         return virt_ptr;
268 }
269 #define pci_free_consistent(dev, size, ptr, dma_ptr)    kfree(ptr)
270
271 #endif /*#if (LINUX_VERSION_CODE < 0x02032a) */
272
273
274 #if (LINUX_VERSION_CODE < 0x02040d)
275
276 #if (LINUX_VERSION_CODE >= 0x020409) && defined(RED_HAT_LINUX_KERNEL)
277
278 #define BCM_32BIT_DMA_MASK ((u64) 0x00000000ffffffffULL)
279 #define BCM_64BIT_DMA_MASK ((u64) 0xffffffffffffffffULL)
280
281 #else
282 /* pci_set_dma_mask is using dma_addr_t */
283
284 #define BCM_32BIT_DMA_MASK ((dma_addr_t) 0xffffffff)
285 #define BCM_64BIT_DMA_MASK ((dma_addr_t) 0xffffffff)
286
287 #endif
288
289 #else /* (LINUX_VERSION_CODE < 0x02040d) */
290
291 #define BCM_32BIT_DMA_MASK ((u64) 0x00000000ffffffffULL)
292 #define BCM_64BIT_DMA_MASK ((u64) 0xffffffffffffffffULL)
293 #endif
294
295 #if (LINUX_VERSION_CODE < 0x020329)
296 #define pci_set_dma_mask(pdev, mask) (0)
297 #else
298 #if (LINUX_VERSION_CODE < 0x020403)
299 int
300 pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask)
301 {
302     if(! pci_dma_supported(dev, mask))
303         return -EIO;
304
305     dev->dma_mask = mask;
306
307     return 0;
308 }
309 #endif
310 #endif
311
312 #if (LINUX_VERSION_CODE < 0x020547)
313 #define pci_set_consistent_dma_mask(pdev, mask) (0)
314 #endif
315
316 #if (LINUX_VERSION_CODE < 0x020402)
317 #define pci_request_regions(pdev, name) (0)
318 #define pci_release_regions(pdev)
319 #endif
320
321 #if !defined(spin_is_locked)
322 #define spin_is_locked(lock)    (test_bit(0,(lock)))
323 #endif
324
325 #define BCM5700_LOCK(pUmDevice, flags)                                  \
326         if ((pUmDevice)->do_global_lock) {                              \
327                 spin_lock_irqsave(&(pUmDevice)->global_lock, flags);    \
328         }
329
330 #define BCM5700_UNLOCK(pUmDevice, flags)                                \
331         if ((pUmDevice)->do_global_lock) {                              \
332                 spin_unlock_irqrestore(&(pUmDevice)->global_lock, flags);\
333         }
334
335 inline void
336 bcm5700_intr_lock(PUM_DEVICE_BLOCK pUmDevice)
337 {
338         if (pUmDevice->do_global_lock) {
339                 spin_lock(&pUmDevice->global_lock);
340         }
341 }
342
343 inline void
344 bcm5700_intr_unlock(PUM_DEVICE_BLOCK pUmDevice)
345 {
346         if (pUmDevice->do_global_lock) {
347                 spin_unlock(&pUmDevice->global_lock);
348         }
349 }
350
351 void
352 bcm5700_intr_off(PUM_DEVICE_BLOCK pUmDevice)
353 {
354         atomic_inc(&pUmDevice->intr_sem);
355         LM_DisableInterrupt(&pUmDevice->lm_dev);
356 #if (LINUX_VERSION_CODE >= 0x2051c)
357         synchronize_irq(pUmDevice->dev->irq);
358 #else
359         synchronize_irq();
360 #endif
361         LM_DisableInterrupt(&pUmDevice->lm_dev);
362 }
363
364 void
365 bcm5700_intr_on(PUM_DEVICE_BLOCK pUmDevice)
366 {
367         if (atomic_dec_and_test(&pUmDevice->intr_sem)) {
368                 LM_EnableInterrupt(&pUmDevice->lm_dev);
369         }
370 }
371
372
373 int MM_Packet_Desc_Size = sizeof(UM_PACKET);
374
375 #if defined(MODULE)
376 MODULE_AUTHOR("Michael Chan <mchan at broadcom dot com> and Gary Zambrano <zambrano at broadcom dot com>");
377 MODULE_DESCRIPTION("BCM5700 Driver");
378 MODULE_LICENSE("GPL");
379
380 #if (LINUX_VERSION_CODE < 0x020605)
381
382 MODULE_PARM(debug, "i");
383 MODULE_PARM(msglevel, "i");
384 MODULE_PARM(activate_gpio, "0-15i");
385 MODULE_PARM(line_speed, "1-" __MODULE_STRING(MAX_UNITS) "i");
386 MODULE_PARM(auto_speed, "1-" __MODULE_STRING(MAX_UNITS) "i");
387 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
388 MODULE_PARM(rx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
389 MODULE_PARM(tx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
390 MODULE_PARM(auto_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
391 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
392 MODULE_PARM(mtu, "1-" __MODULE_STRING(MAX_UNITS) "i");
393 #endif
394 MODULE_PARM(tx_checksum, "1-" __MODULE_STRING(MAX_UNITS) "i");
395 MODULE_PARM(rx_checksum, "1-" __MODULE_STRING(MAX_UNITS) "i");
396 MODULE_PARM(scatter_gather, "1-" __MODULE_STRING(MAX_UNITS) "i");
397 MODULE_PARM(tx_pkt_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
398 MODULE_PARM(rx_std_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
399 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
400 MODULE_PARM(rx_jumbo_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
401 #endif
402 #ifdef BCM_INT_COAL
403 MODULE_PARM(adaptive_coalesce, "1-" __MODULE_STRING(MAX_UNITS) "i");
404 MODULE_PARM(rx_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i");
405 MODULE_PARM(rx_max_coalesce_frames, "1-" __MODULE_STRING(MAX_UNITS) "i");
406 MODULE_PARM(tx_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i");
407 MODULE_PARM(tx_max_coalesce_frames, "1-" __MODULE_STRING(MAX_UNITS) "i");
408 MODULE_PARM(stats_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i");
409 #endif
410 #ifdef BCM_WOL
411 MODULE_PARM(enable_wol, "1-" __MODULE_STRING(MAX_UNITS) "i");
412 #endif
413 #ifdef BCM_TSO
414 MODULE_PARM(enable_tso, "1-" __MODULE_STRING(MAX_UNITS) "i");
415 #endif
416 #ifdef BCM_NIC_SEND_BD
417 MODULE_PARM(nic_tx_bd, "1-" __MODULE_STRING(MAX_UNITS) "i");
418 #endif
419 #ifdef BCM_ASF
420 MODULE_PARM(vlan_tag_mode, "1-" __MODULE_STRING(MAX_UNITS) "i");
421 #endif
422 MODULE_PARM(delay_link, "1-" __MODULE_STRING(MAX_UNITS) "i");
423 MODULE_PARM(disable_d3hot, "1-" __MODULE_STRING(MAX_UNITS) "i");
424
425 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
426 MODULE_PARM(disable_msi, "1-" __MODULE_STRING(MAX_UNITS) "i");
427 #endif
428
429 #else /* parms*/
430
431 #if (LINUX_VERSION_CODE >= 0x020605) && (LINUX_VERSION_CODE < 0x02060a)
432
433 static int var;
434
435 #define numvar var
436
437 #endif
438
439 #if (LINUX_VERSION_CODE >= 0x2060a)
440
441 #define numvar NULL
442
443 #endif
444
445 module_param_array(line_speed, int, numvar, 0);
446 module_param_array(auto_speed, int, numvar, 0);
447 module_param_array(full_duplex, int, numvar, 0);
448 module_param_array(rx_flow_control, int, numvar, 0);
449 module_param_array(tx_flow_control, int, numvar, 0);
450 module_param_array(auto_flow_control, int, numvar, 0);
451 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
452 module_param_array(mtu, int, numvar, 0);
453 #endif
454 module_param_array(tx_checksum, int, numvar, 0);
455 module_param_array(rx_checksum, int, numvar, 0);
456 module_param_array(scatter_gather, int, numvar, 0);
457 module_param_array(tx_pkt_desc_cnt, int, numvar, 0);
458 module_param_array(rx_std_desc_cnt, int, numvar, 0);
459 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
460 module_param_array(rx_jumbo_desc_cnt, int, numvar, 0);
461 #endif
462 #ifdef BCM_INT_COAL
463 module_param_array(adaptive_coalesce, int, numvar, 0);
464 module_param_array(rx_coalesce_ticks, int, numvar, 0);
465 module_param_array(rx_max_coalesce_frames, int, numvar, 0);
466 module_param_array(tx_coalesce_ticks, int, numvar, 0);
467 module_param_array(tx_max_coalesce_frames, int, numvar, 0);
468 module_param_array(stats_coalesce_ticks, int, numvar, 0);
469 #endif
470 #ifdef BCM_WOL
471 module_param_array(enable_wol, int, numvar, 0);
472 #endif
473 #ifdef BCM_TSO
474 module_param_array(enable_tso, int, numvar, 0);
475 #endif
476 #ifdef BCM_NIC_SEND_BD
477 module_param_array(nic_tx_bd, int, numvar, 0);
478 #endif
479 #ifdef BCM_ASF
480 module_param_array(vlan_tag_mode, int, numvar, 0);
481 #endif
482 module_param_array(delay_link, int, numvar, 0);
483 module_param_array(disable_d3hot, int, numvar, 0);
484
485 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
486 module_param_array(disable_msi, int, numvar, 0);
487 #endif
488
489
490 #endif /* params */
491
492
493 #endif
494
495 #define RUN_AT(x) (jiffies + (x))
496
497 char kernel_version[] = UTS_RELEASE;
498
499 #define PCI_SUPPORT_VER2
500
501 #if !defined(CAP_NET_ADMIN)
502 #define capable(CAP_XXX) (suser())
503 #endif
504
505 #define tigon3_debug debug
506 #if TIGON3_DEBUG
507 static int tigon3_debug = TIGON3_DEBUG;
508 #else
509 static int tigon3_debug = 0;
510 #endif
511 static int msglevel = 0xdeadbeef;
512 int b57_msg_level;
513
514 int bcm5700_open(struct net_device *dev);
515 STATIC void bcm5700_timer(unsigned long data);
516 STATIC void bcm5700_stats_timer(unsigned long data);
517 STATIC void bcm5700_reset(struct net_device *dev);
518 STATIC int bcm5700_start_xmit(struct sk_buff *skb, struct net_device *dev);
519 STATIC irqreturn_t bcm5700_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
520 #ifdef BCM_TASKLET
521 STATIC void bcm5700_tasklet(unsigned long data);
522 #endif
523 STATIC int bcm5700_close(struct net_device *dev);
524 STATIC struct net_device_stats *bcm5700_get_stats(struct net_device *dev);
525 STATIC int bcm5700_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
526 STATIC void bcm5700_do_rx_mode(struct net_device *dev);
527 STATIC void bcm5700_set_rx_mode(struct net_device *dev);
528 STATIC int bcm5700_set_mac_addr(struct net_device *dev, void *p);
529 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
530 STATIC int bcm5700_change_mtu(struct net_device *dev, int new_mtu);
531 #endif
532 #ifdef BCM_NAPI_RXPOLL
533 STATIC int bcm5700_poll(struct net_device *dev, int *budget);
534 #endif
535 STATIC int replenish_rx_buffers(PUM_DEVICE_BLOCK pUmDevice, int max);
536 STATIC int bcm5700_freemem(struct net_device *dev);
537 #ifdef BCM_INT_COAL
538 #ifndef BCM_NAPI_RXPOLL
539 STATIC int bcm5700_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice);
540 #endif
541 #endif
542 STATIC void bcm5700_set_vlan_mode(UM_DEVICE_BLOCK *pUmDevice);
543 STATIC int bcm5700_init_counters(PUM_DEVICE_BLOCK pUmDevice);
544 #ifdef BCM_VLAN
545 STATIC void bcm5700_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp);
546 STATIC void bcm5700_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid);
547 #endif
548 void bcm5700_shutdown(UM_DEVICE_BLOCK *pUmDevice);
549 void bcm5700_free_remaining_rx_bufs(UM_DEVICE_BLOCK *pUmDevice);
550 void bcm5700_validate_param_range(UM_DEVICE_BLOCK *pUmDevice, int *param,
551         char *param_name, int min, int max, int deflt);
552
553 static int bcm5700_notify_reboot(struct notifier_block *this, unsigned long event, void *unused);
554 static struct notifier_block bcm5700_reboot_notifier = {
555         bcm5700_notify_reboot,
556         NULL,
557         0
558 };
559
560 #if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
561 STATIC void poll_bcm5700(struct net_device *dev);
562 #endif
563
564 /* A list of all installed bcm5700 devices. */
565 static struct net_device *root_tigon3_dev = NULL;
566
567 #if defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) ||defined(CONFIG_PPC64)
568
569 #endif
570
571 typedef enum {
572         BCM5700A6 = 0,
573         BCM5700T6,
574         BCM5700A9,
575         BCM5700T9,
576         BCM5700,
577         BCM5701A5,
578         BCM5701T1,
579         BCM5701T8,
580         BCM5701A7,
581         BCM5701A10,
582         BCM5701A12,
583         BCM5701,
584         BCM5702,
585         BCM5703,
586         BCM5703A31,
587         BCM5703ARBUCKLE,
588         TC996T,
589         TC996ST,
590         TC996SSX,
591         TC996SX,
592         TC996BT,
593         TC997T,
594         TC997SX,
595         TC1000T,
596         TC1000BT,
597         TC940BR01,
598         TC942BR01,
599         TC998T,
600         TC998SX,
601         TC999T,
602         NC6770,
603         NC1020,
604         NC150T,
605         NC7760,
606         NC7761,
607         NC7770,
608         NC7771,
609         NC7780,
610         NC7781,
611         NC7772,
612         NC7782,
613         NC7783,
614         NC320T,
615         NC320I,
616         NC325I,
617         NC324I,
618         NC326I,
619         BCM5704CIOBE,
620         BCM5704,
621         BCM5704S,
622         BCM5705,
623         BCM5705M,
624         BCM5705F,
625         BCM5901,
626         BCM5782,
627         BCM5788,
628         BCM5789,
629         BCM5750,
630         BCM5750M,
631         BCM5720,
632         BCM5751,
633         BCM5751M,
634         BCM5751F,
635         BCM5721,
636         BCM5753,
637         BCM5753M,
638         BCM5753F,
639         BCM5781,
640         BCM5752,
641         BCM5752M,
642         BCM5714,
643         BCM5780,
644         BCM5780S,
645         BCM5715,
646         BCM4785,
647         BCM5903M,
648         UNK5788
649 } board_t;
650
651
652 /* indexed by board_t, above */
653 static struct {
654         char *name;
655 } board_info[] __devinitdata = {
656         { "Broadcom BCM5700 1000Base-T" },
657         { "Broadcom BCM5700 1000Base-SX" },
658         { "Broadcom BCM5700 1000Base-SX" },
659         { "Broadcom BCM5700 1000Base-T" },
660         { "Broadcom BCM5700" },
661         { "Broadcom BCM5701 1000Base-T" },
662         { "Broadcom BCM5701 1000Base-T" },
663         { "Broadcom BCM5701 1000Base-T" },
664         { "Broadcom BCM5701 1000Base-SX" },
665         { "Broadcom BCM5701 1000Base-T" },
666         { "Broadcom BCM5701 1000Base-T" },
667         { "Broadcom BCM5701" },
668         { "Broadcom BCM5702 1000Base-T" },
669         { "Broadcom BCM5703 1000Base-T" },
670         { "Broadcom BCM5703 1000Base-SX" },
671         { "Broadcom B5703 1000Base-SX" },
672         { "3Com 3C996 10/100/1000 Server NIC" },
673         { "3Com 3C996 10/100/1000 Server NIC" },
674         { "3Com 3C996 Gigabit Fiber-SX Server NIC" },
675         { "3Com 3C996 Gigabit Fiber-SX Server NIC" },
676         { "3Com 3C996B Gigabit Server NIC" },
677         { "3Com 3C997 Gigabit Server NIC" },
678         { "3Com 3C997 Gigabit Fiber-SX Server NIC" },
679         { "3Com 3C1000 Gigabit NIC" },
680         { "3Com 3C1000B-T 10/100/1000 PCI" },
681         { "3Com 3C940 Gigabit LOM (21X21)" },
682         { "3Com 3C942 Gigabit LOM (31X31)" },
683         { "3Com 3C998-T Dual Port 10/100/1000 PCI-X Server NIC" },
684         { "3Com 3C998-SX Dual Port 1000-SX PCI-X Server NIC" },
685         { "3Com 3C999-T Quad Port 10/100/1000 PCI-X Server NIC" },
686         { "HP NC6770 Gigabit Server Adapter" },
687         { "NC1020 HP ProLiant Gigabit Server Adapter 32 PCI" },
688         { "HP ProLiant NC 150T PCI 4-port Gigabit Combo Switch Adapter" },
689         { "HP NC7760 Gigabit Server Adapter" },
690         { "HP NC7761 Gigabit Server Adapter" },
691         { "HP NC7770 Gigabit Server Adapter" },
692         { "HP NC7771 Gigabit Server Adapter" },
693         { "HP NC7780 Gigabit Server Adapter" },
694         { "HP NC7781 Gigabit Server Adapter" },
695         { "HP NC7772 Gigabit Server Adapter" },
696         { "HP NC7782 Gigabit Server Adapter" },
697         { "HP NC7783 Gigabit Server Adapter" },
698         { "HP ProLiant NC 320T PCI Express Gigabit Server Adapter" },
699         { "HP ProLiant NC 320i PCI Express Gigabit Server Adapter" },
700         { "HP NC325i Integrated Dual Port PCI Express Gigabit Server Adapter" },
701         { "HP NC324i Integrated Dual Port PCI Express Gigabit Server Adapter" },
702         { "HP NC326i Integrated Dual Port PCI Express Gigabit Server Adapter" },
703         { "Broadcom BCM5704 CIOB-E 1000Base-T" },
704         { "Broadcom BCM5704 1000Base-T" },
705         { "Broadcom BCM5704 1000Base-SX" },
706         { "Broadcom BCM5705 1000Base-T" },
707         { "Broadcom BCM5705M 1000Base-T" },
708         { "Broadcom 570x 10/100 Integrated Controller" },
709         { "Broadcom BCM5901 100Base-TX" },
710         { "Broadcom NetXtreme Gigabit Ethernet for hp" },
711         { "Broadcom BCM5788 NetLink 1000Base-T" },
712         { "Broadcom BCM5789 NetLink 1000Base-T PCI Express" },
713         { "Broadcom BCM5750 1000Base-T PCI" },
714         { "Broadcom BCM5750M 1000Base-T PCI" },
715         { "Broadcom BCM5720 1000Base-T PCI" },
716         { "Broadcom BCM5751 1000Base-T PCI Express" },
717         { "Broadcom BCM5751M 1000Base-T PCI Express" },
718         { "Broadcom BCM5751F 100Base-TX PCI Express" },
719         { "Broadcom BCM5721 1000Base-T PCI Express" },
720         { "Broadcom BCM5753 1000Base-T PCI Express" },
721         { "Broadcom BCM5753M 1000Base-T PCI Express" },
722         { "Broadcom BCM5753F 100Base-TX PCI Express" },
723         { "Broadcom BCM5781 NetLink 1000Base-T PCI Express" },
724         { "Broadcom BCM5752 1000Base-T PCI Express" },
725         { "Broadcom BCM5752M 1000Base-T PCI Express" },
726         { "Broadcom BCM5714 1000Base-T " },
727         { "Broadcom BCM5780 1000Base-T" },
728         { "Broadcom BCM5780S 1000Base-SX" },
729         { "Broadcom BCM5715 1000Base-T " },
730         { "Broadcom BCM4785 10/100/1000 Integrated Controller" },
731         { "Broadcom BCM5903M Gigabit Ethernet " },
732         { "Unknown BCM5788 Gigabit Ethernet " },
733         { 0 }
734         };
735
736 static struct pci_device_id bcm5700_pci_tbl[] __devinitdata = {
737         {0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6 },
738         {0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6 },
739         {0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9 },
740         {0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9 },
741         {0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700 },
742         {0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700 },
743         {0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700 },
744         {0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700 },
745         {0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T },
746         {0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST },
747         {0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX },
748         {0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T },
749         {0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX },
750         {0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01 },
751         {0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700 },
752         {0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5 },
753         {0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1 },
754         {0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8 },
755         {0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7 },
756         {0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10 },
757         {0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12 },
758         {0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770 },
759         {0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770 },
760         {0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780 },
761         {0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701 },
762         {0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX },
763         {0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT },
764         {0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T },
765         {0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01 },
766         {0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701 },
767         {0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702 },
768         {0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
769         {0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702 },
770         {0x14e4, 0x16a6, 0x14e4, 0x000c, 0, 0, BCM5702 },
771         {0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760 },
772         {0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
773         {0x14e4, 0x16c6, 0x10b7, 0x1100, 0, 0, TC1000BT },
774         {0x14e4, 0x16c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
775         {0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703 },
776         {0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
777         {0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703 },
778         {0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703 },
779         {0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
780         {0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703 },
781         {0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
782         {0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703 },
783         {0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703 },
784         {0x14e4, 0x16a7, 0x0e11, 0xca, 0, 0, NC7771 },
785         {0x14e4, 0x16a7, 0x0e11, 0xcb, 0, 0, NC7781 },
786         {0x14e4, 0x16a7, 0x1014, 0x0281, 0, 0, BCM5703ARBUCKLE },
787         {0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
788         {0x14e4, 0x16c7, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
789         {0x14e4, 0x16c7, 0x0e11, 0xca, 0, 0, NC7771 },
790         {0x14e4, 0x16c7, 0x0e11, 0xcb, 0, 0, NC7781 },
791         {0x14e4, 0x16c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
792         {0x14e4, 0x1648, 0x0e11, 0xcf, 0, 0, NC7772 },
793         {0x14e4, 0x1648, 0x0e11, 0xd0, 0, 0, NC7782 },
794         {0x14e4, 0x1648, 0x0e11, 0xd1, 0, 0, NC7783 },
795         {0x14e4, 0x1648, 0x10b7, 0x2000, 0, 0, TC998T },
796         {0x14e4, 0x1648, 0x10b7, 0x3000, 0, 0, TC999T },
797         {0x14e4, 0x1648, 0x1166, 0x1648, 0, 0, BCM5704CIOBE },
798         {0x14e4, 0x1648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704 },
799         {0x14e4, 0x1649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S },
800         {0x14e4, 0x16a8, 0x14e4, 0x16a8, 0, 0, BCM5704S },
801         {0x14e4, 0x16a8, 0x10b7, 0x2001, 0, 0, TC998SX },
802         {0x14e4, 0x16a8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S },
803         {0x14e4, 0x1653, 0x0e11, 0x00e3, 0, 0, NC7761 },
804         {0x14e4, 0x1653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 },
805         {0x14e4, 0x1654, 0x0e11, 0x00e3, 0, 0, NC7761 },
806         {0x14e4, 0x1654, 0x103c, 0x3100, 0, 0, NC1020 },
807         {0x14e4, 0x1654, 0x103c, 0x3226, 0, 0, NC150T },
808         {0x14e4, 0x1654, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 },
809         {0x14e4, 0x165d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M },
810         {0x14e4, 0x165e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M },
811         {0x14e4, 0x166e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705F },
812         {0x14e4, 0x1696, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5782 },
813         {0x14e4, 0x169c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5788 },
814         {0x14e4, 0x169d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5789 },
815         {0x14e4, 0x170d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 },
816         {0x14e4, 0x170e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 },
817         {0x14e4, 0x1676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750 },
818         {0x14e4, 0x167c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750M },
819         {0x14e4, 0x1677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751 },
820         {0x14e4, 0x167d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751M },
821         {0x14e4, 0x167e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751F },
822         {0x14e4, 0x1658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5720 },
823         {0x14e4, 0x1659, 0x103c, 0x7031, 0, 0, NC320T },
824         {0x14e4, 0x1659, 0x103c, 0x7032, 0, 0, NC320T },
825         {0x14e4, 0x166a, 0x103c, 0x7035, 0, 0, NC325I },
826         {0x14e4, 0x166b, 0x103c, 0x7036, 0, 0, NC325I },
827         {0x14e4, 0x1668, 0x103c, 0x7039, 0, 0, NC324I },
828         {0x14e4, 0x1669, 0x103c, 0x703a, 0, 0, NC324I },
829         {0x14e4, 0x1678, 0x103c, 0x703e, 0, 0, NC326I },
830         {0x14e4, 0x1679, 0x103c, 0x703c, 0, 0, NC326I },
831         {0x14e4, 0x1659, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5721 },
832         {0x14e4, 0x16f7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753 },
833         {0x14e4, 0x16fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753M },
834         {0x14e4, 0x16fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753F },
835         {0x14e4, 0x16dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5781 },
836         {0x14e4, 0x1600, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5752 },
837         {0x14e4, 0x1601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5752M },
838         {0x14e4, 0x1668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5714 },
839         {0x14e4, 0x166a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5780 },
840         {0x14e4, 0x166b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5780S },
841         {0x14e4, 0x1678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5715 },
842         {0x14e4, 0x471f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM4785 },
843         {0x14e4, 0x16ff, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5903M },
844         {0x173b, 0x03ed, PCI_ANY_ID, PCI_ANY_ID, 0, 0, UNK5788 },
845         {0,}
846         };
847
848 MODULE_DEVICE_TABLE(pci, bcm5700_pci_tbl);
849
850 #if (LINUX_VERSION_CODE >= 0x2060a)
851         static struct pci_device_id pci_AMD762id[]={
852                 { PCI_DEVICE(PCI_VENDOR_ID_AMD,
853                         PCI_DEVICE_ID_AMD_FE_GATE_700C) },
854                 { }
855         };
856 #endif
857
858 static int sbgige = -1;
859
860 /*******************************************************************************
861  *******************************************************************************
862 */
863
864 int get_csum_flag(LM_UINT32 ChipRevId)
865 {
866         return NETIF_F_IP_CSUM;
867 }
868
869 /*******************************************************************************
870  *******************************************************************************
871
872    This function returns true if the device passed to it is attached to an
873    ICH-ICH4. If the chip is not attached to an ICH, or is attached to an ICH5
874    or newer, it returns false.
875
876    This function determines which bridge it is attached to by scaning the pci
877    bus looking for bridge chips (hdr_type=1). When a bridge chip is detected,
878    the bridge's subordinate's secondary bus number is compared with this
879    devices bus number. If they match, then the device is attached to this
880    bridge. The bridge's device id is compared to a list of known device ids for
881    ICH-ICH4. Since many older ICH's (ICH2-ICH7) share the same device id, the
882    chip revision must also be checked to determine if the chip is older than an
883    ICH5.
884
885    To scan the bus, one of two functions is used depending on the kernel
886    version. For 2.4 kernels, the pci_find_device function is used. This
887    function has been depricated in the 2.6 kernel and replaced with the
888    fucntion pci_get_device. The macro walk_pci_bus determines which function to
889    use when the driver is built.
890 */
891
892 #if (LINUX_VERSION_CODE >= 0x2060a)
893 #define walk_pci_bus(d)         while ((d = pci_get_device( \
894                                         PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
895
896 #define unwalk_pci_bus(d)       pci_dev_put(d)
897
898 #else
899 #define walk_pci_bus(d)         while ((d = pci_find_device( \
900                                         PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
901 #define unwalk_pci_bus(d)
902
903 #endif
904
905 #define ICH5_CHIP_VERSION       0xc0
906
907 static struct pci_device_id pci_ICHtable[] = {
908         {0x8086, 0x2418}, /* PCI_DEVICE_ID_INTEL_82801AA_8  */
909         {0x8086, 0x2428}, /* PCI_DEVICE_ID_INTEL_82801AB_8  */
910         {0x8086, 0x244e}, /* PCI_DEVICE_ID_INTEL_82801BA_6  */
911         {0x8086, 0x2448}, /* PCI_DEVICE_ID_INTEL_82801BA_11 */
912         {0, 0}
913 };
914
915 int attached_to_ICH4_or_older( struct pci_dev *pdev)
916 {
917         struct pci_dev *tmp_pdev = NULL;
918         struct pci_device_id *ich_table;
919         u8 chip_rev;
920
921         walk_pci_bus (tmp_pdev) {
922                 if ((tmp_pdev->hdr_type == 1) &&
923                    (tmp_pdev->subordinate != NULL) &&
924                    (tmp_pdev->subordinate->secondary == pdev->bus->number)) {
925
926                         ich_table = pci_ICHtable;
927
928                         while (ich_table->vendor) {
929                                 if ((ich_table->vendor == tmp_pdev->vendor) &&
930                                     (ich_table->device == tmp_pdev->device)) {
931
932                                         pci_read_config_byte( tmp_pdev,
933                                                 PCI_REVISION_ID, &chip_rev);
934
935                                         if (chip_rev < ICH5_CHIP_VERSION) {
936                                                 unwalk_pci_bus( tmp_pdev);
937                                                 return 1;
938                                         }
939                                 }
940                                 ich_table++;
941                         }
942                 }
943         }
944         return 0;
945 }
946
947 static void robo_set_power_mode(void *h)
948 {
949         //int status = 0;
950         int i;
951         //uint8 mode8;
952         //uint16 mode16;
953         uint32 flags = 0, temp32 = 0,val32 = 0, savephyaddr = 0;
954         PUM_DEVICE_BLOCK pudev = (PUM_DEVICE_BLOCK)h;
955         PLM_DEVICE_BLOCK pdev = &pudev->lm_dev;
956
957         /*Brcm,Alex,2006.7.20. Adding Phy power mode setting*/
958         BCM5700_PHY_LOCK(pudev, flags);
959         savephyaddr = pdev->PhyAddr;
960
961         for(i = 0; i < 8; i++)
962         {
963                 pdev->PhyAddr = i;
964                 temp32 = 0x2007;
965                 LM_WritePhy(pdev, 0x18, temp32);
966                 LM_ReadPhy(pdev, 0x18, &val32);
967 //              printk(KERN_DEBUG "Alex: port = %x, read value =%x\n",i, val32);
968                 temp32 = 0xc042;
969                 LM_WritePhy(pdev, 0x18, temp32);
970                 /*Read back*/
971                 temp32 = 0x2007;
972                 val32 = 0;
973                 LM_WritePhy(pdev, 0x18, temp32);
974                 LM_ReadPhy(pdev, 0x18, &val32);
975 //              printk(KERN_ERR "Alex: read back value =%x\n",val32);
976         }
977
978         pdev->PhyAddr = savephyaddr;
979         BCM5700_PHY_UNLOCK(pudev, flags);
980
981         /*end of Brcm,Alex,2006.7.20. Adding Phy power mode setting*/
982
983 }
984
985 static int
986 __devinit bcm5700_init_board(struct pci_dev *pdev, struct net_device **dev_out, int board_idx)
987 {
988         struct net_device *dev;
989         PUM_DEVICE_BLOCK pUmDevice;
990         PLM_DEVICE_BLOCK pDevice;
991         bool rgmii = FALSE;
992         sb_t *sbh = NULL;
993         int rc;
994
995         *dev_out = NULL;
996
997         /* dev zeroed in init_etherdev */
998 #if (LINUX_VERSION_CODE >= 0x20600)
999         dev = alloc_etherdev(sizeof(*pUmDevice));
1000 #else
1001         dev = init_etherdev(NULL, sizeof(*pUmDevice));
1002 #endif
1003         if (dev == NULL) {
1004                 printk(KERN_ERR "%s: unable to alloc new ethernet\n", bcm5700_driver);
1005                 return -ENOMEM;
1006         }
1007         SET_MODULE_OWNER(dev);
1008 #if (LINUX_VERSION_CODE >= 0x20600)
1009         SET_NETDEV_DEV(dev, &pdev->dev);
1010 #endif
1011         pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
1012
1013         /* enable device (incl. PCI PM wakeup), and bus-mastering */
1014         rc = pci_enable_device(pdev);
1015         if (rc)
1016                 goto err_out;
1017
1018         /* init core specific stuff */
1019         if (pdev->device == T3_PCI_DEVICE_ID(T3_PCI_ID_BCM471F)) {
1020                 sbh = sb_kattach(SB_OSH);
1021                 sb_gige_init(sbh, ++sbgige, &rgmii);
1022         }
1023
1024         rc = pci_request_regions(pdev, bcm5700_driver);
1025         if (rc) {
1026                 if (!sbh)
1027                         goto err_out;
1028                 printk(KERN_INFO "bcm5700_init_board: pci_request_regions returned error %d\n"
1029                                  "This may be because the region is already requested by"
1030                                  " the SMBus driver. Ignore the PCI error messages.\n", rc);
1031         }
1032
1033         pci_set_master(pdev);
1034
1035         if (pci_set_dma_mask(pdev, BCM_64BIT_DMA_MASK) == 0) {
1036                 pUmDevice->using_dac = 1;
1037                 if (pci_set_consistent_dma_mask(pdev, BCM_64BIT_DMA_MASK) != 0) {
1038                         printk(KERN_ERR "pci_set_consistent_dma_mask failed\n");
1039                         pci_release_regions(pdev);
1040                         goto err_out;
1041                 }
1042         } else if (pci_set_dma_mask(pdev, BCM_32BIT_DMA_MASK) == 0) {
1043                 pUmDevice->using_dac = 0;
1044         } else {
1045                 printk(KERN_ERR "System does not support DMA\n");
1046                 pci_release_regions(pdev);
1047                 goto err_out;
1048         }
1049
1050         pUmDevice->dev = dev;
1051         pUmDevice->pdev = pdev;
1052         pUmDevice->mem_list_num = 0;
1053         pUmDevice->next_module = root_tigon3_dev;
1054         pUmDevice->index = board_idx;
1055         pUmDevice->sbh = (void *)sbh;
1056         root_tigon3_dev = dev;
1057
1058         spin_lock_init(&pUmDevice->global_lock);
1059
1060         spin_lock_init(&pUmDevice->undi_lock);
1061
1062         spin_lock_init(&pUmDevice->phy_lock);
1063
1064         pDevice = &pUmDevice->lm_dev;
1065         pDevice->Flags = 0;
1066         pDevice->FunctNum = PCI_FUNC(pUmDevice->pdev->devfn);
1067         pUmDevice->boardflags = getintvar(NULL, "boardflags");
1068         if (sbh) {
1069                 if (pUmDevice->boardflags & BFL_ENETROBO)
1070                         pDevice->Flags |= ROBO_SWITCH_FLAG;
1071                 pDevice->Flags |= rgmii ? RGMII_MODE_FLAG : 0;
1072                 if (sb_chip(sbh) == BCM4785_CHIP_ID && sb_chiprev(sbh) < 2)
1073                         pDevice->Flags |= ONE_DMA_AT_ONCE_FLAG;
1074                 pDevice->Flags |= SB_CORE_FLAG;
1075                 if (sb_chip(sbh) == BCM4785_CHIP_ID)
1076                         pDevice->Flags |= FLUSH_POSTED_WRITE_FLAG;
1077         }
1078
1079 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
1080         if (board_idx < MAX_UNITS) {
1081                 bcm5700_validate_param_range(pUmDevice, &mtu[board_idx], "mtu", 1500, 9000, 1500);
1082                 dev->mtu = mtu[board_idx];
1083         }
1084 #endif
1085
1086         if (attached_to_ICH4_or_older(pdev)) {
1087                 pDevice->Flags |= UNDI_FIX_FLAG;
1088         }
1089
1090 #if (LINUX_VERSION_CODE >= 0x2060a)
1091         if (pci_dev_present(pci_AMD762id)) {
1092                 pDevice->Flags |= FLUSH_POSTED_WRITE_FLAG;
1093                 pDevice->Flags &= ~NIC_SEND_BD_FLAG;
1094         }
1095 #else
1096         if (pci_find_device(0x1022, 0x700c, NULL)) {
1097                 /* AMD762 writes I/O out of order */
1098                 /* Setting bit 1 in 762's register 0x4C still doesn't work */
1099                 /* in all cases */
1100                 pDevice->Flags |= FLUSH_POSTED_WRITE_FLAG;
1101                 pDevice->Flags &= ~NIC_SEND_BD_FLAG;
1102         }
1103 #endif
1104         if (LM_GetAdapterInfo(pDevice) != LM_STATUS_SUCCESS) {
1105                 rc = -ENODEV;
1106                 goto err_out_unmap;
1107         }
1108
1109         if (pDevice->Flags & ROBO_SWITCH_FLAG) {
1110                 robo_info_t     *robo;
1111
1112                 if ((robo = bcm_robo_attach(sbh, pDevice, dev->name, NULL,
1113                                             robo_miird, robo_miiwr)) == NULL) {
1114                         B57_ERR(("robo_setup: failed to attach robo switch \n"));
1115                         goto robo_fail;
1116                 }
1117
1118                 if (bcm_robo_enable_device(robo)) {
1119                         B57_ERR(("robo_setup: failed to enable robo switch \n"));
1120 robo_fail:
1121                         bcm_robo_detach(robo);
1122                         rc = -ENODEV;
1123                         goto err_out_unmap;
1124                 }
1125
1126                 /* 5397 power mode setting */
1127                 robo_set_power_mode(robo->h);
1128
1129                 pUmDevice->robo = (void *)robo;
1130         }
1131
1132         if ((pDevice->Flags & JUMBO_CAPABLE_FLAG) == 0) {
1133                 if (dev->mtu > 1500) {
1134                         dev->mtu = 1500;
1135                         printk(KERN_WARNING
1136                                "%s-%d: Jumbo mtu sizes not supported, using mtu=1500\n",
1137                                bcm5700_driver, pUmDevice->index);
1138                 }
1139         }
1140
1141         pUmDevice->do_global_lock = 0;
1142         if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
1143                 /* The 5700 chip works best without interleaved register */
1144                 /* accesses on certain machines. */
1145                 pUmDevice->do_global_lock = 1;
1146         }
1147
1148         if ((T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5701) &&
1149                 ((pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS) == 0)) {
1150
1151                 pUmDevice->rx_buf_align = 0;
1152         } else {
1153                 pUmDevice->rx_buf_align = 2;
1154         }
1155         dev->mem_start = pci_resource_start(pdev, 0);
1156         dev->mem_end = dev->mem_start + sizeof(T3_STD_MEM_MAP);
1157         dev->irq = pdev->irq;
1158
1159         *dev_out = dev;
1160         return 0;
1161
1162 err_out_unmap:
1163         pci_release_regions(pdev);
1164         bcm5700_freemem(dev);
1165
1166 err_out:
1167 #if (LINUX_VERSION_CODE < 0x020600)
1168         unregister_netdev(dev);
1169         kfree(dev);
1170 #else
1171         free_netdev(dev);
1172 #endif
1173         return rc;
1174 }
1175
1176 static int __devinit
1177 bcm5700_print_ver(void)
1178 {
1179         printk(KERN_INFO "Broadcom Gigabit Ethernet Driver %s ",
1180                 bcm5700_driver);
1181         printk("ver. %s %s\n", bcm5700_version, bcm5700_date);
1182         return 0;
1183 }
1184
1185 static int __devinit
1186 bcm5700_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1187 {
1188         struct net_device *dev = NULL;
1189         PUM_DEVICE_BLOCK pUmDevice;
1190         PLM_DEVICE_BLOCK pDevice;
1191         int i;
1192         static int board_idx = -1;
1193         static int printed_version = 0;
1194         struct pci_dev *pci_dev;
1195
1196         board_idx++;
1197
1198         if (!printed_version) {
1199                 bcm5700_print_ver();
1200                 printed_version = 1;
1201         }
1202
1203         i = bcm5700_init_board(pdev, &dev, board_idx);
1204         if (i < 0) {
1205                 return i;
1206         }
1207
1208         if (dev == NULL)
1209                 return -ENOMEM;
1210
1211 #ifdef BCM_IOCTL32
1212         if (atomic_read(&bcm5700_load_count) == 0) {
1213                 register_ioctl32_conversion(SIOCNICE, bcm5700_ioctl32);
1214         }
1215         atomic_inc(&bcm5700_load_count);
1216 #endif
1217         dev->open = bcm5700_open;
1218         dev->hard_start_xmit = bcm5700_start_xmit;
1219         dev->stop = bcm5700_close;
1220         dev->get_stats = bcm5700_get_stats;
1221         dev->set_multicast_list = bcm5700_set_rx_mode;
1222         dev->do_ioctl = bcm5700_ioctl;
1223         dev->set_mac_address = &bcm5700_set_mac_addr;
1224 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
1225         dev->change_mtu = &bcm5700_change_mtu;
1226 #endif
1227 #if (LINUX_VERSION_CODE >= 0x20400)
1228         dev->tx_timeout = bcm5700_reset;
1229         dev->watchdog_timeo = TX_TIMEOUT;
1230 #endif
1231 #ifdef BCM_VLAN
1232         dev->vlan_rx_register = &bcm5700_vlan_rx_register;
1233         dev->vlan_rx_kill_vid = &bcm5700_vlan_rx_kill_vid;
1234 #endif
1235 #ifdef BCM_NAPI_RXPOLL
1236         dev->poll = bcm5700_poll;
1237         dev->weight = 64;
1238 #endif
1239
1240         pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
1241         pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
1242
1243         dev->base_addr = pci_resource_start(pdev, 0);
1244         dev->irq = pdev->irq;
1245 #if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
1246         dev->poll_controller = poll_bcm5700;
1247 #endif
1248
1249 #if (LINUX_VERSION_CODE >= 0x20600)
1250         if ((i = register_netdev(dev))) {
1251                 printk(KERN_ERR "%s: Cannot register net device\n",
1252                         bcm5700_driver);
1253                 if (pUmDevice->lm_dev.pMappedMemBase)
1254                         iounmap(pUmDevice->lm_dev.pMappedMemBase);
1255                 pci_release_regions(pdev);
1256                 bcm5700_freemem(dev);
1257                 free_netdev(dev);
1258                 return i;
1259         }
1260 #endif
1261
1262
1263         pci_set_drvdata(pdev, dev);
1264
1265         memcpy(dev->dev_addr, pDevice->NodeAddress, 6);
1266         pUmDevice->name = board_info[ent->driver_data].name,
1267         printk(KERN_INFO "%s: %s found at mem %lx, IRQ %d, ",
1268                 dev->name, pUmDevice->name, dev->base_addr,
1269                 dev->irq);
1270         printk("node addr ");
1271         for (i = 0; i < 6; i++) {
1272                 printk("%2.2x", dev->dev_addr[i]);
1273         }
1274         printk("\n");
1275
1276         printk(KERN_INFO "%s: ", dev->name);
1277         if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID)
1278                 printk("Broadcom BCM5400 Copper ");
1279         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
1280                 printk("Broadcom BCM5401 Copper ");
1281         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID)
1282                 printk("Broadcom BCM5411 Copper ");
1283         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5461_PHY_ID)
1284                 printk("Broadcom BCM5461 Copper ");
1285         else if (((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID) &&
1286                 !(pDevice->TbiFlags & ENABLE_TBI_FLAG)) {
1287                 printk("Broadcom BCM5701 Integrated Copper ");
1288         }
1289         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID) {
1290                 printk("Broadcom BCM5703 Integrated ");
1291                 if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
1292                         printk("SerDes ");
1293                 else
1294                         printk("Copper ");
1295         }
1296         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5704_PHY_ID) {
1297                 printk("Broadcom BCM5704 Integrated ");
1298                 if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
1299                         printk("SerDes ");
1300                 else
1301                         printk("Copper ");
1302         }
1303         else if (pDevice->PhyFlags & PHY_IS_FIBER){
1304             if(( pDevice->PhyId & PHY_ID_MASK ) == PHY_BCM5780_PHY_ID)
1305                 printk("Broadcom BCM5780S Integrated Serdes ");
1306
1307         }        
1308         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5705_PHY_ID)
1309                 printk("Broadcom BCM5705 Integrated Copper ");
1310         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5750_PHY_ID)
1311                 printk("Broadcom BCM5750 Integrated Copper ");
1312
1313         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5714_PHY_ID)
1314                 printk("Broadcom BCM5714 Integrated Copper ");
1315         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5780_PHY_ID)
1316                 printk("Broadcom BCM5780 Integrated Copper ");
1317
1318         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5752_PHY_ID)
1319                 printk("Broadcom BCM5752 Integrated Copper ");
1320         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
1321                 printk("Broadcom BCM8002 SerDes ");
1322         else if (pDevice->TbiFlags & ENABLE_TBI_FLAG) {
1323                 if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) {
1324                         printk("Broadcom BCM5703 Integrated SerDes ");
1325                 }
1326                 else if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) {
1327                         printk("Broadcom BCM5704 Integrated SerDes ");
1328                 }
1329                 else {
1330                         printk("Agilent HDMP-1636 SerDes ");
1331                 }
1332         }
1333         else {
1334                 printk("Unknown ");
1335         }
1336         printk("transceiver found\n");
1337
1338 #if (LINUX_VERSION_CODE >= 0x20400)
1339         if (scatter_gather[board_idx]) {
1340                 dev->features |= NETIF_F_SG;
1341                 if (pUmDevice->using_dac && !(pDevice->Flags & BCM5788_FLAG))
1342                         dev->features |= NETIF_F_HIGHDMA;
1343         }
1344         if ((pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TX_TCP_CHECKSUM) &&
1345                 tx_checksum[board_idx]) {
1346
1347                 dev->features |= get_csum_flag( pDevice->ChipRevId);
1348         }
1349 #ifdef BCM_VLAN
1350         dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
1351 #endif
1352 #ifdef BCM_TSO
1353         /* On 5714/15/80 chips, Jumbo Frames and TSO cannot both be enabled at
1354            the same time. Since only one of these features can be enable at a
1355            time, we'll enable only Jumbo Frames and disable TSO when the user
1356            tries to enable both.
1357         */
1358         dev->features &= ~NETIF_F_TSO;
1359
1360         if ((pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION) &&
1361             (enable_tso[board_idx])) {
1362                 if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
1363                    (dev->mtu > 1500)) {
1364                         printk(KERN_ALERT "%s: Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
1365                 } else {
1366                         dev->features |= NETIF_F_TSO;
1367                 }
1368         }
1369 #endif
1370         printk(KERN_INFO "%s: Scatter-gather %s, 64-bit DMA %s, Tx Checksum %s, ",
1371                         dev->name,
1372                         (char *) ((dev->features & NETIF_F_SG) ? "ON" : "OFF"),
1373                         (char *) ((dev->features & NETIF_F_HIGHDMA) ? "ON" : "OFF"),
1374                         (char *) ((dev->features & get_csum_flag( pDevice->ChipRevId)) ? "ON" : "OFF"));
1375 #endif
1376         if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) &&
1377                 rx_checksum[board_idx])
1378                 printk("Rx Checksum ON");
1379         else
1380                 printk("Rx Checksum OFF");
1381 #ifdef BCM_VLAN
1382         printk(", 802.1Q VLAN ON");
1383 #endif
1384 #ifdef BCM_TSO
1385         if (dev->features & NETIF_F_TSO) {
1386                 printk(", TSO ON");
1387         }
1388         else
1389 #endif
1390 #ifdef BCM_NAPI_RXPOLL
1391         printk(", NAPI ON");
1392 #endif
1393         printk("\n");
1394
1395         register_reboot_notifier(&bcm5700_reboot_notifier);
1396 #ifdef BCM_TASKLET
1397         tasklet_init(&pUmDevice->tasklet, bcm5700_tasklet,
1398                 (unsigned long) pUmDevice);
1399 #endif
1400         if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) {
1401                 if ((REG_RD(pDevice, PciCfg.DualMacCtrl) &
1402                         T3_DUAL_MAC_CH_CTRL_MASK) == 3) {
1403
1404 printk(KERN_WARNING "%s: Device is configured for Hardware Based Teaming which is not supported with this operating system. Please consult the user diagnostic guide to disable Turbo Teaming.\n", dev->name);
1405                 }
1406         }
1407
1408 #if (LINUX_VERSION_CODE > 0x20605)
1409
1410         if ((pci_dev = pci_get_device(0x1022, 0x700c, NULL)))
1411 #else
1412         if ((pci_dev = pci_find_device(0x1022, 0x700c, NULL)))
1413 #endif
1414         {
1415                 u32 val;
1416
1417                 /* Found AMD 762 North bridge */
1418                 pci_read_config_dword(pci_dev, 0x4c, &val);
1419                 if ((val & 0x02) == 0) {
1420                         pci_write_config_dword(pci_dev, 0x4c, val | 0x02);
1421                         printk(KERN_INFO "%s: Setting AMD762 Northbridge to enable PCI ordering compliance\n", bcm5700_driver);
1422                 }
1423         }
1424
1425 #if (LINUX_VERSION_CODE > 0x20605)
1426
1427         pci_dev_put(pci_dev);
1428
1429 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
1430
1431         if ((pci_dev = pci_get_device(0x1066, 0x0017, NULL))) {
1432                 bcm_msi_chipset_bug = 1;
1433         }
1434         pci_dev_put(pci_dev);
1435 #endif
1436 #endif
1437
1438         return 0;
1439 }
1440
1441
1442 static void __devexit
1443 bcm5700_remove_one (struct pci_dev *pdev)
1444 {
1445         struct net_device *dev = pci_get_drvdata (pdev);
1446         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1447
1448 #ifdef BCM_IOCTL32
1449         atomic_dec(&bcm5700_load_count);
1450         if (atomic_read(&bcm5700_load_count) == 0)
1451                 unregister_ioctl32_conversion(SIOCNICE);
1452 #endif
1453         unregister_netdev(dev);
1454
1455         if (pUmDevice->lm_dev.pMappedMemBase)
1456                 iounmap(pUmDevice->lm_dev.pMappedMemBase);
1457
1458         pci_release_regions(pdev);
1459
1460 #if (LINUX_VERSION_CODE < 0x020600)
1461         kfree(dev);
1462 #else
1463         free_netdev(dev);
1464 #endif
1465
1466         pci_set_drvdata(pdev, NULL);
1467
1468 }
1469
1470 int b57_test_intr(UM_DEVICE_BLOCK *pUmDevice);
1471  
1472 #ifdef BCM_WL_EMULATOR
1473 /* new transmit callback  */ 
1474 static int bcm5700emu_start_xmit(struct sk_buff *skb, struct net_device *dev);
1475 /* keep track of the 2 gige devices */ 
1476 static PLM_DEVICE_BLOCK pDev1;
1477 static PLM_DEVICE_BLOCK pDev2;
1478
1479 static void 
1480 bcm5700emu_open(struct net_device *dev)
1481 {
1482         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1483         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;       
1484         static int instance = 0;
1485         static char *wlemu_if = NULL;
1486         char *wlemu_mode = NULL;
1487         //int wlemu_idx = 0;
1488         static int rx_enable = 0;
1489         static int tx_enable = 0;
1490         
1491         /* which interface is the emulator ? */
1492         if(instance == 0) {
1493                 wlemu_if = nvram_get("wlemu_if");
1494                 /* do we emulate rx, tx or both  */
1495                 wlemu_mode = nvram_get("wlemu_mode");
1496                 if(wlemu_mode) {
1497                         if (!strcmp(wlemu_mode,"rx"))
1498                         {
1499                                 rx_enable = 1;
1500                         } 
1501                         else if (!strcmp(wlemu_mode,"tx"))
1502                         {
1503                                 
1504                                 tx_enable = 1;
1505                                 
1506                         }
1507                         else if (!strcmp(wlemu_mode,"rx_tx"))
1508                         {
1509                                 
1510                                 rx_enable = 1;
1511                                 tx_enable = 1;
1512                         }
1513                 }
1514         }
1515         
1516         instance++;
1517
1518         /* The context is used for accessing the OSL for emulating devices */
1519         pDevice->wlc = NULL;
1520         
1521         /* determines if this device is an emulator */
1522         pDevice->wl_emulate_rx = 0;
1523         pDevice->wl_emulate_tx = 0;
1524
1525         if(wlemu_if && !strcmp(dev->name,wlemu_if))
1526         {
1527                 /* create an emulator context. */
1528                 pDevice->wlc = (void *)wlcemu_wlccreate((void *)dev);
1529                 B57_INFO(("Using %s for wl emulation \n", dev->name));
1530                 if(rx_enable)
1531                 {
1532                         B57_INFO(("Enabling wl RX emulation \n"));
1533                         pDevice->wl_emulate_rx = 1;
1534                 }
1535                 /* re-direct transmit callback to emulator */
1536                 if(tx_enable)
1537                 {
1538                         pDevice->wl_emulate_tx = 1;
1539                         dev->hard_start_xmit = bcm5700emu_start_xmit;
1540                         B57_INFO(("Enabling wl TX emulation \n"));
1541                 }  
1542         }
1543         /* for debug access to configured devices only */
1544         if(instance == 1)
1545                 pDev1 = pDevice;
1546         else if (instance == 2)
1547                 pDev2 = pDevice;        
1548 }       
1549
1550 /* Public API to get current emulation info */
1551 int bcm5700emu_get_info(char *buf)
1552 {
1553         int len = 0;
1554         PLM_DEVICE_BLOCK p;
1555         
1556         /* look for an emulating device */
1557         if(pDev1->wlc) {
1558                 p = pDev1;
1559                 len += sprintf(buf+len,"emulation device : eth0\n");
1560         }
1561         else if (pDev2->wlc) {
1562                 p = pDev2;
1563                 len += sprintf(buf+len,"emulation device : eth1\n");
1564         }
1565         else {
1566                 len += sprintf(buf+len,"emulation not activated\n");
1567                 return len;
1568         }
1569         if(p->wl_emulate_rx)
1570                 len += sprintf(buf+len,"RX emulation enabled\n");
1571         else 
1572                 len += sprintf(buf+len,"RX emulation disabled\n");
1573         if(p->wl_emulate_tx)
1574                 len += sprintf(buf+len,"TX emulation enabled\n");
1575         else 
1576                 len += sprintf(buf+len,"TX emulation disabled\n");
1577         return len;
1578         
1579
1580
1581
1582 /* Public API to access the bcm5700_start_xmit callback */
1583
1584 int 
1585 bcm5700emu_forward_xmit(struct sk_buff *skb, struct net_device *dev)
1586 {
1587   return bcm5700_start_xmit(skb, dev);
1588 }
1589
1590
1591 /* hook to kernel txmit callback */
1592 STATIC int
1593 bcm5700emu_start_xmit(struct sk_buff *skb, struct net_device *dev)
1594 {
1595
1596   PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1597   PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
1598   return wlcemu_start_xmit(skb,pDevice->wlc);
1599 }       
1600          
1601 #endif /* BCM_WL_EMULATOR */
1602  
1603 int
1604 bcm5700_open(struct net_device *dev)
1605 {
1606         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1607         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
1608         int rc;
1609
1610         if (pUmDevice->suspended){
1611             return -EAGAIN;
1612         }
1613
1614 #ifdef BCM_WL_EMULATOR
1615         bcm5700emu_open(dev);
1616 #endif
1617
1618         /* delay for 6 seconds */
1619         pUmDevice->delayed_link_ind = (6 * HZ) / pUmDevice->timer_interval;
1620
1621 #ifdef BCM_INT_COAL
1622 #ifndef BCM_NAPI_RXPOLL
1623         pUmDevice->adaptive_expiry = HZ / pUmDevice->timer_interval;
1624 #endif
1625 #endif
1626
1627 #ifdef INCLUDE_TBI_SUPPORT
1628         if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
1629                 (pDevice->TbiFlags & TBI_POLLING_FLAGS)) {
1630                 pUmDevice->poll_tbi_interval = HZ / pUmDevice->timer_interval;
1631                 if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) {
1632                         pUmDevice->poll_tbi_interval /= 4;
1633                 }
1634                 pUmDevice->poll_tbi_expiry = pUmDevice->poll_tbi_interval;
1635         }
1636 #endif
1637         /* set this timer for 2 seconds */
1638         pUmDevice->asf_heartbeat = (2 * HZ) / pUmDevice->timer_interval;
1639
1640 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
1641
1642
1643         if ( (  (T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId) ) &&
1644                 (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5714_A0 ) &&
1645                 (T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5750_AX ) &&
1646                 (T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5750_BX ) ) &&
1647                 !bcm_msi_chipset_bug    ){
1648
1649                 if (disable_msi[pUmDevice->index]==1){
1650                         /* do nothing-it's not turned on */
1651                 }else{
1652                         pDevice->Flags |= USING_MSI_FLAG;
1653
1654                         REG_WR(pDevice, Msi.Mode,  2 );
1655
1656                         rc = pci_enable_msi(pUmDevice->pdev);
1657
1658                         if(rc!=0){
1659                                 pDevice->Flags &= ~ USING_MSI_FLAG;
1660                                 REG_WR(pDevice, Msi.Mode,  1 );
1661                         }
1662                 }
1663         }
1664
1665
1666 #endif
1667
1668         if ((rc= request_irq(pUmDevice->pdev->irq, &bcm5700_interrupt, SA_SHIRQ, dev->name, dev)))
1669         {
1670
1671 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
1672
1673                 if(pDevice->Flags & USING_MSI_FLAG)  {
1674
1675                         pci_disable_msi(pUmDevice->pdev);
1676                         pDevice->Flags &= ~USING_MSI_FLAG;
1677                         REG_WR(pDevice, Msi.Mode,  1 );
1678
1679                 }
1680 #endif
1681                 return rc;
1682         }
1683
1684         pUmDevice->opened = 1;
1685         if (LM_InitializeAdapter(pDevice) != LM_STATUS_SUCCESS) {
1686                 pUmDevice->opened = 0;
1687                 free_irq(dev->irq, dev);
1688                 bcm5700_freemem(dev);
1689                 return -EAGAIN;
1690         }
1691
1692         bcm5700_set_vlan_mode(pUmDevice);
1693         bcm5700_init_counters(pUmDevice);
1694
1695         if (pDevice->Flags & UNDI_FIX_FLAG) {
1696                 printk(KERN_INFO "%s: Using indirect register access\n", dev->name);
1697         }
1698
1699         if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6))
1700         {
1701                 /* Do not use invalid eth addrs: any multicast & all zeros */
1702                 if( is_valid_ether_addr(dev->dev_addr) ){
1703                         LM_SetMacAddress(pDevice, dev->dev_addr);
1704                 }
1705                 else
1706                 {
1707                         printk(KERN_INFO "%s: Invalid administered node address\n",dev->name);
1708                         memcpy(dev->dev_addr, pDevice->NodeAddress, 6);
1709                 }
1710         }
1711
1712         if (tigon3_debug > 1)
1713                 printk(KERN_DEBUG "%s: tigon3_open() irq %d.\n", dev->name, dev->irq);
1714
1715         QQ_InitQueue(&pUmDevice->rx_out_of_buf_q.Container,
1716         MAX_RX_PACKET_DESC_COUNT);
1717
1718
1719 #if (LINUX_VERSION_CODE < 0x020300)
1720         MOD_INC_USE_COUNT;
1721 #endif
1722
1723         atomic_set(&pUmDevice->intr_sem, 0);
1724
1725         LM_EnableInterrupt(pDevice);
1726
1727 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
1728
1729         if (pDevice->Flags & USING_MSI_FLAG){
1730
1731                 /* int test to check support on older machines */
1732                 if (b57_test_intr(pUmDevice) != 1) {
1733
1734                         LM_DisableInterrupt(pDevice);
1735                         free_irq(pUmDevice->pdev->irq, dev);
1736                         pci_disable_msi(pUmDevice->pdev);
1737                         REG_WR(pDevice, Msi.Mode,  1 );
1738                         pDevice->Flags &= ~USING_MSI_FLAG;
1739
1740                         rc = LM_ResetAdapter(pDevice);
1741 printk(KERN_ALERT " The MSI support in this system is not functional.\n");
1742
1743                         if (rc == LM_STATUS_SUCCESS)
1744                                 rc = 0;
1745                         else
1746                                 rc = -ENODEV;
1747
1748                         if(rc == 0){
1749                                 rc = request_irq(pUmDevice->pdev->irq, &bcm5700_interrupt,
1750                                             SA_SHIRQ, dev->name, dev);
1751                         }
1752
1753                         if(rc){
1754                                 LM_Halt(pDevice);
1755                                 bcm5700_freemem(dev);
1756                                 pUmDevice->opened = 0;
1757                                 return rc;
1758                         }
1759
1760
1761                         pDevice->InitDone = TRUE;
1762                         atomic_set(&pUmDevice->intr_sem, 0);
1763                         LM_EnableInterrupt(pDevice);
1764                 }
1765         }
1766 #endif
1767
1768         init_timer(&pUmDevice->timer);
1769         pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
1770         pUmDevice->timer.data = (unsigned long)dev;
1771         pUmDevice->timer.function = &bcm5700_timer;
1772         add_timer(&pUmDevice->timer);
1773
1774         if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) {
1775                 init_timer(&pUmDevice->statstimer);
1776                 pUmDevice->statstimer.expires = RUN_AT(pUmDevice->statstimer_interval);
1777                 pUmDevice->statstimer.data = (unsigned long)dev;
1778                 pUmDevice->statstimer.function = &bcm5700_stats_timer;
1779                 add_timer(&pUmDevice->statstimer);
1780         }
1781
1782         if(pDevice->Flags & USING_MSI_FLAG)
1783                 printk(KERN_INFO "%s: Using Message Signaled Interrupt (MSI)  \n", dev->name);
1784         else
1785                 printk(KERN_INFO "%s: Using PCI INTX interrupt \n", dev->name);
1786
1787         netif_start_queue(dev);
1788
1789         return 0;
1790 }
1791
1792
1793 STATIC void
1794 bcm5700_stats_timer(unsigned long data)
1795 {
1796         struct net_device *dev = (struct net_device *)data;
1797         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1798         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
1799         unsigned long flags = 0;
1800
1801         if (!pUmDevice->opened)
1802                 return;
1803
1804         if (!atomic_read(&pUmDevice->intr_sem) &&
1805             !pUmDevice->suspended              &&
1806            (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE)) {
1807                 BCM5700_LOCK(pUmDevice, flags);
1808                 LM_GetStats(pDevice);
1809                 BCM5700_UNLOCK(pUmDevice, flags);
1810         }
1811
1812         pUmDevice->statstimer.expires = RUN_AT(pUmDevice->statstimer_interval);
1813
1814         add_timer(&pUmDevice->statstimer);
1815 }
1816
1817
1818 STATIC void
1819 bcm5700_timer(unsigned long data)
1820 {
1821         struct net_device *dev = (struct net_device *)data;
1822         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1823         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
1824         unsigned long flags = 0;
1825         LM_UINT32 value32;
1826
1827         if (!pUmDevice->opened)
1828                 return;
1829
1830         /* BCM4785: Flush posted writes from GbE to host memory. */
1831         if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
1832                 REG_RD(pDevice, HostCoalesce.Mode);
1833
1834         if (atomic_read(&pUmDevice->intr_sem) || pUmDevice->suspended) {
1835                 pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
1836                 add_timer(&pUmDevice->timer);
1837                 return;
1838         }
1839
1840 #ifdef INCLUDE_TBI_SUPPORT
1841         if ((pDevice->TbiFlags & TBI_POLLING_FLAGS) &&
1842                 (--pUmDevice->poll_tbi_expiry <= 0)) {
1843
1844                 BCM5700_PHY_LOCK(pUmDevice, flags);
1845                 value32 = REG_RD(pDevice, MacCtrl.Status);
1846                 if (((pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) &&
1847                         ((value32 & (MAC_STATUS_LINK_STATE_CHANGED |
1848                                 MAC_STATUS_CFG_CHANGED)) ||
1849                         !(value32 & MAC_STATUS_PCS_SYNCED)))
1850                         ||
1851                         ((pDevice->LinkStatus != LM_STATUS_LINK_ACTIVE) &&
1852                         (value32 & (MAC_STATUS_PCS_SYNCED |
1853                                 MAC_STATUS_SIGNAL_DETECTED))))
1854                 {
1855                         LM_SetupPhy(pDevice);
1856                 }
1857                 BCM5700_PHY_UNLOCK(pUmDevice, flags);
1858                 pUmDevice->poll_tbi_expiry = pUmDevice->poll_tbi_interval;
1859
1860         }
1861 #endif
1862
1863         if (pUmDevice->delayed_link_ind > 0) {
1864                 if (pUmDevice->delayed_link_ind == 1)
1865                         MM_IndicateStatus(pDevice, pDevice->LinkStatus);
1866                 else
1867                         pUmDevice->delayed_link_ind--;
1868         }
1869
1870         if (pUmDevice->crc_counter_expiry > 0)
1871                 pUmDevice->crc_counter_expiry--;
1872
1873         if (!pUmDevice->interrupt) {
1874                 if (!(pDevice->Flags & USE_TAGGED_STATUS_FLAG)) {
1875                         BCM5700_LOCK(pUmDevice, flags);
1876                         if (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
1877                                 /* This will generate an interrupt */
1878                                 REG_WR(pDevice, Grc.LocalCtrl,
1879                                         pDevice->GrcLocalCtrl |
1880                                         GRC_MISC_LOCAL_CTRL_SET_INT);
1881                         }
1882                         else {
1883                                 REG_WR(pDevice, HostCoalesce.Mode,
1884                                         pDevice->CoalesceMode |
1885                                         HOST_COALESCE_ENABLE |
1886                                         HOST_COALESCE_NOW);
1887                         }
1888                         if (!(REG_RD(pDevice, DmaWrite.Mode) &
1889                                 DMA_WRITE_MODE_ENABLE)) {
1890                                 BCM5700_UNLOCK(pUmDevice, flags);
1891                                 bcm5700_reset(dev);
1892                         }
1893                         else {
1894                                 BCM5700_UNLOCK(pUmDevice, flags);
1895                         }
1896                         if (pUmDevice->tx_queued) {
1897                                 pUmDevice->tx_queued = 0;
1898                                 netif_wake_queue(dev);
1899                         }
1900                 }
1901 #if (LINUX_VERSION_CODE < 0x02032b)
1902                 if ((QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) !=
1903                         pDevice->TxPacketDescCnt) &&
1904                         ((jiffies - dev->trans_start) > TX_TIMEOUT)) {
1905
1906                         printk(KERN_WARNING "%s: Tx hung\n", dev->name);
1907                         bcm5700_reset(dev);
1908                 }
1909 #endif
1910         }
1911 #ifdef BCM_INT_COAL
1912 #ifndef BCM_NAPI_RXPOLL
1913         if (pUmDevice->adaptive_coalesce) {
1914                 pUmDevice->adaptive_expiry--;
1915                 if (pUmDevice->adaptive_expiry == 0) {
1916                         pUmDevice->adaptive_expiry = HZ /
1917                                 pUmDevice->timer_interval;
1918                         bcm5700_adapt_coalesce(pUmDevice);
1919                 }
1920         }
1921 #endif
1922 #endif
1923         if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container) >
1924                 (unsigned int) pUmDevice->rx_buf_repl_panic_thresh) {
1925                 /* Generate interrupt and let isr allocate buffers */
1926                 REG_WR(pDevice, HostCoalesce.Mode, pDevice->CoalesceMode |
1927                         HOST_COALESCE_ENABLE | HOST_COALESCE_NOW);
1928         }
1929
1930 #ifdef BCM_ASF
1931         if (pDevice->AsfFlags & ASF_ENABLED) {
1932                 pUmDevice->asf_heartbeat--;
1933                 if (pUmDevice->asf_heartbeat == 0) {
1934                         if( (pDevice->Flags & UNDI_FIX_FLAG) || 
1935                             (pDevice->Flags & ENABLE_PCIX_FIX_FLAG)) {
1936                                 MEM_WR_OFFSET(pDevice, T3_CMD_MAILBOX,
1937                                         T3_CMD_NICDRV_ALIVE2);
1938                                 MEM_WR_OFFSET(pDevice, T3_CMD_LENGTH_MAILBOX,
1939                                         4);
1940                                 MEM_WR_OFFSET(pDevice, T3_CMD_DATA_MAILBOX, 5);
1941                         } else {
1942                                 LM_RegWr(pDevice, 
1943                                          (T3_NIC_MBUF_POOL_ADDR + 
1944                                           T3_CMD_MAILBOX), 
1945                                          T3_CMD_NICDRV_ALIVE2, 1);
1946                                 LM_RegWr(pDevice, 
1947                                          (T3_NIC_MBUF_POOL_ADDR + 
1948                                           T3_CMD_LENGTH_MAILBOX),4,1);
1949                                 LM_RegWr(pDevice, 
1950                                          (T3_NIC_MBUF_POOL_ADDR + 
1951                                           T3_CMD_DATA_MAILBOX),5,1);
1952                         }
1953
1954                         value32 = REG_RD(pDevice, Grc.RxCpuEvent);
1955                         REG_WR(pDevice, Grc.RxCpuEvent, value32 | BIT_14);
1956                         pUmDevice->asf_heartbeat = (2 * HZ) /
1957                                 pUmDevice->timer_interval;
1958                 }
1959         }
1960 #endif
1961
1962         if (pDevice->PhyFlags & PHY_IS_FIBER){
1963                 BCM5700_PHY_LOCK(pUmDevice, flags);
1964                 LM_5714_FamFiberCheckLink(pDevice);
1965                 BCM5700_PHY_UNLOCK(pUmDevice, flags);
1966         }
1967
1968         pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
1969         add_timer(&pUmDevice->timer);
1970 }
1971
1972 STATIC int
1973 bcm5700_init_counters(PUM_DEVICE_BLOCK pUmDevice)
1974 {
1975 #ifdef BCM_INT_COAL
1976 #ifndef BCM_NAPI_RXPOLL
1977         LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
1978
1979         pUmDevice->rx_curr_coalesce_frames = pDevice->RxMaxCoalescedFrames;
1980         pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks;
1981         pUmDevice->tx_curr_coalesce_frames = pDevice->TxMaxCoalescedFrames;
1982         pUmDevice->rx_last_cnt = 0;
1983         pUmDevice->tx_last_cnt = 0;
1984 #endif
1985 #endif
1986         pUmDevice->phy_crc_count = 0;
1987 #if TIGON3_DEBUG
1988         pUmDevice->tx_zc_count = 0;
1989         pUmDevice->tx_chksum_count = 0;
1990         pUmDevice->tx_himem_count = 0;
1991         pUmDevice->rx_good_chksum_count = 0;
1992         pUmDevice->rx_bad_chksum_count = 0;
1993 #endif
1994 #ifdef BCM_TSO
1995         pUmDevice->tso_pkt_count = 0;
1996 #endif
1997         return 0;
1998 }
1999
2000 #ifdef BCM_INT_COAL
2001 #ifndef BCM_NAPI_RXPOLL
2002 STATIC int
2003 bcm5700_do_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice,
2004         int rx_frames, int rx_ticks, int tx_frames, int rx_frames_intr)
2005 {
2006         unsigned long flags = 0;
2007         LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2008
2009         if (pUmDevice->do_global_lock) {
2010                 if (spin_is_locked(&pUmDevice->global_lock))
2011                         return 0;
2012                 spin_lock_irqsave(&pUmDevice->global_lock, flags);
2013         }
2014         pUmDevice->rx_curr_coalesce_frames = rx_frames;
2015         pUmDevice->rx_curr_coalesce_ticks = rx_ticks;
2016         pUmDevice->tx_curr_coalesce_frames = tx_frames;
2017         pUmDevice->rx_curr_coalesce_frames_intr = rx_frames_intr;
2018         REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFrames, rx_frames);
2019
2020         REG_WR(pDevice, HostCoalesce.RxCoalescingTicks, rx_ticks);
2021
2022         REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFrames, tx_frames);
2023
2024         REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt,
2025                 rx_frames_intr);
2026
2027         BCM5700_UNLOCK(pUmDevice, flags);
2028         return 0;
2029 }
2030
2031 STATIC int
2032 bcm5700_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice)
2033 {
2034         PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
2035         uint rx_curr_cnt, tx_curr_cnt, rx_delta, tx_delta, total_delta;
2036
2037         rx_curr_cnt = pDevice->pStatsBlkVirt->ifHCInUcastPkts.Low;
2038         tx_curr_cnt = pDevice->pStatsBlkVirt->ifHCOutUcastPkts.Low;
2039         if ((rx_curr_cnt <= pUmDevice->rx_last_cnt) ||
2040                 (tx_curr_cnt < pUmDevice->tx_last_cnt)) {
2041
2042                 /* skip if there is counter rollover */
2043                 pUmDevice->rx_last_cnt = rx_curr_cnt;
2044                 pUmDevice->tx_last_cnt = tx_curr_cnt;
2045                 return 0;
2046         }
2047
2048         rx_delta = rx_curr_cnt - pUmDevice->rx_last_cnt;
2049         tx_delta = tx_curr_cnt - pUmDevice->tx_last_cnt;
2050         total_delta = (((rx_delta + rx_delta) + tx_delta) / 3) << 1;
2051
2052         pUmDevice->rx_last_cnt = rx_curr_cnt;
2053         pUmDevice->tx_last_cnt = tx_curr_cnt;
2054
2055         if (total_delta < ADAPTIVE_LO_PKT_THRESH) {
2056                 if (pUmDevice->rx_curr_coalesce_frames !=
2057                         ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES) {
2058
2059                         bcm5700_do_adapt_coalesce(pUmDevice,
2060                                 ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES,
2061                                 ADAPTIVE_LO_RX_COALESCING_TICKS,
2062                                 ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES,
2063                                 ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES_DURING_INT);
2064                 }
2065         }
2066         else if (total_delta < ADAPTIVE_HI_PKT_THRESH) {
2067                 if (pUmDevice->rx_curr_coalesce_frames !=
2068                         DEFAULT_RX_MAX_COALESCED_FRAMES) {
2069
2070                         bcm5700_do_adapt_coalesce(pUmDevice,
2071                                 DEFAULT_RX_MAX_COALESCED_FRAMES,
2072                                 DEFAULT_RX_COALESCING_TICKS,
2073                                 DEFAULT_TX_MAX_COALESCED_FRAMES,
2074                                 DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT);
2075                 }
2076         }
2077         else {
2078                 if (pUmDevice->rx_curr_coalesce_frames !=
2079                         ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES) {
2080
2081                         bcm5700_do_adapt_coalesce(pUmDevice,
2082                                 ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES,
2083                                 ADAPTIVE_HI_RX_COALESCING_TICKS,
2084                                 ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES,
2085                                 ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES_DURING_INT);
2086                 }
2087         }
2088         return 0;
2089 }
2090 #endif
2091 #endif
2092
2093 STATIC void
2094 bcm5700_reset(struct net_device *dev)
2095 {
2096         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2097         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
2098         unsigned long flags;
2099
2100 #ifdef BCM_TSO
2101
2102         if( (dev->features & NETIF_F_TSO) &&
2103                 (pUmDevice->tx_full) )     {
2104
2105                 dev->features &= ~NETIF_F_TSO;
2106         }
2107 #endif
2108
2109         netif_stop_queue(dev);
2110         bcm5700_intr_off(pUmDevice);
2111         BCM5700_PHY_LOCK(pUmDevice, flags);
2112         LM_ResetAdapter(pDevice);
2113         pDevice->InitDone = TRUE;
2114         bcm5700_do_rx_mode(dev);
2115         bcm5700_set_vlan_mode(pUmDevice);
2116         bcm5700_init_counters(pUmDevice);
2117         if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) {
2118                 LM_SetMacAddress(pDevice, dev->dev_addr);
2119         }
2120         BCM5700_PHY_UNLOCK(pUmDevice, flags);
2121         atomic_set(&pUmDevice->intr_sem, 1);
2122         bcm5700_intr_on(pUmDevice);
2123         netif_wake_queue(dev);
2124 }
2125
2126 STATIC void
2127 bcm5700_set_vlan_mode(UM_DEVICE_BLOCK *pUmDevice)
2128 {
2129         LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2130         LM_UINT32 ReceiveMask = pDevice->ReceiveMask;
2131         int vlan_tag_mode = pUmDevice->vlan_tag_mode;
2132
2133         if (vlan_tag_mode == VLAN_TAG_MODE_AUTO_STRIP) {
2134                 if (pDevice->AsfFlags & ASF_ENABLED) {
2135                         vlan_tag_mode = VLAN_TAG_MODE_FORCED_STRIP;
2136                 }
2137                 else {
2138                         vlan_tag_mode = VLAN_TAG_MODE_NORMAL_STRIP;
2139                 }
2140         }
2141         if (vlan_tag_mode == VLAN_TAG_MODE_NORMAL_STRIP) {
2142                 ReceiveMask |= LM_KEEP_VLAN_TAG;
2143 #ifdef BCM_VLAN
2144                 if (pUmDevice->vlgrp)
2145                         ReceiveMask &= ~LM_KEEP_VLAN_TAG;
2146 #endif
2147         }
2148         else if (vlan_tag_mode == VLAN_TAG_MODE_FORCED_STRIP) {
2149                 ReceiveMask &= ~LM_KEEP_VLAN_TAG;
2150         }
2151         if (ReceiveMask != pDevice->ReceiveMask)
2152         {
2153                 LM_SetReceiveMask(pDevice, ReceiveMask);
2154         }
2155 }
2156
2157 static void
2158 bcm5700_poll_wait(UM_DEVICE_BLOCK *pUmDevice)
2159 {
2160 #ifdef BCM_NAPI_RXPOLL
2161         while (pUmDevice->lm_dev.RxPoll) {
2162                 current->state = TASK_INTERRUPTIBLE;
2163                 schedule_timeout(1);
2164         }
2165 #endif
2166 }
2167
2168
2169 #ifdef BCM_VLAN
2170 STATIC void
2171 bcm5700_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
2172 {
2173         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
2174
2175         bcm5700_intr_off(pUmDevice);
2176         bcm5700_poll_wait(pUmDevice);
2177         pUmDevice->vlgrp = vlgrp;
2178         bcm5700_set_vlan_mode(pUmDevice);
2179         bcm5700_intr_on(pUmDevice);
2180 }
2181
2182 STATIC void
2183 bcm5700_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
2184 {
2185         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
2186
2187         bcm5700_intr_off(pUmDevice);
2188         bcm5700_poll_wait(pUmDevice);
2189         if (pUmDevice->vlgrp) {
2190                 pUmDevice->vlgrp->vlan_devices[vid] = NULL;
2191         }
2192         bcm5700_intr_on(pUmDevice);
2193 }
2194 #endif
2195
2196 STATIC int
2197 bcm5700_start_xmit(struct sk_buff *skb, struct net_device *dev)
2198 {
2199         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2200         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
2201         PLM_PACKET pPacket;
2202         PUM_PACKET pUmPacket;
2203         unsigned long flags = 0;
2204         int frag_no;
2205 #ifdef BCM_TSO
2206         LM_UINT32 mss = 0 ;
2207         uint16_t ip_tcp_len, tcp_opt_len, tcp_seg_flags;
2208 #endif
2209
2210         if ((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) ||
2211                 !pDevice->InitDone || pUmDevice->suspended)
2212         {
2213                 dev_kfree_skb(skb);
2214                 return 0;
2215         }
2216
2217 #if (LINUX_VERSION_CODE < 0x02032b)
2218         if (test_and_set_bit(0, &dev->tbusy)) {
2219             return 1;
2220         }
2221 #endif
2222
2223         if (pUmDevice->do_global_lock && pUmDevice->interrupt) {
2224                 netif_stop_queue(dev);
2225                 pUmDevice->tx_queued = 1;
2226                 if (!pUmDevice->interrupt) {
2227                         netif_wake_queue(dev);
2228                         pUmDevice->tx_queued = 0;
2229                 }
2230             return 1;
2231         }
2232
2233         pPacket = (PLM_PACKET)
2234                 QQ_PopHead(&pDevice->TxPacketFreeQ.Container);
2235         if (pPacket == 0) {
2236                 netif_stop_queue(dev);
2237                 pUmDevice->tx_full = 1;
2238                 if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container)) {
2239                         netif_wake_queue(dev);
2240                         pUmDevice->tx_full = 0;
2241                 }
2242             return 1;
2243         }
2244         pUmPacket = (PUM_PACKET) pPacket;
2245         pUmPacket->skbuff = skb;
2246         pUmDevice->stats.tx_bytes += skb->len; 
2247
2248         if (skb->ip_summed == CHECKSUM_HW) {
2249                 pPacket->Flags = SND_BD_FLAG_TCP_UDP_CKSUM;
2250 #if TIGON3_DEBUG
2251                 pUmDevice->tx_chksum_count++;
2252 #endif
2253         }
2254         else {
2255                 pPacket->Flags = 0;
2256         }
2257 #if MAX_SKB_FRAGS
2258         frag_no = skb_shinfo(skb)->nr_frags;
2259 #else
2260         frag_no = 0;
2261 #endif
2262         if (atomic_read(&pDevice->SendBdLeft) < (frag_no + 1)) {
2263                 netif_stop_queue(dev);
2264                 pUmDevice->tx_full = 1;
2265                 QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
2266                 if (atomic_read(&pDevice->SendBdLeft) >= (frag_no + 1)) {
2267                         netif_wake_queue(dev);
2268                         pUmDevice->tx_full = 0;
2269                 }
2270                 return 1;
2271         }
2272
2273         pPacket->u.Tx.FragCount = frag_no + 1;
2274 #if TIGON3_DEBUG
2275         if (pPacket->u.Tx.FragCount > 1)
2276                 pUmDevice->tx_zc_count++;
2277 #endif
2278
2279 #ifdef BCM_VLAN
2280         if (pUmDevice->vlgrp && vlan_tx_tag_present(skb)) {
2281                 pPacket->VlanTag = vlan_tx_tag_get(skb);
2282                 pPacket->Flags |= SND_BD_FLAG_VLAN_TAG;
2283         }
2284 #endif
2285
2286 #ifdef BCM_TSO
2287         if ((mss = (LM_UINT32) skb_shinfo(skb)->tso_size) &&
2288                 (skb->len > pDevice->TxMtu)) {
2289
2290 #if (LINUX_VERSION_CODE >= 0x02060c)
2291
2292                 if (skb_header_cloned(skb) &&
2293                         pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
2294
2295                         dev_kfree_skb(skb);
2296                         return 0;
2297                 }
2298 #endif
2299                 pUmDevice->tso_pkt_count++;
2300
2301                 pPacket->Flags |= SND_BD_FLAG_CPU_PRE_DMA |
2302                         SND_BD_FLAG_CPU_POST_DMA;
2303
2304                 tcp_opt_len = 0;
2305                 if (skb->h.th->doff > 5) {
2306                         tcp_opt_len = (skb->h.th->doff - 5) << 2;
2307                 }
2308                 ip_tcp_len = (skb->nh.iph->ihl << 2) + sizeof(struct tcphdr);
2309                 skb->nh.iph->check = 0;
2310
2311                 if ( T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId) ){
2312                         skb->h.th->check = 0;
2313                         pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM;
2314                 }
2315                 else {
2316                         skb->h.th->check = ~csum_tcpudp_magic(
2317                                 skb->nh.iph->saddr, skb->nh.iph->daddr,
2318                                 0, IPPROTO_TCP, 0);
2319                 }
2320
2321                 skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
2322                 tcp_seg_flags = 0;
2323
2324                 if (tcp_opt_len || (skb->nh.iph->ihl > 5)) {
2325                         if ( T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId) ){
2326                                 tcp_seg_flags =
2327                                         ((skb->nh.iph->ihl - 5) +
2328                                         (tcp_opt_len >> 2)) << 11;
2329                         }
2330                         else {
2331                                 pPacket->Flags |=
2332                                         ((skb->nh.iph->ihl - 5) +
2333                                         (tcp_opt_len >> 2)) << 12;
2334                         }
2335                 }
2336                 pPacket->u.Tx.MaxSegmentSize = mss | tcp_seg_flags;
2337         }
2338         else
2339         {
2340                 pPacket->u.Tx.MaxSegmentSize = 0;
2341         }
2342 #endif
2343         BCM5700_LOCK(pUmDevice, flags);
2344         LM_SendPacket(pDevice, pPacket);
2345         BCM5700_UNLOCK(pUmDevice, flags);
2346
2347 #if (LINUX_VERSION_CODE < 0x02032b)
2348         netif_wake_queue(dev);
2349 #endif
2350         dev->trans_start = jiffies;
2351
2352
2353         return 0;
2354 }
2355
2356 #ifdef BCM_NAPI_RXPOLL
2357 STATIC int
2358 bcm5700_poll(struct net_device *dev, int *budget)
2359 {
2360         int orig_budget = *budget;
2361         int work_done;
2362         UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) dev->priv;
2363         LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2364         unsigned long flags = 0;
2365         LM_UINT32 tag;
2366
2367         if (orig_budget > dev->quota)
2368                 orig_budget = dev->quota;
2369
2370         BCM5700_LOCK(pUmDevice, flags);
2371         /* BCM4785: Flush posted writes from GbE to host memory. */
2372         if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
2373                 REG_RD(pDevice, HostCoalesce.Mode);
2374         work_done = LM_ServiceRxPoll(pDevice, orig_budget);
2375         *budget -= work_done;
2376         dev->quota -= work_done;
2377
2378         if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
2379                 replenish_rx_buffers(pUmDevice, 0);
2380         }
2381         BCM5700_UNLOCK(pUmDevice, flags);
2382         if (work_done) {
2383                 MM_IndicateRxPackets(pDevice);
2384                 BCM5700_LOCK(pUmDevice, flags);
2385                 LM_QueueRxPackets(pDevice);
2386                 BCM5700_UNLOCK(pUmDevice, flags);
2387         }
2388         if ((work_done < orig_budget) || atomic_read(&pUmDevice->intr_sem) ||
2389                 pUmDevice->suspended) {
2390
2391                 netif_rx_complete(dev);
2392                 BCM5700_LOCK(pUmDevice, flags);
2393                 REG_WR(pDevice, Grc.Mode, pDevice->GrcMode);
2394                 pDevice->RxPoll = FALSE;
2395                 if (pDevice->RxPoll) {
2396                         BCM5700_UNLOCK(pUmDevice, flags);
2397                         return 0;
2398                 }
2399                 /* Take care of possible missed rx interrupts */
2400                 REG_RD_BACK(pDevice, Grc.Mode); /* flush the register write */
2401                 tag = pDevice->pStatusBlkVirt->StatusTag;
2402                 if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
2403                         (pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx !=
2404                         pDevice->RcvRetConIdx)) {
2405
2406                         REG_WR(pDevice, HostCoalesce.Mode,
2407                                 pDevice->CoalesceMode | HOST_COALESCE_ENABLE |
2408                                 HOST_COALESCE_NOW);
2409                 }
2410                 /* If a new status block is pending in the WDMA state machine */
2411                 /* before the register write to enable the rx interrupt,      */
2412                 /* the new status block may DMA with no interrupt. In this    */
2413                 /* scenario, the tag read above will be older than the tag in */
2414                 /* the pending status block and writing the older tag will    */
2415                 /* cause interrupt to be generated.                           */
2416                 else if (pDevice->Flags & USE_TAGGED_STATUS_FLAG) {
2417                         MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low,
2418                                 tag << 24);
2419                         /* Make sure we service tx in case some tx interrupts */
2420                         /* are cleared */
2421                         if (atomic_read(&pDevice->SendBdLeft) <
2422                                 (T3_SEND_RCB_ENTRY_COUNT / 2)) {
2423                                 REG_WR(pDevice, HostCoalesce.Mode,
2424                                         pDevice->CoalesceMode |
2425                                         HOST_COALESCE_ENABLE |
2426                                         HOST_COALESCE_NOW);
2427                         }
2428                 }
2429                 BCM5700_UNLOCK(pUmDevice, flags);
2430                 return 0;
2431         }
2432         return 1;
2433 }
2434 #endif /* BCM_NAPI_RXPOLL */
2435
2436 STATIC irqreturn_t
2437 bcm5700_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
2438 {
2439         struct net_device *dev = (struct net_device *)dev_instance;
2440         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2441         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
2442         LM_UINT32 oldtag, newtag;
2443         int i, max_intr_loop;
2444 #ifdef BCM_TASKLET
2445         int repl_buf_count;
2446 #endif
2447         unsigned int handled = 1;
2448
2449         if (!pDevice->InitDone) {
2450                 handled = 0;
2451                 return IRQ_RETVAL(handled);
2452         }
2453
2454         bcm5700_intr_lock(pUmDevice);
2455         if (atomic_read(&pUmDevice->intr_sem)) {
2456                 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
2457                 bcm5700_intr_unlock(pUmDevice);
2458                 handled = 0;
2459                 return IRQ_RETVAL(handled);
2460         }
2461
2462         if (test_and_set_bit(0, (void*)&pUmDevice->interrupt)) {
2463                 printk(KERN_ERR "%s: Duplicate entry of the interrupt handler\n",
2464                         dev->name);
2465                 bcm5700_intr_unlock(pUmDevice);
2466                 handled = 0;
2467                 return IRQ_RETVAL(handled);
2468         }
2469
2470         /* BCM4785: Flush posted writes from GbE to host memory. */
2471         if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
2472                 REG_RD(pDevice, HostCoalesce.Mode);
2473
2474         if ((pDevice->Flags & USING_MSI_FLAG) ||
2475                 (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
2476                 !(REG_RD(pDevice,PciCfg.PciState) & T3_PCI_STATE_INTERRUPT_NOT_ACTIVE) )
2477         {
2478
2479                 if (pUmDevice->intr_test) {
2480                         if (!(REG_RD(pDevice, PciCfg.PciState) &
2481                                         T3_PCI_STATE_INTERRUPT_NOT_ACTIVE) ||
2482                                                 pDevice->Flags & USING_MSI_FLAG ) {
2483                                 pUmDevice->intr_test_result = 1;
2484                         }
2485                         pUmDevice->intr_test = 0;
2486                 }
2487
2488 #ifdef BCM_NAPI_RXPOLL
2489                 max_intr_loop = 1;
2490 #else
2491                 max_intr_loop = 50;
2492 #endif
2493                 if (pDevice->Flags & USE_TAGGED_STATUS_FLAG) {
2494                         MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
2495                         oldtag = pDevice->pStatusBlkVirt->StatusTag;
2496
2497                         for (i = 0; ; i++) {
2498                                 pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
2499
2500                                 LM_ServiceInterrupts(pDevice);
2501                                 /* BCM4785: Flush GbE posted writes to host memory. */
2502                                 if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
2503                                         MB_REG_RD(pDevice, Mailbox.Interrupt[0].Low);
2504                                 newtag = pDevice->pStatusBlkVirt->StatusTag;
2505                                 if ((newtag == oldtag) || (i > max_intr_loop)) {
2506                                         MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, oldtag << 24);
2507                                         pDevice->LastTag = oldtag;
2508                                         if (pDevice->Flags & UNDI_FIX_FLAG) {
2509                                                 REG_WR(pDevice, Grc.LocalCtrl,
2510                                                 pDevice->GrcLocalCtrl | 0x2);
2511                                         }
2512                                         break;
2513                                 }
2514                                 oldtag = newtag;
2515                         }
2516                 }
2517                 else
2518                 {
2519                         i = 0;
2520                         do {
2521                                 uint dummy;
2522
2523                                 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
2524                                 pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
2525                                 LM_ServiceInterrupts(pDevice);
2526                                 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0);
2527                                 dummy = MB_REG_RD(pDevice, Mailbox.Interrupt[0].Low);
2528                                 i++;
2529                         }
2530                         while ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) &&
2531                                 (i < max_intr_loop));
2532
2533                         if (pDevice->Flags & UNDI_FIX_FLAG) {
2534                                 REG_WR(pDevice, Grc.LocalCtrl,
2535                                 pDevice->GrcLocalCtrl | 0x2);
2536                         }
2537                 }
2538         }
2539         else
2540         {
2541                 /* not my interrupt */
2542                 handled = 0;
2543         }
2544
2545 #ifdef BCM_TASKLET
2546         repl_buf_count = QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container);
2547         if (((repl_buf_count > pUmDevice->rx_buf_repl_panic_thresh) ||
2548                 pDevice->QueueAgain) &&
2549                 (!test_and_set_bit(0, &pUmDevice->tasklet_busy))) {
2550
2551                 replenish_rx_buffers(pUmDevice, pUmDevice->rx_buf_repl_isr_limit);
2552                 clear_bit(0, (void*)&pUmDevice->tasklet_busy);
2553         }
2554         else if ((repl_buf_count > pUmDevice->rx_buf_repl_thresh) &&
2555                 !pUmDevice->tasklet_pending) {
2556
2557                 pUmDevice->tasklet_pending = 1;
2558                 tasklet_schedule(&pUmDevice->tasklet);
2559         }
2560 #else
2561 #ifdef BCM_NAPI_RXPOLL
2562         if (!pDevice->RxPoll &&
2563                 QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
2564                 pDevice->RxPoll = 1;
2565                 MM_ScheduleRxPoll(pDevice);
2566         }
2567 #else
2568         if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
2569                 replenish_rx_buffers(pUmDevice, 0);
2570         }
2571
2572         if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container) ||
2573                 pDevice->QueueAgain) {
2574
2575                 LM_QueueRxPackets(pDevice);
2576         }
2577 #endif
2578 #endif
2579
2580         clear_bit(0, (void*)&pUmDevice->interrupt);
2581         bcm5700_intr_unlock(pUmDevice);
2582         if (pUmDevice->tx_queued) {
2583                 pUmDevice->tx_queued = 0;
2584                 netif_wake_queue(dev);
2585         }
2586         return IRQ_RETVAL(handled);
2587 }
2588
2589
2590 #ifdef BCM_TASKLET
2591 STATIC void
2592 bcm5700_tasklet(unsigned long data)
2593 {
2594         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)data;
2595         unsigned long flags = 0;
2596
2597         /* RH 7.2 Beta 3 tasklets are reentrant */
2598         if (test_and_set_bit(0, &pUmDevice->tasklet_busy)) {
2599                 pUmDevice->tasklet_pending = 0;
2600                 return;
2601         }
2602
2603         pUmDevice->tasklet_pending = 0;
2604         if (pUmDevice->opened && !pUmDevice->suspended) {
2605                 BCM5700_LOCK(pUmDevice, flags);
2606                 replenish_rx_buffers(pUmDevice, 0);
2607                 BCM5700_UNLOCK(pUmDevice, flags);
2608         }
2609
2610         clear_bit(0, &pUmDevice->tasklet_busy);
2611 }
2612 #endif
2613
2614 STATIC int
2615 bcm5700_close(struct net_device *dev)
2616 {
2617
2618         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2619         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
2620
2621 #if (LINUX_VERSION_CODE < 0x02032b)
2622         dev->start = 0;
2623 #endif
2624         netif_stop_queue(dev);
2625         pUmDevice->opened = 0;
2626
2627 #ifdef BCM_ASF
2628         if( !(pDevice->AsfFlags & ASF_ENABLED) )
2629 #endif
2630 #ifdef BCM_WOL
2631                 if( enable_wol[pUmDevice->index] == 0 )
2632 #endif
2633                         B57_INFO(("%s: %s NIC Link is DOWN\n", bcm5700_driver, dev->name));
2634
2635         if (tigon3_debug > 1)
2636                 printk(KERN_DEBUG "%s: Shutting down Tigon3\n",
2637                            dev->name);
2638
2639         LM_MulticastClear(pDevice);
2640         bcm5700_shutdown(pUmDevice);
2641
2642         if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) {
2643                 del_timer_sync(&pUmDevice->statstimer);
2644         }
2645
2646         del_timer_sync(&pUmDevice->timer);
2647
2648         free_irq(pUmDevice->pdev->irq, dev);
2649
2650 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
2651
2652         if(pDevice->Flags & USING_MSI_FLAG) {
2653                 pci_disable_msi(pUmDevice->pdev);
2654                 REG_WR(pDevice, Msi.Mode,  1 );
2655                 pDevice->Flags &= ~USING_MSI_FLAG;
2656         }
2657
2658 #endif
2659
2660
2661 #if (LINUX_VERSION_CODE < 0x020300)
2662         MOD_DEC_USE_COUNT;
2663 #endif
2664         {
2665         /* BCM4785: Don't go to low-power state because it will power down the smbus block. */
2666         if (!(pDevice->Flags & SB_CORE_FLAG))
2667                 LM_SetPowerState(pDevice, LM_POWER_STATE_D3);
2668         }
2669
2670         bcm5700_freemem(dev);
2671
2672         QQ_InitQueue(&pDevice->RxPacketFreeQ.Container,
2673                         MAX_RX_PACKET_DESC_COUNT);
2674
2675         return 0;
2676 }
2677
2678 STATIC int
2679 bcm5700_freemem(struct net_device *dev)
2680 {
2681         int i;
2682         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2683         LM_DEVICE_BLOCK  *pDevice = &pUmDevice->lm_dev;
2684
2685         for (i = 0; i < pUmDevice->mem_list_num; i++) {
2686                 if (pUmDevice->mem_size_list[i] == 0) {
2687                         kfree(pUmDevice->mem_list[i]);
2688                 }
2689                 else {
2690                         pci_free_consistent(pUmDevice->pdev,
2691                                 (size_t) pUmDevice->mem_size_list[i],
2692                                 pUmDevice->mem_list[i],
2693                                 pUmDevice->dma_list[i]);
2694                 }
2695         }
2696
2697         pDevice->pStatusBlkVirt = 0;
2698         pDevice->pStatsBlkVirt  = 0;
2699         pUmDevice->mem_list_num = 0;
2700
2701         return 0;
2702 }
2703
2704 uint64_t
2705 bcm5700_crc_count(PUM_DEVICE_BLOCK pUmDevice)
2706 {
2707         PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
2708         LM_UINT32 Value32;
2709         PT3_STATS_BLOCK pStats = (PT3_STATS_BLOCK) pDevice->pStatsBlkVirt;
2710         unsigned long flags;
2711
2712         if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
2713                 T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) &&
2714                 !(pDevice->TbiFlags & ENABLE_TBI_FLAG)) {
2715
2716                 if (!pUmDevice->opened || !pDevice->InitDone)
2717                 {
2718
2719                         return 0;
2720                 }
2721
2722                 /* regulate MDIO access during run time */
2723                 if (pUmDevice->crc_counter_expiry > 0)
2724                         return pUmDevice->phy_crc_count;
2725
2726                 pUmDevice->crc_counter_expiry = (5 * HZ) /
2727                         pUmDevice->timer_interval;
2728
2729                 BCM5700_PHY_LOCK(pUmDevice, flags);
2730                 LM_ReadPhy(pDevice, 0x1e, &Value32);
2731                 if ((Value32 & 0x8000) == 0)
2732                         LM_WritePhy(pDevice, 0x1e, Value32 | 0x8000);
2733                 LM_ReadPhy(pDevice, 0x14, &Value32);
2734                 BCM5700_PHY_UNLOCK(pUmDevice, flags);
2735                 /* Sometimes data on the MDIO bus can be corrupted */
2736                 if (Value32 != 0xffff)
2737                         pUmDevice->phy_crc_count += Value32;
2738                 return pUmDevice->phy_crc_count;
2739         }
2740         else if (pStats == 0) {
2741                 return 0;
2742         }
2743         else {
2744                 return (MM_GETSTATS64(pStats->dot3StatsFCSErrors));
2745         }
2746 }
2747
2748 uint64_t
2749 bcm5700_rx_err_count(UM_DEVICE_BLOCK *pUmDevice)
2750 {
2751         LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2752         T3_STATS_BLOCK *pStats = (T3_STATS_BLOCK *) pDevice->pStatsBlkVirt;
2753
2754         if (pStats == 0)
2755                 return 0;
2756         return (bcm5700_crc_count(pUmDevice) +
2757                 MM_GETSTATS64(pStats->dot3StatsAlignmentErrors) +
2758                 MM_GETSTATS64(pStats->etherStatsUndersizePkts) +
2759                 MM_GETSTATS64(pStats->etherStatsFragments) +
2760                 MM_GETSTATS64(pStats->dot3StatsFramesTooLong) +
2761                 MM_GETSTATS64(pStats->etherStatsJabbers));
2762 }
2763
2764 STATIC struct net_device_stats *
2765 bcm5700_get_stats(struct net_device *dev)
2766 {
2767         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2768         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
2769         PT3_STATS_BLOCK pStats = (PT3_STATS_BLOCK) pDevice->pStatsBlkVirt;
2770         struct net_device_stats *p_netstats = &pUmDevice->stats;
2771
2772         if (pStats == 0)
2773                 return p_netstats;
2774
2775         /* Get stats from LM */
2776         p_netstats->rx_packets =
2777                 MM_GETSTATS(pStats->ifHCInUcastPkts) +
2778                 MM_GETSTATS(pStats->ifHCInMulticastPkts) +
2779                 MM_GETSTATS(pStats->ifHCInBroadcastPkts);
2780         p_netstats->tx_packets =
2781                 MM_GETSTATS(pStats->ifHCOutUcastPkts) +
2782                 MM_GETSTATS(pStats->ifHCOutMulticastPkts) +
2783                 MM_GETSTATS(pStats->ifHCOutBroadcastPkts);
2784         /* There counters seem to be innacurate. Use byte number accumulation 
2785            instead.
2786            p_netstats->rx_bytes = MM_GETSTATS(pStats->ifHCInOctets);
2787            p_netstats->tx_bytes = MM_GETSTATS(pStats->ifHCOutOctets);
2788         */
2789         p_netstats->tx_errors =
2790                 MM_GETSTATS(pStats->dot3StatsInternalMacTransmitErrors) +
2791                 MM_GETSTATS(pStats->dot3StatsCarrierSenseErrors) +
2792                 MM_GETSTATS(pStats->ifOutDiscards) +
2793                 MM_GETSTATS(pStats->ifOutErrors);
2794         p_netstats->multicast = MM_GETSTATS(pStats->ifHCInMulticastPkts);
2795         p_netstats->collisions = MM_GETSTATS(pStats->etherStatsCollisions);
2796         p_netstats->rx_length_errors =
2797                 MM_GETSTATS(pStats->dot3StatsFramesTooLong) +
2798                 MM_GETSTATS(pStats->etherStatsUndersizePkts);
2799         p_netstats->rx_over_errors = MM_GETSTATS(pStats->nicNoMoreRxBDs);
2800         p_netstats->rx_frame_errors =
2801                 MM_GETSTATS(pStats->dot3StatsAlignmentErrors);
2802         p_netstats->rx_crc_errors = (unsigned long)
2803                 bcm5700_crc_count(pUmDevice);
2804         p_netstats->rx_errors = (unsigned long)
2805                 bcm5700_rx_err_count(pUmDevice);
2806
2807         p_netstats->tx_aborted_errors = MM_GETSTATS(pStats->ifOutDiscards);
2808         p_netstats->tx_carrier_errors =
2809                 MM_GETSTATS(pStats->dot3StatsCarrierSenseErrors);
2810
2811         return p_netstats;
2812 }
2813
2814 void
2815 b57_suspend_chip(UM_DEVICE_BLOCK *pUmDevice)
2816 {
2817         LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2818
2819         if (pUmDevice->opened) {
2820                 bcm5700_intr_off(pUmDevice);
2821                 netif_carrier_off(pUmDevice->dev);
2822                 netif_stop_queue(pUmDevice->dev);
2823 #ifdef BCM_TASKLET
2824                 tasklet_kill(&pUmDevice->tasklet);
2825 #endif
2826                 bcm5700_poll_wait(pUmDevice);
2827         }
2828         pUmDevice->suspended = 1;
2829         LM_ShutdownChip(pDevice, LM_SUSPEND_RESET);
2830 }
2831
2832 void
2833 b57_resume_chip(UM_DEVICE_BLOCK *pUmDevice)
2834 {
2835         LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2836
2837         if (pUmDevice->suspended) {
2838                 pUmDevice->suspended = 0;
2839                 if (pUmDevice->opened) {
2840                         bcm5700_reset(pUmDevice->dev);
2841                 }
2842                 else {
2843                         LM_ShutdownChip(pDevice, LM_SHUTDOWN_RESET);
2844                 }
2845         }
2846 }
2847
2848 /* Returns 0 on failure, 1 on success */
2849 int
2850 b57_test_intr(UM_DEVICE_BLOCK *pUmDevice)
2851 {
2852         LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2853         int j;
2854
2855         if (!pUmDevice->opened)
2856                 return 0;
2857         pUmDevice->intr_test_result = 0;
2858         pUmDevice->intr_test = 1;
2859
2860         REG_WR(pDevice, HostCoalesce.Mode,
2861                 pDevice->CoalesceMode | HOST_COALESCE_ENABLE |
2862                 HOST_COALESCE_NOW);
2863
2864         for (j = 0; j < 10; j++) {
2865                 if (pUmDevice->intr_test_result){
2866                         break;
2867                 }
2868
2869                 REG_WR(pDevice, HostCoalesce.Mode,
2870                 pDevice->CoalesceMode | HOST_COALESCE_ENABLE |
2871                 HOST_COALESCE_NOW);
2872
2873                 MM_Sleep(pDevice, 1);
2874         }
2875
2876         return pUmDevice->intr_test_result;
2877
2878 }
2879
2880 #ifdef SIOCETHTOOL
2881
2882 #ifdef ETHTOOL_GSTRINGS
2883
2884 #define ETH_NUM_STATS 30
2885 #define RX_CRC_IDX 5
2886 #define RX_MAC_ERR_IDX 14
2887
2888 struct {
2889         char string[ETH_GSTRING_LEN];
2890 } bcm5700_stats_str_arr[ETH_NUM_STATS] = {
2891         { "rx_unicast_packets" },
2892         { "rx_multicast_packets" },
2893         { "rx_broadcast_packets" },
2894         { "rx_bytes" },
2895         { "rx_fragments" },
2896         { "rx_crc_errors" },    /* this needs to be calculated */
2897         { "rx_align_errors" },
2898         { "rx_xon_frames" },
2899         { "rx_xoff_frames" },
2900         { "rx_long_frames" },
2901         { "rx_short_frames" },
2902         { "rx_jabber" },
2903         { "rx_discards" },
2904         { "rx_errors" },
2905         { "rx_mac_errors" },    /* this needs to be calculated */
2906         { "tx_unicast_packets" },
2907         { "tx_multicast_packets" },
2908         { "tx_broadcast_packets" },
2909         { "tx_bytes" },
2910         { "tx_deferred" },
2911         { "tx_single_collisions" },
2912         { "tx_multi_collisions" },
2913         { "tx_total_collisions" },
2914         { "tx_excess_collisions" },
2915         { "tx_late_collisions" },
2916         { "tx_xon_frames" },
2917         { "tx_xoff_frames" },
2918         { "tx_internal_mac_errors" },
2919         { "tx_carrier_errors" },
2920         { "tx_errors" },
2921 };
2922
2923 #define STATS_OFFSET(offset_name) ((OFFSETOF(T3_STATS_BLOCK, offset_name)) / sizeof(uint64_t))
2924
2925 #ifdef __BIG_ENDIAN
2926 #define SWAP_DWORD_64(x) (x)
2927 #else
2928 #define SWAP_DWORD_64(x) ((x << 32) | (x >> 32))
2929 #endif
2930
2931 unsigned long bcm5700_stats_offset_arr[ETH_NUM_STATS] = {
2932         STATS_OFFSET(ifHCInUcastPkts),
2933         STATS_OFFSET(ifHCInMulticastPkts),
2934         STATS_OFFSET(ifHCInBroadcastPkts),
2935         STATS_OFFSET(ifHCInOctets),
2936         STATS_OFFSET(etherStatsFragments),
2937         0,
2938         STATS_OFFSET(dot3StatsAlignmentErrors),
2939         STATS_OFFSET(xonPauseFramesReceived),
2940         STATS_OFFSET(xoffPauseFramesReceived),
2941         STATS_OFFSET(dot3StatsFramesTooLong),
2942         STATS_OFFSET(etherStatsUndersizePkts),
2943         STATS_OFFSET(etherStatsJabbers),
2944         STATS_OFFSET(ifInDiscards),
2945         STATS_OFFSET(ifInErrors),
2946         0,
2947         STATS_OFFSET(ifHCOutUcastPkts),
2948         STATS_OFFSET(ifHCOutMulticastPkts),
2949         STATS_OFFSET(ifHCOutBroadcastPkts),
2950         STATS_OFFSET(ifHCOutOctets),
2951         STATS_OFFSET(dot3StatsDeferredTransmissions),
2952         STATS_OFFSET(dot3StatsSingleCollisionFrames),
2953         STATS_OFFSET(dot3StatsMultipleCollisionFrames),
2954         STATS_OFFSET(etherStatsCollisions),
2955         STATS_OFFSET(dot3StatsExcessiveCollisions),
2956         STATS_OFFSET(dot3StatsLateCollisions),
2957         STATS_OFFSET(outXonSent),
2958         STATS_OFFSET(outXoffSent),
2959         STATS_OFFSET(dot3StatsInternalMacTransmitErrors),
2960         STATS_OFFSET(dot3StatsCarrierSenseErrors),
2961         STATS_OFFSET(ifOutErrors),
2962 };
2963
2964 #endif /* ETHTOOL_GSTRINGS */
2965
2966
2967 #ifdef ETHTOOL_GREGS
2968 #if (LINUX_VERSION_CODE >= 0x02040f)
2969 static void
2970 bcm5700_get_reg_blk(UM_DEVICE_BLOCK *pUmDevice, u32 **buf, u32 start, u32 end,
2971                 int reserved)
2972 {
2973         u32 offset;
2974         LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2975
2976         if (reserved) {
2977                 memset(*buf, 0, end - start);
2978                 *buf = *buf + (end - start)/4;
2979                 return;
2980         }
2981         for (offset = start; offset < end; offset+=4, *buf = *buf + 1) {
2982                 if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)){
2983                         if (((offset >= 0x3400) && (offset < 0x3c00)) ||
2984                                 ((offset >= 0x5400) && (offset < 0x5800)) ||
2985                                 ((offset >= 0x6400) && (offset < 0x6800))) {
2986                                 **buf = 0;
2987                                 continue;
2988                         }
2989                 }
2990                 **buf = REG_RD_OFFSET(pDevice, offset);
2991         }
2992 }
2993 #endif
2994 #endif
2995
2996 static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
2997 {
2998         struct ethtool_cmd ethcmd;
2999         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
3000         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
3001
3002         if (mm_copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
3003                 return -EFAULT;
3004
3005         switch (ethcmd.cmd) {
3006 #ifdef ETHTOOL_GDRVINFO
3007         case ETHTOOL_GDRVINFO: {
3008                 struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
3009
3010                 strcpy(info.driver,  bcm5700_driver);
3011 #ifdef INCLUDE_5701_AX_FIX
3012                 if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0) {
3013                         extern int t3FwReleaseMajor;
3014                         extern int t3FwReleaseMinor;
3015                         extern int t3FwReleaseFix;
3016
3017                         sprintf(info.fw_version, "%i.%i.%i",
3018                                 t3FwReleaseMajor, t3FwReleaseMinor,
3019                                 t3FwReleaseFix);
3020                 }
3021 #endif
3022                 strcpy(info.fw_version, pDevice->BootCodeVer);
3023                 strcpy(info.version, bcm5700_version);
3024 #if (LINUX_VERSION_CODE <= 0x020422)
3025                 strcpy(info.bus_info, pUmDevice->pdev->slot_name);
3026 #else
3027                 strcpy(info.bus_info, pci_name(pUmDevice->pdev));
3028 #endif
3029
3030
3031
3032 #ifdef ETHTOOL_GEEPROM
3033                 BCM_EEDUMP_LEN(&info, pDevice->NvramSize);
3034 #endif
3035 #ifdef ETHTOOL_GREGS
3036                 /* dump everything, including holes in the register space */
3037                 info.regdump_len = 0x6c00;
3038 #endif
3039 #ifdef ETHTOOL_GSTATS
3040                 info.n_stats = ETH_NUM_STATS;
3041 #endif
3042                 if (mm_copy_to_user(useraddr, &info, sizeof(info)))
3043                         return -EFAULT;
3044                 return 0;
3045         }
3046 #endif
3047         case ETHTOOL_GSET: {
3048                 if ((pDevice->TbiFlags & ENABLE_TBI_FLAG)||
3049                         (pDevice->PhyFlags & PHY_IS_FIBER)) {
3050                         ethcmd.supported =
3051                                 (SUPPORTED_1000baseT_Full |
3052                                 SUPPORTED_Autoneg);
3053                         ethcmd.supported |= SUPPORTED_FIBRE;
3054                         ethcmd.port = PORT_FIBRE;
3055                 } else {
3056                         ethcmd.supported =
3057                                 (SUPPORTED_10baseT_Half |
3058                                 SUPPORTED_10baseT_Full |
3059                                 SUPPORTED_100baseT_Half |
3060                                 SUPPORTED_100baseT_Full |
3061                                 SUPPORTED_1000baseT_Half |
3062                                 SUPPORTED_1000baseT_Full |
3063                                 SUPPORTED_Autoneg);
3064                         ethcmd.supported |= SUPPORTED_TP;
3065                         ethcmd.port = PORT_TP;
3066                 }
3067
3068                 ethcmd.transceiver = XCVR_INTERNAL;
3069                 ethcmd.phy_address = 0;
3070
3071                 if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS)
3072                         ethcmd.speed = SPEED_1000;
3073                 else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS)
3074                         ethcmd.speed = SPEED_100;
3075                 else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
3076                         ethcmd.speed = SPEED_10;
3077                 else
3078                         ethcmd.speed = 0;
3079
3080                 if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
3081                         ethcmd.duplex = DUPLEX_FULL;
3082                 else
3083                         ethcmd.duplex = DUPLEX_HALF;
3084
3085                 if (pDevice->DisableAutoNeg == FALSE) {
3086                         ethcmd.autoneg = AUTONEG_ENABLE;
3087                         ethcmd.advertising = ADVERTISED_Autoneg;
3088                         if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) ||
3089                                 (pDevice->PhyFlags & PHY_IS_FIBER)) {
3090                                 ethcmd.advertising |=
3091                                         ADVERTISED_1000baseT_Full |
3092                                         ADVERTISED_FIBRE;
3093                         }
3094                         else {
3095                                 ethcmd.advertising |=
3096                                         ADVERTISED_TP;
3097                                 if (pDevice->advertising &
3098                                         PHY_AN_AD_10BASET_HALF) {
3099
3100                                         ethcmd.advertising |=
3101                                                 ADVERTISED_10baseT_Half;
3102                                 }
3103                                 if (pDevice->advertising &
3104                                         PHY_AN_AD_10BASET_FULL) {
3105
3106                                         ethcmd.advertising |=
3107                                                 ADVERTISED_10baseT_Full;
3108                                 }
3109                                 if (pDevice->advertising &
3110                                         PHY_AN_AD_100BASETX_HALF) {
3111
3112                                         ethcmd.advertising |=
3113                                                 ADVERTISED_100baseT_Half;
3114                                 }
3115                                 if (pDevice->advertising &
3116                                         PHY_AN_AD_100BASETX_FULL) {
3117
3118                                         ethcmd.advertising |=
3119                                                 ADVERTISED_100baseT_Full;
3120                                 }
3121                                 if (pDevice->advertising1000 &
3122                                         BCM540X_AN_AD_1000BASET_HALF) {
3123
3124                                         ethcmd.advertising |=
3125                                                 ADVERTISED_1000baseT_Half;
3126                                 }
3127                                 if (pDevice->advertising1000 &
3128                                         BCM540X_AN_AD_1000BASET_FULL) {
3129
3130                                         ethcmd.advertising |=
3131                                                 ADVERTISED_1000baseT_Full;
3132                                 }
3133                         }
3134                 }
3135                 else {
3136                         ethcmd.autoneg = AUTONEG_DISABLE;
3137                         ethcmd.advertising = 0;
3138                 }
3139
3140                 ethcmd.maxtxpkt = pDevice->TxMaxCoalescedFrames;
3141                 ethcmd.maxrxpkt = pDevice->RxMaxCoalescedFrames;
3142
3143                 if(mm_copy_to_user(useraddr, &ethcmd, sizeof(ethcmd)))
3144                         return -EFAULT;
3145                 return 0;
3146         }
3147         case ETHTOOL_SSET: {
3148                 unsigned long flags;
3149
3150                 if(!capable(CAP_NET_ADMIN))
3151                         return -EPERM;
3152                 if (ethcmd.autoneg == AUTONEG_ENABLE) {
3153                         pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
3154                         pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
3155                         pDevice->DisableAutoNeg = FALSE;
3156                 }
3157                 else {
3158                         if (ethcmd.speed == SPEED_1000 &&
3159                                 pDevice->PhyFlags & PHY_NO_GIGABIT)
3160                                         return -EINVAL;
3161
3162                         if (ethcmd.speed == SPEED_1000 &&
3163                             (pDevice->TbiFlags & ENABLE_TBI_FLAG ||
3164                              pDevice->PhyFlags & PHY_IS_FIBER ) ) {
3165
3166                                 pDevice->RequestedLineSpeed =
3167                                         LM_LINE_SPEED_1000MBPS;
3168
3169                                 pDevice->RequestedDuplexMode =
3170                                         LM_DUPLEX_MODE_FULL;
3171                         }
3172                         else if (ethcmd.speed == SPEED_100 &&
3173                                 !(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
3174                                 !(pDevice->PhyFlags & PHY_IS_FIBER)) {
3175
3176                                 pDevice->RequestedLineSpeed =
3177                                         LM_LINE_SPEED_100MBPS;
3178                         }
3179                         else if (ethcmd.speed == SPEED_10  &&
3180                                 !(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
3181                                 !(pDevice->PhyFlags & PHY_IS_FIBER)) {
3182
3183                                 pDevice->RequestedLineSpeed =
3184                                         LM_LINE_SPEED_10MBPS;
3185                         }
3186                         else {
3187                                 return -EINVAL;
3188                         }
3189
3190                         pDevice->DisableAutoNeg = TRUE;
3191                         if (ethcmd.duplex == DUPLEX_FULL) {
3192                                 pDevice->RequestedDuplexMode =
3193                                         LM_DUPLEX_MODE_FULL;
3194                         }
3195                         else {
3196                                 if (!(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
3197                                     !(pDevice->PhyFlags & PHY_IS_FIBER)  ) {
3198
3199                                         pDevice->RequestedDuplexMode =
3200                                                         LM_DUPLEX_MODE_HALF;
3201                                 }
3202                         }
3203                 }
3204                 if (netif_running(dev)) {
3205                         BCM5700_PHY_LOCK(pUmDevice, flags);
3206                         LM_SetupPhy(pDevice);
3207                         BCM5700_PHY_UNLOCK(pUmDevice, flags);
3208                 }
3209                 return 0;
3210         }
3211 #ifdef ETHTOOL_GWOL
3212 #ifdef BCM_WOL
3213         case ETHTOOL_GWOL: {
3214                 struct ethtool_wolinfo wol = {ETHTOOL_GWOL};
3215
3216                 if (((pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
3217                         !(pDevice->Flags & FIBER_WOL_CAPABLE_FLAG)) ||
3218                         (pDevice->Flags & DISABLE_D3HOT_FLAG)) {
3219                         wol.supported = 0;
3220                         wol.wolopts = 0;
3221                 }
3222                 else {
3223                         wol.supported = WAKE_MAGIC;
3224                         if (pDevice->WakeUpMode == LM_WAKE_UP_MODE_MAGIC_PACKET)
3225                         {
3226                                 wol.wolopts = WAKE_MAGIC;
3227                         }
3228                         else {
3229                                 wol.wolopts = 0;
3230                         }
3231                 }
3232                 if (mm_copy_to_user(useraddr, &wol, sizeof(wol)))
3233                         return -EFAULT;
3234                 return 0;
3235         }
3236         case ETHTOOL_SWOL: {
3237                 struct ethtool_wolinfo wol;
3238
3239                 if(!capable(CAP_NET_ADMIN))
3240                         return -EPERM;
3241                 if (mm_copy_from_user(&wol, useraddr, sizeof(wol)))
3242                         return -EFAULT;
3243                 if ((((pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
3244                         !(pDevice->Flags & FIBER_WOL_CAPABLE_FLAG)) ||
3245                         (pDevice->Flags & DISABLE_D3HOT_FLAG)) &&
3246                         wol.wolopts) {
3247                         return -EINVAL;
3248                 }
3249
3250                 if ((wol.wolopts & ~WAKE_MAGIC) != 0) {
3251                         return -EINVAL;
3252                 }
3253                 if (wol.wolopts & WAKE_MAGIC) {
3254                         pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
3255                         pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
3256                 }
3257                 else {
3258                         pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE;
3259                         pDevice->WakeUpMode = LM_WAKE_UP_MODE_NONE;
3260                 }
3261                 return 0;
3262         }
3263 #endif
3264 #endif
3265 #ifdef ETHTOOL_GLINK
3266         case ETHTOOL_GLINK: {
3267                 struct ethtool_value edata = {ETHTOOL_GLINK};
3268
3269                 /* ifup only waits for 5 seconds for link up */
3270                 /* NIC may take more than 5 seconds to establish link */
3271                 if ((pUmDevice->delayed_link_ind > 0) &&
3272                         delay_link[pUmDevice->index])
3273                         return -EOPNOTSUPP;
3274
3275                 if (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) {
3276                         edata.data =  1;
3277                 }
3278                 else {
3279                         edata.data =  0;
3280                 }
3281                 if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
3282                         return -EFAULT;
3283                 return 0;
3284         }
3285 #endif
3286 #ifdef ETHTOOL_NWAY_RST
3287         case ETHTOOL_NWAY_RST: {
3288                 LM_UINT32 phyctrl;
3289                 unsigned long flags;
3290
3291                 if(!capable(CAP_NET_ADMIN))
3292                         return -EPERM;
3293                 if (pDevice->DisableAutoNeg) {
3294                         return -EINVAL;
3295                 }
3296                 if (!netif_running(dev))
3297                         return -EAGAIN;
3298                 BCM5700_PHY_LOCK(pUmDevice, flags);
3299                 if (pDevice->TbiFlags & ENABLE_TBI_FLAG) { 
3300                         pDevice->RequestedLineSpeed = LM_LINE_SPEED_1000MBPS;
3301                         pDevice->DisableAutoNeg = TRUE;
3302                         LM_SetupPhy(pDevice);
3303
3304                         pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
3305                         pDevice->DisableAutoNeg = FALSE;
3306                         LM_SetupPhy(pDevice);
3307                 }
3308                 else {
3309                         if ((T3_ASIC_REV(pDevice->ChipRevId) ==
3310                                         T3_ASIC_REV_5703) ||
3311                                 (T3_ASIC_REV(pDevice->ChipRevId) ==
3312                                         T3_ASIC_REV_5704) ||
3313                                 (T3_ASIC_REV(pDevice->ChipRevId) ==
3314                                         T3_ASIC_REV_5705))
3315                         {
3316                                 LM_ResetPhy(pDevice);
3317                                 LM_SetupPhy(pDevice);
3318                         }
3319                         pDevice->PhyFlags &= ~PHY_FIBER_FALLBACK;
3320                         LM_ReadPhy(pDevice, PHY_CTRL_REG, &phyctrl);
3321                         LM_WritePhy(pDevice, PHY_CTRL_REG, phyctrl |
3322                                 PHY_CTRL_AUTO_NEG_ENABLE |
3323                                 PHY_CTRL_RESTART_AUTO_NEG);
3324                 }
3325                 BCM5700_PHY_UNLOCK(pUmDevice, flags);
3326                 return 0;
3327         }
3328 #endif
3329 #ifdef ETHTOOL_GEEPROM
3330         case ETHTOOL_GEEPROM: {
3331                 struct ethtool_eeprom eeprom;
3332                 LM_UINT32 *buf = 0;
3333                 LM_UINT32 buf1[64/4];
3334                 int i, j, offset, len;
3335
3336                 if (mm_copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
3337                         return -EFAULT;
3338
3339                 if (eeprom.offset >= pDevice->NvramSize)
3340                         return -EFAULT;
3341
3342                 /* maximum data limited */
3343                 /* to read more, call again with a different offset */
3344                 if (eeprom.len > 0x800) {
3345                         eeprom.len = 0x800;
3346                         if (mm_copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
3347                                 return -EFAULT;
3348                 }
3349
3350                 if (eeprom.len > 64) {
3351                         buf = kmalloc(eeprom.len, GFP_KERNEL);
3352                         if (!buf)
3353                                 return -ENOMEM;
3354                 }
3355                 else {
3356                         buf = buf1;
3357                 }
3358                 useraddr += offsetof(struct ethtool_eeprom, data);
3359
3360                 offset = eeprom.offset;
3361                 len = eeprom.len;
3362                 if (offset & 3) {
3363                         offset &= 0xfffffffc;
3364                         len += (offset & 3);
3365                 }
3366                 len = (len + 3) & 0xfffffffc;
3367                 for (i = 0, j = 0; j < len; i++, j += 4) {
3368                         if (LM_NvramRead(pDevice, offset + j, buf + i) !=
3369                                 LM_STATUS_SUCCESS) {
3370                                 break;
3371                         }
3372                 }
3373                 if (j >= len) {
3374                         buf += (eeprom.offset & 3);
3375                         i = mm_copy_to_user(useraddr, buf, eeprom.len);
3376                 }
3377                 if (eeprom.len > 64) {
3378                         kfree(buf);
3379                 }
3380                 if ((j < len) || i)
3381                         return -EFAULT;
3382                 return 0;
3383         }
3384         case ETHTOOL_SEEPROM: {
3385                 struct ethtool_eeprom eeprom;
3386                 LM_UINT32 buf[64/4];
3387                 int i, offset, len;
3388
3389                 if(!capable(CAP_NET_ADMIN))
3390                         return -EPERM;
3391                 if (mm_copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
3392                         return -EFAULT;
3393
3394                 if ((eeprom.offset & 3) || (eeprom.len & 3) ||
3395                         (eeprom.offset >= pDevice->NvramSize)) {
3396                         return -EFAULT;
3397                 }
3398
3399                 if ((eeprom.offset + eeprom.len) >= pDevice->NvramSize) {
3400                         eeprom.len = pDevice->NvramSize - eeprom.offset;
3401                 }
3402
3403                 useraddr += offsetof(struct ethtool_eeprom, data);
3404
3405                 len = eeprom.len;
3406                 offset = eeprom.offset;
3407                 for (; len > 0; ) {
3408                         if (len < 64)
3409                                 i = len;
3410                         else
3411                                 i = 64;
3412                         if (mm_copy_from_user(&buf, useraddr, i))
3413                                 return -EFAULT;
3414
3415                         bcm5700_intr_off(pUmDevice);
3416                         /* Prevent race condition on Grc.Mode register */
3417                         bcm5700_poll_wait(pUmDevice);
3418
3419                         if (LM_NvramWriteBlock(pDevice, offset, buf, i/4) !=
3420                                 LM_STATUS_SUCCESS) {
3421                                 bcm5700_intr_on(pUmDevice);
3422                                 return -EFAULT;
3423                         }
3424                         bcm5700_intr_on(pUmDevice);
3425                         len -= i;
3426                         offset += i;
3427                         useraddr += i;
3428                 }
3429                 return 0;
3430         }
3431 #endif
3432 #ifdef ETHTOOL_GREGS
3433 #if (LINUX_VERSION_CODE >= 0x02040f)
3434         case ETHTOOL_GREGS: {
3435                 struct ethtool_regs eregs;
3436                 LM_UINT32 *buf, *buf1;
3437                 unsigned int i;
3438
3439                 if(!capable(CAP_NET_ADMIN))
3440                         return -EPERM;
3441                 if (pDevice->Flags & UNDI_FIX_FLAG)
3442                         return -EOPNOTSUPP;
3443                 if (mm_copy_from_user(&eregs, useraddr, sizeof(eregs)))
3444                         return -EFAULT;
3445                 if (eregs.len > 0x6c00)
3446                         eregs.len = 0x6c00;
3447                 eregs.version = 0x0;
3448                 if (mm_copy_to_user(useraddr, &eregs, sizeof(eregs)))
3449                         return -EFAULT;
3450                 buf = buf1 = kmalloc(eregs.len, GFP_KERNEL);
3451                 if (!buf)
3452                         return -ENOMEM;
3453                 bcm5700_get_reg_blk(pUmDevice, &buf, 0,      0xb0,   0);
3454                 bcm5700_get_reg_blk(pUmDevice, &buf, 0xb0,   0x200,  1);
3455                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x200,  0x8f0,  0);
3456                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x8f0,  0xc00,  1);
3457                 bcm5700_get_reg_blk(pUmDevice, &buf, 0xc00,  0xce0,  0);
3458                 bcm5700_get_reg_blk(pUmDevice, &buf, 0xce0,  0x1000, 1);
3459                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1000, 0x1004, 0);
3460                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1004, 0x1400, 1);
3461                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1400, 0x1480, 0);
3462                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1480, 0x1800, 1);
3463                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1800, 0x1848, 0);
3464                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1848, 0x1c00, 1);
3465                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1c00, 0x1c04, 0);
3466                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1c04, 0x2000, 1);
3467                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2000, 0x225c, 0);
3468                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x225c, 0x2400, 1);
3469                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2400, 0x24c4, 0);
3470                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x24c4, 0x2800, 1);
3471                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2800, 0x2804, 0);
3472                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2804, 0x2c00, 1);
3473                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2c00, 0x2c20, 0);
3474                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2c20, 0x3000, 1);
3475                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3000, 0x3014, 0);
3476                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3014, 0x3400, 1);
3477                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3400, 0x3408, 0);
3478                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3408, 0x3800, 1);
3479                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3800, 0x3808, 0);
3480                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3808, 0x3c00, 1);
3481                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3c00, 0x3d00, 0);
3482                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3d00, 0x4000, 1);
3483                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4000, 0x4010, 0);
3484                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4010, 0x4400, 1);
3485                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4400, 0x4458, 0);
3486                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4458, 0x4800, 1);
3487                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4800, 0x4808, 0);
3488                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4808, 0x4c00, 1);
3489                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4c00, 0x4c08, 0);
3490                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4c08, 0x5000, 1);
3491                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5000, 0x5050, 0);
3492                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5050, 0x5400, 1);
3493                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5400, 0x5450, 0);
3494                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5450, 0x5800, 1);
3495                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5800, 0x5a10, 0);
3496                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5a10, 0x6000, 1);
3497                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x6000, 0x600c, 0);
3498                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x600c, 0x6400, 1);
3499                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x6400, 0x6404, 0);
3500                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x6404, 0x6800, 1);
3501                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x6800, 0x6848, 0);
3502                 bcm5700_get_reg_blk(pUmDevice, &buf, 0x6848, 0x6c00, 1);
3503
3504                 i = mm_copy_to_user(useraddr + sizeof(eregs), buf1, eregs.len);
3505                 kfree(buf1);
3506                 if (i)
3507                         return -EFAULT;
3508                 return 0;
3509         }
3510 #endif
3511 #endif
3512 #ifdef ETHTOOL_GPAUSEPARAM
3513         case ETHTOOL_GPAUSEPARAM: {
3514                 struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM };
3515
3516                 if (!pDevice->DisableAutoNeg) {
3517                         epause.autoneg = (pDevice->FlowControlCap &
3518                                 LM_FLOW_CONTROL_AUTO_PAUSE) != 0;
3519                 }
3520                 else {
3521                         epause.autoneg = 0;
3522                 }
3523                 epause.rx_pause =
3524                         (pDevice->FlowControl &
3525                         LM_FLOW_CONTROL_RECEIVE_PAUSE) != 0;
3526                 epause.tx_pause =
3527                         (pDevice->FlowControl &
3528                         LM_FLOW_CONTROL_TRANSMIT_PAUSE) != 0;
3529                 if (mm_copy_to_user(useraddr, &epause, sizeof(epause)))
3530                         return -EFAULT;
3531
3532                 return 0;
3533         }
3534         case ETHTOOL_SPAUSEPARAM: {
3535                 struct ethtool_pauseparam epause;
3536                 unsigned long flags;
3537
3538                 if(!capable(CAP_NET_ADMIN))
3539                         return -EPERM;
3540                 if (mm_copy_from_user(&epause, useraddr, sizeof(epause)))
3541                         return -EFAULT;
3542                 pDevice->FlowControlCap = 0;
3543                 if (epause.autoneg && !pDevice->DisableAutoNeg) {
3544                         pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
3545                 }
3546                 if (epause.rx_pause)  {
3547                         pDevice->FlowControlCap |=
3548                                 LM_FLOW_CONTROL_RECEIVE_PAUSE;
3549                 }
3550                 if (epause.tx_pause)  {
3551                         pDevice->FlowControlCap |=
3552                                 LM_FLOW_CONTROL_TRANSMIT_PAUSE;
3553                 }
3554                 if (netif_running(dev)) {
3555                         BCM5700_PHY_LOCK(pUmDevice, flags);
3556                         LM_SetupPhy(pDevice);
3557                         BCM5700_PHY_UNLOCK(pUmDevice, flags);
3558                 }
3559
3560                 return 0;
3561         }
3562 #endif
3563 #ifdef ETHTOOL_GRXCSUM
3564         case ETHTOOL_GRXCSUM: {
3565                 struct ethtool_value edata = { ETHTOOL_GRXCSUM };
3566
3567                 edata.data =
3568                         (pDevice->TaskToOffload &
3569                         LM_TASK_OFFLOAD_RX_TCP_CHECKSUM) != 0;
3570                 if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
3571                         return -EFAULT;
3572
3573                 return 0;
3574         }
3575         case ETHTOOL_SRXCSUM: {
3576                 struct ethtool_value edata;
3577
3578                 if(!capable(CAP_NET_ADMIN))
3579                         return -EPERM;
3580                 if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
3581                         return -EFAULT;
3582                 if (edata.data) {
3583                         if (!(pDevice->TaskOffloadCap &
3584                                 LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) {
3585
3586                                 return -EINVAL;
3587                         }
3588                         pDevice->TaskToOffload |=
3589                                 LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
3590                                 LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
3591                 }
3592                 else {
3593                         pDevice->TaskToOffload &=
3594                                 ~(LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
3595                                 LM_TASK_OFFLOAD_RX_UDP_CHECKSUM);
3596                 }
3597                 return 0;
3598         }
3599         case ETHTOOL_GTXCSUM: {
3600                 struct ethtool_value edata = { ETHTOOL_GTXCSUM };
3601
3602                 edata.data =
3603                         (dev->features & get_csum_flag( pDevice->ChipRevId)) != 0;
3604                 if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
3605                         return -EFAULT;
3606
3607                 return 0;
3608         }
3609         case ETHTOOL_STXCSUM: {
3610                 struct ethtool_value edata;
3611
3612                 if(!capable(CAP_NET_ADMIN))
3613                         return -EPERM;
3614                 if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
3615                         return -EFAULT;
3616                 if (edata.data) {
3617                         if (!(pDevice->TaskOffloadCap &
3618                                 LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) {
3619
3620                                 return -EINVAL;
3621                         }
3622                         dev->features |= get_csum_flag( pDevice->ChipRevId);
3623                         pDevice->TaskToOffload |=
3624                                 LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
3625                                 LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
3626                 }
3627                 else {
3628                         dev->features &= ~get_csum_flag( pDevice->ChipRevId);
3629                         pDevice->TaskToOffload &=
3630                                 ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
3631                                 LM_TASK_OFFLOAD_TX_UDP_CHECKSUM);
3632                 }
3633                 return 0;
3634         }
3635         case ETHTOOL_GSG: {
3636                 struct ethtool_value edata = { ETHTOOL_GSG };
3637
3638                 edata.data =
3639                         (dev->features & NETIF_F_SG) != 0;
3640                 if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
3641                         return -EFAULT;
3642                 return 0;
3643         }
3644         case ETHTOOL_SSG: {
3645                 struct ethtool_value edata;
3646
3647                 if(!capable(CAP_NET_ADMIN))
3648                         return -EPERM;
3649                 if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
3650                         return -EFAULT;
3651                 if (edata.data) {
3652                         dev->features |= NETIF_F_SG;
3653                 }
3654                 else {
3655                         dev->features &= ~NETIF_F_SG;
3656                 }
3657                 return 0;
3658         }
3659 #endif
3660 #ifdef ETHTOOL_GRINGPARAM
3661         case ETHTOOL_GRINGPARAM: {
3662                 struct ethtool_ringparam ering = { ETHTOOL_GRINGPARAM };
3663
3664                 ering.rx_max_pending = T3_STD_RCV_RCB_ENTRY_COUNT - 1;
3665                 ering.rx_pending = pDevice->RxStdDescCnt;
3666                 ering.rx_mini_max_pending = 0;
3667                 ering.rx_mini_pending = 0;
3668 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
3669                 ering.rx_jumbo_max_pending = T3_JUMBO_RCV_RCB_ENTRY_COUNT - 1;
3670                 ering.rx_jumbo_pending = pDevice->RxJumboDescCnt;
3671 #else
3672                 ering.rx_jumbo_max_pending = 0;
3673                 ering.rx_jumbo_pending = 0;
3674 #endif
3675                 ering.tx_max_pending = MAX_TX_PACKET_DESC_COUNT - 1;
3676                 ering.tx_pending = pDevice->TxPacketDescCnt;
3677                 if (mm_copy_to_user(useraddr, &ering, sizeof(ering)))
3678                         return -EFAULT;
3679                 return 0;
3680         }
3681 #endif
3682 #ifdef ETHTOOL_PHYS_ID
3683         case ETHTOOL_PHYS_ID: {
3684                 struct ethtool_value edata;
3685
3686                 if(!capable(CAP_NET_ADMIN))
3687                         return -EPERM;
3688                 if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
3689                         return -EFAULT;
3690                 if (LM_BlinkLED(pDevice, edata.data) == LM_STATUS_SUCCESS)
3691                         return 0;
3692                 return -EINTR;
3693         }
3694 #endif
3695 #ifdef ETHTOOL_GSTRINGS
3696         case ETHTOOL_GSTRINGS: {
3697                 struct ethtool_gstrings egstr = { ETHTOOL_GSTRINGS };
3698
3699                 if (mm_copy_from_user(&egstr, useraddr, sizeof(egstr)))
3700                         return -EFAULT;
3701                 switch(egstr.string_set) {
3702 #ifdef ETHTOOL_GSTATS
3703                 case ETH_SS_STATS:
3704                         egstr.len = ETH_NUM_STATS;
3705                         if (mm_copy_to_user(useraddr, &egstr, sizeof(egstr)))
3706                                 return -EFAULT;
3707                         if (mm_copy_to_user(useraddr + sizeof(egstr),
3708                                 bcm5700_stats_str_arr,
3709                                 sizeof(bcm5700_stats_str_arr)))
3710                                 return -EFAULT;
3711                         return 0;
3712 #endif
3713                 default:
3714                         return -EOPNOTSUPP;
3715                 }
3716                 }
3717 #endif
3718 #ifdef ETHTOOL_GSTATS
3719         case ETHTOOL_GSTATS: {
3720                 struct ethtool_stats estats = { ETHTOOL_GSTATS };
3721                 uint64_t stats[ETH_NUM_STATS];
3722                 int i;
3723                 uint64_t *pStats =
3724                         (uint64_t *) pDevice->pStatsBlkVirt;
3725
3726                 estats.n_stats = ETH_NUM_STATS;
3727                 if (pStats == 0) {
3728                         memset(stats, 0, sizeof(stats));
3729                 }
3730                 else {
3731
3732                         for (i = 0; i < ETH_NUM_STATS; i++) {
3733                                 if (bcm5700_stats_offset_arr[i] != 0) {
3734                                         stats[i] = SWAP_DWORD_64(*(pStats +
3735                                                 bcm5700_stats_offset_arr[i]));
3736                                 }
3737                                 else if (i == RX_CRC_IDX) {
3738                                         stats[i] =
3739                                                 bcm5700_crc_count(pUmDevice);
3740                                 }
3741                                 else if (i == RX_MAC_ERR_IDX) {
3742                                         stats[i] =
3743                                                 bcm5700_rx_err_count(pUmDevice);
3744                                 }
3745                         }
3746                 }
3747                 if (mm_copy_to_user(useraddr, &estats, sizeof(estats))) {
3748                         return -EFAULT;
3749                 }
3750                 if (mm_copy_to_user(useraddr + sizeof(estats), &stats,
3751                         sizeof(stats))) {
3752                         return -EFAULT;
3753                 }
3754                 return 0;
3755         }
3756 #endif
3757 #ifdef ETHTOOL_GTSO
3758         case ETHTOOL_GTSO: {
3759                 struct ethtool_value edata = { ETHTOOL_GTSO };
3760
3761 #ifdef BCM_TSO
3762                 edata.data =
3763                         (dev->features & NETIF_F_TSO) != 0;
3764 #else
3765                 edata.data = 0;
3766 #endif
3767                 if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
3768                         return -EFAULT;
3769                 return 0;
3770         }
3771 #endif
3772 #ifdef ETHTOOL_STSO
3773         case ETHTOOL_STSO: {
3774 #ifdef BCM_TSO
3775                 struct ethtool_value edata;
3776
3777                 if (!capable(CAP_NET_ADMIN))
3778                         return -EPERM;
3779
3780                 if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
3781                         return -EFAULT;
3782
3783                 if (!(pDevice->TaskToOffload &
3784                         LM_TASK_OFFLOAD_TCP_SEGMENTATION)) {
3785                         return -EINVAL;
3786                 }
3787
3788                 dev->features &= ~NETIF_F_TSO;
3789
3790                 if (edata.data) {
3791                         if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
3792                            (dev->mtu > 1500)) {
3793                                 printk(KERN_ALERT "%s: Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
3794                         return -EINVAL;
3795                         } else {
3796                                 dev->features |= NETIF_F_TSO;
3797                         }
3798                 }
3799                 return 0;
3800 #else
3801                 return -EINVAL;
3802 #endif
3803         }
3804 #endif
3805         }
3806
3807         return -EOPNOTSUPP;
3808 }
3809 #endif /* #ifdef SIOCETHTOOL */
3810
3811 #if (LINUX_VERSION_CODE >= 0x20400) && (LINUX_VERSION_CODE < 0x20600)
3812 #include <linux/iobuf.h>
3813 #endif
3814
3815 /* Provide ioctl() calls to examine the MII xcvr state. */
3816 STATIC int bcm5700_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3817 {
3818         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
3819         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
3820         u16 *data = (u16 *)&rq->ifr_data;
3821         u32 value = 0;
3822         u16 page_num =0, addr_num =0, len =0;
3823         unsigned long flags;
3824
3825         switch(cmd) {
3826         case SIOCGREG_STATUS: //Get register
3827         {
3828                 struct reg_ioctl_data *rdata =(struct reg_ioctl_data *)rq->ifr_data;
3829                 robo_info_t *robo = (robo_info_t *)pUmDevice->robo;
3830                 page_num = rdata->page_num;
3831                 addr_num = rdata->addr_num;
3832                 len = rdata->len;
3833                 printk("b57um SIOCGREG_STATUS cmd page[0x%x]addr[0x%x]len[%d].\n",page_num,addr_num,len);
3834                 if (len == 6)
3835                 {
3836                         ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
3837                         printk("val[0x%04x-0x%04x-0x%04x].\n",rdata->val_out[0],rdata->val_out[1],rdata->val_out[2]);
3838                 }
3839                 else if (len == 8)
3840                 {
3841                         ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
3842                         printk("val[0x%04x%04x-0x%04x%04x].\n",rdata->val_out[0],rdata->val_out[1],
3843                                 rdata->val_out[2],rdata->val_out[3]);
3844                 }
3845                 else if (len == 4) 
3846                 {
3847                         ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
3848                         printk("val[0x%04x%04x].\n",rdata->val_out[0],rdata->val_out[1]);
3849                 }
3850                 else 
3851                 {
3852                         ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
3853                         printk("val[0x%04x].\n",rdata->val_out[0]);
3854
3855                 }
3856                 if (mm_copy_to_user(rq->ifr_data, rdata, sizeof(struct reg_ioctl_data)))
3857                 {
3858                         printk("Fail mm_copy_to_user.\n");
3859                         return -EFAULT;
3860                 }
3861                 return 0;
3862         }
3863         break;
3864         case SIOCSREG_STATUS://Set register
3865         {
3866                 struct reg_ioctl_data * wdata =(struct reg_ioctl_data *)rq->ifr_data;
3867                 len = wdata->len;
3868                 page_num = wdata->page_num;
3869                 addr_num = wdata->addr_num;
3870                 robo_info_t *robo = (robo_info_t *)pUmDevice->robo;
3871                 if (len == 6)
3872                 {
3873                         WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
3874                         //printk("val[0x%04x-0x%04x-0x%04x].\n",val48[0],val48[1],val48[2]);
3875                 }
3876                 else if (len == 8)
3877                 {
3878                         WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
3879                         //printk("val[0x%04x-0x%04x-0x%04x-0x%04x].\n",val64[0],val64[1],val64[2],val64[3]);
3880                 }
3881                 else if (len == 4)
3882                 {
3883                         WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
3884                         //printk("val[0x%08x].\n",value);
3885                 }
3886                 else
3887                 {
3888                         WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
3889                         //printk("len[%d] val[0x%04x].\n",len,val16);
3890                 }
3891
3892                 return 0;
3893         }
3894         break;
3895 #ifdef SIOCGMIIPHY
3896         case SIOCGMIIPHY:               /* Get the address of the PHY in use. */
3897
3898                 data[0] = pDevice->PhyAddr;
3899                 return 0;
3900 #endif
3901
3902 #ifdef SIOCGMIIREG
3903         case SIOCGMIIREG:               /* Read the specified MII register. */
3904         {
3905                 uint32 savephyaddr = 0;
3906
3907                 if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
3908                         return -EOPNOTSUPP;
3909
3910                 /* ifup only waits for 5 seconds for link up */
3911                 /* NIC may take more than 5 seconds to establish link */
3912                 if ((pUmDevice->delayed_link_ind > 0) &&
3913                         delay_link[pUmDevice->index]) {
3914                         return -EAGAIN;
3915                 }
3916
3917                 BCM5700_PHY_LOCK(pUmDevice, flags);
3918                 if (data[0] != 0xffff) {
3919                         savephyaddr = pDevice->PhyAddr;
3920                         pDevice->PhyAddr = data[0];
3921                 }
3922                 LM_ReadPhy(pDevice, data[1] & 0x1f, (LM_UINT32 *)&value);
3923                 if (data[0] != 0xffff)
3924                         pDevice->PhyAddr = savephyaddr;
3925                 BCM5700_PHY_UNLOCK(pUmDevice, flags);
3926                 data[3] = value & 0xffff;
3927                 return 0;
3928         }
3929 #endif
3930
3931 #ifdef SIOCSMIIREG
3932         case SIOCSMIIREG:               /* Write the specified MII register */
3933         {
3934                 uint32 savephyaddr = 0;
3935
3936                 if (!capable(CAP_NET_ADMIN))
3937                         return -EPERM;
3938
3939                 if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
3940                         return -EOPNOTSUPP;
3941
3942                 BCM5700_PHY_LOCK(pUmDevice, flags);
3943                 if (data[0] != 0xffff) {
3944                         savephyaddr = pDevice->PhyAddr;
3945                         pDevice->PhyAddr = data[0];
3946                 }
3947                 LM_WritePhy(pDevice, data[1] & 0x1f, data[2]);
3948                 if (data[0] != 0xffff)
3949                         pDevice->PhyAddr = savephyaddr;
3950                 BCM5700_PHY_UNLOCK(pUmDevice, flags);
3951                 data[3] = 0;
3952                 return 0;
3953         }
3954 #endif
3955
3956 #ifdef SIOCETHTOOL
3957         case SIOCETHTOOL:
3958                 return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
3959 #endif
3960         default:
3961                 return -EOPNOTSUPP;
3962         }
3963         return -EOPNOTSUPP;
3964 }
3965
3966 STATIC void bcm5700_do_rx_mode(struct net_device *dev)
3967 {
3968         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
3969         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
3970         int i;
3971         struct dev_mc_list *mclist;
3972
3973         LM_MulticastClear(pDevice);
3974         for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
3975                          i++, mclist = mclist->next) {
3976                 LM_MulticastAdd(pDevice, (PLM_UINT8) &mclist->dmi_addr);
3977         }
3978         if (dev->flags & IFF_ALLMULTI) {
3979                 if (!(pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST)) {
3980                         LM_SetReceiveMask(pDevice,
3981                                 pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
3982                 }
3983         }
3984         else if (pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST) {
3985                 LM_SetReceiveMask(pDevice,
3986                         pDevice->ReceiveMask & ~LM_ACCEPT_ALL_MULTICAST);
3987         }
3988         if (dev->flags & IFF_PROMISC) {
3989                 if (!(pDevice->ReceiveMask & LM_PROMISCUOUS_MODE)) {
3990                         LM_SetReceiveMask(pDevice,
3991                                 pDevice->ReceiveMask | LM_PROMISCUOUS_MODE);
3992                 }
3993         }
3994         else if (pDevice->ReceiveMask & LM_PROMISCUOUS_MODE) {
3995                 LM_SetReceiveMask(pDevice,
3996                         pDevice->ReceiveMask & ~LM_PROMISCUOUS_MODE);
3997         }
3998
3999 }
4000
4001 STATIC void bcm5700_set_rx_mode(struct net_device *dev)
4002 {
4003         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
4004         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
4005         int i;
4006         struct dev_mc_list *mclist;
4007         unsigned long flags;
4008
4009         BCM5700_PHY_LOCK(pUmDevice, flags);
4010
4011         LM_MulticastClear(pDevice);
4012         for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
4013                          i++, mclist = mclist->next) {
4014                 LM_MulticastAdd(pDevice, (PLM_UINT8) &mclist->dmi_addr);
4015         }
4016         if (dev->flags & IFF_ALLMULTI) {
4017                 if (!(pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST)) {
4018                         LM_SetReceiveMask(pDevice,
4019                                 pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
4020                 }
4021         }
4022         else if (pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST) {
4023                 LM_SetReceiveMask(pDevice,
4024                         pDevice->ReceiveMask & ~LM_ACCEPT_ALL_MULTICAST);
4025         }
4026         if (dev->flags & IFF_PROMISC) {
4027                 if (!(pDevice->ReceiveMask & LM_PROMISCUOUS_MODE)) {
4028                         LM_SetReceiveMask(pDevice,
4029                                 pDevice->ReceiveMask | LM_PROMISCUOUS_MODE);
4030                 }
4031         }
4032         else if (pDevice->ReceiveMask & LM_PROMISCUOUS_MODE) {
4033                 LM_SetReceiveMask(pDevice,
4034                         pDevice->ReceiveMask & ~LM_PROMISCUOUS_MODE);
4035         }
4036
4037         BCM5700_PHY_UNLOCK(pUmDevice, flags);
4038 }
4039
4040 /*
4041  * Set the hardware MAC address.
4042  */
4043 STATIC int bcm5700_set_mac_addr(struct net_device *dev, void *p)
4044 {
4045         struct sockaddr *addr=p;
4046         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) dev->priv;
4047         UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
4048
4049         if(is_valid_ether_addr(addr->sa_data)){
4050
4051             memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
4052             if (pUmDevice->opened)
4053                 LM_SetMacAddress(pDevice, dev->dev_addr);
4054                         bcm_robo_set_macaddr(pUmDevice->robo, dev->dev_addr);
4055             return 0;
4056         }
4057         return -EINVAL;
4058 }
4059
4060 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
4061 STATIC int bcm5700_change_mtu(struct net_device *dev, int new_mtu)
4062 {
4063         int pkt_size = new_mtu + ETHERNET_PACKET_HEADER_SIZE;
4064         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
4065         PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
4066         unsigned long flags;
4067         int reinit = 0;
4068
4069         if ((pkt_size < MIN_ETHERNET_PACKET_SIZE_NO_CRC) ||
4070                 (pkt_size > MAX_ETHERNET_JUMBO_PACKET_SIZE_NO_CRC)) {
4071
4072                 return -EINVAL;
4073         }
4074         if ( !(pDevice->Flags & JUMBO_CAPABLE_FLAG)    &&
4075                 (pkt_size > MAX_ETHERNET_PACKET_SIZE_NO_CRC) ) {
4076
4077                 return -EINVAL;
4078         }
4079         if (pUmDevice->suspended)
4080                 return -EAGAIN;
4081
4082         if (pUmDevice->opened && (new_mtu != dev->mtu) &&
4083                 (pDevice->Flags & JUMBO_CAPABLE_FLAG)) {
4084                 reinit = 1;
4085         }
4086
4087         BCM5700_PHY_LOCK(pUmDevice, flags);
4088         if (reinit) {
4089                 netif_stop_queue(dev);
4090                 bcm5700_shutdown(pUmDevice);
4091                 bcm5700_freemem(dev);
4092         }
4093
4094         dev->mtu = new_mtu;
4095         if (pkt_size < MAX_ETHERNET_PACKET_SIZE_NO_CRC) {
4096                 pDevice->RxMtu = pDevice->TxMtu =
4097                         MAX_ETHERNET_PACKET_SIZE_NO_CRC;
4098         }
4099         else {
4100                 pDevice->RxMtu = pDevice->TxMtu = pkt_size;
4101         }
4102
4103         if (dev->mtu <= 1514)  {
4104                 pDevice->RxJumboDescCnt = 0;
4105         }
4106         else if (pDevice->Flags & JUMBO_CAPABLE_FLAG){
4107                 pDevice->RxJumboDescCnt =
4108                         rx_jumbo_desc_cnt[pUmDevice->index];
4109         }
4110         pDevice->RxPacketDescCnt = pDevice->RxJumboDescCnt +
4111                 pDevice->RxStdDescCnt;
4112
4113         pDevice->RxJumboBufferSize = (pDevice->RxMtu + 8 /* CRC + VLAN */ +
4114                 COMMON_CACHE_LINE_SIZE-1) & ~COMMON_CACHE_LINE_MASK;
4115
4116 #ifdef BCM_TSO
4117         if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
4118            (dev->mtu > 1514) ) {
4119                 if (dev->features & NETIF_F_TSO) {
4120                         dev->features &= ~NETIF_F_TSO;
4121                         printk(KERN_ALERT "%s: TSO previously enabled. Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
4122                 }
4123         }
4124 #endif
4125
4126         if (reinit) {
4127                 LM_InitializeAdapter(pDevice);
4128                 bcm5700_do_rx_mode(dev);
4129                 bcm5700_set_vlan_mode(pUmDevice);
4130                 bcm5700_init_counters(pUmDevice);
4131                 if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) {
4132                         LM_SetMacAddress(pDevice, dev->dev_addr);
4133                 }
4134                 netif_start_queue(dev);
4135                 bcm5700_intr_on(pUmDevice);
4136         }
4137         BCM5700_PHY_UNLOCK(pUmDevice, flags);
4138
4139         return 0;
4140 }
4141 #endif
4142
4143
4144 #if (LINUX_VERSION_CODE < 0x020300)
4145 int
4146 bcm5700_probe(struct net_device *dev)
4147 {
4148         int cards_found = 0;
4149         struct pci_dev *pdev = NULL;
4150         struct pci_device_id *pci_tbl;
4151         u16 ssvid, ssid;
4152
4153         if ( ! pci_present())
4154                 return -ENODEV;
4155
4156         pci_tbl = bcm5700_pci_tbl;
4157         while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
4158                 int idx;
4159
4160                 pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &ssvid);
4161                 pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &ssid);
4162                 for (idx = 0; pci_tbl[idx].vendor; idx++) {
4163                         if ((pci_tbl[idx].vendor == PCI_ANY_ID ||
4164                                 pci_tbl[idx].vendor == pdev->vendor) &&
4165                                 (pci_tbl[idx].device == PCI_ANY_ID ||
4166                                 pci_tbl[idx].device == pdev->device) &&
4167                                 (pci_tbl[idx].subvendor == PCI_ANY_ID ||
4168                                 pci_tbl[idx].subvendor == ssvid) &&
4169                                 (pci_tbl[idx].subdevice == PCI_ANY_ID ||
4170                                 pci_tbl[idx].subdevice == ssid))
4171                         {
4172
4173                                 break;
4174                         }
4175                 }
4176                 if (pci_tbl[idx].vendor == 0)
4177                         continue;
4178
4179
4180                 if (bcm5700_init_one(pdev, &pci_tbl[idx]) == 0)
4181                         cards_found++;
4182         }
4183
4184         return cards_found ? 0 : -ENODEV;
4185 }
4186
4187 #ifdef MODULE
4188 int init_module(void)
4189 {
4190         return bcm5700_probe(NULL);
4191 }
4192
4193 void cleanup_module(void)
4194 {
4195         struct net_device *next_dev;
4196         PUM_DEVICE_BLOCK pUmDevice;
4197
4198         /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
4199         while (root_tigon3_dev) {
4200                 pUmDevice = (PUM_DEVICE_BLOCK)root_tigon3_dev->priv;
4201                 next_dev = pUmDevice->next_module;
4202                 unregister_netdev(root_tigon3_dev);
4203                 if (pUmDevice->lm_dev.pMappedMemBase)
4204                         iounmap(pUmDevice->lm_dev.pMappedMemBase);
4205 #if (LINUX_VERSION_CODE < 0x020600)
4206                 kfree(root_tigon3_dev);
4207 #else
4208                 free_netdev(root_tigon3_dev);
4209 #endif
4210                 root_tigon3_dev = next_dev;
4211         }
4212 #ifdef BCM_IOCTL32
4213         unregister_ioctl32_conversion(SIOCNICE);
4214 #endif
4215 }
4216
4217 #endif  /* MODULE */
4218 #else   /* LINUX_VERSION_CODE < 0x020300 */
4219
4220 #if (LINUX_VERSION_CODE >= 0x020406)
4221 static int bcm5700_suspend (struct pci_dev *pdev, u32 state)
4222 #else
4223 static void bcm5700_suspend (struct pci_dev *pdev)
4224 #endif
4225 {
4226         struct net_device *dev = (struct net_device *) pci_get_drvdata(pdev);
4227         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
4228         PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
4229
4230         if (!netif_running(dev))
4231 #if (LINUX_VERSION_CODE >= 0x020406)
4232                 return 0;
4233 #else
4234                 return;
4235 #endif
4236
4237         netif_device_detach (dev);
4238         bcm5700_shutdown(pUmDevice);
4239
4240         LM_SetPowerState(pDevice, LM_POWER_STATE_D3);
4241
4242 /*      pci_power_off(pdev, -1);*/
4243 #if (LINUX_VERSION_CODE >= 0x020406)
4244         return 0;
4245 #endif
4246 }
4247
4248
4249 #if (LINUX_VERSION_CODE >= 0x020406)
4250 static int bcm5700_resume(struct pci_dev *pdev)
4251 #else
4252 static void bcm5700_resume(struct pci_dev *pdev)
4253 #endif
4254 {
4255         struct net_device *dev = (struct net_device *) pci_get_drvdata(pdev);
4256         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
4257         PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
4258
4259         if (!netif_running(dev))
4260 #if (LINUX_VERSION_CODE >= 0x020406)
4261                 return 0;
4262 #else
4263                 return;
4264 #endif
4265 /*      pci_power_on(pdev);*/
4266         netif_device_attach(dev);
4267         LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
4268         MM_InitializeUmPackets(pDevice);
4269         bcm5700_reset(dev);
4270 #if (LINUX_VERSION_CODE >= 0x020406)
4271         return 0;
4272 #endif
4273 }
4274
4275
4276 static struct pci_driver bcm5700_pci_driver = {
4277         name:           bcm5700_driver,
4278         id_table:       bcm5700_pci_tbl,
4279         probe:          bcm5700_init_one,
4280         remove:         __devexit_p(bcm5700_remove_one),
4281         suspend:        bcm5700_suspend,
4282         resume:         bcm5700_resume,
4283 };
4284
4285 static int
4286 bcm5700_notify_reboot(struct notifier_block *this, unsigned long event, void *unused)
4287 {
4288         switch (event) {
4289         case SYS_HALT:
4290         case SYS_POWER_OFF:
4291         case SYS_RESTART:
4292                 break;
4293         default:
4294                 return NOTIFY_DONE;
4295         }
4296
4297         B57_INFO(("bcm5700 reboot notification\n"));
4298         pci_unregister_driver(&bcm5700_pci_driver);
4299         return NOTIFY_DONE;
4300 }
4301
4302 static int __init bcm5700_init_module (void)
4303 {
4304         int pin = 1 << 2;
4305
4306         if (nvram_match("disabled_5397", "1") || (activate_gpio != -1)) {
4307                 if ( activate_gpio != -1 ) pin = activate_gpio;
4308                 printk("5397 switch GPIO-Reset (pin %d)\n", pin);
4309                 sb_t *gpio_sbh;
4310                 if (!(gpio_sbh = sb_kattach(SB_OSH))) return -ENODEV;
4311                 sb_gpiosetcore(gpio_sbh);
4312 //              sb_gpioreserve(gpio_sbh, 0x4, GPIO_HI_PRIORITY);
4313                 sb_gpioouten(gpio_sbh, 0x4, 0x4, GPIO_HI_PRIORITY);
4314                 sb_gpioout(gpio_sbh, 0x4, 0x4, GPIO_HI_PRIORITY);
4315                 sb_detach(gpio_sbh);
4316         }
4317
4318         if (msglevel != 0xdeadbeef) {
4319                 b57_msg_level = msglevel;
4320                 printf("%s: msglevel set to 0x%x\n", __FUNCTION__, b57_msg_level);
4321         } else
4322                 b57_msg_level = B57_ERR_VAL;
4323
4324         return pci_module_init(&bcm5700_pci_driver);
4325 }
4326
4327 static void __exit bcm5700_cleanup_module (void)
4328 {
4329         unregister_reboot_notifier(&bcm5700_reboot_notifier);
4330         pci_unregister_driver(&bcm5700_pci_driver);
4331 }
4332
4333 module_init(bcm5700_init_module);
4334 module_exit(bcm5700_cleanup_module);
4335 #endif
4336
4337 /*
4338  * Middle Module
4339  *
4340  */
4341
4342
4343 #ifdef BCM_NAPI_RXPOLL
4344 LM_STATUS
4345 MM_ScheduleRxPoll(LM_DEVICE_BLOCK *pDevice)
4346 {
4347         struct net_device *dev = ((UM_DEVICE_BLOCK *) pDevice)->dev;
4348
4349         if (netif_rx_schedule_prep(dev)) {
4350                 __netif_rx_schedule(dev);
4351                 return LM_STATUS_SUCCESS;
4352         }
4353         return LM_STATUS_FAILURE;
4354 }
4355 #endif
4356
4357 LM_STATUS
4358 MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
4359         LM_UINT16 *pValue16)
4360 {
4361         UM_DEVICE_BLOCK *pUmDevice;
4362
4363         pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
4364         pci_read_config_word(pUmDevice->pdev, Offset, (u16 *) pValue16);
4365         return LM_STATUS_SUCCESS;
4366 }
4367
4368 LM_STATUS
4369 MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
4370         LM_UINT32 *pValue32)
4371 {
4372         UM_DEVICE_BLOCK *pUmDevice;
4373
4374         pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
4375         pci_read_config_dword(pUmDevice->pdev, Offset, (u32 *) pValue32);
4376         return LM_STATUS_SUCCESS;
4377 }
4378
4379 LM_STATUS
4380 MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
4381         LM_UINT16 Value16)
4382 {
4383         UM_DEVICE_BLOCK *pUmDevice;
4384
4385         pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
4386         pci_write_config_word(pUmDevice->pdev, Offset, Value16);
4387         return LM_STATUS_SUCCESS;
4388 }
4389
4390 LM_STATUS
4391 MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
4392         LM_UINT32 Value32)
4393 {
4394         UM_DEVICE_BLOCK *pUmDevice;
4395
4396         pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
4397         pci_write_config_dword(pUmDevice->pdev, Offset, Value32);
4398         return LM_STATUS_SUCCESS;
4399 }
4400
4401 LM_STATUS
4402 MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
4403         PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy,
4404         LM_BOOL Cached)
4405 {
4406         PLM_VOID pvirt;
4407         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
4408         dma_addr_t mapping;
4409
4410         pvirt = pci_alloc_consistent(pUmDevice->pdev, BlockSize,
4411                                                &mapping);
4412         if (!pvirt) {
4413                 return LM_STATUS_FAILURE;
4414         }
4415         pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
4416         pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping;
4417         pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
4418         memset(pvirt, 0, BlockSize);
4419         *pMemoryBlockVirt = (PLM_VOID) pvirt;
4420         MM_SetAddr(pMemoryBlockPhy, mapping);
4421         return LM_STATUS_SUCCESS;
4422 }
4423
4424 LM_STATUS
4425 MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
4426         PLM_VOID *pMemoryBlockVirt)
4427 {
4428         PLM_VOID pvirt;
4429         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
4430
4431
4432         /* Maximum in slab.c */
4433         if (BlockSize > 131072) {
4434                 goto MM_Alloc_error;
4435         }
4436
4437         pvirt = kmalloc(BlockSize, GFP_ATOMIC);
4438         if (!pvirt) {
4439                 goto MM_Alloc_error;
4440         }
4441         pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
4442         pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
4443         pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = 0;
4444         /* mem_size_list[i] == 0 indicates that the memory should be freed */
4445         /* using kfree */
4446         memset(pvirt, 0, BlockSize);
4447         *pMemoryBlockVirt = pvirt;
4448         return LM_STATUS_SUCCESS;
4449
4450 MM_Alloc_error:
4451         printk(KERN_WARNING "%s: Memory allocation failed - buffer parameters may be set too high\n", pUmDevice->dev->name);
4452         return LM_STATUS_FAILURE;
4453 }
4454
4455 LM_STATUS
4456 MM_MapMemBase(PLM_DEVICE_BLOCK pDevice)
4457 {
4458         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
4459
4460         pDevice->pMappedMemBase = ioremap_nocache(
4461                 pci_resource_start(pUmDevice->pdev, 0), sizeof(T3_STD_MEM_MAP));
4462         if (pDevice->pMappedMemBase == 0)
4463                 return LM_STATUS_FAILURE;
4464
4465         return LM_STATUS_SUCCESS;
4466 }
4467
4468 LM_STATUS
4469 MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice)
4470 {
4471         unsigned int i;
4472         struct sk_buff *skb;
4473         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
4474         PUM_PACKET pUmPacket;
4475         PLM_PACKET pPacket;
4476
4477         for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
4478                 pPacket = QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
4479                 pUmPacket = (PUM_PACKET) pPacket;
4480                 if (pPacket == 0) {
4481                         printk(KERN_DEBUG "Bad RxPacketFreeQ\n");
4482                 }
4483                 if (pUmPacket->skbuff == 0) {
4484 #ifdef BCM_WL_EMULATOR
4485                         skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2);
4486 #else
4487                         skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR);
4488 #endif
4489                         if (skb == 0) {
4490                                 pUmPacket->skbuff = 0;
4491                                 QQ_PushTail(
4492                                         &pUmDevice->rx_out_of_buf_q.Container,
4493                                         pPacket);
4494                                 continue;
4495                         }
4496                         pUmPacket->skbuff = skb;
4497                         skb->dev = pUmDevice->dev;
4498 #ifndef BCM_WL_EMULATOR
4499                         skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align);
4500 #endif
4501                 }
4502                 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
4503         }
4504         if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
4505                 /* reallocate buffers in the ISR */
4506                 pUmDevice->rx_buf_repl_thresh = 0;
4507                 pUmDevice->rx_buf_repl_panic_thresh = 0;
4508                 pUmDevice->rx_buf_repl_isr_limit = 0;
4509         }
4510         else {
4511                 pUmDevice->rx_buf_repl_thresh = pDevice->RxPacketDescCnt / 8;
4512                 pUmDevice->rx_buf_repl_panic_thresh =
4513                         pDevice->RxPacketDescCnt  * 7 / 8;
4514
4515                 /* This limits the time spent in the ISR when the receiver */
4516                 /* is in a steady state of being overrun. */
4517                 pUmDevice->rx_buf_repl_isr_limit = pDevice->RxPacketDescCnt / 8;
4518
4519 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
4520                 if (pDevice->RxJumboDescCnt != 0) {
4521                         if (pUmDevice->rx_buf_repl_thresh >=
4522                                 pDevice->RxJumboDescCnt) {
4523
4524                                 pUmDevice->rx_buf_repl_thresh =
4525                                 pUmDevice->rx_buf_repl_panic_thresh =
4526                                         pDevice->RxJumboDescCnt - 1;
4527                         }
4528                         if (pUmDevice->rx_buf_repl_thresh >=
4529                                 pDevice->RxStdDescCnt) {
4530
4531                                 pUmDevice->rx_buf_repl_thresh =
4532                                 pUmDevice->rx_buf_repl_panic_thresh =
4533                                         pDevice->RxStdDescCnt - 1;
4534                         }
4535                 }
4536 #endif
4537         }
4538         return LM_STATUS_SUCCESS;
4539 }
4540
4541 LM_STATUS
4542 MM_GetConfig(PLM_DEVICE_BLOCK pDevice)
4543 {
4544         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
4545         int index = pUmDevice->index;
4546         struct net_device *dev = pUmDevice->dev;
4547
4548         if (index >= MAX_UNITS)
4549                 return LM_STATUS_SUCCESS;
4550
4551 #if LINUX_KERNEL_VERSION < 0x0020609
4552
4553         bcm5700_validate_param_range(pUmDevice, &auto_speed[index], "auto_speed",
4554                 0, 1, 1);
4555         if (auto_speed[index] == 0)
4556                 pDevice->DisableAutoNeg = TRUE;
4557         else
4558                 pDevice->DisableAutoNeg = FALSE;
4559
4560         if (line_speed[index] == 0) {
4561                 pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
4562                 pDevice->DisableAutoNeg = FALSE;
4563         }
4564         else {
4565                 bcm5700_validate_param_range(pUmDevice, &full_duplex[index],
4566                         "full_duplex", 0, 1, 1);
4567                 if (full_duplex[index]) {
4568                         pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL;
4569                 }
4570                 else {
4571                         pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_HALF;
4572                 }
4573
4574                 if (line_speed[index] == 1000) {
4575                         pDevice->RequestedLineSpeed = LM_LINE_SPEED_1000MBPS;
4576                         if (pDevice->PhyFlags & PHY_NO_GIGABIT) {
4577                                 pDevice->RequestedLineSpeed =
4578                                         LM_LINE_SPEED_100MBPS;
4579                                 printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (1000), using 100\n", bcm5700_driver, index);
4580                         }
4581                         else {
4582                                 if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
4583                                         !full_duplex[index]) {
4584                                         printk(KERN_WARNING "%s-%d: Invalid full_duplex parameter (0) for fiber, using 1\n", bcm5700_driver, index);
4585                                         pDevice->RequestedDuplexMode =
4586                                                 LM_DUPLEX_MODE_FULL;
4587                                 }
4588
4589                                 if (!(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
4590                                         !auto_speed[index] && !(pDevice->PhyFlags & PHY_IS_FIBER) ) {
4591                                         printk(KERN_WARNING "%s-%d: Invalid auto_speed parameter (0) for copper, using 1\n", bcm5700_driver, index);
4592                                         pDevice->DisableAutoNeg = FALSE;
4593                                 }
4594                         }
4595                 }
4596                 else if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) ||
4597                          (pDevice->PhyFlags & PHY_IS_FIBER)){
4598                          pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
4599                          pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL;
4600                          pDevice->DisableAutoNeg = FALSE;
4601                          printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (%d), using auto\n", bcm5700_driver, index, line_speed[index]);
4602                 }
4603                 else if (line_speed[index] == 100) {
4604
4605                         pDevice->RequestedLineSpeed = LM_LINE_SPEED_100MBPS;
4606                 }
4607                 else if (line_speed[index] == 10) {
4608
4609                         pDevice->RequestedLineSpeed = LM_LINE_SPEED_10MBPS;
4610                 }
4611                 else {
4612                         pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
4613                         pDevice->DisableAutoNeg = FALSE;
4614                         printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (%d), using 0\n", bcm5700_driver, index, line_speed[index]);
4615                 }
4616
4617         }
4618
4619 #endif /* LINUX_KERNEL_VERSION */
4620
4621         /* This is an unmanageable switch nic and will have link problems if
4622            not set to auto
4623         */
4624         if(pDevice->SubsystemVendorId==0x103c && pDevice->SubsystemId==0x3226)
4625         {
4626             if(pDevice->RequestedLineSpeed != LM_LINE_SPEED_AUTO)
4627             {
4628                 printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (%d), using 0\n",
4629                         bcm5700_driver, index, line_speed[index]);
4630             }
4631             pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
4632             pDevice->DisableAutoNeg = FALSE;
4633         }
4634
4635 #if LINUX_KERNEL_VERSION < 0x0020609
4636
4637         pDevice->FlowControlCap = 0;
4638         bcm5700_validate_param_range(pUmDevice, &rx_flow_control[index],
4639                 "rx_flow_control", 0, 1, 0);
4640         if (rx_flow_control[index] != 0) {
4641                 pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
4642         }
4643         bcm5700_validate_param_range(pUmDevice, &tx_flow_control[index],
4644                 "tx_flow_control", 0, 1, 0);
4645         if (tx_flow_control[index] != 0) {
4646                 pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
4647         }
4648         bcm5700_validate_param_range(pUmDevice, &auto_flow_control[index],
4649                 "auto_flow_control", 0, 1, 0);
4650         if (auto_flow_control[index] != 0) {
4651                 if (pDevice->DisableAutoNeg == FALSE) {
4652
4653                         pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
4654                         if ((tx_flow_control[index] == 0) &&
4655                                 (rx_flow_control[index] == 0)) {
4656
4657                                 pDevice->FlowControlCap |=
4658                                         LM_FLOW_CONTROL_TRANSMIT_PAUSE |
4659                                         LM_FLOW_CONTROL_RECEIVE_PAUSE;
4660                         }
4661                 }
4662         }
4663
4664         if (dev->mtu > 1500) {
4665 #ifdef BCM_TSO
4666                 if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
4667                    (dev->features & NETIF_F_TSO)) {
4668                                 dev->features &= ~NETIF_F_TSO;
4669                                 printk(KERN_ALERT "%s: TSO previously enabled. Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
4670                 }
4671 #endif
4672                 pDevice->RxMtu = dev->mtu + 14;
4673         }
4674
4675         if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) &&
4676                 !(pDevice->Flags & BCM5788_FLAG)) {
4677                 pDevice->Flags |= USE_TAGGED_STATUS_FLAG;
4678                 pUmDevice->timer_interval = HZ;
4679                 if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) &&
4680                         (pDevice->TbiFlags & ENABLE_TBI_FLAG)) {
4681                         pUmDevice->timer_interval = HZ/4;
4682                 }
4683         }
4684         else {
4685                 pUmDevice->timer_interval = HZ/10;
4686         }
4687
4688         bcm5700_validate_param_range(pUmDevice, &tx_pkt_desc_cnt[index],
4689                 "tx_pkt_desc_cnt", 1, MAX_TX_PACKET_DESC_COUNT-1, TX_DESC_CNT);
4690         pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
4691         bcm5700_validate_param_range(pUmDevice, &rx_std_desc_cnt[index],
4692                 "rx_std_desc_cnt", 1, T3_STD_RCV_RCB_ENTRY_COUNT-1,
4693                 RX_DESC_CNT);
4694         pDevice->RxStdDescCnt = rx_std_desc_cnt[index];
4695
4696 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
4697         bcm5700_validate_param_range(pUmDevice, &rx_jumbo_desc_cnt[index],
4698                 "rx_jumbo_desc_cnt", 1, T3_JUMBO_RCV_RCB_ENTRY_COUNT-1,
4699                 JBO_DESC_CNT);
4700
4701         if (mtu[index] <= 1514)
4702                 pDevice->RxJumboDescCnt = 0;
4703         else if(!T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)){
4704                 pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
4705         }
4706 #endif
4707
4708 #ifdef BCM_INT_COAL
4709         bcm5700_validate_param_range(pUmDevice, &adaptive_coalesce[index],
4710                 "adaptive_coalesce", 0, 1, 1);
4711 #ifdef BCM_NAPI_RXPOLL
4712         if (adaptive_coalesce[index]) {
4713                 printk(KERN_WARNING "%s-%d: adaptive_coalesce not used in NAPI mode\n", bcm5700_driver, index);
4714                 adaptive_coalesce[index] = 0;
4715
4716         }
4717 #endif
4718         pUmDevice->adaptive_coalesce = adaptive_coalesce[index];
4719         if (!pUmDevice->adaptive_coalesce) {
4720                 bcm5700_validate_param_range(pUmDevice,
4721                         &rx_coalesce_ticks[index], "rx_coalesce_ticks", 0,
4722                         MAX_RX_COALESCING_TICKS, RX_COAL_TK);
4723                 if ((rx_coalesce_ticks[index] == 0) &&
4724                         (rx_max_coalesce_frames[index] == 0)) {
4725
4726                         printk(KERN_WARNING "%s-%d: Conflicting rx_coalesce_ticks (0) and rx_max_coalesce_frames (0) parameters, using %d and %d respectively\n",
4727                                 bcm5700_driver, index, RX_COAL_TK, RX_COAL_FM);
4728
4729                         rx_coalesce_ticks[index] = RX_COAL_TK;
4730                         rx_max_coalesce_frames[index] = RX_COAL_FM;
4731                 }
4732                 pDevice->RxCoalescingTicks = pUmDevice->rx_curr_coalesce_ticks =
4733                         rx_coalesce_ticks[index];
4734 #ifdef BCM_NAPI_RXPOLL
4735                 pDevice->RxCoalescingTicksDuringInt = rx_coalesce_ticks[index];
4736 #endif
4737
4738                 bcm5700_validate_param_range(pUmDevice,
4739                         &rx_max_coalesce_frames[index],
4740                         "rx_max_coalesce_frames", 0,
4741                         MAX_RX_MAX_COALESCED_FRAMES, RX_COAL_FM);
4742
4743                 pDevice->RxMaxCoalescedFrames =
4744                         pUmDevice->rx_curr_coalesce_frames =
4745                         rx_max_coalesce_frames[index];
4746 #ifdef BCM_NAPI_RXPOLL
4747                 pDevice->RxMaxCoalescedFramesDuringInt =
4748                         rx_max_coalesce_frames[index];
4749 #endif
4750
4751                 bcm5700_validate_param_range(pUmDevice,
4752                         &tx_coalesce_ticks[index], "tx_coalesce_ticks", 0,
4753                         MAX_TX_COALESCING_TICKS, TX_COAL_TK);
4754                 if ((tx_coalesce_ticks[index] == 0) &&
4755                         (tx_max_coalesce_frames[index] == 0)) {
4756
4757                         printk(KERN_WARNING "%s-%d: Conflicting tx_coalesce_ticks (0) and tx_max_coalesce_frames (0) parameters, using %d and %d respectively\n",
4758                                 bcm5700_driver, index, TX_COAL_TK, TX_COAL_FM);
4759
4760                         tx_coalesce_ticks[index] = TX_COAL_TK;
4761                         tx_max_coalesce_frames[index] = TX_COAL_FM;
4762                 }
4763                 pDevice->TxCoalescingTicks = tx_coalesce_ticks[index];
4764                 bcm5700_validate_param_range(pUmDevice,
4765                         &tx_max_coalesce_frames[index],
4766                         "tx_max_coalesce_frames", 0,
4767                         MAX_TX_MAX_COALESCED_FRAMES, TX_COAL_FM);
4768                 pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index];
4769                 pUmDevice->tx_curr_coalesce_frames =
4770                         pDevice->TxMaxCoalescedFrames;
4771
4772                 bcm5700_validate_param_range(pUmDevice,
4773                         &stats_coalesce_ticks[index], "stats_coalesce_ticks",
4774                         0, MAX_STATS_COALESCING_TICKS, ST_COAL_TK);
4775                 if (adaptive_coalesce[index]) {
4776                         printk(KERN_WARNING "%s-%d: Invalid stats_coalesce_ticks parameter set with with adaptive_coalesce parameter. Using adaptive_coalesce.\n", bcm5700_driver, index);
4777                 }else{
4778                         if ((stats_coalesce_ticks[index] > 0) &&
4779                                 (stats_coalesce_ticks[index] < 100)) {
4780                                 printk(KERN_WARNING "%s-%d: Invalid stats_coalesce_ticks parameter (%u), using 100\n", bcm5700_driver, index, (unsigned int) stats_coalesce_ticks[index]);
4781                                 stats_coalesce_ticks[index] = 100;
4782                                 pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
4783                                 pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
4784                         }
4785                 }
4786         }
4787         else {
4788                 pUmDevice->rx_curr_coalesce_frames = RX_COAL_FM;
4789                 pUmDevice->rx_curr_coalesce_ticks = RX_COAL_TK;
4790                 pUmDevice->tx_curr_coalesce_frames = TX_COAL_FM;
4791         }
4792 #endif
4793
4794         if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) {
4795                 unsigned int tmpvar;
4796
4797                 tmpvar = pDevice->StatsCoalescingTicks / BCM_TIMER_GRANULARITY;
4798
4799                 /*
4800                  * If the result is zero, the request is too demanding.
4801                  */
4802                 if (tmpvar == 0) {
4803                         tmpvar = 1;
4804                 }
4805
4806                 pDevice->StatsCoalescingTicks = tmpvar * BCM_TIMER_GRANULARITY;
4807
4808                 pUmDevice->statstimer_interval = tmpvar;
4809         }
4810
4811 #ifdef BCM_WOL
4812         bcm5700_validate_param_range(pUmDevice, &enable_wol[index],
4813                 "enable_wol", 0, 1, 0);
4814         if (enable_wol[index]) {
4815                 pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
4816                 pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
4817         }
4818 #endif
4819 #ifdef INCLUDE_TBI_SUPPORT
4820         if (pDevice->TbiFlags & ENABLE_TBI_FLAG) {
4821                 if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) ||
4822                         (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)) {
4823                         /* just poll since we have hardware autoneg. in 5704 */
4824                         pDevice->TbiFlags |= TBI_PURE_POLLING_FLAG;
4825                 }
4826                 else {
4827                         pDevice->TbiFlags |= TBI_POLLING_INTR_FLAG;
4828                 }
4829         }
4830 #endif
4831         bcm5700_validate_param_range(pUmDevice, &scatter_gather[index],
4832                 "scatter_gather", 0, 1, 1);
4833         bcm5700_validate_param_range(pUmDevice, &tx_checksum[index],
4834                 "tx_checksum", 0, 1, 1);
4835         bcm5700_validate_param_range(pUmDevice, &rx_checksum[index],
4836                 "rx_checksum", 0, 1, 1);
4837         if (!(pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) {
4838                 if (tx_checksum[index] || rx_checksum[index]) {
4839
4840                         pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
4841                         printk(KERN_WARNING "%s-%d: Checksum offload not available on this NIC\n", bcm5700_driver, index);
4842                 }
4843         }
4844         else {
4845                 if (rx_checksum[index]) {
4846                         pDevice->TaskToOffload |=
4847                                 LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
4848                                 LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
4849                 }
4850                 if (tx_checksum[index]) {
4851                         pDevice->TaskToOffload |=
4852                                 LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
4853                                 LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
4854                         pDevice->Flags |= NO_TX_PSEUDO_HDR_CSUM_FLAG;
4855                 }
4856         }
4857 #ifdef BCM_TSO
4858         bcm5700_validate_param_range(pUmDevice, &enable_tso[index],
4859                 "enable_tso", 0, 1, 1);
4860
4861         /* Always enable TSO firmware if supported */
4862         /* This way we can turn it on or off on the fly */
4863         if (pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TCP_SEGMENTATION)
4864         {
4865                 pDevice->TaskToOffload |=
4866                         LM_TASK_OFFLOAD_TCP_SEGMENTATION;
4867         }
4868         if (enable_tso[index] &&
4869                 !(pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION))
4870         {
4871                 printk(KERN_WARNING "%s-%d: TSO not available on this NIC\n", bcm5700_driver, index);
4872         }
4873 #endif
4874 #ifdef BCM_ASF
4875         bcm5700_validate_param_range(pUmDevice, &vlan_tag_mode[index],
4876                 "vlan_strip_mode", 0, 2, 0);
4877         pUmDevice->vlan_tag_mode = vlan_tag_mode[index];
4878 #else
4879         pUmDevice->vlan_tag_mode = VLAN_TAG_MODE_NORMAL_STRIP;
4880 #endif
4881
4882 #endif /* LINUX_KERNEL_VERSION */
4883
4884 #ifdef BCM_NIC_SEND_BD
4885         bcm5700_validate_param_range(pUmDevice, &nic_tx_bd[index], "nic_tx_bd",
4886                 0, 1, 0);
4887         if (nic_tx_bd[index])
4888                 pDevice->Flags |= NIC_SEND_BD_FLAG;
4889         if ((pDevice->Flags & ENABLE_PCIX_FIX_FLAG) ||
4890                 (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)) {
4891                 if (pDevice->Flags & NIC_SEND_BD_FLAG) {
4892                         pDevice->Flags &= ~NIC_SEND_BD_FLAG;
4893                         printk(KERN_WARNING "%s-%d: Nic Send BDs not available on this NIC or not possible on this system\n", bcm5700_driver, index);
4894                 }
4895         }
4896 #endif
4897 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
4898         bcm5700_validate_param_range(pUmDevice, &disable_msi[pUmDevice->index],
4899                 "disable_msi", 0, 1, 0);
4900 #endif
4901
4902         bcm5700_validate_param_range(pUmDevice, &delay_link[index],
4903                 "delay_link", 0, 1, 0);
4904
4905         bcm5700_validate_param_range(pUmDevice, &disable_d3hot[index],
4906                 "disable_d3hot", 0, 1, 0);
4907         if (disable_d3hot[index]) {
4908
4909 #ifdef BCM_WOL
4910                 if (enable_wol[index]) {
4911                         pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE;
4912                         pDevice->WakeUpMode = LM_WAKE_UP_MODE_NONE;
4913                         printk(KERN_WARNING "%s-%d: Wake-On-Lan disabled because D3Hot is disabled\n", bcm5700_driver, index);
4914                 }
4915 #endif
4916                 pDevice->Flags |= DISABLE_D3HOT_FLAG;
4917         }
4918
4919     return LM_STATUS_SUCCESS;
4920 }
4921
4922 /* From include/proto/ethernet.h */
4923 #define ETHER_TYPE_8021Q        0x8100          /* 802.1Q */
4924
4925 /* From include/proto/vlan.h */
4926 #define VLAN_PRI_MASK           7       /* 3 bits of priority */
4927 #define VLAN_PRI_SHIFT          13
4928
4929 /* Replace the priority in a vlan tag */
4930 #define UPD_VLANTAG_PRIO(tag, prio) do { \
4931         tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); \
4932         tag |= prio << VLAN_PRI_SHIFT; \
4933 } while (0)
4934
4935 /* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
4936  * Also updates the inplace vlan tag if requested.
4937  * For debugging, it returns an indication of what it did.
4938  */
4939 #define PKTPRIO_VDSCP   0x100           /* DSCP prio found after VLAN tag */
4940 #define PKTPRIO_VLAN    0x200           /* VLAN prio found */
4941 #define PKTPRIO_UPD     0x400           /* DSCP used to update VLAN prio */
4942 #define PKTPRIO_DSCP    0x800           /* DSCP prio found */
4943 #define PKTSETPRIO(skb, x)              (((struct sk_buff*)(skb))->priority = (x))
4944 static uint
4945 pktsetprio(void *pkt, bool update_vtag)
4946 {
4947         struct ether_header *eh;
4948         struct ethervlan_header *evh;
4949         uint8 *pktdata;
4950         int priority = 0;
4951         int rc = 0;
4952
4953         pktdata = (uint8 *) PKTDATA(NULL, pkt);
4954         ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
4955
4956         eh = (struct ether_header *) pktdata;
4957
4958         if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) {
4959                 uint16 vlan_tag;
4960                 int vlan_prio, dscp_prio = 0;
4961
4962                 evh = (struct ethervlan_header *)eh;
4963
4964                 vlan_tag = ntoh16(evh->vlan_tag);
4965                 vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
4966
4967                 if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) {
4968                         uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
4969                         uint8 tos_tc = IP_TOS(ip_body);
4970                         dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
4971                         if ((IP_VER(ip_body) == IP_VER_4) && (IPV4_PROT(ip_body) == IP_PROT_TCP)) {
4972                                 int ip_len;
4973                                 int src_port;
4974                                 bool src_port_exc;
4975                                 uint8 *tcp_hdr;
4976
4977                                 ip_len = IPV4_PAYLOAD_LEN(ip_body);
4978                                 tcp_hdr = IPV4_NO_OPTIONS_PAYLOAD(ip_body);
4979                                 src_port = TCP_SRC_PORT(tcp_hdr);
4980                                 src_port_exc = (src_port == 10110) || (src_port == 10120) ||
4981                                         (src_port == 10130) || (src_port == 10140);
4982
4983                                 if ((ip_len == 40) && src_port_exc && TCP_IS_ACK(tcp_hdr)) {
4984                                         dscp_prio = 7;
4985                                 }
4986                         }
4987                 }
4988
4989                 /* DSCP priority gets precedence over 802.1P (vlan tag) */
4990                 if (dscp_prio != 0) {
4991                         priority = dscp_prio;
4992                         rc |= PKTPRIO_VDSCP;
4993                 } else {
4994                         priority = vlan_prio;
4995                         rc |= PKTPRIO_VLAN;
4996                 }
4997                 /* 
4998                  * If the DSCP priority is not the same as the VLAN priority,
4999                  * then overwrite the priority field in the vlan tag, with the
5000                  * DSCP priority value. This is required for Linux APs because
5001                  * the VLAN driver on Linux, overwrites the skb->priority field
5002                  * with the priority value in the vlan tag
5003                  */
5004                 if (update_vtag && (priority != vlan_prio)) {
5005                         vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
5006                         vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
5007                         evh->vlan_tag = hton16(vlan_tag);
5008                         rc |= PKTPRIO_UPD;
5009                 }
5010         } else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) {
5011                 uint8 *ip_body = pktdata + sizeof(struct ether_header);
5012                 uint8 tos_tc = IP_TOS(ip_body);
5013                 priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
5014                 rc |= PKTPRIO_DSCP;
5015                 if ((IP_VER(ip_body) == IP_VER_4) && (IPV4_PROT(ip_body) == IP_PROT_TCP)) {
5016                         int ip_len;
5017                         int src_port;
5018                         bool src_port_exc;
5019                         uint8 *tcp_hdr;
5020
5021                         ip_len = IPV4_PAYLOAD_LEN(ip_body);
5022                         tcp_hdr = IPV4_NO_OPTIONS_PAYLOAD(ip_body);
5023                         src_port = TCP_SRC_PORT(tcp_hdr);
5024                         src_port_exc = (src_port == 10110) || (src_port == 10120) ||
5025                                 (src_port == 10130) || (src_port == 10140);
5026
5027                         if ((ip_len == 40) && src_port_exc && TCP_IS_ACK(tcp_hdr)) {
5028                                 priority = 7;
5029                         }
5030                 }
5031         }
5032
5033         ASSERT(priority >= 0 && priority <= MAXPRIO);
5034         PKTSETPRIO(pkt, priority);
5035         return (rc | priority);
5036 }
5037
5038 LM_STATUS
5039 MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice)
5040 {
5041         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
5042         PLM_PACKET pPacket;
5043         PUM_PACKET pUmPacket;
5044         struct sk_buff *skb;
5045         int size;
5046         int vlan_tag_size = 0;
5047         uint16 dscp_prio;
5048
5049         if (pDevice->ReceiveMask & LM_KEEP_VLAN_TAG)
5050                 vlan_tag_size = 4;
5051
5052         while (1) {
5053                 pPacket = (PLM_PACKET)
5054                         QQ_PopHead(&pDevice->RxPacketReceivedQ.Container);
5055                 if (pPacket == 0)
5056                         break;
5057                 pUmPacket = (PUM_PACKET) pPacket;
5058 #if !defined(NO_PCI_UNMAP)
5059                 pci_unmap_single(pUmDevice->pdev,
5060                                 pci_unmap_addr(pUmPacket, map[0]),
5061                                 pPacket->u.Rx.RxBufferSize,
5062                                 PCI_DMA_FROMDEVICE);
5063 #endif
5064                 if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
5065                         ((size = pPacket->PacketSize) >
5066                         (pDevice->RxMtu + vlan_tag_size))) {
5067
5068                         /* reuse skb */
5069 #ifdef BCM_TASKLET
5070                         QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
5071 #else
5072                         QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
5073 #endif
5074                         pUmDevice->rx_misc_errors++;
5075                         continue;
5076                 }
5077                 skb = pUmPacket->skbuff;
5078                 skb_put(skb, size);
5079                 skb->pkt_type = 0;
5080                 /* Extract priority from payload and put it in skb->priority */
5081                 dscp_prio = 0;
5082                 if (pUmDevice->qos) {
5083                         uint rc;
5084
5085                         rc = pktsetprio(skb, TRUE);
5086                         if (rc & (PKTPRIO_VDSCP | PKTPRIO_DSCP))
5087                                 dscp_prio = rc & VLAN_PRI_MASK;
5088                         if (rc != 0)
5089                                 B57_INFO(("pktsetprio returned 0x%x, skb->priority: %d\n",
5090                                           rc, skb->priority));
5091                 }
5092                 skb->protocol = eth_type_trans(skb, skb->dev);
5093                 if (size > pDevice->RxMtu) {
5094                         /* Make sure we have a valid VLAN tag */
5095                         if (htons(skb->protocol) != ETHER_TYPE_8021Q) {
5096                                 dev_kfree_skb_irq(skb);
5097                                 pUmDevice->rx_misc_errors++;
5098                                 goto drop_rx;
5099                         }
5100                 }
5101
5102                 pUmDevice->stats.rx_bytes += skb->len;
5103
5104                 if ((pPacket->Flags & RCV_BD_FLAG_TCP_UDP_CHKSUM_FIELD) &&
5105                         (pDevice->TaskToOffload &
5106                                 LM_TASK_OFFLOAD_RX_TCP_CHECKSUM)) {
5107                         if (pPacket->u.Rx.TcpUdpChecksum == 0xffff) {
5108
5109                                 skb->ip_summed = CHECKSUM_UNNECESSARY;
5110 #if TIGON3_DEBUG
5111                                 pUmDevice->rx_good_chksum_count++;
5112 #endif
5113                         }
5114                         else {
5115                                 skb->ip_summed = CHECKSUM_NONE;
5116                                 pUmDevice->rx_bad_chksum_count++;
5117                         }
5118                 }
5119                 else {
5120                         skb->ip_summed = CHECKSUM_NONE;
5121                 }
5122                 {
5123 #ifdef BCM_VLAN
5124                         if (pUmDevice->vlgrp &&
5125                                 (pPacket->Flags & RCV_BD_FLAG_VLAN_TAG)) {
5126                                 /* Override vlan priority with dscp priority */
5127                                 if (dscp_prio)
5128                                         UPD_VLANTAG_PRIO(pPacket->VlanTag, dscp_prio);
5129 #ifdef BCM_NAPI_RXPOLL
5130                                 vlan_hwaccel_receive_skb(skb, pUmDevice->vlgrp,
5131                                         pPacket->VlanTag);
5132 #else
5133                                 vlan_hwaccel_rx(skb, pUmDevice->vlgrp,
5134                                         pPacket->VlanTag);
5135 #endif
5136                         } else
5137 #endif
5138                         {
5139 #ifdef BCM_WL_EMULATOR
5140                                 if(pDevice->wl_emulate_rx) {
5141                                         /* bcmstats("emu recv %d %d"); */
5142                                         wlcemu_receive_skb(pDevice->wlc, skb);
5143                                         /* bcmstats("emu recv end %d %d"); */
5144                                 }
5145                                 else 
5146 #endif /* BCM_WL_EMULATOR  */
5147                                 {
5148 #ifdef BCM_NAPI_RXPOLL
5149                                 netif_receive_skb(skb);
5150 #else
5151                                 netif_rx(skb);
5152 #endif
5153                                 }
5154                         }
5155                 }
5156                 pUmDevice->dev->last_rx = jiffies;
5157
5158 drop_rx:
5159 #ifdef BCM_TASKLET
5160                 pUmPacket->skbuff = 0;
5161                 QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
5162 #else
5163 #ifdef BCM_WL_EMULATOR
5164                 skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2);
5165 #else
5166                 skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR);
5167 #endif /* BCM_WL_EMULATOR  */
5168                 if (skb == 0) {
5169                         pUmPacket->skbuff = 0;
5170                         QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
5171                 }
5172                 else {
5173                         pUmPacket->skbuff = skb;
5174                         skb->dev = pUmDevice->dev;
5175 #ifndef BCM_WL_EMULATOR
5176                         skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align);
5177 #endif
5178                         QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
5179                 }
5180 #endif
5181         }
5182         return LM_STATUS_SUCCESS;
5183 }
5184
5185 LM_STATUS
5186 MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
5187 {
5188         PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
5189         struct sk_buff *skb = pUmPacket->skbuff;
5190         struct sk_buff *nskb;
5191 #if !defined(NO_PCI_UNMAP)
5192         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
5193
5194         pci_unmap_single(pUmDevice->pdev,
5195                         pci_unmap_addr(pUmPacket, map[0]),
5196                         pci_unmap_len(pUmPacket, map_len[0]),
5197                         PCI_DMA_TODEVICE);
5198 #if MAX_SKB_FRAGS
5199         {
5200                 int i;
5201
5202                 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
5203                         pci_unmap_page(pUmDevice->pdev,
5204                                 pci_unmap_addr(pUmPacket, map[i + 1]),
5205                                 pci_unmap_len(pUmPacket, map_len[i + 1]),
5206                                 PCI_DMA_TODEVICE);
5207                 }
5208         }
5209 #endif
5210 #endif
5211         if ((nskb = skb_copy(skb, GFP_ATOMIC))) {
5212                 pUmPacket->lm_packet.u.Tx.FragCount = 1;
5213                 dev_kfree_skb(skb);
5214                 pUmPacket->skbuff = nskb;
5215                 return LM_STATUS_SUCCESS;
5216         }
5217         dev_kfree_skb(skb);
5218         pUmPacket->skbuff = 0;
5219         return LM_STATUS_FAILURE;
5220 }
5221
5222 /* Returns 1 if not all buffers are allocated */
5223 STATIC int
5224 replenish_rx_buffers(PUM_DEVICE_BLOCK pUmDevice, int max)
5225 {
5226         PLM_PACKET pPacket;
5227         PUM_PACKET pUmPacket;
5228         PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
5229         struct sk_buff *skb;
5230         int queue_rx = 0;
5231         int alloc_cnt = 0;
5232         int ret = 0;
5233
5234         while ((pUmPacket = (PUM_PACKET)
5235                 QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
5236                 pPacket = (PLM_PACKET) pUmPacket;
5237                 if (pUmPacket->skbuff) {
5238                         /* reuse an old skb */
5239                         QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
5240                         queue_rx = 1;
5241                         continue;
5242                 }
5243 #ifdef BCM_WL_EMULATOR
5244                 if ((skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2)) == 0)
5245 #else 
5246                if ((skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR)) == 0)
5247 #endif /* BCM_WL_EMULATOR  */
5248                {
5249                        QQ_PushHead(&pUmDevice->rx_out_of_buf_q.Container,
5250                                    pPacket);
5251                        ret = 1;
5252                        break;
5253                }
5254                 pUmPacket->skbuff = skb;
5255                 skb->dev = pUmDevice->dev;
5256 #ifndef BCM_WL_EMULATOR
5257                         skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align);
5258 #endif
5259                 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
5260                 queue_rx = 1;
5261                 if (max > 0) {
5262                         alloc_cnt++;
5263                         if (alloc_cnt >= max)
5264                                 break;
5265                 }
5266         }
5267         if (queue_rx || pDevice->QueueAgain) {
5268                 LM_QueueRxPackets(pDevice);
5269         }
5270         return ret;
5271 }
5272
5273 LM_STATUS
5274 MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)
5275 {
5276         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
5277         PLM_PACKET pPacket;
5278         PUM_PACKET pUmPacket;
5279         struct sk_buff *skb;
5280 #if !defined(NO_PCI_UNMAP) && MAX_SKB_FRAGS
5281         int i;
5282 #endif
5283
5284         while (1) {
5285                 pPacket = (PLM_PACKET)
5286                         QQ_PopHead(&pDevice->TxPacketXmittedQ.Container);
5287                 if (pPacket == 0)
5288                         break;
5289                 pUmPacket = (PUM_PACKET) pPacket;
5290                 skb = pUmPacket->skbuff;
5291 #if !defined(NO_PCI_UNMAP)
5292                 pci_unmap_single(pUmDevice->pdev,
5293                                 pci_unmap_addr(pUmPacket, map[0]),
5294                                 pci_unmap_len(pUmPacket, map_len[0]),
5295                                 PCI_DMA_TODEVICE);
5296 #if MAX_SKB_FRAGS
5297                 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
5298                         pci_unmap_page(pUmDevice->pdev,
5299                                 pci_unmap_addr(pUmPacket, map[i + 1]),
5300                                 pci_unmap_len(pUmPacket, map_len[i + 1]),
5301                                 PCI_DMA_TODEVICE);
5302                 }
5303 #endif
5304 #endif
5305                 dev_kfree_skb_irq(skb);
5306                 pUmPacket->skbuff = 0;
5307                 QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
5308         }
5309         if (pUmDevice->tx_full) {
5310                 if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) >=
5311                         (pDevice->TxPacketDescCnt >> 1)) {
5312
5313                         pUmDevice->tx_full = 0;
5314                         netif_wake_queue(pUmDevice->dev);
5315                 }
5316         }
5317         return LM_STATUS_SUCCESS;
5318 }
5319
5320 LM_STATUS
5321 MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
5322 {
5323         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
5324         struct net_device *dev = pUmDevice->dev;
5325         LM_FLOW_CONTROL flow_control;
5326         int speed = 0;
5327
5328         if (!pUmDevice->opened)
5329                 return LM_STATUS_SUCCESS;
5330
5331         if (!pUmDevice->suspended) {
5332                 if (Status == LM_STATUS_LINK_DOWN) {
5333                         netif_carrier_off(dev);
5334                 }
5335                 else if (Status == LM_STATUS_LINK_ACTIVE) {
5336                         netif_carrier_on(dev);
5337                 }
5338         }
5339
5340         if (pUmDevice->delayed_link_ind > 0) {
5341                 pUmDevice->delayed_link_ind = 0;
5342                 if (Status == LM_STATUS_LINK_DOWN) {
5343                         B57_INFO(("%s: %s NIC Link is DOWN\n", bcm5700_driver, dev->name));
5344                 }
5345                 else if (Status == LM_STATUS_LINK_ACTIVE) {
5346                         B57_INFO(("%s: %s NIC Link is UP, ", bcm5700_driver, dev->name));
5347                 }
5348         }
5349         else {
5350                 if (Status == LM_STATUS_LINK_DOWN) {
5351                         B57_INFO(("%s: %s NIC Link is Down\n", bcm5700_driver, dev->name));
5352                 }
5353                 else if (Status == LM_STATUS_LINK_ACTIVE) {
5354                         B57_INFO(("%s: %s NIC Link is Up, ", bcm5700_driver, dev->name));
5355                 }
5356         }
5357
5358         if (Status == LM_STATUS_LINK_ACTIVE) {
5359                 if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS)
5360                         speed = 1000;
5361                 else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS)
5362                         speed = 100;
5363                 else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
5364                         speed = 10;
5365
5366                 B57_INFO(("%d Mbps ", speed));
5367
5368                 if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
5369                         B57_INFO(("full duplex"));
5370                 else
5371                         B57_INFO(("half duplex"));
5372
5373                 flow_control = pDevice->FlowControl &
5374                         (LM_FLOW_CONTROL_RECEIVE_PAUSE |
5375                         LM_FLOW_CONTROL_TRANSMIT_PAUSE);
5376                 if (flow_control) {
5377                         if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) {
5378                                 B57_INFO((", receive "));
5379                                 if (flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
5380                                         B57_INFO(("& transmit "));
5381                         }
5382                         else {
5383                                 B57_INFO((", transmit "));
5384                         }
5385                         B57_INFO(("flow control ON"));
5386                 }
5387                 B57_INFO(("\n"));
5388         }
5389         return LM_STATUS_SUCCESS;
5390 }
5391
5392 void
5393 MM_UnmapRxDma(LM_DEVICE_BLOCK *pDevice, LM_PACKET *pPacket)
5394 {
5395 #if !defined(NO_PCI_UNMAP)
5396         UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
5397         UM_PACKET *pUmPacket = (UM_PACKET *) pPacket;
5398
5399         if (!pUmPacket->skbuff)
5400                 return;
5401
5402         pci_unmap_single(pUmDevice->pdev,
5403                         pci_unmap_addr(pUmPacket, map[0]),
5404                         pPacket->u.Rx.RxBufferSize,
5405                         PCI_DMA_FROMDEVICE);
5406 #endif
5407 }
5408
5409 LM_STATUS
5410 MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
5411 {
5412         PUM_PACKET pUmPacket;
5413         struct sk_buff *skb;
5414
5415         if (pPacket == 0)
5416                 return LM_STATUS_SUCCESS;
5417         pUmPacket = (PUM_PACKET) pPacket;
5418         if ((skb = pUmPacket->skbuff)) {
5419                 /* DMA address already unmapped */
5420                 dev_kfree_skb(skb);
5421         }
5422         pUmPacket->skbuff = 0;
5423         return LM_STATUS_SUCCESS;
5424 }
5425
5426 LM_STATUS
5427 MM_Sleep(LM_DEVICE_BLOCK *pDevice, LM_UINT32 msec)
5428 {
5429         current->state = TASK_INTERRUPTIBLE;
5430         if (schedule_timeout(HZ * msec / 1000) != 0) {
5431                 return LM_STATUS_FAILURE;
5432         }
5433         if (signal_pending(current))
5434                 return LM_STATUS_FAILURE;
5435
5436         return LM_STATUS_SUCCESS;
5437 }
5438
5439 void
5440 bcm5700_shutdown(UM_DEVICE_BLOCK *pUmDevice)
5441 {
5442         LM_DEVICE_BLOCK *pDevice = (LM_DEVICE_BLOCK *) pUmDevice;
5443
5444         bcm5700_intr_off(pUmDevice);
5445         netif_carrier_off(pUmDevice->dev);
5446 #ifdef BCM_TASKLET
5447         tasklet_kill(&pUmDevice->tasklet);
5448 #endif
5449         bcm5700_poll_wait(pUmDevice);
5450
5451         LM_Halt(pDevice);
5452
5453         pDevice->InitDone = 0;
5454         bcm5700_free_remaining_rx_bufs(pUmDevice);
5455 }
5456
5457 void
5458 bcm5700_free_remaining_rx_bufs(UM_DEVICE_BLOCK *pUmDevice)
5459 {
5460         LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
5461         UM_PACKET *pUmPacket;
5462         int cnt, i;
5463
5464         cnt = QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container);
5465         for (i = 0; i < cnt; i++) {
5466                 if ((pUmPacket =
5467                         QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container))
5468                         != 0) {
5469
5470                         MM_UnmapRxDma(pDevice, (LM_PACKET *) pUmPacket);
5471                         MM_FreeRxBuffer(pDevice, &pUmPacket->lm_packet);
5472                         QQ_PushTail(&pDevice->RxPacketFreeQ.Container,
5473                                 pUmPacket);
5474                 }
5475         }
5476 }
5477
5478 void
5479 bcm5700_validate_param_range(UM_DEVICE_BLOCK *pUmDevice, int *param,
5480         char *param_name, int min, int max, int deflt)
5481 {
5482         if (((unsigned int) *param < (unsigned int) min) ||
5483                 ((unsigned int) *param > (unsigned int) max)) {
5484
5485                 printk(KERN_WARNING "%s-%d: Invalid %s parameter (%u), using %u\n", bcm5700_driver, pUmDevice->index, param_name, (unsigned int) *param, (unsigned int) deflt);
5486                 *param = deflt;
5487         }
5488 }
5489
5490 struct net_device *
5491 bcm5700_find_peer(struct net_device *dev)
5492 {
5493         struct net_device *tmp_dev;
5494         UM_DEVICE_BLOCK *pUmDevice, *pUmTmp;
5495         LM_DEVICE_BLOCK *pDevice;
5496
5497         tmp_dev = 0;
5498         pUmDevice = (UM_DEVICE_BLOCK *) dev->priv;
5499         pDevice = &pUmDevice->lm_dev;
5500         if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) {
5501                 tmp_dev = root_tigon3_dev;
5502                 while (tmp_dev) {
5503                         pUmTmp = (PUM_DEVICE_BLOCK) tmp_dev->priv;
5504                         if ((tmp_dev != dev) &&
5505                                 (pUmDevice->pdev->bus->number ==
5506                                 pUmTmp->pdev->bus->number) &&
5507                                 PCI_SLOT(pUmDevice->pdev->devfn) ==
5508                                 PCI_SLOT(pUmTmp->pdev->devfn)) {
5509
5510                                 break;
5511                         }
5512                         tmp_dev = pUmTmp->next_module;
5513                 }
5514         }
5515         return tmp_dev;
5516 }
5517
5518 LM_DEVICE_BLOCK *
5519 MM_FindPeerDev(LM_DEVICE_BLOCK *pDevice)
5520 {
5521         UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
5522         struct net_device *dev = pUmDevice->dev;
5523         struct net_device *peer_dev;
5524
5525         peer_dev = bcm5700_find_peer(dev);
5526         if (!peer_dev)
5527                 return 0;
5528         return ((LM_DEVICE_BLOCK *) peer_dev->priv);
5529 }
5530
5531 int MM_FindCapability(LM_DEVICE_BLOCK *pDevice, int capability)
5532 {
5533         UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
5534         return (pci_find_capability(pUmDevice->pdev, capability));
5535 }
5536
5537 #if defined(HAVE_POLL_CONTROLLER)||defined(CONFIG_NET_POLL_CONTROLLER)
5538 STATIC void
5539 poll_bcm5700(struct net_device *dev)
5540 {
5541         UM_DEVICE_BLOCK *pUmDevice = dev->priv;
5542
5543 #if defined(RED_HAT_LINUX_KERNEL) && (LINUX_VERSION_CODE < 0x020605)
5544         if (netdump_mode) {
5545                 bcm5700_interrupt(pUmDevice->pdev->irq, dev, NULL);
5546 #ifdef BCM_NAPI_RXPOLL
5547                 if (dev->poll_list.prev) {
5548                         int budget = 64;
5549
5550                         bcm5700_poll(dev, &budget);
5551                 }
5552 #endif
5553         }
5554         else
5555 #endif
5556         {
5557                 disable_irq(pUmDevice->pdev->irq);
5558                 bcm5700_interrupt(pUmDevice->pdev->irq, dev, NULL);
5559                 enable_irq(pUmDevice->pdev->irq);
5560         }
5561 }
5562 #endif