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