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

Archive Download this file



interactive