Merge branch 'master' of git://www.denx.de/git/u-boot-arm
[platform/kernel/u-boot.git] / drivers / net / bcm570x.c
1 /*
2  * Broadcom BCM570x Ethernet Driver for U-Boot.
3  * Support 5701, 5702, 5703, and 5704. Single instance driver.
4  * Copyright (C) 2002 James F. Dougherty (jfd@broadcom.com)
5  */
6
7 #include <common.h>
8
9 #if defined(CONFIG_CMD_NET) \
10         && (!defined(CONFIG_NET_MULTI)) && defined(CONFIG_BCM570x)
11
12 #ifdef CONFIG_BMW
13 #include <mpc824x.h>
14 #endif
15 #include <net.h>
16 #include "bcm570x_mm.h"
17 #include "bcm570x_autoneg.h"
18 #include <pci.h>
19 #include <malloc.h>
20
21 /*
22  * PCI Registers and definitions.
23  */
24 #define PCI_CMD_MASK    0xffff0000      /* mask to save status bits */
25 #define PCI_ANY_ID (~0)
26
27 /*
28  * PCI memory base for Ethernet device as well as device Interrupt.
29  */
30 #define BCM570X_MBAR    0x80100000
31 #define BCM570X_ILINE   1
32
33 #define SECOND_USEC     1000000
34 #define MAX_PACKET_SIZE 1600
35 #define MAX_UNITS       4
36
37 /* Globals to this module */
38 int initialized = 0;
39 unsigned int ioBase = 0;
40 volatile PLM_DEVICE_BLOCK pDevice = NULL;       /* 570x softc */
41 volatile PUM_DEVICE_BLOCK pUmDevice = NULL;
42
43 /* Used to pass the full-duplex flag, etc. */
44 int line_speed[MAX_UNITS] = { 0, 0, 0, 0 };
45 static int full_duplex[MAX_UNITS] = { 1, 1, 1, 1 };
46 static int rx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
47 static int tx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
48 static int auto_flow_control[MAX_UNITS] = { 0, 0, 0, 0 };
49 static int tx_checksum[MAX_UNITS] = { 1, 1, 1, 1 };
50 static int rx_checksum[MAX_UNITS] = { 1, 1, 1, 1 };
51 static int auto_speed[MAX_UNITS] = { 1, 1, 1, 1 };
52
53 #if JUMBO_FRAMES
54 /* Jumbo MTU for interfaces. */
55 static int mtu[MAX_UNITS] = { 0, 0, 0, 0 };
56 #endif
57
58 /* Turn on Wake-on lan for a device unit */
59 static int enable_wol[MAX_UNITS] = { 0, 0, 0, 0 };
60
61 #define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT
62 static unsigned int tx_pkt_desc_cnt[MAX_UNITS] =
63     { TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT };
64
65 #define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT
66 static unsigned int rx_std_desc_cnt[MAX_UNITS] =
67     { RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT };
68
69 static unsigned int rx_adaptive_coalesce[MAX_UNITS] = { 1, 1, 1, 1 };
70
71 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
72 #define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT
73 static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] =
74     { JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT };
75 #endif
76 #define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS
77 static unsigned int rx_coalesce_ticks[MAX_UNITS] =
78     { RX_COAL_TK, RX_COAL_TK, RX_COAL_TK, RX_COAL_TK };
79
80 #define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES
81 static unsigned int rx_max_coalesce_frames[MAX_UNITS] =
82     { RX_COAL_FM, RX_COAL_FM, RX_COAL_FM, RX_COAL_FM };
83
84 #define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS
85 static unsigned int tx_coalesce_ticks[MAX_UNITS] =
86     { TX_COAL_TK, TX_COAL_TK, TX_COAL_TK, TX_COAL_TK };
87
88 #define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES
89 static unsigned int tx_max_coalesce_frames[MAX_UNITS] =
90     { TX_COAL_FM, TX_COAL_FM, TX_COAL_FM, TX_COAL_FM };
91
92 #define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS
93 static unsigned int stats_coalesce_ticks[MAX_UNITS] =
94     { ST_COAL_TK, ST_COAL_TK, ST_COAL_TK, ST_COAL_TK };
95
96 /*
97  * Legitimate values for BCM570x device types
98  */
99 typedef enum {
100         BCM5700VIGIL = 0,
101         BCM5700A6,
102         BCM5700T6,
103         BCM5700A9,
104         BCM5700T9,
105         BCM5700,
106         BCM5701A5,
107         BCM5701T1,
108         BCM5701T8,
109         BCM5701A7,
110         BCM5701A10,
111         BCM5701A12,
112         BCM5701,
113         BCM5702,
114         BCM5703,
115         BCM5703A31,
116         TC996T,
117         TC996ST,
118         TC996SSX,
119         TC996SX,
120         TC996BT,
121         TC997T,
122         TC997SX,
123         TC1000T,
124         TC940BR01,
125         TC942BR01,
126         NC6770,
127         NC7760,
128         NC7770,
129         NC7780
130 } board_t;
131
132 /* Chip-Rev names for each device-type */
133 static struct {
134         char *name;
135 } chip_rev[] = {
136         {
137         "BCM5700VIGIL"}, {
138         "BCM5700A6"}, {
139         "BCM5700T6"}, {
140         "BCM5700A9"}, {
141         "BCM5700T9"}, {
142         "BCM5700"}, {
143         "BCM5701A5"}, {
144         "BCM5701T1"}, {
145         "BCM5701T8"}, {
146         "BCM5701A7"}, {
147         "BCM5701A10"}, {
148         "BCM5701A12"}, {
149         "BCM5701"}, {
150         "BCM5702"}, {
151         "BCM5703"}, {
152         "BCM5703A31"}, {
153         "TC996T"}, {
154         "TC996ST"}, {
155         "TC996SSX"}, {
156         "TC996SX"}, {
157         "TC996BT"}, {
158         "TC997T"}, {
159         "TC997SX"}, {
160         "TC1000T"}, {
161         "TC940BR01"}, {
162         "TC942BR01"}, {
163         "NC6770"}, {
164         "NC7760"}, {
165         "NC7770"}, {
166         "NC7780"}, {
167         0}
168 };
169
170 /* indexed by board_t, above */
171 static struct {
172         char *name;
173 } board_info[] = {
174         {
175         "Broadcom Vigil B5700 1000Base-T"}, {
176         "Broadcom BCM5700 1000Base-T"}, {
177         "Broadcom BCM5700 1000Base-SX"}, {
178         "Broadcom BCM5700 1000Base-SX"}, {
179         "Broadcom BCM5700 1000Base-T"}, {
180         "Broadcom BCM5700"}, {
181         "Broadcom BCM5701 1000Base-T"}, {
182         "Broadcom BCM5701 1000Base-T"}, {
183         "Broadcom BCM5701 1000Base-T"}, {
184         "Broadcom BCM5701 1000Base-SX"}, {
185         "Broadcom BCM5701 1000Base-T"}, {
186         "Broadcom BCM5701 1000Base-T"}, {
187         "Broadcom BCM5701"}, {
188         "Broadcom BCM5702 1000Base-T"}, {
189         "Broadcom BCM5703 1000Base-T"}, {
190         "Broadcom BCM5703 1000Base-SX"}, {
191         "3Com 3C996 10/100/1000 Server NIC"}, {
192         "3Com 3C996 10/100/1000 Server NIC"}, {
193         "3Com 3C996 Gigabit Fiber-SX Server NIC"}, {
194         "3Com 3C996 Gigabit Fiber-SX Server NIC"}, {
195         "3Com 3C996B Gigabit Server NIC"}, {
196         "3Com 3C997 Gigabit Server NIC"}, {
197         "3Com 3C997 Gigabit Fiber-SX Server NIC"}, {
198         "3Com 3C1000 Gigabit NIC"}, {
199         "3Com 3C940 Gigabit LOM (21X21)"}, {
200         "3Com 3C942 Gigabit LOM (31X31)"}, {
201         "Compaq NC6770 Gigabit Server Adapter"}, {
202         "Compaq NC7760 Gigabit Server Adapter"}, {
203         "Compaq NC7770 Gigabit Server Adapter"}, {
204         "Compaq NC7780 Gigabit Server Adapter"}, {
205 0},};
206
207 /* PCI Devices which use the 570x chipset */
208 struct pci_device_table {
209         unsigned short vendor_id, device_id;    /* Vendor/DeviceID */
210         unsigned short subvendor, subdevice;    /* Subsystem ID's or PCI_ANY_ID */
211         unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
212         unsigned long board_id; /* Data private to the driver */
213         int io_size, min_latency;
214 } bcm570xDevices[] = {
215         {
216         0x14e4, 0x1644, 0x1014, 0x0277, 0, 0, BCM5700VIGIL, 128, 32}, {
217         0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6, 128, 32}, {
218         0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6, 128, 32}, {
219         0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9, 128, 32}, {
220         0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9, 128, 32}, {
221         0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700, 128, 32}, {
222         0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700, 128, 32}, {
223         0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700, 128, 32}, {
224         0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700, 128, 32}, {
225         0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T, 128, 32}, {
226         0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST, 128, 32}, {
227         0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX, 128, 32}, {
228         0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T, 128, 32}, {
229         0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX, 128, 32}, {
230         0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01, 128, 32}, {
231         0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700, 128, 32}, {
232         0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5, 128, 32}, {
233         0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1, 128, 32}, {
234         0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8, 128, 32}, {
235         0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7, 128, 32}, {
236         0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10, 128, 32}, {
237         0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12, 128, 32}, {
238         0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770, 128, 32}, {
239         0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770, 128, 32}, {
240         0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780, 128, 32}, {
241         0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701, 128, 32}, {
242         0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX, 128, 32}, {
243         0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT, 128, 32}, {
244         0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T, 128, 32}, {
245         0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01, 128, 32}, {
246         0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701, 128, 32}, {
247         0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, {
248         0x14e4, 0x1646, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, {
249         0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, {
250         0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, {
251         0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, {
252         0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, {
253         0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, {
254         0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, {
255         0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, {
256         0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, {
257         0x14e4, 0x1647, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, {
258         0x14e4, 0x1647, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, {
259         0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32}, {
260         0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, {
261         0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, {
262         0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, {
263         0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, {
264         0x14e4, 0x16a7, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, {
265         0x14e4, 0x16a7, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, {
266         0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32}
267 };
268
269 #define n570xDevices   (sizeof(bcm570xDevices)/sizeof(bcm570xDevices[0]))
270
271 /*
272  * Allocate a packet buffer from the bcm570x packet pool.
273  */
274 void *bcm570xPktAlloc (int u, int pksize)
275 {
276         return malloc (pksize);
277 }
278
279 /*
280  * Free a packet previously allocated from the bcm570x packet
281  * buffer pool.
282  */
283 void bcm570xPktFree (int u, void *p)
284 {
285         free (p);
286 }
287
288 int bcm570xReplenishRxBuffers (PUM_DEVICE_BLOCK pUmDevice)
289 {
290         PLM_PACKET pPacket;
291         PUM_PACKET pUmPacket;
292         void *skb;
293         int queue_rx = 0;
294         int ret = 0;
295
296         while ((pUmPacket = (PUM_PACKET)
297                 QQ_PopHead (&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
298
299                 pPacket = (PLM_PACKET) pUmPacket;
300
301                 /* reuse an old skb */
302                 if (pUmPacket->skbuff) {
303                         QQ_PushTail (&pDevice->RxPacketFreeQ.Container,
304                                      pPacket);
305                         queue_rx = 1;
306                         continue;
307                 }
308                 if ((skb = bcm570xPktAlloc (pUmDevice->index,
309                                             pPacket->u.Rx.RxBufferSize + 2)) ==
310                     0) {
311                         QQ_PushHead (&pUmDevice->rx_out_of_buf_q.Container,
312                                      pPacket);
313                         printf ("NOTICE: Out of RX memory.\n");
314                         ret = 1;
315                         break;
316                 }
317
318                 pUmPacket->skbuff = skb;
319                 QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
320                 queue_rx = 1;
321         }
322
323         if (queue_rx) {
324                 LM_QueueRxPackets (pDevice);
325         }
326
327         return ret;
328 }
329
330 /*
331  * Probe, Map, and Init 570x device.
332  */
333 int eth_init (bd_t * bis)
334 {
335         int i, rv, devFound = FALSE;
336         pci_dev_t devbusfn;
337         unsigned short status;
338
339         /* Find PCI device, if it exists, configure ...  */
340         for (i = 0; i < n570xDevices; i++) {
341                 devbusfn = pci_find_device (bcm570xDevices[i].vendor_id,
342                                             bcm570xDevices[i].device_id, 0);
343                 if (devbusfn == -1) {
344                         continue;       /* No device of that vendor/device ID */
345                 } else {
346
347                         /* Set ILINE */
348                         pci_write_config_byte (devbusfn,
349                                                PCI_INTERRUPT_LINE,
350                                                BCM570X_ILINE);
351
352                         /*
353                          * 0x10 - 0x14 define one 64-bit MBAR.
354                          * 0x14 is the higher-order address bits of the BAR.
355                          */
356                         pci_write_config_dword (devbusfn,
357                                                 PCI_BASE_ADDRESS_1, 0);
358
359                         ioBase = BCM570X_MBAR;
360
361                         pci_write_config_dword (devbusfn,
362                                                 PCI_BASE_ADDRESS_0, ioBase);
363
364                         /*
365                          * Enable PCI memory, IO, and Master -- don't
366                          * reset any status bits in doing so.
367                          */
368                         pci_read_config_word (devbusfn, PCI_COMMAND, &status);
369
370                         status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
371
372                         pci_write_config_word (devbusfn, PCI_COMMAND, status);
373
374                         printf
375                             ("\n%s: bus %d, device %d, function %d: MBAR=0x%x\n",
376                              board_info[bcm570xDevices[i].board_id].name,
377                              PCI_BUS (devbusfn), PCI_DEV (devbusfn),
378                              PCI_FUNC (devbusfn), ioBase);
379
380                         /* Allocate once, but always clear on init */
381                         if (!pDevice) {
382                                 pDevice = malloc (sizeof (UM_DEVICE_BLOCK));
383                                 pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
384                                 memset (pDevice, 0x0, sizeof (UM_DEVICE_BLOCK));
385                         }
386
387                         /* Configure pci dev structure */
388                         pUmDevice->pdev = devbusfn;
389                         pUmDevice->index = 0;
390                         pUmDevice->tx_pkt = 0;
391                         pUmDevice->rx_pkt = 0;
392                         devFound = TRUE;
393                         break;
394                 }
395         }
396
397         if (!devFound) {
398                 printf
399                     ("eth_init: FAILURE: no BCM570x Ethernet devices found.\n");
400                 return -1;
401         }
402
403         /* Setup defaults for chip */
404         pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
405
406         if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) {
407                 pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
408         } else {
409
410                 if (rx_checksum[i]) {
411                         pDevice->TaskToOffload |=
412                             LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
413                             LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
414                 }
415
416                 if (tx_checksum[i]) {
417                         pDevice->TaskToOffload |=
418                             LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
419                             LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
420                         pDevice->NoTxPseudoHdrChksum = TRUE;
421                 }
422         }
423
424         /* Set Device PCI Memory base address */
425         pDevice->pMappedMemBase = (PLM_UINT8) ioBase;
426
427         /* Pull down adapter info */
428         if ((rv = LM_GetAdapterInfo (pDevice)) != LM_STATUS_SUCCESS) {
429                 printf ("bcm570xEnd: LM_GetAdapterInfo failed: rv=%d!\n", rv);
430                 return -2;
431         }
432
433         /* Lock not needed */
434         pUmDevice->do_global_lock = 0;
435
436         if (T3_ASIC_REV (pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
437                 /* The 5700 chip works best without interleaved register */
438                 /* accesses on certain machines. */
439                 pUmDevice->do_global_lock = 1;
440         }
441
442         /* Setup timer delays */
443         if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) {
444                 pDevice->UseTaggedStatus = TRUE;
445                 pUmDevice->timer_interval = CFG_HZ;
446         } else {
447                 pUmDevice->timer_interval = CFG_HZ / 50;
448         }
449
450         /* Grab name .... */
451         pUmDevice->name =
452             (char *)malloc (strlen (board_info[bcm570xDevices[i].board_id].name)
453                             + 1);
454         strcpy (pUmDevice->name, board_info[bcm570xDevices[i].board_id].name);
455
456         memcpy (pDevice->NodeAddress, bis->bi_enetaddr, 6);
457         LM_SetMacAddress (pDevice, bis->bi_enetaddr);
458         /* Init queues  .. */
459         QQ_InitQueue (&pUmDevice->rx_out_of_buf_q.Container,
460                       MAX_RX_PACKET_DESC_COUNT);
461         pUmDevice->rx_last_cnt = pUmDevice->tx_last_cnt = 0;
462
463         /* delay for 4 seconds */
464         pUmDevice->delayed_link_ind = (4 * CFG_HZ) / pUmDevice->timer_interval;
465
466         pUmDevice->adaptive_expiry = CFG_HZ / pUmDevice->timer_interval;
467
468         /* Sometimes we get spurious ints. after reset when link is down. */
469         /* This field tells the isr to service the int. even if there is */
470         /* no status block update. */
471         pUmDevice->adapter_just_inited =
472             (3 * CFG_HZ) / pUmDevice->timer_interval;
473
474         /* Initialize 570x */
475         if (LM_InitializeAdapter (pDevice) != LM_STATUS_SUCCESS) {
476                 printf ("ERROR: Adapter initialization failed.\n");
477                 return ERROR;
478         }
479
480         /* Enable chip ISR */
481         LM_EnableInterrupt (pDevice);
482
483         /* Clear MC table */
484         LM_MulticastClear (pDevice);
485
486         /* Enable Multicast */
487         LM_SetReceiveMask (pDevice,
488                            pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
489
490         pUmDevice->opened = 1;
491         pUmDevice->tx_full = 0;
492         pUmDevice->tx_pkt = 0;
493         pUmDevice->rx_pkt = 0;
494         printf ("eth%d: %s @0x%lx,",
495                 pDevice->index, pUmDevice->name, (unsigned long)ioBase);
496         printf ("node addr ");
497         for (i = 0; i < 6; i++) {
498                 printf ("%2.2x", pDevice->NodeAddress[i]);
499         }
500         printf ("\n");
501
502         printf ("eth%d: ", pDevice->index);
503         printf ("%s with ", chip_rev[bcm570xDevices[i].board_id].name);
504
505         if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID)
506                 printf ("Broadcom BCM5400 Copper ");
507         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
508                 printf ("Broadcom BCM5401 Copper ");
509         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID)
510                 printf ("Broadcom BCM5411 Copper ");
511         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID)
512                 printf ("Broadcom BCM5701 Integrated Copper ");
513         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID)
514                 printf ("Broadcom BCM5703 Integrated Copper ");
515         else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
516                 printf ("Broadcom BCM8002 SerDes ");
517         else if (pDevice->EnableTbi)
518                 printf ("Agilent HDMP-1636 SerDes ");
519         else
520                 printf ("Unknown ");
521         printf ("transceiver found\n");
522
523         printf ("eth%d: %s, MTU: %d,",
524                 pDevice->index, pDevice->BusSpeedStr, 1500);
525
526         if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) && rx_checksum[i])
527                 printf ("Rx Checksum ON\n");
528         else
529                 printf ("Rx Checksum OFF\n");
530         initialized++;
531
532         return 0;
533 }
534
535 /* Ethernet Interrupt service routine */
536 void eth_isr (void)
537 {
538         LM_UINT32 oldtag, newtag;
539         int i;
540
541         pUmDevice->interrupt = 1;
542
543         if (pDevice->UseTaggedStatus) {
544                 if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
545                     pUmDevice->adapter_just_inited) {
546                         MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 1);
547                         oldtag = pDevice->pStatusBlkVirt->StatusTag;
548
549                         for (i = 0;; i++) {
550                                 pDevice->pStatusBlkVirt->Status &=
551                                     ~STATUS_BLOCK_UPDATED;
552                                 LM_ServiceInterrupts (pDevice);
553                                 newtag = pDevice->pStatusBlkVirt->StatusTag;
554                                 if ((newtag == oldtag) || (i > 50)) {
555                                         MB_REG_WR (pDevice,
556                                                    Mailbox.Interrupt[0].Low,
557                                                    newtag << 24);
558                                         if (pDevice->UndiFix) {
559                                                 REG_WR (pDevice, Grc.LocalCtrl,
560                                                         pDevice->
561                                                         GrcLocalCtrl | 0x2);
562                                         }
563                                         break;
564                                 }
565                                 oldtag = newtag;
566                         }
567                 }
568         } else {
569                 while (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
570                         unsigned int dummy;
571
572                         pDevice->pMemView->Mailbox.Interrupt[0].Low = 1;
573                         pDevice->pStatusBlkVirt->Status &=
574                             ~STATUS_BLOCK_UPDATED;
575                         LM_ServiceInterrupts (pDevice);
576                         pDevice->pMemView->Mailbox.Interrupt[0].Low = 0;
577                         dummy = pDevice->pMemView->Mailbox.Interrupt[0].Low;
578                 }
579         }
580
581         /* Allocate new RX buffers */
582         if (QQ_GetEntryCnt (&pUmDevice->rx_out_of_buf_q.Container)) {
583                 bcm570xReplenishRxBuffers (pUmDevice);
584         }
585
586         /* Queue packets */
587         if (QQ_GetEntryCnt (&pDevice->RxPacketFreeQ.Container)) {
588                 LM_QueueRxPackets (pDevice);
589         }
590
591         if (pUmDevice->tx_queued) {
592                 pUmDevice->tx_queued = 0;
593         }
594
595         if (pUmDevice->tx_full) {
596                 if (pDevice->LinkStatus != LM_STATUS_LINK_DOWN) {
597                         printf
598                             ("NOTICE: tx was previously blocked, restarting MUX\n");
599                         pUmDevice->tx_full = 0;
600                 }
601         }
602
603         pUmDevice->interrupt = 0;
604
605 }
606
607 int eth_send (volatile void *packet, int length)
608 {
609         int status = 0;
610 #if ET_DEBUG
611         unsigned char *ptr = (unsigned char *)packet;
612 #endif
613         PLM_PACKET pPacket;
614         PUM_PACKET pUmPacket;
615
616         /* Link down, return */
617         while (pDevice->LinkStatus == LM_STATUS_LINK_DOWN) {
618 #if 0
619                 printf ("eth%d: link down - check cable or link partner.\n",
620                         pUmDevice->index);
621 #endif
622                 eth_isr ();
623
624                 /* Wait to see link for one-half a second before sending ... */
625                 udelay (1500000);
626
627         }
628
629         /* Clear sent flag */
630         pUmDevice->tx_pkt = 0;
631
632         /* Previously blocked */
633         if (pUmDevice->tx_full) {
634                 printf ("eth%d: tx blocked.\n", pUmDevice->index);
635                 return 0;
636         }
637
638         pPacket = (PLM_PACKET)
639             QQ_PopHead (&pDevice->TxPacketFreeQ.Container);
640
641         if (pPacket == 0) {
642                 pUmDevice->tx_full = 1;
643                 printf ("bcm570xEndSend: TX full!\n");
644                 return 0;
645         }
646
647         if (pDevice->SendBdLeft.counter == 0) {
648                 pUmDevice->tx_full = 1;
649                 printf ("bcm570xEndSend: no more TX descriptors!\n");
650                 QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
651                 return 0;
652         }
653
654         if (length <= 0) {
655                 printf ("eth: bad packet size: %d\n", length);
656                 goto out;
657         }
658
659         /* Get packet buffers and fragment list */
660         pUmPacket = (PUM_PACKET) pPacket;
661         /* Single DMA Descriptor transmit.
662          * Fragments may be provided, but one DMA descriptor max is
663          * used to send the packet.
664          */
665         if (MM_CoalesceTxBuffer (pDevice, pPacket) != LM_STATUS_SUCCESS) {
666                 if (pUmPacket->skbuff == NULL) {
667                         /* Packet was discarded */
668                         printf ("TX: failed (1)\n");
669                         status = 1;
670                 } else {
671                         printf ("TX: failed (2)\n");
672                         status = 2;
673                 }
674                 QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
675                 return status;
676         }
677
678         /* Copy packet to DMA buffer */
679         memset (pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE);
680         memcpy ((void *)pUmPacket->skbuff, (void *)packet, length);
681         pPacket->PacketSize = length;
682         pPacket->Flags |= SND_BD_FLAG_END | SND_BD_FLAG_COAL_NOW;
683         pPacket->u.Tx.FragCount = 1;
684         /* We've already provided a frame ready for transmission */
685         pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM;
686
687         if (LM_SendPacket (pDevice, pPacket) == LM_STATUS_FAILURE) {
688                 /*
689                  *  A lower level send failure will push the packet descriptor back
690                  *  in the free queue, so just deal with the VxWorks clusters.
691                  */
692                 if (pUmPacket->skbuff == NULL) {
693                         printf ("TX failed (1)!\n");
694                         /* Packet was discarded */
695                         status = 3;
696                 } else {
697                         /* A resource problem ... */
698                         printf ("TX failed (2)!\n");
699                         status = 4;
700                 }
701
702                 if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) == 0) {
703                         printf ("TX: emptyQ!\n");
704                         pUmDevice->tx_full = 1;
705                 }
706         }
707
708         while (pUmDevice->tx_pkt == 0) {
709                 /* Service TX */
710                 eth_isr ();
711         }
712 #if ET_DEBUG
713         printf ("eth_send: 0x%x, %d bytes\n"
714                 "[%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x] ...\n",
715                 (int)pPacket, length,
716                 ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5],
717                 ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12],
718                 ptr[13], ptr[14], ptr[15]);
719 #endif
720         pUmDevice->tx_pkt = 0;
721         QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
722
723         /* Done with send */
724       out:
725         return status;
726 }
727
728 /* Ethernet receive */
729 int eth_rx (void)
730 {
731         PLM_PACKET pPacket = NULL;
732         PUM_PACKET pUmPacket = NULL;
733         void *skb;
734         int size = 0;
735
736         while (TRUE) {
737
738               bcm570x_service_isr:
739                 /* Pull down packet if it is there */
740                 eth_isr ();
741
742                 /* Indicate RX packets called */
743                 if (pUmDevice->rx_pkt) {
744                         /* printf("eth_rx: got a packet...\n"); */
745                         pUmDevice->rx_pkt = 0;
746                 } else {
747                         /* printf("eth_rx: waiting for packet...\n"); */
748                         goto bcm570x_service_isr;
749                 }
750
751                 pPacket = (PLM_PACKET)
752                     QQ_PopHead (&pDevice->RxPacketReceivedQ.Container);
753
754                 if (pPacket == 0) {
755                         printf ("eth_rx: empty packet!\n");
756                         goto bcm570x_service_isr;
757                 }
758
759                 pUmPacket = (PUM_PACKET) pPacket;
760 #if ET_DEBUG
761                 printf ("eth_rx: packet @0x%x\n", (int)pPacket);
762 #endif
763                 /* If the packet generated an error, reuse buffer */
764                 if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
765                     ((size = pPacket->PacketSize) > pDevice->RxMtu)) {
766
767                         /* reuse skb */
768                         QQ_PushTail (&pDevice->RxPacketFreeQ.Container,
769                                      pPacket);
770                         printf ("eth_rx: error in packet dma!\n");
771                         goto bcm570x_service_isr;
772                 }
773
774                 /* Set size and address */
775                 skb = pUmPacket->skbuff;
776                 size = pPacket->PacketSize;
777
778                 /* Pass the packet up to the protocol
779                  * layers.
780                  */
781                 NetReceive (skb, size);
782
783                 /* Free packet buffer */
784                 bcm570xPktFree (pUmDevice->index, skb);
785                 pUmPacket->skbuff = NULL;
786
787                 /* Reuse SKB */
788                 QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
789
790                 return 0;       /* Got a packet, bail ... */
791         }
792         return size;
793 }
794
795 /* Shut down device */
796 void eth_halt (void)
797 {
798         int i;
799         if (initialized)
800                 if (pDevice && pUmDevice && pUmDevice->opened) {
801                         printf ("\neth%d:%s,", pUmDevice->index,
802                                 pUmDevice->name);
803                         printf ("HALT,");
804                         /* stop device */
805                         LM_Halt (pDevice);
806                         printf ("POWER DOWN,");
807                         LM_SetPowerState (pDevice, LM_POWER_STATE_D3);
808
809                         /* Free the memory allocated by the device in tigon3 */
810                         for (i = 0; i < pUmDevice->mem_list_num; i++) {
811                                 if (pUmDevice->mem_list[i]) {
812                                         /* sanity check */
813                                         if (pUmDevice->dma_list[i]) {   /* cache-safe memory */
814                                                 free (pUmDevice->mem_list[i]);
815                                         } else {
816                                                 free (pUmDevice->mem_list[i]);  /* normal memory   */
817                                         }
818                                 }
819                         }
820                         pUmDevice->opened = 0;
821                         free (pDevice);
822                         pDevice = NULL;
823                         pUmDevice = NULL;
824                         initialized = 0;
825                         printf ("done - offline.\n");
826                 }
827 }
828
829 /*
830  *
831  * Middle Module: Interface between the HW driver (tigon3 modules) and
832  * the native (SENS) driver.  These routines implement the system
833  * interface for tigon3 on VxWorks.
834  */
835
836 /* Middle module dependency - size of a packet descriptor */
837 int MM_Packet_Desc_Size = sizeof (UM_PACKET);
838
839 LM_STATUS
840 MM_ReadConfig32 (PLM_DEVICE_BLOCK pDevice,
841                  LM_UINT32 Offset, LM_UINT32 * pValue32)
842 {
843         UM_DEVICE_BLOCK *pUmDevice;
844         pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
845         pci_read_config_dword (pUmDevice->pdev, Offset, (u32 *) pValue32);
846         return LM_STATUS_SUCCESS;
847 }
848
849 LM_STATUS
850 MM_WriteConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 Value32)
851 {
852         UM_DEVICE_BLOCK *pUmDevice;
853         pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
854         pci_write_config_dword (pUmDevice->pdev, Offset, Value32);
855         return LM_STATUS_SUCCESS;
856 }
857
858 LM_STATUS
859 MM_ReadConfig16 (PLM_DEVICE_BLOCK pDevice,
860                  LM_UINT32 Offset, LM_UINT16 * pValue16)
861 {
862         UM_DEVICE_BLOCK *pUmDevice;
863         pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
864         pci_read_config_word (pUmDevice->pdev, Offset, (u16 *) pValue16);
865         return LM_STATUS_SUCCESS;
866 }
867
868 LM_STATUS
869 MM_WriteConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT16 Value16)
870 {
871         UM_DEVICE_BLOCK *pUmDevice;
872         pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
873         pci_write_config_word (pUmDevice->pdev, Offset, Value16);
874         return LM_STATUS_SUCCESS;
875 }
876
877 LM_STATUS
878 MM_AllocateSharedMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
879                          PLM_VOID * pMemoryBlockVirt,
880                          PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, LM_BOOL Cached)
881 {
882         PLM_VOID pvirt;
883         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
884         dma_addr_t mapping;
885
886         pvirt = malloc (BlockSize);
887         mapping = (dma_addr_t) (pvirt);
888         if (!pvirt)
889                 return LM_STATUS_FAILURE;
890
891         pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
892         pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping;
893         pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
894         memset (pvirt, 0, BlockSize);
895
896         *pMemoryBlockVirt = (PLM_VOID) pvirt;
897         MM_SetAddr (pMemoryBlockPhy, (dma_addr_t) mapping);
898
899         return LM_STATUS_SUCCESS;
900 }
901
902 LM_STATUS
903 MM_AllocateMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
904                    PLM_VOID * pMemoryBlockVirt)
905 {
906         PLM_VOID pvirt;
907         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
908
909         pvirt = malloc (BlockSize);
910
911         if (!pvirt)
912                 return LM_STATUS_FAILURE;
913
914         pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
915         pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
916         pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
917         memset (pvirt, 0, BlockSize);
918         *pMemoryBlockVirt = pvirt;
919
920         return LM_STATUS_SUCCESS;
921 }
922
923 LM_STATUS MM_MapMemBase (PLM_DEVICE_BLOCK pDevice)
924 {
925         printf ("BCM570x PCI Memory base address @0x%x\n",
926                 (unsigned int)pDevice->pMappedMemBase);
927         return LM_STATUS_SUCCESS;
928 }
929
930 LM_STATUS MM_InitializeUmPackets (PLM_DEVICE_BLOCK pDevice)
931 {
932         int i;
933         void *skb;
934         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
935         PUM_PACKET pUmPacket = NULL;
936         PLM_PACKET pPacket = NULL;
937
938         for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
939                 pPacket = QQ_PopHead (&pDevice->RxPacketFreeQ.Container);
940                 pUmPacket = (PUM_PACKET) pPacket;
941
942                 if (pPacket == 0) {
943                         printf ("MM_InitializeUmPackets: Bad RxPacketFreeQ\n");
944                 }
945
946                 skb = bcm570xPktAlloc (pUmDevice->index,
947                                        pPacket->u.Rx.RxBufferSize + 2);
948
949                 if (skb == 0) {
950                         pUmPacket->skbuff = 0;
951                         QQ_PushTail (&pUmDevice->rx_out_of_buf_q.Container,
952                                      pPacket);
953                         printf ("MM_InitializeUmPackets: out of buffer.\n");
954                         continue;
955                 }
956
957                 pUmPacket->skbuff = skb;
958                 QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket);
959         }
960
961         pUmDevice->rx_low_buf_thresh = pDevice->RxPacketDescCnt / 8;
962
963         return LM_STATUS_SUCCESS;
964 }
965
966 LM_STATUS MM_GetConfig (PLM_DEVICE_BLOCK pDevice)
967 {
968         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
969         int index = pDevice->index;
970
971         if (auto_speed[index] == 0)
972                 pDevice->DisableAutoNeg = TRUE;
973         else
974                 pDevice->DisableAutoNeg = FALSE;
975
976         if (line_speed[index] == 0) {
977                 pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO;
978                 pDevice->DisableAutoNeg = FALSE;
979         } else {
980                 if (line_speed[index] == 1000) {
981                         if (pDevice->EnableTbi) {
982                                 pDevice->RequestedMediaType =
983                                     LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX;
984                         } else if (full_duplex[index]) {
985                                 pDevice->RequestedMediaType =
986                                     LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX;
987                         } else {
988                                 pDevice->RequestedMediaType =
989                                     LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS;
990                         }
991                         if (!pDevice->EnableTbi)
992                                 pDevice->DisableAutoNeg = FALSE;
993                 } else if (line_speed[index] == 100) {
994                         if (full_duplex[index]) {
995                                 pDevice->RequestedMediaType =
996                                     LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX;
997                         } else {
998                                 pDevice->RequestedMediaType =
999                                     LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS;
1000                         }
1001                 } else if (line_speed[index] == 10) {
1002                         if (full_duplex[index]) {
1003                                 pDevice->RequestedMediaType =
1004                                     LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX;
1005                         } else {
1006                                 pDevice->RequestedMediaType =
1007                                     LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS;
1008                         }
1009                 } else {
1010                         pDevice->RequestedMediaType =
1011                             LM_REQUESTED_MEDIA_TYPE_AUTO;
1012                         pDevice->DisableAutoNeg = FALSE;
1013                 }
1014
1015         }
1016         pDevice->FlowControlCap = 0;
1017         if (rx_flow_control[index] != 0) {
1018                 pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
1019         }
1020         if (tx_flow_control[index] != 0) {
1021                 pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
1022         }
1023         if ((auto_flow_control[index] != 0) &&
1024             (pDevice->DisableAutoNeg == FALSE)) {
1025
1026                 pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
1027                 if ((tx_flow_control[index] == 0) &&
1028                     (rx_flow_control[index] == 0)) {
1029                         pDevice->FlowControlCap |=
1030                             LM_FLOW_CONTROL_TRANSMIT_PAUSE |
1031                             LM_FLOW_CONTROL_RECEIVE_PAUSE;
1032                 }
1033         }
1034
1035         /* Default MTU for now */
1036         pUmDevice->mtu = 1500;
1037
1038 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
1039         if (pUmDevice->mtu > 1500) {
1040                 pDevice->RxMtu = pUmDevice->mtu;
1041                 pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT;
1042         } else {
1043                 pDevice->RxJumboDescCnt = 0;
1044         }
1045         pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
1046 #else
1047         pDevice->RxMtu = pUmDevice->mtu;
1048 #endif
1049
1050         if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) {
1051                 pDevice->UseTaggedStatus = TRUE;
1052                 pUmDevice->timer_interval = CFG_HZ;
1053         } else {
1054                 pUmDevice->timer_interval = CFG_HZ / 50;
1055         }
1056
1057         pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
1058         pDevice->RxStdDescCnt = rx_std_desc_cnt[index];
1059         /* Note:  adaptive coalescence really isn't adaptive in this driver */
1060         pUmDevice->rx_adaptive_coalesce = rx_adaptive_coalesce[index];
1061         if (!pUmDevice->rx_adaptive_coalesce) {
1062                 pDevice->RxCoalescingTicks = rx_coalesce_ticks[index];
1063                 if (pDevice->RxCoalescingTicks > MAX_RX_COALESCING_TICKS)
1064                         pDevice->RxCoalescingTicks = MAX_RX_COALESCING_TICKS;
1065                 pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks;
1066
1067                 pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index];
1068                 if (pDevice->RxMaxCoalescedFrames > MAX_RX_MAX_COALESCED_FRAMES)
1069                         pDevice->RxMaxCoalescedFrames =
1070                             MAX_RX_MAX_COALESCED_FRAMES;
1071                 pUmDevice->rx_curr_coalesce_frames =
1072                     pDevice->RxMaxCoalescedFrames;
1073                 pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
1074                 if (pDevice->StatsCoalescingTicks > MAX_STATS_COALESCING_TICKS)
1075                         pDevice->StatsCoalescingTicks =
1076                             MAX_STATS_COALESCING_TICKS;
1077         } else {
1078                 pUmDevice->rx_curr_coalesce_frames =
1079                     DEFAULT_RX_MAX_COALESCED_FRAMES;
1080                 pUmDevice->rx_curr_coalesce_ticks = DEFAULT_RX_COALESCING_TICKS;
1081         }
1082         pDevice->TxCoalescingTicks = tx_coalesce_ticks[index];
1083         if (pDevice->TxCoalescingTicks > MAX_TX_COALESCING_TICKS)
1084                 pDevice->TxCoalescingTicks = MAX_TX_COALESCING_TICKS;
1085         pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index];
1086         if (pDevice->TxMaxCoalescedFrames > MAX_TX_MAX_COALESCED_FRAMES)
1087                 pDevice->TxMaxCoalescedFrames = MAX_TX_MAX_COALESCED_FRAMES;
1088
1089         if (enable_wol[index]) {
1090                 pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
1091                 pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
1092         }
1093         pDevice->NicSendBd = TRUE;
1094
1095         /* Don't update status blocks during interrupt */
1096         pDevice->RxCoalescingTicksDuringInt = 0;
1097         pDevice->TxCoalescingTicksDuringInt = 0;
1098
1099         return LM_STATUS_SUCCESS;
1100
1101 }
1102
1103 LM_STATUS MM_StartTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
1104 {
1105         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1106         printf ("Start TX DMA: dev=%d packet @0x%x\n",
1107                 (int)pUmDevice->index, (unsigned int)pPacket);
1108
1109         return LM_STATUS_SUCCESS;
1110 }
1111
1112 LM_STATUS MM_CompleteTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
1113 {
1114         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1115         printf ("Complete TX DMA: dev=%d packet @0x%x\n",
1116                 (int)pUmDevice->index, (unsigned int)pPacket);
1117         return LM_STATUS_SUCCESS;
1118 }
1119
1120 LM_STATUS MM_IndicateStatus (PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
1121 {
1122         char buf[128];
1123         char lcd[4];
1124         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1125         LM_FLOW_CONTROL flow_control;
1126
1127         pUmDevice->delayed_link_ind = 0;
1128         memset (lcd, 0x0, 4);
1129
1130         if (Status == LM_STATUS_LINK_DOWN) {
1131                 sprintf (buf, "eth%d: %s: NIC Link is down\n",
1132                          pUmDevice->index, pUmDevice->name);
1133                 lcd[0] = 'L';
1134                 lcd[1] = 'N';
1135                 lcd[2] = 'K';
1136                 lcd[3] = '?';
1137         } else if (Status == LM_STATUS_LINK_ACTIVE) {
1138                 sprintf (buf, "eth%d:%s: ", pUmDevice->index, pUmDevice->name);
1139
1140                 if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) {
1141                         strcat (buf, "1000 Mbps ");
1142                         lcd[0] = '1';
1143                         lcd[1] = 'G';
1144                         lcd[2] = 'B';
1145                 } else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) {
1146                         strcat (buf, "100 Mbps ");
1147                         lcd[0] = '1';
1148                         lcd[1] = '0';
1149                         lcd[2] = '0';
1150                 } else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) {
1151                         strcat (buf, "10 Mbps ");
1152                         lcd[0] = '1';
1153                         lcd[1] = '0';
1154                         lcd[2] = ' ';
1155                 }
1156                 if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) {
1157                         strcat (buf, "full duplex");
1158                         lcd[3] = 'F';
1159                 } else {
1160                         strcat (buf, "half duplex");
1161                         lcd[3] = 'H';
1162                 }
1163                 strcat (buf, " link up");
1164
1165                 flow_control = pDevice->FlowControl &
1166                     (LM_FLOW_CONTROL_RECEIVE_PAUSE |
1167                      LM_FLOW_CONTROL_TRANSMIT_PAUSE);
1168
1169                 if (flow_control) {
1170                         if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) {
1171                                 strcat (buf, ", receive ");
1172                                 if (flow_control &
1173                                     LM_FLOW_CONTROL_TRANSMIT_PAUSE)
1174                                         strcat (buf, " & transmit ");
1175                         } else {
1176                                 strcat (buf, ", transmit ");
1177                         }
1178                         strcat (buf, "flow control ON");
1179                 } else {
1180                         strcat (buf, ", flow control OFF");
1181                 }
1182                 strcat (buf, "\n");
1183                 printf ("%s", buf);
1184         }
1185 #if 0
1186         sysLedDsply (lcd[0], lcd[1], lcd[2], lcd[3]);
1187 #endif
1188         return LM_STATUS_SUCCESS;
1189 }
1190
1191 LM_STATUS MM_FreeRxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
1192 {
1193
1194         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1195         PUM_PACKET pUmPacket;
1196         void *skb;
1197
1198         pUmPacket = (PUM_PACKET) pPacket;
1199
1200         if ((skb = pUmPacket->skbuff))
1201                 bcm570xPktFree (pUmDevice->index, skb);
1202
1203         pUmPacket->skbuff = 0;
1204
1205         return LM_STATUS_SUCCESS;
1206 }
1207
1208 unsigned long MM_AnGetCurrentTime_us (PAN_STATE_INFO pAnInfo)
1209 {
1210         return get_timer (0);
1211 }
1212
1213 /*
1214  *   Transform an MBUF chain into a single MBUF.
1215  *   This routine will fail if the amount of data in the
1216  *   chain overflows a transmit buffer.  In that case,
1217  *   the incoming MBUF chain will be freed.  This routine can
1218  *   also fail by not being able to allocate a new MBUF (including
1219  *   cluster and mbuf headers).  In that case the failure is
1220  *   non-fatal.  The incoming cluster chain is not freed, giving
1221  *   the caller the choice of whether to try a retransmit later.
1222  */
1223 LM_STATUS MM_CoalesceTxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
1224 {
1225         PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
1226         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1227         void *skbnew;
1228         int len = 0;
1229
1230         if (len == 0)
1231                 return (LM_STATUS_SUCCESS);
1232
1233         if (len > MAX_PACKET_SIZE) {
1234                 printf ("eth%d: xmit frame discarded, too big!, size = %d\n",
1235                         pUmDevice->index, len);
1236                 return (LM_STATUS_FAILURE);
1237         }
1238
1239         skbnew = bcm570xPktAlloc (pUmDevice->index, MAX_PACKET_SIZE);
1240
1241         if (skbnew == NULL) {
1242                 pUmDevice->tx_full = 1;
1243                 printf ("eth%d: out of transmit buffers", pUmDevice->index);
1244                 return (LM_STATUS_FAILURE);
1245         }
1246
1247         /* New packet values */
1248         pUmPacket->skbuff = skbnew;
1249         pUmPacket->lm_packet.u.Tx.FragCount = 1;
1250
1251         return (LM_STATUS_SUCCESS);
1252 }
1253
1254 LM_STATUS MM_IndicateRxPackets (PLM_DEVICE_BLOCK pDevice)
1255 {
1256         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1257         pUmDevice->rx_pkt = 1;
1258         return LM_STATUS_SUCCESS;
1259 }
1260
1261 LM_STATUS MM_IndicateTxPackets (PLM_DEVICE_BLOCK pDevice)
1262 {
1263         PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
1264         PLM_PACKET pPacket;
1265         PUM_PACKET pUmPacket;
1266         void *skb;
1267         while (TRUE) {
1268
1269                 pPacket = (PLM_PACKET)
1270                     QQ_PopHead (&pDevice->TxPacketXmittedQ.Container);
1271
1272                 if (pPacket == 0)
1273                         break;
1274
1275                 pUmPacket = (PUM_PACKET) pPacket;
1276                 skb = (void *)pUmPacket->skbuff;
1277
1278                 /*
1279                  * Free MBLK if we transmitted a fragmented packet or a
1280                  * non-fragmented packet straight from the VxWorks
1281                  * buffer pool. If packet was copied to a local transmit
1282                  * buffer, then there's no MBUF to free, just free
1283                  * the transmit buffer back to the cluster pool.
1284                  */
1285
1286                 if (skb)
1287                         bcm570xPktFree (pUmDevice->index, skb);
1288
1289                 pUmPacket->skbuff = 0;
1290                 QQ_PushTail (&pDevice->TxPacketFreeQ.Container, pPacket);
1291                 pUmDevice->tx_pkt = 1;
1292         }
1293         if (pUmDevice->tx_full) {
1294                 if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) >=
1295                     (QQ_GetSize (&pDevice->TxPacketFreeQ.Container) >> 1))
1296                         pUmDevice->tx_full = 0;
1297         }
1298         return LM_STATUS_SUCCESS;
1299 }
1300
1301 /*
1302  *  Scan an MBUF chain until we reach fragment number "frag"
1303  *  Return its length and physical address.
1304  */
1305 void MM_MapTxDma
1306     (PLM_DEVICE_BLOCK pDevice,
1307      struct _LM_PACKET *pPacket,
1308      T3_64BIT_HOST_ADDR * paddr, LM_UINT32 * len, int frag) {
1309         PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
1310         *len = pPacket->PacketSize;
1311         MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff);
1312 }
1313
1314 /*
1315  *  Convert an mbuf address, a CPU local virtual address,
1316  *  to a physical address as seen from a PCI device.  Store the
1317  *  result at paddr.
1318  */
1319 void MM_MapRxDma (PLM_DEVICE_BLOCK pDevice,
1320                   struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR * paddr)
1321 {
1322         PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
1323         MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff);
1324 }
1325
1326 void MM_SetAddr (LM_PHYSICAL_ADDRESS * paddr, dma_addr_t addr)
1327 {
1328 #if (BITS_PER_LONG == 64)
1329         paddr->High = ((unsigned long)addr) >> 32;
1330         paddr->Low = ((unsigned long)addr) & 0xffffffff;
1331 #else
1332         paddr->High = 0;
1333         paddr->Low = (unsigned long)addr;
1334 #endif
1335 }
1336
1337 void MM_SetT3Addr (T3_64BIT_HOST_ADDR * paddr, dma_addr_t addr)
1338 {
1339         unsigned long baddr = (unsigned long)addr;
1340 #if (BITS_PER_LONG == 64)
1341         set_64bit_addr (paddr, baddr & 0xffffffff, baddr >> 32);
1342 #else
1343         set_64bit_addr (paddr, baddr, 0);
1344 #endif
1345 }
1346
1347 /*
1348  * This combination of `inline' and `extern' has almost the effect of a
1349  * macro.  The way to use it is to put a function definition in a header
1350  * file with these keywords, and put another copy of the definition
1351  * (lacking `inline' and `extern') in a library file.  The definition in
1352  * the header file will cause most calls to the function to be inlined.
1353  * If any uses of the function remain, they will refer to the single copy
1354  * in the library.
1355  */
1356 void atomic_set (atomic_t * entry, int val)
1357 {
1358         entry->counter = val;
1359 }
1360
1361 int atomic_read (atomic_t * entry)
1362 {
1363         return entry->counter;
1364 }
1365
1366 void atomic_inc (atomic_t * entry)
1367 {
1368         if (entry)
1369                 entry->counter++;
1370 }
1371
1372 void atomic_dec (atomic_t * entry)
1373 {
1374         if (entry)
1375                 entry->counter--;
1376 }
1377
1378 void atomic_sub (int a, atomic_t * entry)
1379 {
1380         if (entry)
1381                 entry->counter -= a;
1382 }
1383
1384 void atomic_add (int a, atomic_t * entry)
1385 {
1386         if (entry)
1387                 entry->counter += a;
1388 }
1389
1390 /******************************************************************************/
1391 /* Description:                                                               */
1392 /*                                                                            */
1393 /* Return:                                                                    */
1394 /******************************************************************************/
1395 void QQ_InitQueue (PQQ_CONTAINER pQueue, unsigned int QueueSize)
1396 {
1397         pQueue->Head = 0;
1398         pQueue->Tail = 0;
1399         pQueue->Size = QueueSize + 1;
1400         atomic_set (&pQueue->EntryCnt, 0);
1401 }                               /* QQ_InitQueue */
1402
1403 /******************************************************************************/
1404 /* Description:                                                               */
1405 /*                                                                            */
1406 /* Return:                                                                    */
1407 /******************************************************************************/
1408 char QQ_Full (PQQ_CONTAINER pQueue)
1409 {
1410         unsigned int NewHead;
1411
1412         NewHead = (pQueue->Head + 1) % pQueue->Size;
1413
1414         return (NewHead == pQueue->Tail);
1415 }                               /* QQ_Full */
1416
1417 /******************************************************************************/
1418 /* Description:                                                               */
1419 /*                                                                            */
1420 /* Return:                                                                    */
1421 /******************************************************************************/
1422 char QQ_Empty (PQQ_CONTAINER pQueue)
1423 {
1424         return (pQueue->Head == pQueue->Tail);
1425 }                               /* QQ_Empty */
1426
1427 /******************************************************************************/
1428 /* Description:                                                               */
1429 /*                                                                            */
1430 /* Return:                                                                    */
1431 /******************************************************************************/
1432 unsigned int QQ_GetSize (PQQ_CONTAINER pQueue)
1433 {
1434         return pQueue->Size;
1435 }                               /* QQ_GetSize */
1436
1437 /******************************************************************************/
1438 /* Description:                                                               */
1439 /*                                                                            */
1440 /* Return:                                                                    */
1441 /******************************************************************************/
1442 unsigned int QQ_GetEntryCnt (PQQ_CONTAINER pQueue)
1443 {
1444         return atomic_read (&pQueue->EntryCnt);
1445 }                               /* QQ_GetEntryCnt */
1446
1447 /******************************************************************************/
1448 /* Description:                                                               */
1449 /*                                                                            */
1450 /* Return:                                                                    */
1451 /*    TRUE entry was added successfully.                                      */
1452 /*    FALSE queue is full.                                                    */
1453 /******************************************************************************/
1454 char QQ_PushHead (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)
1455 {
1456         unsigned int Head;
1457
1458         Head = (pQueue->Head + 1) % pQueue->Size;
1459
1460 #if !defined(QQ_NO_OVERFLOW_CHECK)
1461         if (Head == pQueue->Tail) {
1462                 return 0;
1463         }                       /* if */
1464 #endif                          /* QQ_NO_OVERFLOW_CHECK */
1465
1466         pQueue->Array[pQueue->Head] = pEntry;
1467         wmb ();
1468         pQueue->Head = Head;
1469         atomic_inc (&pQueue->EntryCnt);
1470
1471         return -1;
1472 }                               /* QQ_PushHead */
1473
1474 /******************************************************************************/
1475 /* Description:                                                               */
1476 /*                                                                            */
1477 /* Return:                                                                    */
1478 /*    TRUE entry was added successfully.                                      */
1479 /*    FALSE queue is full.                                                    */
1480 /******************************************************************************/
1481 char QQ_PushTail (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry)
1482 {
1483         unsigned int Tail;
1484
1485         Tail = pQueue->Tail;
1486         if (Tail == 0) {
1487                 Tail = pQueue->Size;
1488         }                       /* if */
1489         Tail--;
1490
1491 #if !defined(QQ_NO_OVERFLOW_CHECK)
1492         if (Tail == pQueue->Head) {
1493                 return 0;
1494         }                       /* if */
1495 #endif                          /* QQ_NO_OVERFLOW_CHECK */
1496
1497         pQueue->Array[Tail] = pEntry;
1498         wmb ();
1499         pQueue->Tail = Tail;
1500         atomic_inc (&pQueue->EntryCnt);
1501
1502         return -1;
1503 }                               /* QQ_PushTail */
1504
1505 /******************************************************************************/
1506 /* Description:                                                               */
1507 /*                                                                            */
1508 /* Return:                                                                    */
1509 /******************************************************************************/
1510 PQQ_ENTRY QQ_PopHead (PQQ_CONTAINER pQueue)
1511 {
1512         unsigned int Head;
1513         PQQ_ENTRY Entry;
1514
1515         Head = pQueue->Head;
1516
1517 #if !defined(QQ_NO_UNDERFLOW_CHECK)
1518         if (Head == pQueue->Tail) {
1519                 return (PQQ_ENTRY) 0;
1520         }                       /* if */
1521 #endif                          /* QQ_NO_UNDERFLOW_CHECK */
1522
1523         if (Head == 0) {
1524                 Head = pQueue->Size;
1525         }                       /* if */
1526         Head--;
1527
1528         Entry = pQueue->Array[Head];
1529         membar ();
1530
1531         pQueue->Head = Head;
1532         atomic_dec (&pQueue->EntryCnt);
1533
1534         return Entry;
1535 }                               /* QQ_PopHead */
1536
1537 /******************************************************************************/
1538 /* Description:                                                               */
1539 /*                                                                            */
1540 /* Return:                                                                    */
1541 /******************************************************************************/
1542 PQQ_ENTRY QQ_PopTail (PQQ_CONTAINER pQueue)
1543 {
1544         unsigned int Tail;
1545         PQQ_ENTRY Entry;
1546
1547         Tail = pQueue->Tail;
1548
1549 #if !defined(QQ_NO_UNDERFLOW_CHECK)
1550         if (Tail == pQueue->Head) {
1551                 return (PQQ_ENTRY) 0;
1552         }                       /* if */
1553 #endif                          /* QQ_NO_UNDERFLOW_CHECK */
1554
1555         Entry = pQueue->Array[Tail];
1556         membar ();
1557         pQueue->Tail = (Tail + 1) % pQueue->Size;
1558         atomic_dec (&pQueue->EntryCnt);
1559
1560         return Entry;
1561 }                               /* QQ_PopTail */
1562
1563 /******************************************************************************/
1564 /* Description:                                                               */
1565 /*                                                                            */
1566 /* Return:                                                                    */
1567 /******************************************************************************/
1568 PQQ_ENTRY QQ_GetHead (PQQ_CONTAINER pQueue, unsigned int Idx)
1569 {
1570         if (Idx >= atomic_read (&pQueue->EntryCnt)) {
1571                 return (PQQ_ENTRY) 0;
1572         }
1573
1574         if (pQueue->Head > Idx) {
1575                 Idx = pQueue->Head - Idx;
1576         } else {
1577                 Idx = pQueue->Size - (Idx - pQueue->Head);
1578         }
1579         Idx--;
1580
1581         return pQueue->Array[Idx];
1582 }
1583
1584 /******************************************************************************/
1585 /* Description:                                                               */
1586 /*                                                                            */
1587 /* Return:                                                                    */
1588 /******************************************************************************/
1589 PQQ_ENTRY QQ_GetTail (PQQ_CONTAINER pQueue, unsigned int Idx)
1590 {
1591         if (Idx >= atomic_read (&pQueue->EntryCnt)) {
1592                 return (PQQ_ENTRY) 0;
1593         }
1594
1595         Idx += pQueue->Tail;
1596         if (Idx >= pQueue->Size) {
1597                 Idx = Idx - pQueue->Size;
1598         }
1599
1600         return pQueue->Array[Idx];
1601 }
1602
1603 #endif