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