]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/npe/IxEthAccMac.c
Merge 'u-boot-microblaze/zynq' into (u-boot-arm/master'
[karo-tx-uboot.git] / drivers / net / npe / IxEthAccMac.c
1 /**
2  * @file IxEthAccMac.c
3  *
4  * @author Intel Corporation
5  * @date
6  *
7  * @brief  MAC control functions
8  *
9  * Design Notes:
10  *
11  * @par
12  * IXP400 SW Release version 2.0
13  *
14  * -- Copyright Notice --
15  *
16  * @par
17  * Copyright 2001-2005, Intel Corporation.
18  * All rights reserved.
19  *
20  * @par
21  * SPDX-License-Identifier:     BSD-3-Clause
22  * @par
23  * -- End of Copyright Notice --
24  */
25
26 #include "IxOsal.h"
27 #include "IxNpeMh.h"
28 #ifdef CONFIG_IXP425_COMPONENT_ETHDB
29 #include "IxEthDB.h"
30 #endif
31 #include "IxEthDBPortDefs.h"
32 #include "IxEthNpe.h"
33 #include "IxEthAcc.h"
34 #include "IxEthAccDataPlane_p.h"
35 #include "IxEthAcc_p.h"
36 #include "IxEthAccMac_p.h"
37
38 /* Maximum number of retries during ixEthAccPortDisable, which
39  * is approximately 10 seconds
40 */
41 #define IX_ETH_ACC_MAX_RETRY 500
42
43 /* Maximum number of retries during ixEthAccPortDisable when expecting
44  * timeout
45  */
46 #define IX_ETH_ACC_MAX_RETRY_TIMEOUT 5
47
48 #define IX_ETH_ACC_VALIDATE_PORT_ID(portId) \
49     do                                                           \
50     {                                                            \
51         if(!IX_ETH_ACC_IS_PORT_VALID(portId))   \
52         {                                                        \
53             return IX_ETH_ACC_INVALID_PORT;                      \
54         }                                                        \
55     } while(0)
56
57 PUBLIC IxEthAccMacState ixEthAccMacState[IX_ETH_ACC_NUMBER_OF_PORTS];
58
59 PRIVATE UINT32 ixEthAccMacBase[IX_ETH_ACC_NUMBER_OF_PORTS];
60
61 /*Forward function declarations*/
62 PRIVATE void
63 ixEthAccPortDisableRx (IxEthAccPortId portId,
64                        IX_OSAL_MBUF * mBufPtr,
65                        BOOL useMultiBufferCallback);
66
67 PRIVATE void
68 ixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId,
69                                    IX_OSAL_MBUF * mBufPtr,
70                                    BOOL useMultiBufferCallback);
71
72 PRIVATE void
73 ixEthAccPortDisableTxDone (UINT32 cbTag,
74                            IX_OSAL_MBUF *mbuf);
75
76 PRIVATE void
77 ixEthAccPortDisableTxDoneAndSubmit (UINT32 cbTag,
78                                     IX_OSAL_MBUF *mbuf);
79
80 PRIVATE void
81 ixEthAccPortDisableRxCallback (UINT32 cbTag,
82                                IX_OSAL_MBUF * mBufPtr,
83                                UINT32 learnedPortId);
84
85 PRIVATE void
86 ixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag,
87                                           IX_OSAL_MBUF **mBufPtr);
88
89 PRIVATE IxEthAccStatus
90 ixEthAccPortDisableTryTransmit(UINT32 portId);
91
92 PRIVATE IxEthAccStatus
93 ixEthAccPortDisableTryReplenish(UINT32 portId);
94
95 PRIVATE IxEthAccStatus
96 ixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId,
97                                     IxEthAccMacAddr *macAddr);
98
99 PRIVATE IxEthAccStatus
100 ixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId,
101                                    IxEthAccMacAddr *macAddr);
102
103 PRIVATE void
104 ixEthAccMacNpeStatsMessageCallback (IxNpeMhNpeId npeId,
105                                     IxNpeMhMessage msg);
106
107 PRIVATE void
108 ixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId,
109                                          IxNpeMhMessage msg);
110
111 PRIVATE void
112 ixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId,
113                                     IxNpeMhMessage msg);
114
115 PRIVATE void
116 ixEthAccMulticastAddressSet(IxEthAccPortId portId);
117
118 PRIVATE BOOL
119 ixEthAccMacEqual(IxEthAccMacAddr *macAddr1,
120                  IxEthAccMacAddr *macAddr2);
121
122 PRIVATE void
123 ixEthAccMacPrint(IxEthAccMacAddr *m);
124
125 PRIVATE void
126 ixEthAccMacStateUpdate(IxEthAccPortId portId);
127
128 IxEthAccStatus
129 ixEthAccMacMemInit(void)
130 {
131     ixEthAccMacBase[IX_ETH_PORT_1] =
132         (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_0_BASE,
133                                  IX_OSAL_IXP400_ETHA_MAP_SIZE);
134     ixEthAccMacBase[IX_ETH_PORT_2] =
135         (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_1_BASE,
136                                  IX_OSAL_IXP400_ETHB_MAP_SIZE);
137 #ifdef __ixp46X
138     ixEthAccMacBase[IX_ETH_PORT_3] =
139         (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_2_BASE,
140                                  IX_OSAL_IXP400_ETH_NPEA_MAP_SIZE);
141     if (ixEthAccMacBase[IX_ETH_PORT_3] == 0)
142     {
143         ixOsalLog(IX_OSAL_LOG_LVL_FATAL,
144                   IX_OSAL_LOG_DEV_STDOUT,
145                   "EthAcc: Could not map MAC I/O memory\n",
146                   0, 0, 0, 0, 0 ,0);
147
148         return IX_ETH_ACC_FAIL;
149     }
150 #endif
151
152     if (ixEthAccMacBase[IX_ETH_PORT_1] == 0
153         || ixEthAccMacBase[IX_ETH_PORT_2] == 0)
154     {
155         ixOsalLog(IX_OSAL_LOG_LVL_FATAL,
156                   IX_OSAL_LOG_DEV_STDOUT,
157                   "EthAcc: Could not map MAC I/O memory\n",
158                   0, 0, 0, 0, 0 ,0);
159
160         return IX_ETH_ACC_FAIL;
161     }
162
163     return IX_ETH_ACC_SUCCESS;
164 }
165
166 void
167 ixEthAccMacUnload(void)
168 {
169     IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_1]);
170     IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_2]);
171 #ifdef __ixp46X
172     IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_3]);
173     ixEthAccMacBase[IX_ETH_PORT_3] = 0;
174 #endif
175     ixEthAccMacBase[IX_ETH_PORT_2] = 0;
176     ixEthAccMacBase[IX_ETH_PORT_1] = 0;
177 }
178
179 IxEthAccStatus
180 ixEthAccPortEnablePriv(IxEthAccPortId portId)
181 {
182     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
183
184     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
185     {
186         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable port.\n",(INT32)portId,0,0,0,0,0);
187         return IX_ETH_ACC_SUCCESS ;
188     }
189
190     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
191     {
192         printf("EthAcc: (Mac) cannot enable port %d, port not initialized\n", portId);
193         return (IX_ETH_ACC_PORT_UNINITIALIZED);
194     }
195
196     if (ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn == NULL)
197     {
198         /* TxDone callback not registered */
199         printf("EthAcc: (Mac) cannot enable port %d, TxDone callback not registered\n", portId);
200         return (IX_ETH_ACC_PORT_UNINITIALIZED);
201     }
202
203     if ((ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn == NULL)
204         && (ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn == NULL))
205     {
206         /* Receive callback not registered */
207         printf("EthAcc: (Mac) cannot enable port %d, Rx callback not registered\n", portId);
208         return (IX_ETH_ACC_PORT_UNINITIALIZED);
209     }
210
211     if(!ixEthAccMacState[portId].initDone)
212     {
213         printf("EthAcc: (Mac) cannot enable port %d, MAC address not set\n", portId);
214         return (IX_ETH_ACC_MAC_UNINITIALIZED);
215     }
216
217     /* if the state is being set to what it is already at, do nothing*/
218     if (ixEthAccMacState[portId].enabled)
219     {
220         return IX_ETH_ACC_SUCCESS;
221     }
222
223 #ifdef CONFIG_IXP425_COMPONENT_ETHDB
224     /* enable ethernet database for this port */
225     if (ixEthDBPortEnable(portId) != IX_ETH_DB_SUCCESS)
226     {
227         printf("EthAcc: (Mac) cannot enable port %d, EthDB failure\n", portId);
228         return IX_ETH_ACC_FAIL;
229     }
230 #endif
231
232     /* set the MAC core registers */
233     REG_WRITE(ixEthAccMacBase[portId],
234               IX_ETH_ACC_MAC_TX_CNTRL2,
235               IX_ETH_ACC_TX_CNTRL2_RETRIES_MASK);
236
237     REG_WRITE(ixEthAccMacBase[portId],
238               IX_ETH_ACC_MAC_RANDOM_SEED,
239               IX_ETH_ACC_RANDOM_SEED_DEFAULT);
240
241     REG_WRITE(ixEthAccMacBase[portId],
242               IX_ETH_ACC_MAC_THRESH_P_EMPTY,
243               IX_ETH_ACC_MAC_THRESH_P_EMPTY_DEFAULT);
244
245     REG_WRITE(ixEthAccMacBase[portId],
246               IX_ETH_ACC_MAC_THRESH_P_FULL,
247               IX_ETH_ACC_MAC_THRESH_P_FULL_DEFAULT);
248
249     REG_WRITE(ixEthAccMacBase[portId],
250               IX_ETH_ACC_MAC_TX_DEFER,
251               IX_ETH_ACC_MAC_TX_DEFER_DEFAULT);
252
253     REG_WRITE(ixEthAccMacBase[portId],
254               IX_ETH_ACC_MAC_TX_TWO_DEFER_1,
255               IX_ETH_ACC_MAC_TX_TWO_DEFER_1_DEFAULT);
256
257     REG_WRITE(ixEthAccMacBase[portId],
258               IX_ETH_ACC_MAC_TX_TWO_DEFER_2,
259               IX_ETH_ACC_MAC_TX_TWO_DEFER_2_DEFAULT);
260
261     REG_WRITE(ixEthAccMacBase[portId],
262               IX_ETH_ACC_MAC_SLOT_TIME,
263               IX_ETH_ACC_MAC_SLOT_TIME_DEFAULT);
264
265     REG_WRITE(ixEthAccMacBase[portId],
266               IX_ETH_ACC_MAC_INT_CLK_THRESH,
267               IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
268
269     REG_WRITE(ixEthAccMacBase[portId],
270               IX_ETH_ACC_MAC_BUF_SIZE_TX,
271               IX_ETH_ACC_MAC_BUF_SIZE_TX_DEFAULT);
272
273     REG_WRITE(ixEthAccMacBase[portId],
274               IX_ETH_ACC_MAC_TX_CNTRL1,
275               IX_ETH_ACC_TX_CNTRL1_DEFAULT);
276
277     REG_WRITE(ixEthAccMacBase[portId],
278               IX_ETH_ACC_MAC_RX_CNTRL1,
279               IX_ETH_ACC_RX_CNTRL1_DEFAULT);
280
281     /* set the global state */
282     ixEthAccMacState[portId].portDisableState = ACTIVE;
283     ixEthAccMacState[portId].enabled = true;
284
285     /* rewrite the setup (including mac filtering) depending
286      * on current options
287      */
288     ixEthAccMacStateUpdate(portId);
289
290     return IX_ETH_ACC_SUCCESS;
291 }
292
293 /*
294  * PortDisable local variables. They contain the intermediate steps
295  * while the port is being disabled and the buffers being drained out
296  * of the NPE.
297  */
298 typedef void (*IxEthAccPortDisableRx)(IxEthAccPortId portId,
299                                       IX_OSAL_MBUF * mBufPtr,
300                                       BOOL useMultiBufferCallback);
301 static IxEthAccPortRxCallback
302 ixEthAccPortDisableFn[IX_ETH_ACC_NUMBER_OF_PORTS];
303 static IxEthAccPortMultiBufferRxCallback
304 ixEthAccPortDisableMultiBufferFn[IX_ETH_ACC_NUMBER_OF_PORTS];
305 static IxEthAccPortDisableRx
306 ixEthAccPortDisableRxTable[IX_ETH_ACC_NUMBER_OF_PORTS];
307 static UINT32
308 ixEthAccPortDisableCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
309 static UINT32
310 ixEthAccPortDisableMultiBufferCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
311
312 static IxEthAccPortTxDoneCallback
313 ixEthAccPortDisableTxDoneFn[IX_ETH_ACC_NUMBER_OF_PORTS];
314 static UINT32
315 ixEthAccPortDisableTxDoneCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
316
317 static UINT32
318 ixEthAccPortDisableUserBufferCount[IX_ETH_ACC_NUMBER_OF_PORTS];
319
320 /*
321  * PortDisable private callbacks functions. They handle the user
322  * traffic, and the special buffers (one for tx, one for rx) used
323  * in portDisable.
324  */
325 PRIVATE void
326 ixEthAccPortDisableTxDone(UINT32 cbTag,
327                           IX_OSAL_MBUF *mbuf)
328 {
329     IxEthAccPortId portId = (IxEthAccPortId)cbTag;
330     volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState;
331
332     /* check for the special mbuf used in portDisable */
333     if (mbuf == ixEthAccMacState[portId].portDisableTxMbufPtr)
334     {
335         *txState = TRANSMIT_DONE;
336     }
337     else
338     {
339         /* increment the count of user traffic during portDisable */
340         ixEthAccPortDisableUserBufferCount[portId]++;
341
342        /* call client TxDone function */
343         ixEthAccPortDisableTxDoneFn[portId](ixEthAccPortDisableTxDoneCbTag[portId], mbuf);
344     }
345 }
346
347 PRIVATE IxEthAccStatus
348 ixEthAccPortDisableTryTransmit(UINT32 portId)
349 {
350     int key;
351     IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
352     volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState;
353     /* transmit the special buffer again if it is transmitted
354      * and update the txState
355      * This section is protected because the portDisable context
356      * run an identical code, so the system keeps transmitting at the
357      * maximum rate.
358      */
359     key = ixOsalIrqLock();
360     if (*txState == TRANSMIT_DONE)
361     {
362         IX_OSAL_MBUF *mbufTxPtr = ixEthAccMacState[portId].portDisableTxMbufPtr;
363         *txState = TRANSMIT;
364         status = ixEthAccPortTxFrameSubmit(portId,
365                                            mbufTxPtr,
366                                            IX_ETH_ACC_TX_DEFAULT_PRIORITY);
367     }
368     ixOsalIrqUnlock(key);
369
370     return status;
371 }
372
373 PRIVATE void
374 ixEthAccPortDisableTxDoneAndSubmit(UINT32 cbTag,
375                                    IX_OSAL_MBUF *mbuf)
376 {
377     IxEthAccPortId portId = (IxEthAccPortId)cbTag;
378
379     /* call the callback which forwards the traffic to the client */
380     ixEthAccPortDisableTxDone(cbTag, mbuf);
381
382     /* try to transmit the buffer used in portDisable
383      * if seen in TxDone
384      */
385     ixEthAccPortDisableTryTransmit(portId);
386 }
387
388 PRIVATE void
389 ixEthAccPortDisableRx (IxEthAccPortId portId,
390                        IX_OSAL_MBUF * mBufPtr,
391                        BOOL useMultiBufferCallback)
392 {
393     volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState;
394     IX_OSAL_MBUF *mNextPtr;
395
396     while (mBufPtr)
397     {
398         mNextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr);
399         IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr) = NULL;
400
401         /* check for the special mbuf used in portDisable */
402         if (mBufPtr == ixEthAccMacState[portId].portDisableRxMbufPtr)
403         {
404             *rxState = RECEIVE;
405         }
406         else
407         {
408             /* increment the count of user traffic during portDisable */
409             ixEthAccPortDisableUserBufferCount[portId]++;
410
411             /* reset the received payload length during portDisable */
412             IX_OSAL_MBUF_MLEN(mBufPtr)    = 0;
413             IX_OSAL_MBUF_PKT_LEN(mBufPtr) = 0;
414
415             if (useMultiBufferCallback)
416             {
417                 /* call the user callback with one unchained
418                  * buffer, without payload. A small array is built
419                  * to be used as a parameter (the user callback expects
420                  * to receive an array ended by a NULL pointer.
421                  */
422                 IX_OSAL_MBUF *mBufPtrArray[2];
423
424                 mBufPtrArray[0] = mBufPtr;
425                 mBufPtrArray[1] = NULL;
426                 ixEthAccPortDisableMultiBufferFn[portId](
427                          ixEthAccPortDisableMultiBufferCbTag[portId],
428                          mBufPtrArray);
429             }
430             else
431             {
432                 /* call the user callback with a unchained
433                  * buffer, without payload and the destination port is
434                  * unknown.
435                  */
436                 ixEthAccPortDisableFn[portId](
437                       ixEthAccPortDisableCbTag[portId],
438                       mBufPtr,
439                       IX_ETH_DB_UNKNOWN_PORT /* port not found */);
440             }
441         }
442
443         mBufPtr = mNextPtr;
444     }
445 }
446
447 PRIVATE IxEthAccStatus
448 ixEthAccPortDisableTryReplenish(UINT32 portId)
449 {
450     int key;
451     IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
452     volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState;
453     /* replenish with the special buffer again if it is received
454      * and update the rxState
455      * This section is protected because the portDisable context
456      * run an identical code, so the system keeps replenishing at the
457      * maximum rate.
458      */
459     key = ixOsalIrqLock();
460     if (*rxState == RECEIVE)
461     {
462         IX_OSAL_MBUF *mbufRxPtr = ixEthAccMacState[portId].portDisableRxMbufPtr;
463         *rxState = REPLENISH;
464         IX_OSAL_MBUF_MLEN(mbufRxPtr) = IX_ETHACC_RX_MBUF_MIN_SIZE;
465         status = ixEthAccPortRxFreeReplenish(portId, mbufRxPtr);
466     }
467     ixOsalIrqUnlock(key);
468
469     return status;
470 }
471
472 PRIVATE void
473 ixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId,
474                                    IX_OSAL_MBUF * mBufPtr,
475                                    BOOL useMultiBufferCallback)
476 {
477     /* call the callback which forwards the traffic to the client */
478     ixEthAccPortDisableRx(portId, mBufPtr, useMultiBufferCallback);
479
480     /* try to replenish with the buffer used in portDisable
481      * if seen in Rx
482      */
483     ixEthAccPortDisableTryReplenish(portId);
484 }
485
486 PRIVATE void
487 ixEthAccPortDisableRxCallback (UINT32 cbTag,
488                                IX_OSAL_MBUF * mBufPtr,
489                                UINT32 learnedPortId)
490 {
491     IxEthAccPortId portId = (IxEthAccPortId)cbTag;
492
493     /* call the portDisable receive callback */
494    (ixEthAccPortDisableRxTable[portId])(portId, mBufPtr, false);
495 }
496
497 PRIVATE void
498 ixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag,
499                                           IX_OSAL_MBUF **mBufPtr)
500 {
501     IxEthAccPortId portId = (IxEthAccPortId)cbTag;
502
503     while (*mBufPtr)
504     {
505         /* call the portDisable receive callback with one buffer at a time */
506         (ixEthAccPortDisableRxTable[portId])(portId, *mBufPtr++, true);
507     }
508 }
509
510 IxEthAccStatus
511 ixEthAccPortDisablePriv(IxEthAccPortId portId)
512 {
513     IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
514     int key;
515     int retry, retryTimeout;
516     volatile IxEthAccPortDisableState *state = &ixEthAccMacState[portId].portDisableState;
517     volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState;
518     volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState;
519
520     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
521
522     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
523     {
524         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disable port.\n",(INT32)portId,0,0,0,0,0);
525         return IX_ETH_ACC_SUCCESS ;
526     }
527
528     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
529     {
530         return (IX_ETH_ACC_PORT_UNINITIALIZED);
531     }
532
533     /* if the state is being set to what it is already at, do nothing */
534     if (!ixEthAccMacState[portId].enabled)
535     {
536         return IX_ETH_ACC_SUCCESS;
537     }
538
539     *state = DISABLED;
540
541     /* disable MAC receive first */
542     ixEthAccPortRxDisablePriv(portId);
543
544 #ifdef CONFIG_IXP425_COMPONENT_ETHDB
545     /* disable ethernet database for this port - It is done now to avoid
546      * issuing ELT maintenance after requesting 'port disable' in an NPE
547      */
548     if (ixEthDBPortDisable(portId) != IX_ETH_DB_SUCCESS)
549     {
550         status = IX_ETH_ACC_FAIL;
551         IX_ETH_ACC_FATAL_LOG("ixEthAccPortDisable: failed to disable EthDB for this port\n", 0, 0, 0, 0, 0, 0);
552     }
553 #endif
554
555     /* enter the critical section */
556     key = ixOsalIrqLock();
557
558     /* swap the Rx and TxDone callbacks */
559     ixEthAccPortDisableFn[portId]            = ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn;
560     ixEthAccPortDisableMultiBufferFn[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn;
561     ixEthAccPortDisableCbTag[portId]         = ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag;
562     ixEthAccPortDisableMultiBufferCbTag[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag;
563     ixEthAccPortDisableTxDoneFn[portId]      = ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn;
564     ixEthAccPortDisableTxDoneCbTag[portId]   = ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag;
565     ixEthAccPortDisableRxTable[portId]       =  ixEthAccPortDisableRx;
566
567     /* register temporary callbacks */
568     ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn            = ixEthAccPortDisableRxCallback;
569     ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag           = portId;
570
571     ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = ixEthAccPortDisableMultiBufferRxCallback;
572     ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = portId;
573
574     ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn  = ixEthAccPortDisableTxDone;
575     ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag           = portId;
576
577     /* initialise the Rx state and Tx states */
578     *txState = TRANSMIT_DONE;
579     *rxState = RECEIVE;
580
581     /* exit the critical section */
582     ixOsalIrqUnlock(key);
583
584     /* enable a NPE loopback */
585     if (ixEthAccNpeLoopbackEnablePriv(portId) != IX_ETH_ACC_SUCCESS)
586     {
587         status = IX_ETH_ACC_FAIL;
588     }
589
590     if (status == IX_ETH_ACC_SUCCESS)
591     {
592         retry = 0;
593
594         /* Step 1 : Drain Tx traffic and TxDone queues :
595          *
596          * Transmit and replenish at least once with the
597          * special buffers until both of them are seen
598          * in the callback hook
599          *
600          * (the receive callback keeps replenishing, so once we see
601          * the special Tx buffer, we can be sure that Tx drain is complete)
602          */
603         ixEthAccPortDisableRxTable[portId]
604             =  ixEthAccPortDisableRxAndReplenish;
605         ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn
606             = ixEthAccPortDisableTxDone;
607
608         do
609         {
610             /* keep replenishing */
611             status = ixEthAccPortDisableTryReplenish(portId);
612             if (status == IX_ETH_ACC_SUCCESS)
613             {
614                 /* keep transmitting */
615                 status = ixEthAccPortDisableTryTransmit(portId);
616             }
617             if (status == IX_ETH_ACC_SUCCESS)
618             {
619                 /* wait for some traffic being processed */
620                 ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
621             }
622         }
623         while ((status == IX_ETH_ACC_SUCCESS)
624                && (retry++ < IX_ETH_ACC_MAX_RETRY)
625                && (*txState == TRANSMIT));
626
627         /* Step 2 : Drain Rx traffic, RxFree and Rx queues :
628          *
629          * Transmit and replenish at least once with the
630          * special buffers until both of them are seen
631          * in the callback hook
632          * (the transmit callback keeps transmitting, and when we see
633          * the special Rx buffer, we can be sure that rxFree drain
634          * is complete)
635          *
636          * The nested loop helps to retry if the user was keeping
637          * replenishing or transmitting during portDisable.
638          *
639          * The 2 nested loops ensure more retries if user traffic is
640          * seen during portDisable : the user should not replenish
641          * or transmit while portDisable is running. However, because of
642          * the queueing possibilities in ethAcc dataplane, it is possible
643          * that a lot of traffic is left in the queues (e.g. when
644          * transmitting over a low speed link) and therefore, more
645          * retries are allowed to help flushing the buffers out.
646          */
647         ixEthAccPortDisableRxTable[portId]
648             =  ixEthAccPortDisableRx;
649         ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn
650             = ixEthAccPortDisableTxDoneAndSubmit;
651
652         do
653         {
654             do
655             {
656                 ixEthAccPortDisableUserBufferCount[portId] = 0;
657
658                 /* keep replenishing */
659                 status = ixEthAccPortDisableTryReplenish(portId);
660                 if (status == IX_ETH_ACC_SUCCESS)
661                 {
662                     /* keep transmitting */
663                     status = ixEthAccPortDisableTryTransmit(portId);
664                 }
665                 if (status == IX_ETH_ACC_SUCCESS)
666                 {
667                     /* wait for some traffic being processed */
668                     ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
669                 }
670             }
671             while ((status == IX_ETH_ACC_SUCCESS)
672                    && (retry++ < IX_ETH_ACC_MAX_RETRY)
673                    && ((ixEthAccPortDisableUserBufferCount[portId] != 0)
674                        || (*rxState == REPLENISH)));
675
676             /* After the first iteration, change the receive callbacks,
677              * to process only 1 buffer at a time
678              */
679             ixEthAccPortDisableRxTable[portId]
680                 = ixEthAccPortDisableRx;
681             ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn
682                 = ixEthAccPortDisableTxDone;
683
684             /* repeat the whole process while user traffic is seen in TxDone
685              *
686              * The conditions to stop the loop are
687              * - Xscale has both Rx and Tx special buffers
688              *   (txState = transmit, rxState = receive)
689              * - any error in txSubmit or rxReplenish
690              * - no user traffic seen
691              * - an excessive amount of retries
692              */
693         }
694         while ((status == IX_ETH_ACC_SUCCESS)
695                && (retry < IX_ETH_ACC_MAX_RETRY)
696                && (*txState == TRANSMIT));
697
698         /* check the loop exit conditions. The NPE should not hold
699          * the special buffers.
700          */
701         if ((*rxState == REPLENISH) || (*txState == TRANSMIT))
702         {
703             status = IX_ETH_ACC_FAIL;
704         }
705
706         if (status == IX_ETH_ACC_SUCCESS)
707         {
708             /* Step 3 : Replenish without transmitting until a timeout
709              * occurs, in order to drain the internal NPE fifos
710              *
711              * we can expect a few frames srill held
712              * in the NPE.
713              *
714              * The 2 nested loops take care about the NPE dropping traffic
715              * (including loopback traffic) when the Rx queue is full.
716              *
717              * The timeout value is very conservative
718              * since the loopback used keeps replenishhing.
719              *
720              */
721             do
722             {
723                 ixEthAccPortDisableRxTable[portId] = ixEthAccPortDisableRxAndReplenish;
724                 ixEthAccPortDisableUserBufferCount[portId] = 0;
725                 retryTimeout = 0;
726                 do
727                 {
728                     /* keep replenishing */
729                     status = ixEthAccPortDisableTryReplenish(portId);
730                     if (status == IX_ETH_ACC_SUCCESS)
731                     {
732                         /* wait for some traffic being processed */
733                         ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
734                     }
735                 }
736                 while ((status == IX_ETH_ACC_SUCCESS)
737                        && (retryTimeout++ < IX_ETH_ACC_MAX_RETRY_TIMEOUT));
738
739                 /* Step 4 : Transmit once. Stop replenish
740                  *
741                  * After the Rx timeout, we are sure that the NPE does not
742                  * hold any frame in its internal NPE fifos.
743                  *
744                  * At this point, the NPE still holds the last rxFree buffer.
745                  * By transmitting a single frame, this should unblock the
746                  * last rxFree buffer. This code just transmit once and
747                  * wait for both frames seen in TxDone and in rxFree.
748                  *
749                  */
750                 ixEthAccPortDisableRxTable[portId] =  ixEthAccPortDisableRx;
751                 status = ixEthAccPortDisableTryTransmit(portId);
752
753                 /* the NPE should immediatelyt release
754                  * the last Rx buffer and the last transmitted buffer
755                  * unless the last Tx frame was dropped (rx queue full)
756                  */
757                 if (status == IX_ETH_ACC_SUCCESS)
758                 {
759                     retryTimeout = 0;
760                     do
761                     {
762                         ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
763                     }
764                     while ((*rxState == REPLENISH)
765                            && (retryTimeout++ < IX_ETH_ACC_MAX_RETRY_TIMEOUT));
766                 }
767
768                 /* the NPE may have dropped the traffic because of Rx
769                  * queue being full. This code ensures that the last
770                  * Tx and Rx frames are both received.
771                  */
772             }
773             while ((status == IX_ETH_ACC_SUCCESS)
774                    && (retry++ < IX_ETH_ACC_MAX_RETRY)
775                    && ((*txState == TRANSMIT)
776                        || (*rxState == REPLENISH)
777                        || (ixEthAccPortDisableUserBufferCount[portId] != 0)));
778
779             /* Step 5 : check the final states : the NPE has
780              * no buffer left, nor in Tx , nor in Rx directions.
781              */
782             if ((*rxState == REPLENISH) || (*txState == TRANSMIT))
783             {
784                 status = IX_ETH_ACC_FAIL;
785             }
786         }
787
788         /* now all the buffers are drained, disable NPE loopback
789          * This is done regardless of the logic to drain the queues and
790          * the internal buffers held by the NPE.
791          */
792         if (ixEthAccNpeLoopbackDisablePriv(portId) != IX_ETH_ACC_SUCCESS)
793         {
794             status = IX_ETH_ACC_FAIL;
795         }
796     }
797
798     /* disable MAC Tx and Rx services */
799     ixEthAccMacState[portId].enabled = false;
800     ixEthAccMacStateUpdate(portId);
801
802     /* restore the Rx and TxDone callbacks (within a critical section) */
803     key = ixOsalIrqLock();
804
805     ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn            = ixEthAccPortDisableFn[portId];
806     ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag           = ixEthAccPortDisableCbTag[portId];
807     ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = ixEthAccPortDisableMultiBufferFn[portId];
808     ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = ixEthAccPortDisableMultiBufferCbTag[portId];
809     ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn  = ixEthAccPortDisableTxDoneFn[portId];
810     ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag           = ixEthAccPortDisableTxDoneCbTag[portId];
811
812     ixOsalIrqUnlock(key);
813
814     /* the MAC core rx/tx disable may left the MAC hardware in an
815      * unpredictable state. A hw reset is executed before resetting
816      * all the MAC parameters to a known value.
817      */
818     REG_WRITE(ixEthAccMacBase[portId],
819               IX_ETH_ACC_MAC_CORE_CNTRL,
820               IX_ETH_ACC_CORE_RESET);
821
822     ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY);
823
824     /* rewrite all parameters to their current value */
825     ixEthAccMacStateUpdate(portId);
826
827     REG_WRITE(ixEthAccMacBase[portId],
828               IX_ETH_ACC_MAC_INT_CLK_THRESH,
829               IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
830
831     REG_WRITE(ixEthAccMacBase[portId],
832               IX_ETH_ACC_MAC_CORE_CNTRL,
833               IX_ETH_ACC_CORE_MDC_EN);
834
835     return status;
836 }
837
838 IxEthAccStatus
839 ixEthAccPortEnabledQueryPriv(IxEthAccPortId portId, BOOL *enabled)
840 {
841     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
842
843     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
844     {
845         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable port.\n",(INT32)portId,0,0,0,0,0);
846
847         /* Since Eth NPE is not available, port must be disabled */
848         *enabled = false ;
849         return IX_ETH_ACC_SUCCESS ;
850     }
851
852     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
853     {
854         /* Since Eth NPE is not available, port must be disabled */
855         *enabled = false ;
856         return (IX_ETH_ACC_PORT_UNINITIALIZED);
857     }
858
859     *enabled = ixEthAccMacState[portId].enabled;
860
861     return IX_ETH_ACC_SUCCESS;
862 }
863
864 IxEthAccStatus
865 ixEthAccPortMacResetPriv(IxEthAccPortId portId)
866 {
867     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
868
869     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
870     {
871         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot reset Ethernet coprocessor.\n",(INT32)portId,0,0,0,0,0);
872         return IX_ETH_ACC_SUCCESS ;
873     }
874
875     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
876     {
877         return (IX_ETH_ACC_PORT_UNINITIALIZED);
878     }
879
880     REG_WRITE(ixEthAccMacBase[portId],
881               IX_ETH_ACC_MAC_CORE_CNTRL,
882               IX_ETH_ACC_CORE_RESET);
883
884     ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY);
885
886     /* rewrite all parameters to their current value */
887     ixEthAccMacStateUpdate(portId);
888
889     REG_WRITE(ixEthAccMacBase[portId],
890               IX_ETH_ACC_MAC_INT_CLK_THRESH,
891               IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
892
893     REG_WRITE(ixEthAccMacBase[portId],
894               IX_ETH_ACC_MAC_CORE_CNTRL,
895               IX_ETH_ACC_CORE_MDC_EN);
896
897     return IX_ETH_ACC_SUCCESS;
898 }
899
900 IxEthAccStatus
901 ixEthAccPortLoopbackEnable(IxEthAccPortId portId)
902 {
903     UINT32 regval;
904
905     /* Turn off promiscuous mode */
906     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
907
908     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
909     {
910         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable loopback.\n",(INT32)portId,0,0,0,0,0);
911         return IX_ETH_ACC_SUCCESS ;
912     }
913
914     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
915     {
916         return (IX_ETH_ACC_PORT_UNINITIALIZED);
917     }
918
919     /* read register */
920     REG_READ(ixEthAccMacBase[portId],
921              IX_ETH_ACC_MAC_RX_CNTRL1,
922              regval);
923
924     /* update register */
925     REG_WRITE(ixEthAccMacBase[portId],
926               IX_ETH_ACC_MAC_RX_CNTRL1,
927               regval | IX_ETH_ACC_RX_CNTRL1_LOOP_EN);
928
929     return IX_ETH_ACC_SUCCESS;
930 }
931
932 PRIVATE void
933 ixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId,
934                                     IxNpeMhMessage msg)
935 {
936     IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
937
938 #ifndef NDEBUG
939     /* Prudent to at least check the port is within range */
940     if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)
941     {
942         IX_ETH_ACC_FATAL_LOG("IXETHACC:ixEthAccPortDisableMessageCallback: Illegal port: %u\n",
943             (UINT32) portId, 0, 0, 0, 0, 0);
944
945         return;
946     }
947 #endif
948
949     /* unlock message reception mutex */
950     ixOsalMutexUnlock(&ixEthAccMacState[portId].npeLoopbackMessageLock);
951 }
952
953 IxEthAccStatus
954 ixEthAccNpeLoopbackEnablePriv(IxEthAccPortId portId)
955 {
956     IX_STATUS npeMhStatus;
957     IxNpeMhMessage message;
958     IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
959
960     /* Turn off promiscuous mode */
961     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
962
963     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
964     {
965         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable NPE loopback.\n",(INT32)portId,0,0,0,0,0);
966         return IX_ETH_ACC_SUCCESS ;
967     }
968
969     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
970     {
971         return (IX_ETH_ACC_PORT_UNINITIALIZED);
972     }
973
974     /* enable NPE loopback (lsb of the message contains the value 1) */
975     message.data[0] = (IX_ETHNPE_SETLOOPBACK_MODE << IX_ETH_ACC_MAC_MSGID_SHL)
976         | 0x01;
977     message.data[1] = 0;
978
979     npeMhStatus = ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
980                 message,
981                 IX_ETHNPE_SETLOOPBACK_MODE_ACK,
982                 ixEthAccNpeLoopbackMessageCallback,
983                 IX_NPEMH_SEND_RETRIES_DEFAULT);
984
985     if (npeMhStatus != IX_SUCCESS)
986     {
987         status = IX_ETH_ACC_FAIL;
988     }
989     else
990     {
991         /* wait for NPE loopbackEnable response */
992         if (ixOsalMutexLock(&ixEthAccMacState[portId]. npeLoopbackMessageLock,
993                             IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS)
994             != IX_SUCCESS)
995         {
996             status = IX_ETH_ACC_FAIL;
997         }
998     }
999
1000     return status;
1001 }
1002
1003 IxEthAccStatus
1004 ixEthAccPortTxEnablePriv(IxEthAccPortId portId)
1005 {
1006     UINT32 regval;
1007
1008     /* Turn off promiscuous mode */
1009     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1010
1011     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1012     {
1013         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable TX.\n",(INT32)portId,0,0,0,0,0);
1014         return IX_ETH_ACC_SUCCESS ;
1015     }
1016
1017     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1018     {
1019         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1020     }
1021
1022     /* read register */
1023     REG_READ(ixEthAccMacBase[portId],
1024              IX_ETH_ACC_MAC_TX_CNTRL1,
1025              regval);
1026
1027     /* update register */
1028     REG_WRITE(ixEthAccMacBase[portId],
1029               IX_ETH_ACC_MAC_TX_CNTRL1,
1030               regval | IX_ETH_ACC_TX_CNTRL1_TX_EN);
1031
1032     return IX_ETH_ACC_SUCCESS;
1033 }
1034
1035 IxEthAccStatus
1036 ixEthAccPortRxEnablePriv(IxEthAccPortId portId)
1037 {
1038     UINT32 regval;
1039
1040     /* Turn off promiscuous mode */
1041     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1042
1043     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1044     {
1045         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable RX.\n",(INT32)portId,0,0,0,0,0);
1046         return IX_ETH_ACC_SUCCESS ;
1047     }
1048
1049     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1050     {
1051         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1052     }
1053
1054     /* read register */
1055     REG_READ(ixEthAccMacBase[portId],
1056              IX_ETH_ACC_MAC_RX_CNTRL1,
1057              regval);
1058
1059     /* update register */
1060     REG_WRITE(ixEthAccMacBase[portId],
1061               IX_ETH_ACC_MAC_RX_CNTRL1,
1062               regval | IX_ETH_ACC_RX_CNTRL1_RX_EN);
1063
1064     return IX_ETH_ACC_SUCCESS;
1065 }
1066
1067 IxEthAccStatus
1068 ixEthAccPortLoopbackDisable(IxEthAccPortId portId)
1069 {
1070     UINT32 regval;
1071
1072     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1073
1074     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1075     {
1076         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable loopback.\n",(INT32)portId,0,0,0,0,0);
1077         return IX_ETH_ACC_SUCCESS ;
1078     }
1079
1080     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1081     {
1082         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1083     }
1084
1085     /*disable MAC loopabck */
1086     REG_READ(ixEthAccMacBase[portId],
1087              IX_ETH_ACC_MAC_RX_CNTRL1,
1088              regval);
1089
1090     REG_WRITE(ixEthAccMacBase[portId],
1091               IX_ETH_ACC_MAC_RX_CNTRL1,
1092               (regval & ~IX_ETH_ACC_RX_CNTRL1_LOOP_EN));
1093
1094     return IX_ETH_ACC_SUCCESS;
1095 }
1096
1097 IxEthAccStatus
1098 ixEthAccNpeLoopbackDisablePriv(IxEthAccPortId portId)
1099 {
1100     IX_STATUS npeMhStatus;
1101     IxNpeMhMessage message;
1102     IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
1103
1104     /* Turn off promiscuous mode */
1105     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1106
1107     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1108     {
1109         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable NPE loopback.\n",(INT32)portId,0,0,0,0,0);
1110         return IX_ETH_ACC_SUCCESS ;
1111     }
1112
1113     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1114     {
1115         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1116     }
1117
1118     /* disable NPE loopback (lsb of the message contains the value 0) */
1119     message.data[0] = (IX_ETHNPE_SETLOOPBACK_MODE << IX_ETH_ACC_MAC_MSGID_SHL);
1120     message.data[1] = 0;
1121
1122     npeMhStatus = ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
1123                 message,
1124                 IX_ETHNPE_SETLOOPBACK_MODE_ACK,
1125                 ixEthAccNpeLoopbackMessageCallback,
1126                 IX_NPEMH_SEND_RETRIES_DEFAULT);
1127
1128     if (npeMhStatus != IX_SUCCESS)
1129     {
1130         status = IX_ETH_ACC_FAIL;
1131     }
1132     else
1133     {
1134         /* wait for NPE loopbackEnable response */
1135         if (ixOsalMutexLock(&ixEthAccMacState[portId].npeLoopbackMessageLock,
1136                             IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS)
1137             != IX_SUCCESS)
1138         {
1139             status = IX_ETH_ACC_FAIL;
1140         }
1141     }
1142
1143     return status;
1144 }
1145
1146 IxEthAccStatus
1147 ixEthAccPortTxDisablePriv(IxEthAccPortId portId)
1148 {
1149     UINT32 regval;
1150
1151     /* Turn off promiscuous mode */
1152     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1153
1154     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1155     {
1156         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable TX.\n", (INT32)portId,0,0,0,0,0);
1157         return IX_ETH_ACC_SUCCESS ;
1158     }
1159
1160     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1161     {
1162         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1163     }
1164
1165     /* read register */
1166     REG_READ(ixEthAccMacBase[portId],
1167              IX_ETH_ACC_MAC_TX_CNTRL1,
1168              regval);
1169
1170     /* update register */
1171     REG_WRITE(ixEthAccMacBase[portId],
1172               IX_ETH_ACC_MAC_TX_CNTRL1,
1173               (regval & ~IX_ETH_ACC_TX_CNTRL1_TX_EN));
1174
1175     return IX_ETH_ACC_SUCCESS;
1176 }
1177
1178 IxEthAccStatus
1179 ixEthAccPortRxDisablePriv(IxEthAccPortId portId)
1180 {
1181     UINT32 regval;
1182
1183     /* Turn off promiscuous mode */
1184     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1185
1186     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1187     {
1188         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable RX.\n", (INT32)portId,0,0,0,0,0);
1189         return IX_ETH_ACC_SUCCESS ;
1190     }
1191
1192     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1193     {
1194         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1195     }
1196
1197     /* read register */
1198     REG_READ(ixEthAccMacBase[portId],
1199              IX_ETH_ACC_MAC_RX_CNTRL1,
1200              regval);
1201
1202     /* update register */
1203     REG_WRITE(ixEthAccMacBase[portId],
1204               IX_ETH_ACC_MAC_RX_CNTRL1,
1205               (regval & ~IX_ETH_ACC_RX_CNTRL1_RX_EN));
1206
1207     return IX_ETH_ACC_SUCCESS;
1208 }
1209
1210 IxEthAccStatus
1211 ixEthAccPortPromiscuousModeClearPriv(IxEthAccPortId portId)
1212 {
1213     UINT32 regval;
1214
1215     /* Turn off promiscuous mode */
1216     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1217
1218     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1219     {
1220         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot clear promiscuous mode.\n",(INT32)portId,0,0,0,0,0);
1221         return IX_ETH_ACC_SUCCESS ;
1222     }
1223
1224     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1225     {
1226         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1227     }
1228
1229     /*set bit 5 of Rx control 1 - enable address filtering*/
1230     REG_READ(ixEthAccMacBase[portId],
1231              IX_ETH_ACC_MAC_RX_CNTRL1,
1232              regval);
1233
1234     REG_WRITE(ixEthAccMacBase[portId],
1235               IX_ETH_ACC_MAC_RX_CNTRL1,
1236               regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN);
1237
1238     ixEthAccMacState[portId].promiscuous = false;
1239
1240     ixEthAccMulticastAddressSet(portId);
1241
1242     return IX_ETH_ACC_SUCCESS;
1243 }
1244
1245 IxEthAccStatus
1246 ixEthAccPortPromiscuousModeSetPriv(IxEthAccPortId portId)
1247 {
1248     UINT32 regval;
1249
1250     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1251
1252     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1253     {
1254         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot set promiscuous mode.\n",(INT32)portId,0,0,0,0,0);
1255         return IX_ETH_ACC_SUCCESS ;
1256     }
1257
1258     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1259     {
1260         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1261     }
1262
1263     /*
1264      * Set bit 5 of Rx control 1 - We enable address filtering even in
1265      * promiscuous mode because we want the MAC to set the appropriate
1266      * bits in m_flags which doesn't happen if we turn off filtering.
1267      */
1268     REG_READ(ixEthAccMacBase[portId],
1269              IX_ETH_ACC_MAC_RX_CNTRL1,
1270              regval);
1271
1272     REG_WRITE(ixEthAccMacBase[portId],
1273               IX_ETH_ACC_MAC_RX_CNTRL1,
1274               regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN);
1275
1276     ixEthAccMacState[portId].promiscuous = true;
1277
1278     ixEthAccMulticastAddressSet(portId);
1279
1280     return IX_ETH_ACC_SUCCESS;
1281 }
1282
1283 IxEthAccStatus
1284 ixEthAccPortUnicastMacAddressSetPriv (IxEthAccPortId portId,
1285                                   IxEthAccMacAddr *macAddr)
1286 {
1287     UINT32 i;
1288
1289     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1290
1291     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1292     {
1293         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot set Unicast Mac Address.\n",(INT32)portId,0,0,0,0,0);
1294         return IX_ETH_ACC_SUCCESS ;
1295     }
1296
1297     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1298     {
1299         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1300     }
1301
1302
1303     if (macAddr == NULL)
1304     {
1305         return IX_ETH_ACC_FAIL;
1306     }
1307
1308     if ( macAddr->macAddress[0] & IX_ETH_ACC_ETH_MAC_BCAST_MCAST_BIT )
1309     {
1310         /* This is a multicast/broadcast address cant set it ! */
1311         return IX_ETH_ACC_FAIL;
1312     }
1313
1314     if ( macAddr->macAddress[0] == 0 &&
1315          macAddr->macAddress[1] == 0 &&
1316          macAddr->macAddress[2] == 0 &&
1317          macAddr->macAddress[3] == 0 &&
1318          macAddr->macAddress[4] == 0 &&
1319          macAddr->macAddress[5] == 0  )
1320     {
1321         /* This is an invalid mac address cant set it ! */
1322         return IX_ETH_ACC_FAIL;
1323     }
1324
1325 #ifdef CONFIG_IXP425_COMPONENT_ETHDB
1326     /* update the MAC address in the ethernet database */
1327     if (ixEthDBPortAddressSet(portId, (IxEthDBMacAddr *) macAddr) != IX_ETH_DB_SUCCESS)
1328     {
1329         return IX_ETH_ACC_FAIL;
1330     }
1331 #endif
1332
1333     /*Set the Unicast MAC to the specified value*/
1334     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1335     {
1336         REG_WRITE(ixEthAccMacBase[portId],
1337                   IX_ETH_ACC_MAC_UNI_ADDR_1 + i*sizeof(UINT32),
1338                   macAddr->macAddress[i]);
1339     }
1340     ixEthAccMacState[portId].initDone = true;
1341
1342     return IX_ETH_ACC_SUCCESS;
1343 }
1344
1345 IxEthAccStatus
1346 ixEthAccPortUnicastMacAddressGetPriv (IxEthAccPortId portId,
1347                                   IxEthAccMacAddr *macAddr)
1348 {
1349     /*Return the current value of the Unicast MAC from h/w
1350       for the specified port*/
1351     UINT32 i;
1352
1353     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1354
1355     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1356     {
1357         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get Unicast Mac Address.\n",(INT32)portId,0,0,0,0,0);
1358         /* Since Eth Npe is unavailable, return invalid MAC Address = 00:00:00:00:00:00 */
1359         for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1360         {
1361             macAddr->macAddress[i] = 0;
1362         }
1363         return IX_ETH_ACC_SUCCESS ;
1364     }
1365
1366     if(!ixEthAccMacState[portId].initDone)
1367     {
1368         return (IX_ETH_ACC_MAC_UNINITIALIZED);
1369     }
1370
1371     if (macAddr == NULL)
1372     {
1373         return IX_ETH_ACC_FAIL;
1374     }
1375
1376
1377     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1378     {
1379         REG_READ(ixEthAccMacBase[portId],
1380                  IX_ETH_ACC_MAC_UNI_ADDR_1 + i*sizeof(UINT32),
1381                  macAddr->macAddress[i]);
1382     }
1383     return IX_ETH_ACC_SUCCESS;
1384 }
1385
1386 PRIVATE IxEthAccStatus
1387 ixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId,
1388                                     IxEthAccMacAddr *macAddr)
1389 {
1390     /*Return the current value of the Multicast MAC from h/w
1391       for the specified port*/
1392     UINT32 i;
1393
1394     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1395     {
1396
1397         REG_READ(ixEthAccMacBase[portId],
1398                  IX_ETH_ACC_MAC_ADDR_1 + i*sizeof(UINT32),
1399                  macAddr->macAddress[i]);
1400     }
1401
1402     return IX_ETH_ACC_SUCCESS;
1403 }
1404
1405 PRIVATE IxEthAccStatus
1406 ixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId,
1407                                    IxEthAccMacAddr *macAddr)
1408 {
1409     /*Return the current value of the Multicast MAC from h/w
1410       for the specified port*/
1411     UINT32 i;
1412
1413     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1414     {
1415
1416         REG_READ(ixEthAccMacBase[portId],
1417                  IX_ETH_ACC_MAC_ADDR_MASK_1 + i*sizeof(UINT32),
1418                  macAddr->macAddress[i]);
1419     }
1420     return IX_ETH_ACC_SUCCESS;
1421 }
1422
1423 IxEthAccStatus
1424 ixEthAccPortMulticastAddressJoinPriv (IxEthAccPortId portId,
1425                                   IxEthAccMacAddr *macAddr)
1426 {
1427     UINT32 i;
1428     IxEthAccMacAddr broadcastAddr = {{0xff,0xff,0xff,0xff,0xff,0xff}};
1429
1430     /*Check that the port parameter is valid*/
1431     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1432
1433     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1434     {
1435         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot join Multicast Mac Address.\n",(INT32)portId,0,0,0,0,0);
1436         return IX_ETH_ACC_SUCCESS ;
1437     }
1438
1439     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1440     {
1441         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1442     }
1443
1444     /*Check that the mac address is valid*/
1445     if(macAddr == NULL)
1446     {
1447         return IX_ETH_ACC_FAIL;
1448     }
1449
1450     /* Check that this is a multicast address */
1451     if (!(macAddr->macAddress[0] & IX_ETH_ACC_ETH_MAC_BCAST_MCAST_BIT))
1452     {
1453         return IX_ETH_ACC_FAIL;
1454     }
1455
1456     /* We don't add the Broadcast address */
1457     if(ixEthAccMacEqual(&broadcastAddr, macAddr))
1458     {
1459         return IX_ETH_ACC_FAIL;
1460     }
1461
1462     for (i = 0;
1463          i<ixEthAccMacState[portId].mcastAddrIndex;
1464          i++)
1465     {
1466         /*Check if the current entry already match an existing matches*/
1467         if(ixEthAccMacEqual(&ixEthAccMacState[portId].mcastAddrsTable[i], macAddr))
1468         {
1469             /* Address found in the list and already configured,
1470              * return a success status
1471              */
1472             return IX_ETH_ACC_SUCCESS;
1473         }
1474     }
1475
1476     /* check for availability at the end of the current table */
1477     if(ixEthAccMacState[portId].mcastAddrIndex >= IX_ETH_ACC_MAX_MULTICAST_ADDRESSES)
1478     {
1479         return IX_ETH_ACC_FAIL;
1480     }
1481
1482     /*First add the address to the multicast table for the
1483       specified port*/
1484     i=ixEthAccMacState[portId].mcastAddrIndex;
1485
1486     memcpy(&ixEthAccMacState[portId].mcastAddrsTable[i],
1487            &macAddr->macAddress,
1488            IX_IEEE803_MAC_ADDRESS_SIZE);
1489
1490     /*Increment the index into the table, this must be done here
1491      as MulticastAddressSet below needs to know about the latest
1492      entry.
1493     */
1494     ixEthAccMacState[portId].mcastAddrIndex++;
1495
1496     /*Then calculate the new value to be written to the address and
1497       address mask registers*/
1498     ixEthAccMulticastAddressSet(portId);
1499
1500     return IX_ETH_ACC_SUCCESS;
1501 }
1502
1503
1504 IxEthAccStatus
1505 ixEthAccPortMulticastAddressJoinAllPriv (IxEthAccPortId portId)
1506 {
1507     IxEthAccMacAddr mcastMacAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}};
1508
1509     /*Check that the port parameter is valid*/
1510     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1511
1512     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1513     {
1514         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot join all Multicast Address.\n",(INT32)portId,0,0,0,0,0);
1515         return IX_ETH_ACC_SUCCESS ;
1516     }
1517
1518     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1519     {
1520         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1521     }
1522
1523     /* remove all entries from the database and
1524     *  insert a multicast entry
1525     */
1526     memcpy(&ixEthAccMacState[portId].mcastAddrsTable[0],
1527            &mcastMacAddr.macAddress,
1528            IX_IEEE803_MAC_ADDRESS_SIZE);
1529
1530     ixEthAccMacState[portId].mcastAddrIndex = 1;
1531     ixEthAccMacState[portId].joinAll = true;
1532
1533     ixEthAccMulticastAddressSet(portId);
1534
1535     return IX_ETH_ACC_SUCCESS;
1536 }
1537
1538 IxEthAccStatus
1539 ixEthAccPortMulticastAddressLeavePriv (IxEthAccPortId portId,
1540                                    IxEthAccMacAddr *macAddr)
1541 {
1542     UINT32 i;
1543     IxEthAccMacAddr mcastMacAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}};
1544
1545     /*Check that the port parameter is valid*/
1546     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1547
1548     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1549     {
1550         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot leave Multicast Address.\n",(INT32)portId,0,0,0,0,0);
1551         return IX_ETH_ACC_SUCCESS ;
1552     }
1553
1554     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1555     {
1556         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1557     }
1558
1559     /*Check that the mac address is valid*/
1560     if(macAddr == NULL)
1561     {
1562         return IX_ETH_ACC_FAIL;
1563     }
1564     /* Remove this mac address from the mask for the specified port
1565      * we copy down all entries above the blanked entry, and
1566      * decrement the index
1567      */
1568     i=0;
1569
1570     while(i<ixEthAccMacState[portId].mcastAddrIndex)
1571     {
1572         /*Check if the current entry matches*/
1573         if(ixEthAccMacEqual(&ixEthAccMacState[portId].mcastAddrsTable[i],
1574                             macAddr))
1575         {
1576             if(ixEthAccMacEqual(macAddr, &mcastMacAddr))
1577             {
1578                 ixEthAccMacState[portId].joinAll = false;
1579             }
1580             /*Decrement the index into the multicast address table
1581               for the current port*/
1582             ixEthAccMacState[portId].mcastAddrIndex--;
1583
1584             /*Copy down all entries above the current entry*/
1585             while(i<ixEthAccMacState[portId].mcastAddrIndex)
1586             {
1587                 memcpy(&ixEthAccMacState[portId].mcastAddrsTable[i],
1588                        &ixEthAccMacState[portId].mcastAddrsTable[i+1],
1589                        IX_IEEE803_MAC_ADDRESS_SIZE);
1590                 i++;
1591             }
1592             /*recalculate the mask and write it to the MAC*/
1593             ixEthAccMulticastAddressSet(portId);
1594
1595             return IX_ETH_ACC_SUCCESS;
1596         }
1597         /* search the next entry */
1598         i++;
1599     }
1600     /* no matching entry found */
1601     return IX_ETH_ACC_NO_SUCH_ADDR;
1602 }
1603
1604 IxEthAccStatus
1605 ixEthAccPortMulticastAddressLeaveAllPriv (IxEthAccPortId portId)
1606 {
1607     /*Check that the port parameter is valid*/
1608     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1609
1610     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1611     {
1612         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot leave all Multicast Address.\n",(INT32)portId,0,0,0,0,0);
1613         return IX_ETH_ACC_SUCCESS ;
1614     }
1615
1616     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1617     {
1618         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1619     }
1620
1621     ixEthAccMacState[portId].mcastAddrIndex = 0;
1622     ixEthAccMacState[portId].joinAll = false;
1623
1624     ixEthAccMulticastAddressSet(portId);
1625
1626     return IX_ETH_ACC_SUCCESS;
1627 }
1628
1629
1630 IxEthAccStatus
1631 ixEthAccPortUnicastAddressShowPriv (IxEthAccPortId portId)
1632 {
1633     IxEthAccMacAddr macAddr;
1634
1635     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1636
1637     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1638     {
1639         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot show Unicast Address.\n",(INT32)portId,0,0,0,0,0);
1640         return IX_ETH_ACC_SUCCESS ;
1641     }
1642
1643     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1644     {
1645         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1646     }
1647
1648     /*Get the MAC (UINICAST) address from hardware*/
1649     if(ixEthAccPortUnicastMacAddressGetPriv(portId, &macAddr) != IX_ETH_ACC_SUCCESS)
1650     {
1651         IX_ETH_ACC_WARNING_LOG("EthAcc: MAC address uninitialised port %u\n",
1652                                (INT32)portId,0,0,0,0,0);
1653         return IX_ETH_ACC_MAC_UNINITIALIZED;
1654     }
1655
1656     /*print it out*/
1657     ixEthAccMacPrint(&macAddr);
1658     printf("\n");
1659     return IX_ETH_ACC_SUCCESS;
1660 }
1661
1662
1663
1664 void
1665 ixEthAccPortMulticastAddressShowPriv(IxEthAccPortId portId)
1666 {
1667     IxEthAccMacAddr macAddr;
1668     UINT32 i;
1669
1670     if(!IX_ETH_ACC_IS_PORT_VALID(portId))
1671     {
1672         return;
1673     }
1674
1675     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1676     {
1677         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot show Multicast Address.\n",(INT32)portId,0,0,0,0,0);
1678         return ;
1679     }
1680
1681     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1682     {
1683         return;
1684     }
1685
1686     printf("Multicast MAC: ");
1687     /*Get the MAC (MULTICAST) address from hardware*/
1688     ixEthAccPortMulticastMacAddressGet(portId, &macAddr);
1689     /*print it out*/
1690     ixEthAccMacPrint(&macAddr);
1691     /*Get the MAC (MULTICAST) filter from hardware*/
1692     ixEthAccPortMulticastMacFilterGet(portId, &macAddr);
1693     /*print it out*/
1694     printf(" ( ");
1695     ixEthAccMacPrint(&macAddr);
1696     printf(" )\n");
1697     printf("Constituent Addresses:\n");
1698     for(i=0;i<ixEthAccMacState[portId].mcastAddrIndex;i++)
1699     {
1700         ixEthAccMacPrint(&ixEthAccMacState[portId].mcastAddrsTable[i]);
1701         printf("\n");
1702     }
1703     return;
1704 }
1705
1706 /*Set the duplex mode*/
1707 IxEthAccStatus
1708 ixEthAccPortDuplexModeSetPriv (IxEthAccPortId portId,
1709                            IxEthAccDuplexMode mode)
1710 {
1711     UINT32 txregval;
1712     UINT32 rxregval;
1713
1714     /*This is bit 1 of the transmit control reg, set to 1 for half
1715       duplex, 0 for full duplex*/
1716     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1717
1718     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1719     {
1720         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot set Duplex Mode.\n",(INT32)portId,0,0,0,0,0);
1721         return IX_ETH_ACC_SUCCESS ;
1722     }
1723
1724     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1725     {
1726         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1727     }
1728
1729     REG_READ(ixEthAccMacBase[portId],
1730              IX_ETH_ACC_MAC_TX_CNTRL1,
1731              txregval);
1732
1733     REG_READ(ixEthAccMacBase[portId],
1734              IX_ETH_ACC_MAC_RX_CNTRL1,
1735              rxregval);
1736
1737     if (mode ==  IX_ETH_ACC_FULL_DUPLEX)
1738     {
1739         /*Clear half duplex bit in TX*/
1740         REG_WRITE(ixEthAccMacBase[portId],
1741                   IX_ETH_ACC_MAC_TX_CNTRL1,
1742                   txregval & ~IX_ETH_ACC_TX_CNTRL1_DUPLEX);
1743
1744         /*We must set the pause enable in the receive logic when in
1745           full duplex mode*/
1746         REG_WRITE(ixEthAccMacBase[portId],
1747                   IX_ETH_ACC_MAC_RX_CNTRL1,
1748                   rxregval | IX_ETH_ACC_RX_CNTRL1_PAUSE_EN);
1749         ixEthAccMacState[portId].fullDuplex = true;
1750
1751     }
1752     else if (mode ==  IX_ETH_ACC_HALF_DUPLEX)
1753     {
1754         /*Set half duplex bit in TX*/
1755         REG_WRITE(ixEthAccMacBase[portId],
1756                   IX_ETH_ACC_MAC_TX_CNTRL1,
1757                   txregval | IX_ETH_ACC_TX_CNTRL1_DUPLEX);
1758
1759         /*We must clear pause enable in the receive logic when in
1760           half duplex mode*/
1761         REG_WRITE(ixEthAccMacBase[portId],
1762                   IX_ETH_ACC_MAC_RX_CNTRL1,
1763                   rxregval & ~IX_ETH_ACC_RX_CNTRL1_PAUSE_EN);
1764
1765         ixEthAccMacState[portId].fullDuplex = false;
1766     }
1767     else
1768     {
1769         return IX_ETH_ACC_FAIL;
1770     }
1771
1772
1773     return IX_ETH_ACC_SUCCESS;
1774
1775 }
1776
1777
1778
1779 IxEthAccStatus
1780 ixEthAccPortDuplexModeGetPriv (IxEthAccPortId portId,
1781                            IxEthAccDuplexMode *mode)
1782 {
1783     /*Return the duplex mode for the specified port*/
1784     UINT32 regval;
1785
1786     /*This is bit 1 of the transmit control reg, set to 1 for half
1787       duplex, 0 for full duplex*/
1788     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1789
1790     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1791     {
1792         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get Duplex Mode.\n",(INT32)portId,0,0,0,0,0);
1793         /* return hald duplex */
1794         *mode = IX_ETH_ACC_HALF_DUPLEX ;
1795         return IX_ETH_ACC_SUCCESS ;
1796     }
1797
1798     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1799     {
1800         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1801     }
1802
1803     if (mode == NULL)
1804     {
1805         return (IX_ETH_ACC_FAIL);
1806     }
1807
1808     REG_READ(ixEthAccMacBase[portId],
1809              IX_ETH_ACC_MAC_TX_CNTRL1,
1810              regval);
1811
1812     if( regval & IX_ETH_ACC_TX_CNTRL1_DUPLEX)
1813     {
1814         *mode = IX_ETH_ACC_HALF_DUPLEX;
1815     }
1816     else
1817     {
1818         *mode = IX_ETH_ACC_FULL_DUPLEX;
1819     }
1820
1821     return IX_ETH_ACC_SUCCESS;
1822 }
1823
1824
1825
1826 IxEthAccStatus
1827 ixEthAccPortTxFrameAppendPaddingEnablePriv (IxEthAccPortId portId)
1828 {
1829     UINT32 regval;
1830     /*Enable FCS computation by the MAC and appending to the
1831       frame*/
1832
1833     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1834
1835     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1836     {
1837         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable Tx Frame Append Padding.\n",(INT32)portId,0,0,0,0,0);
1838         return IX_ETH_ACC_SUCCESS ;
1839     }
1840
1841     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1842     {
1843         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1844     }
1845
1846     REG_READ(ixEthAccMacBase[portId],
1847              IX_ETH_ACC_MAC_TX_CNTRL1,
1848              regval);
1849
1850     REG_WRITE(ixEthAccMacBase[portId],
1851               IX_ETH_ACC_MAC_TX_CNTRL1,
1852               regval |
1853               IX_ETH_ACC_TX_CNTRL1_PAD_EN);
1854
1855     ixEthAccMacState[portId].txPADAppend = true;
1856     return IX_ETH_ACC_SUCCESS;
1857 }
1858
1859 IxEthAccStatus
1860 ixEthAccPortTxFrameAppendPaddingDisablePriv (IxEthAccPortId portId)
1861 {
1862     UINT32 regval;
1863
1864     /*disable FCS computation and appending*/
1865     /*Set bit 4 of Tx control register one to zero*/
1866     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1867
1868     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1869     {
1870         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disble Tx Frame Append Padding.\n",(INT32)portId,0,0,0,0,0);
1871         return IX_ETH_ACC_SUCCESS ;
1872     }
1873
1874     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1875     {
1876         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1877     }
1878
1879     REG_READ(ixEthAccMacBase[portId],
1880              IX_ETH_ACC_MAC_TX_CNTRL1,
1881              regval);
1882
1883     REG_WRITE(ixEthAccMacBase[portId],
1884               IX_ETH_ACC_MAC_TX_CNTRL1,
1885               regval & ~IX_ETH_ACC_TX_CNTRL1_PAD_EN);
1886
1887     ixEthAccMacState[portId].txPADAppend = false;
1888     return IX_ETH_ACC_SUCCESS;
1889 }
1890
1891 IxEthAccStatus
1892 ixEthAccPortTxFrameAppendFCSEnablePriv (IxEthAccPortId portId)
1893 {
1894     UINT32 regval;
1895
1896     /*Enable FCS computation by the MAC and appending to the
1897       frame*/
1898
1899     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1900
1901     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1902     {
1903         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable Tx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0);
1904         return IX_ETH_ACC_SUCCESS ;
1905     }
1906
1907     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1908     {
1909         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1910     }
1911
1912     REG_READ(ixEthAccMacBase[portId],
1913              IX_ETH_ACC_MAC_TX_CNTRL1,
1914              regval);
1915
1916     REG_WRITE(ixEthAccMacBase[portId],
1917               IX_ETH_ACC_MAC_TX_CNTRL1,
1918               regval | IX_ETH_ACC_TX_CNTRL1_FCS_EN);
1919
1920     ixEthAccMacState[portId].txFCSAppend = true;
1921     return IX_ETH_ACC_SUCCESS;
1922 }
1923
1924 IxEthAccStatus
1925 ixEthAccPortTxFrameAppendFCSDisablePriv (IxEthAccPortId portId)
1926 {
1927     UINT32 regval;
1928
1929     /*disable FCS computation and appending*/
1930     /*Set bit 4 of Tx control register one to zero*/
1931     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1932
1933     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1934     {
1935         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disable Tx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0);
1936         return IX_ETH_ACC_SUCCESS ;
1937     }
1938
1939     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1940     {
1941         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1942     }
1943
1944     REG_READ(ixEthAccMacBase[portId],
1945              IX_ETH_ACC_MAC_TX_CNTRL1,
1946              regval);
1947
1948     REG_WRITE(ixEthAccMacBase[portId],
1949               IX_ETH_ACC_MAC_TX_CNTRL1,
1950               regval & ~IX_ETH_ACC_TX_CNTRL1_FCS_EN);
1951
1952     ixEthAccMacState[portId].txFCSAppend = false;
1953     return IX_ETH_ACC_SUCCESS;
1954 }
1955
1956 IxEthAccStatus
1957 ixEthAccPortRxFrameAppendFCSEnablePriv (IxEthAccPortId portId)
1958 {
1959     /*Set bit 2 of Rx control 1*/
1960     UINT32 regval;
1961
1962     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1963
1964     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1965     {
1966         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable Rx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0);
1967         return IX_ETH_ACC_SUCCESS ;
1968     }
1969
1970     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1971     {
1972         return (IX_ETH_ACC_PORT_UNINITIALIZED);
1973     }
1974
1975     REG_READ(ixEthAccMacBase[portId],
1976              IX_ETH_ACC_MAC_RX_CNTRL1,
1977              regval);
1978
1979     REG_WRITE(ixEthAccMacBase[portId],
1980               IX_ETH_ACC_MAC_RX_CNTRL1,
1981               regval | IX_ETH_ACC_RX_CNTRL1_CRC_EN);
1982
1983     ixEthAccMacState[portId].rxFCSAppend = true;
1984     return IX_ETH_ACC_SUCCESS;
1985 }
1986
1987 IxEthAccStatus
1988 ixEthAccPortRxFrameAppendFCSDisablePriv (IxEthAccPortId portId)
1989 {
1990     UINT32 regval;
1991
1992     /*Clear bit 2 of Rx control 1*/
1993     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1994
1995     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1996     {
1997         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disable Rx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0);
1998         return IX_ETH_ACC_SUCCESS ;
1999     }
2000
2001     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
2002     {
2003         return (IX_ETH_ACC_PORT_UNINITIALIZED);
2004     }
2005
2006     REG_READ(ixEthAccMacBase[portId],
2007              IX_ETH_ACC_MAC_RX_CNTRL1,
2008              regval);
2009
2010     REG_WRITE(ixEthAccMacBase[portId],
2011               IX_ETH_ACC_MAC_RX_CNTRL1,
2012               regval & ~IX_ETH_ACC_RX_CNTRL1_CRC_EN);
2013
2014     ixEthAccMacState[portId].rxFCSAppend = false;
2015     return IX_ETH_ACC_SUCCESS;
2016 }
2017
2018
2019
2020 PRIVATE void
2021 ixEthAccMacNpeStatsMessageCallback (IxNpeMhNpeId npeId,
2022                                     IxNpeMhMessage msg)
2023 {
2024     IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
2025
2026 #ifndef NDEBUG
2027     /* Prudent to at least check the port is within range */
2028     if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)
2029     {
2030         IX_ETH_ACC_FATAL_LOG(
2031      "IXETHACC:ixEthAccMacNpeStatsMessageCallback: Illegal port: %u\n",
2032      (UINT32)portId, 0, 0, 0, 0, 0);
2033         return;
2034     }
2035 #endif
2036
2037     /*Unblock Stats Get call*/
2038     ixOsalMutexUnlock(&ixEthAccMacState[portId].ackMIBStatsLock);
2039
2040 }
2041
2042 PRIVATE void
2043 ixEthAccMibIIStatsEndianConvert (IxEthEthObjStats *retStats)
2044 {
2045     /* endianness conversion */
2046
2047     /* Rx stats */
2048     retStats->dot3StatsAlignmentErrors =
2049         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsAlignmentErrors);
2050     retStats->dot3StatsFCSErrors =
2051         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsFCSErrors);
2052     retStats->dot3StatsInternalMacReceiveErrors =
2053         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsInternalMacReceiveErrors);
2054     retStats->RxOverrunDiscards =
2055         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxOverrunDiscards);
2056     retStats->RxLearnedEntryDiscards =
2057         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxLearnedEntryDiscards);
2058     retStats->RxLargeFramesDiscards =
2059         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxLargeFramesDiscards);
2060     retStats->RxSTPBlockedDiscards =
2061         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxSTPBlockedDiscards);
2062     retStats->RxVLANTypeFilterDiscards =
2063         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxVLANTypeFilterDiscards);
2064     retStats->RxVLANIdFilterDiscards =
2065         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxVLANIdFilterDiscards);
2066     retStats->RxInvalidSourceDiscards =
2067         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxInvalidSourceDiscards);
2068     retStats->RxBlackListDiscards =
2069         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxBlackListDiscards);
2070     retStats->RxWhiteListDiscards =
2071         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxWhiteListDiscards);
2072     retStats->RxUnderflowEntryDiscards =
2073         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxUnderflowEntryDiscards);
2074
2075     /* Tx stats */
2076     retStats->dot3StatsSingleCollisionFrames =
2077         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsSingleCollisionFrames);
2078     retStats->dot3StatsMultipleCollisionFrames =
2079         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsMultipleCollisionFrames);
2080     retStats->dot3StatsDeferredTransmissions =
2081         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsDeferredTransmissions);
2082     retStats->dot3StatsLateCollisions =
2083         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsLateCollisions);
2084     retStats->dot3StatsExcessiveCollsions =
2085         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsExcessiveCollsions);
2086     retStats->dot3StatsInternalMacTransmitErrors =
2087         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsInternalMacTransmitErrors);
2088     retStats->dot3StatsCarrierSenseErrors =
2089         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsCarrierSenseErrors);
2090     retStats->TxLargeFrameDiscards =
2091         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->TxLargeFrameDiscards);
2092     retStats->TxVLANIdFilterDiscards =
2093         IX_OSAL_SWAP_BE_SHARED_LONG(retStats->TxVLANIdFilterDiscards);
2094 }
2095
2096 IxEthAccStatus
2097 ixEthAccMibIIStatsGet (IxEthAccPortId portId,
2098                        IxEthEthObjStats *retStats )
2099 {
2100     IxNpeMhMessage message;
2101
2102     if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
2103     {
2104         printf("EthAcc: ixEthAccMibIIStatsGet (Mac) EthAcc service is not initialized\n");
2105         return (IX_ETH_ACC_FAIL);
2106     }
2107
2108     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2109
2110     if (retStats == NULL)
2111     {
2112         printf("EthAcc: ixEthAccMibIIStatsGet (Mac) NULL argument\n");
2113         return (IX_ETH_ACC_FAIL);
2114     }
2115
2116     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2117     {
2118         printf("EthAcc: ixEthAccMibIIStatsGet (Mac) NPE for port %d is not available\n", portId);
2119
2120         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get MIB II Stats.\n",(INT32)portId,0,0,0,0,0);
2121
2122         /* Return all zero stats */
2123         IX_ETH_ACC_MEMSET(retStats, 0, sizeof(IxEthEthObjStats));
2124
2125         return IX_ETH_ACC_SUCCESS ;
2126     }
2127
2128     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
2129     {
2130         printf("EthAcc: ixEthAccMibIIStatsGet (Mac) port %d is not initialized\n", portId);
2131         return (IX_ETH_ACC_PORT_UNINITIALIZED);
2132     }
2133
2134     IX_OSAL_CACHE_INVALIDATE(retStats, sizeof(IxEthEthObjStats));
2135
2136     message.data[0] = IX_ETHNPE_GETSTATS << IX_ETH_ACC_MAC_MSGID_SHL;
2137     message.data[1] = (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS(retStats);
2138
2139     /* Permit only one task to request MIB statistics Get operation
2140        at a time */
2141     ixOsalMutexLock(&ixEthAccMacState[portId].MIBStatsGetAccessLock, IX_OSAL_WAIT_FOREVER);
2142
2143     if(ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
2144                                       message,
2145                                       IX_ETHNPE_GETSTATS,
2146                                       ixEthAccMacNpeStatsMessageCallback,
2147                                       IX_NPEMH_SEND_RETRIES_DEFAULT)
2148        != IX_SUCCESS)
2149     {
2150         ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetAccessLock);
2151
2152         printf("EthAcc: (Mac) StatsGet failed to send NPE message\n");
2153
2154         return IX_ETH_ACC_FAIL;
2155     }
2156
2157     /* Wait for callback invocation indicating response to
2158        this request - we need this mutex in order to ensure
2159        that the return from this function is synchronous */
2160     ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsLock, IX_ETH_ACC_MIB_STATS_DELAY_MSECS);
2161
2162     /* Permit other tasks to perform MIB statistics Get operation */
2163     ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetAccessLock);
2164
2165     ixEthAccMibIIStatsEndianConvert (retStats);
2166
2167     return IX_ETH_ACC_SUCCESS;
2168 }
2169
2170
2171 PRIVATE void
2172 ixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId,
2173                                          IxNpeMhMessage msg)
2174 {
2175     IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
2176
2177 #ifndef NDEBUG
2178     /* Prudent to at least check the port is within range */
2179     if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)
2180     {
2181         IX_ETH_ACC_FATAL_LOG(
2182      "IXETHACC:ixEthAccMacNpeStatsResetMessageCallback: Illegal port: %u\n",
2183      (UINT32)portId, 0, 0, 0, 0, 0);
2184         return;
2185     }
2186 #endif
2187
2188     /*Unblock Stats Get & reset call*/
2189     ixOsalMutexUnlock(&ixEthAccMacState[portId].ackMIBStatsResetLock);
2190
2191 }
2192
2193
2194
2195 IxEthAccStatus
2196 ixEthAccMibIIStatsGetClear (IxEthAccPortId portId,
2197                             IxEthEthObjStats *retStats)
2198 {
2199     IxNpeMhMessage message;
2200
2201     if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
2202     {
2203         printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) EthAcc service is not initialized\n");
2204         return (IX_ETH_ACC_FAIL);
2205     }
2206
2207     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2208
2209     if (retStats == NULL)
2210     {
2211         printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) NULL argument\n");
2212         return (IX_ETH_ACC_FAIL);
2213     }
2214
2215     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2216     {
2217         printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) NPE for port %d is not available\n", portId);
2218
2219         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get and clear MIB II Stats.\n", (INT32)portId, 0, 0, 0, 0, 0);
2220
2221         /* Return all zero stats */
2222         IX_ETH_ACC_MEMSET(retStats, 0, sizeof(IxEthEthObjStats));
2223
2224         return IX_ETH_ACC_SUCCESS ;
2225     }
2226
2227     if (!IX_ETH_IS_PORT_INITIALIZED(portId))
2228     {
2229         printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) port %d is not initialized\n", portId);
2230         return (IX_ETH_ACC_PORT_UNINITIALIZED);
2231     }
2232
2233     IX_OSAL_CACHE_INVALIDATE(retStats, sizeof(IxEthEthObjStats));
2234
2235     message.data[0] = IX_ETHNPE_RESETSTATS << IX_ETH_ACC_MAC_MSGID_SHL;
2236     message.data[1] = (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS(retStats);
2237
2238     /* Permit only one task to request MIB statistics Get-Reset operation at a time */
2239     ixOsalMutexLock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock, IX_OSAL_WAIT_FOREVER);
2240
2241     if(ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
2242                                       message,
2243                                       IX_ETHNPE_RESETSTATS,
2244                                       ixEthAccMacNpeStatsResetMessageCallback,
2245                                       IX_NPEMH_SEND_RETRIES_DEFAULT)
2246        != IX_SUCCESS)
2247     {
2248         ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock);
2249
2250         printf("EthAcc: (Mac) ixEthAccMibIIStatsGetClear failed to send NPE message\n");
2251
2252         return IX_ETH_ACC_FAIL;
2253     }
2254
2255     /* Wait for callback invocation indicating response to this request */
2256     ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsResetLock, IX_ETH_ACC_MIB_STATS_DELAY_MSECS);
2257
2258     /* permit other tasks to get and reset MIB stats*/
2259     ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock);
2260
2261     ixEthAccMibIIStatsEndianConvert(retStats);
2262
2263     return IX_ETH_ACC_SUCCESS;
2264 }
2265
2266 IxEthAccStatus
2267 ixEthAccMibIIStatsClear (IxEthAccPortId portId)
2268 {
2269     static IxEthEthObjStats retStats;
2270     IxEthAccStatus status;
2271
2272     if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
2273     {
2274         return (IX_ETH_ACC_FAIL);
2275     }
2276
2277     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2278
2279     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2280     {
2281         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot clear MIB II Stats.\n",(INT32)portId,0,0,0,0,0);
2282         return IX_ETH_ACC_SUCCESS ;
2283     }
2284
2285     /* there is no reset operation without a corresponding Get */
2286     status = ixEthAccMibIIStatsGetClear(portId, &retStats);
2287
2288     return status;
2289 }
2290
2291 /* Initialize the ethernet MAC settings */
2292 IxEthAccStatus
2293 ixEthAccMacInit(IxEthAccPortId portId)
2294 {
2295     IX_OSAL_MBUF_POOL* portDisablePool;
2296     UINT8 *data;
2297
2298     IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2299
2300     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2301     {
2302         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot initialize Mac.\n",(INT32)portId,0,0,0,0,0);
2303         return IX_ETH_ACC_SUCCESS ;
2304     }
2305
2306     if(ixEthAccMacState[portId].macInitialised == false)
2307     {
2308         ixEthAccMacState[portId].fullDuplex  = true;
2309         ixEthAccMacState[portId].rxFCSAppend = true;
2310         ixEthAccMacState[portId].txFCSAppend = true;
2311         ixEthAccMacState[portId].txPADAppend = true;
2312         ixEthAccMacState[portId].enabled     = false;
2313         ixEthAccMacState[portId].promiscuous = true;
2314         ixEthAccMacState[portId].joinAll     = false;
2315         ixEthAccMacState[portId].initDone    = false;
2316         ixEthAccMacState[portId].macInitialised = true;
2317
2318         /* initialize MIB stats mutexes */
2319         ixOsalMutexInit(&ixEthAccMacState[portId].ackMIBStatsLock);
2320         ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsLock, IX_OSAL_WAIT_FOREVER);
2321
2322         ixOsalMutexInit(&ixEthAccMacState[portId].ackMIBStatsResetLock);
2323         ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsResetLock, IX_OSAL_WAIT_FOREVER);
2324
2325         ixOsalMutexInit(&ixEthAccMacState[portId].MIBStatsGetAccessLock);
2326
2327         ixOsalMutexInit(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock);
2328
2329         ixOsalMutexInit(&ixEthAccMacState[portId].npeLoopbackMessageLock);
2330
2331         ixEthAccMacState[portId].portDisableRxMbufPtr = NULL;
2332         ixEthAccMacState[portId].portDisableTxMbufPtr = NULL;
2333
2334         portDisablePool = IX_OSAL_MBUF_POOL_INIT(2,
2335                           IX_ETHACC_RX_MBUF_MIN_SIZE,
2336                           "portDisable Pool");
2337
2338         IX_OSAL_ENSURE(portDisablePool != NULL, "Failed to initialize PortDisable pool");
2339
2340         ixEthAccMacState[portId].portDisableRxMbufPtr = IX_OSAL_MBUF_POOL_GET(portDisablePool);
2341         ixEthAccMacState[portId].portDisableTxMbufPtr = IX_OSAL_MBUF_POOL_GET(portDisablePool);
2342
2343         IX_OSAL_ENSURE(ixEthAccMacState[portId].portDisableRxMbufPtr != NULL,
2344                   "Pool allocation failed");
2345         IX_OSAL_ENSURE(ixEthAccMacState[portId].portDisableTxMbufPtr != NULL,
2346                   "Pool allocation failed");
2347         /* fill the payload of the Rx mbuf used in portDisable */
2348         IX_OSAL_MBUF_MLEN(ixEthAccMacState[portId].portDisableRxMbufPtr) = IX_ETHACC_RX_MBUF_MIN_SIZE;
2349
2350         memset(IX_OSAL_MBUF_MDATA(ixEthAccMacState[portId].portDisableRxMbufPtr),
2351                0xAA,
2352                IX_ETHACC_RX_MBUF_MIN_SIZE);
2353
2354         /* fill the payload of the Tx mbuf used in portDisable (64 bytes) */
2355         IX_OSAL_MBUF_MLEN(ixEthAccMacState[portId].portDisableTxMbufPtr) = 64;
2356         IX_OSAL_MBUF_PKT_LEN(ixEthAccMacState[portId].portDisableTxMbufPtr) = 64;
2357
2358         data = (UINT8 *) IX_OSAL_MBUF_MDATA(ixEthAccMacState[portId].portDisableTxMbufPtr);
2359         memset(data, 0xBB, 64);
2360         data[0] = 0x00; /* unicast destination MAC address */
2361         data[6] = 0x00; /* unicast source MAC address */
2362         data[12] = 0x08; /* typelength : IP frame */
2363         data[13] = 0x00; /* typelength : IP frame */
2364
2365         IX_OSAL_CACHE_FLUSH(data, 64);
2366     }
2367
2368     IX_OSAL_ASSERT (ixEthAccMacBase[portId] != 0);
2369
2370     REG_WRITE(ixEthAccMacBase[portId],
2371               IX_ETH_ACC_MAC_CORE_CNTRL,
2372               IX_ETH_ACC_CORE_RESET);
2373
2374     ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY);
2375
2376     REG_WRITE(ixEthAccMacBase[portId],
2377               IX_ETH_ACC_MAC_CORE_CNTRL,
2378               IX_ETH_ACC_CORE_MDC_EN);
2379
2380     REG_WRITE(ixEthAccMacBase[portId],
2381               IX_ETH_ACC_MAC_INT_CLK_THRESH,
2382               IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
2383
2384     ixEthAccMacStateUpdate(portId);
2385
2386     return IX_ETH_ACC_SUCCESS;
2387 }
2388
2389 /* PRIVATE Functions*/
2390
2391 PRIVATE void
2392 ixEthAccMacStateUpdate(IxEthAccPortId portId)
2393 {
2394     UINT32 regval;
2395
2396     if ( ixEthAccMacState[portId].enabled == false )
2397     {
2398         /*  Just disable both the transmitter and reciver in the MAC.  */
2399         REG_READ(ixEthAccMacBase[portId],
2400                  IX_ETH_ACC_MAC_RX_CNTRL1,
2401                  regval);
2402         REG_WRITE(ixEthAccMacBase[portId],
2403                   IX_ETH_ACC_MAC_RX_CNTRL1,
2404                   regval & ~IX_ETH_ACC_RX_CNTRL1_RX_EN);
2405
2406         REG_READ(ixEthAccMacBase[portId],
2407                  IX_ETH_ACC_MAC_TX_CNTRL1,
2408                  regval);
2409         REG_WRITE(ixEthAccMacBase[portId],
2410                   IX_ETH_ACC_MAC_TX_CNTRL1,
2411                   regval & ~IX_ETH_ACC_TX_CNTRL1_TX_EN);
2412     }
2413
2414     if(ixEthAccMacState[portId].fullDuplex)
2415     {
2416         ixEthAccPortDuplexModeSetPriv (portId, IX_ETH_ACC_FULL_DUPLEX);
2417     }
2418     else
2419     {
2420         ixEthAccPortDuplexModeSetPriv (portId, IX_ETH_ACC_HALF_DUPLEX);
2421     }
2422
2423     if(ixEthAccMacState[portId].rxFCSAppend)
2424     {
2425         ixEthAccPortRxFrameAppendFCSEnablePriv (portId);
2426     }
2427     else
2428     {
2429         ixEthAccPortRxFrameAppendFCSDisablePriv (portId);
2430     }
2431
2432     if(ixEthAccMacState[portId].txFCSAppend)
2433     {
2434         ixEthAccPortTxFrameAppendFCSEnablePriv (portId);
2435     }
2436     else
2437     {
2438         ixEthAccPortTxFrameAppendFCSDisablePriv (portId);
2439     }
2440
2441     if(ixEthAccMacState[portId].txPADAppend)
2442     {
2443         ixEthAccPortTxFrameAppendPaddingEnablePriv (portId);
2444     }
2445     else
2446     {
2447         ixEthAccPortTxFrameAppendPaddingDisablePriv (portId);
2448     }
2449
2450     if(ixEthAccMacState[portId].promiscuous)
2451     {
2452         ixEthAccPortPromiscuousModeSetPriv(portId);
2453     }
2454     else
2455     {
2456         ixEthAccPortPromiscuousModeClearPriv(portId);
2457     }
2458
2459     if ( ixEthAccMacState[portId].enabled == true )
2460     {
2461         /*   Enable both the transmitter and reciver in the MAC.  */
2462         REG_READ(ixEthAccMacBase[portId],
2463                  IX_ETH_ACC_MAC_RX_CNTRL1,
2464                  regval);
2465         REG_WRITE(ixEthAccMacBase[portId],
2466                   IX_ETH_ACC_MAC_RX_CNTRL1,
2467                   regval | IX_ETH_ACC_RX_CNTRL1_RX_EN);
2468
2469         REG_READ(ixEthAccMacBase[portId],
2470                  IX_ETH_ACC_MAC_TX_CNTRL1,
2471                  regval);
2472         REG_WRITE(ixEthAccMacBase[portId],
2473                   IX_ETH_ACC_MAC_TX_CNTRL1,
2474                   regval | IX_ETH_ACC_TX_CNTRL1_TX_EN);
2475     }
2476 }
2477
2478
2479 PRIVATE BOOL
2480 ixEthAccMacEqual(IxEthAccMacAddr *macAddr1,
2481                  IxEthAccMacAddr *macAddr2)
2482 {
2483     UINT32 i;
2484     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE; i++)
2485     {
2486         if(macAddr1->macAddress[i] != macAddr2->macAddress[i])
2487         {
2488             return false;
2489         }
2490     }
2491     return true;
2492 }
2493
2494 PRIVATE void
2495 ixEthAccMacPrint(IxEthAccMacAddr *m)
2496 {
2497     printf("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
2498            m->macAddress[0], m->macAddress[1],
2499            m->macAddress[2], m->macAddress[3],
2500            m->macAddress[4], m->macAddress[5]);
2501 }
2502
2503 /* Set the multicast address and address mask registers
2504  *
2505  * A bit in the address mask register must be set if
2506  * all multicast addresses always have that bit set, or if
2507  * all multicast addresses always have that bit cleared.
2508  *
2509  * A bit in the address register must be set if all multicast
2510  * addresses have that bit set, otherwise, it should be cleared
2511  */
2512
2513 PRIVATE void
2514 ixEthAccMulticastAddressSet(IxEthAccPortId portId)
2515 {
2516     UINT32 i;
2517     UINT32 j;
2518     IxEthAccMacAddr addressMask;
2519     IxEthAccMacAddr address;
2520     IxEthAccMacAddr alwaysClearBits;
2521     IxEthAccMacAddr alwaysSetBits;
2522
2523     /* calculate alwaysClearBits and alwaysSetBits:
2524      * alwaysClearBits is calculated by ORing all
2525      * multicast addresses, those bits that are always
2526      * clear are clear in the result
2527      *
2528      * alwaysSetBits is calculated by ANDing all
2529      * multicast addresses, those bits that are always set
2530      * are set in the result
2531      */
2532
2533     if (ixEthAccMacState[portId].promiscuous == true)
2534     {
2535         /* Promiscuous Mode is set, and filtering
2536          * allow all packets, and enable the mcast and
2537          * bcast detection.
2538          */
2539         memset(&addressMask.macAddress,
2540                0,
2541                IX_IEEE803_MAC_ADDRESS_SIZE);
2542         memset(&address.macAddress,
2543                0,
2544                IX_IEEE803_MAC_ADDRESS_SIZE);
2545     }
2546     else
2547     {
2548         if(ixEthAccMacState[portId].joinAll == true)
2549         {
2550             /* Join all is set. The mask and address are
2551              * the multicast settings.
2552              */
2553             IxEthAccMacAddr macAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}};
2554
2555             memcpy(addressMask.macAddress,
2556                    macAddr.macAddress,
2557                    IX_IEEE803_MAC_ADDRESS_SIZE);
2558             memcpy(address.macAddress,
2559                    macAddr.macAddress,
2560                    IX_IEEE803_MAC_ADDRESS_SIZE);
2561         }
2562         else if(ixEthAccMacState[portId].mcastAddrIndex == 0)
2563         {
2564             /* No entry in the filtering database,
2565              * Promiscuous Mode is cleared, Broadcast filtering
2566              * is configured.
2567              */
2568             memset(addressMask.macAddress,
2569                    IX_ETH_ACC_MAC_ALL_BITS_SET,
2570                    IX_IEEE803_MAC_ADDRESS_SIZE);
2571             memset(address.macAddress,
2572                    IX_ETH_ACC_MAC_ALL_BITS_SET,
2573                    IX_IEEE803_MAC_ADDRESS_SIZE);
2574         }
2575         else
2576         {
2577             /* build a mask and an address which mix all entreis
2578              * from the list of multicast addresses
2579              */
2580             memset(alwaysClearBits.macAddress,
2581                    0,
2582                    IX_IEEE803_MAC_ADDRESS_SIZE);
2583             memset(alwaysSetBits.macAddress,
2584                    IX_ETH_ACC_MAC_ALL_BITS_SET,
2585                    IX_IEEE803_MAC_ADDRESS_SIZE);
2586
2587             for(i=0;i<ixEthAccMacState[portId].mcastAddrIndex;i++)
2588             {
2589                 for(j=0;j<IX_IEEE803_MAC_ADDRESS_SIZE;j++)
2590                 {
2591                     alwaysClearBits.macAddress[j] |=
2592                         ixEthAccMacState[portId].mcastAddrsTable[i].macAddress[j];
2593                     alwaysSetBits.macAddress[j] &=
2594                         ixEthAccMacState[portId].mcastAddrsTable[i].macAddress[j];
2595                 }
2596             }
2597
2598             for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
2599             {
2600                 addressMask.macAddress[i] = alwaysSetBits.macAddress[i]
2601                     | ~alwaysClearBits.macAddress[i];
2602                 address.macAddress[i] = alwaysSetBits.macAddress[i];
2603             }
2604         }
2605     }
2606
2607     /*write the new addr filtering to h/w*/
2608     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
2609     {
2610         REG_WRITE(ixEthAccMacBase[portId],
2611                   IX_ETH_ACC_MAC_ADDR_MASK_1+i*sizeof(UINT32),
2612                   addressMask.macAddress[i]);
2613         REG_WRITE(ixEthAccMacBase[portId],
2614                   IX_ETH_ACC_MAC_ADDR_1+i*sizeof(UINT32),
2615                   address.macAddress[i]);
2616     }
2617 }