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