source: SVN/rincon/u-boot/cpu/ixp/npe/IxEthAccMac.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 74.2 KB
Line 
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
81PUBLIC IxEthAccMacState ixEthAccMacState[IX_ETH_ACC_NUMBER_OF_PORTS];
82
83PRIVATE UINT32 ixEthAccMacBase[IX_ETH_ACC_NUMBER_OF_PORTS];
84
85/*Forward function declarations*/
86PRIVATE void
87ixEthAccPortDisableRx (IxEthAccPortId portId,
88                       IX_OSAL_MBUF * mBufPtr,
89                       BOOL useMultiBufferCallback);
90
91PRIVATE void
92ixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId,
93                                   IX_OSAL_MBUF * mBufPtr,
94                                   BOOL useMultiBufferCallback);
95
96PRIVATE void
97ixEthAccPortDisableTxDone (UINT32 cbTag,
98                           IX_OSAL_MBUF *mbuf);
99
100PRIVATE void
101ixEthAccPortDisableTxDoneAndSubmit (UINT32 cbTag,
102                                    IX_OSAL_MBUF *mbuf);
103
104PRIVATE void
105ixEthAccPortDisableRxCallback (UINT32 cbTag,
106                               IX_OSAL_MBUF * mBufPtr,
107                               UINT32 learnedPortId);
108
109PRIVATE void
110ixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag,
111                                          IX_OSAL_MBUF **mBufPtr);
112
113PRIVATE IxEthAccStatus
114ixEthAccPortDisableTryTransmit(UINT32 portId);
115
116PRIVATE IxEthAccStatus
117ixEthAccPortDisableTryReplenish(UINT32 portId);
118
119PRIVATE IxEthAccStatus
120ixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId,
121                                    IxEthAccMacAddr *macAddr);
122
123PRIVATE IxEthAccStatus
124ixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId,
125                                   IxEthAccMacAddr *macAddr);
126
127PRIVATE void
128ixEthAccMacNpeStatsMessageCallback (IxNpeMhNpeId npeId,
129                                    IxNpeMhMessage msg);
130
131PRIVATE void
132ixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId,
133                                         IxNpeMhMessage msg);
134
135PRIVATE void
136ixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId,
137                                    IxNpeMhMessage msg);
138
139PRIVATE void
140ixEthAccMulticastAddressSet(IxEthAccPortId portId);
141
142PRIVATE BOOL
143ixEthAccMacEqual(IxEthAccMacAddr *macAddr1,
144                 IxEthAccMacAddr *macAddr2);
145
146PRIVATE void
147ixEthAccMacPrint(IxEthAccMacAddr *m);
148
149PRIVATE void
150ixEthAccMacStateUpdate(IxEthAccPortId portId);
151
152IxEthAccStatus
153ixEthAccMacMemInit(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
190void
191ixEthAccMacUnload(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
203IxEthAccStatus
204ixEthAccPortEnablePriv(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 */
322typedef void (*IxEthAccPortDisableRx)(IxEthAccPortId portId,
323                                      IX_OSAL_MBUF * mBufPtr,
324                                      BOOL useMultiBufferCallback);
325static IxEthAccPortRxCallback
326ixEthAccPortDisableFn[IX_ETH_ACC_NUMBER_OF_PORTS];
327static IxEthAccPortMultiBufferRxCallback
328ixEthAccPortDisableMultiBufferFn[IX_ETH_ACC_NUMBER_OF_PORTS];
329static IxEthAccPortDisableRx
330ixEthAccPortDisableRxTable[IX_ETH_ACC_NUMBER_OF_PORTS];
331static UINT32
332ixEthAccPortDisableCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
333static UINT32
334ixEthAccPortDisableMultiBufferCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
335
336static IxEthAccPortTxDoneCallback
337ixEthAccPortDisableTxDoneFn[IX_ETH_ACC_NUMBER_OF_PORTS];
338static UINT32
339ixEthAccPortDisableTxDoneCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
340
341static UINT32
342ixEthAccPortDisableUserBufferCount[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 */
349PRIVATE void
350ixEthAccPortDisableTxDone(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
371PRIVATE IxEthAccStatus
372ixEthAccPortDisableTryTransmit(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
397PRIVATE void
398ixEthAccPortDisableTxDoneAndSubmit(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
412PRIVATE void
413ixEthAccPortDisableRx (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
471PRIVATE IxEthAccStatus
472ixEthAccPortDisableTryReplenish(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
496PRIVATE void
497ixEthAccPortDisableRxAndReplenish (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
510PRIVATE void
511ixEthAccPortDisableRxCallback (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
521PRIVATE void
522ixEthAccPortDisableMultiBufferRxCallback (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
534IxEthAccStatus
535ixEthAccPortDisablePriv(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
862IxEthAccStatus
863ixEthAccPortEnabledQueryPriv(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
888IxEthAccStatus
889ixEthAccPortMacResetPriv(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
924IxEthAccStatus
925ixEthAccPortLoopbackEnable(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
956PRIVATE void
957ixEthAccNpeLoopbackMessageCallback (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
977IxEthAccStatus
978ixEthAccNpeLoopbackEnablePriv(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
1027IxEthAccStatus
1028ixEthAccPortTxEnablePriv(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
1059IxEthAccStatus
1060ixEthAccPortRxEnablePriv(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
1091IxEthAccStatus
1092ixEthAccPortLoopbackDisable(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
1121IxEthAccStatus
1122ixEthAccNpeLoopbackDisablePriv(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
1170IxEthAccStatus
1171ixEthAccPortTxDisablePriv(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
1202IxEthAccStatus
1203ixEthAccPortRxDisablePriv(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
1234IxEthAccStatus
1235ixEthAccPortPromiscuousModeClearPriv(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
1269IxEthAccStatus
1270ixEthAccPortPromiscuousModeSetPriv(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
1307IxEthAccStatus
1308ixEthAccPortUnicastMacAddressSetPriv (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
1369IxEthAccStatus
1370ixEthAccPortUnicastMacAddressGetPriv (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
1410PRIVATE IxEthAccStatus
1411ixEthAccPortMulticastMacAddressGet (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
1429PRIVATE IxEthAccStatus
1430ixEthAccPortMulticastMacFilterGet (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
1447IxEthAccStatus
1448ixEthAccPortMulticastAddressJoinPriv (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
1528IxEthAccStatus
1529ixEthAccPortMulticastAddressJoinAllPriv (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
1562IxEthAccStatus
1563ixEthAccPortMulticastAddressLeavePriv (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
1628IxEthAccStatus
1629ixEthAccPortMulticastAddressLeaveAllPriv (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
1654IxEthAccStatus
1655ixEthAccPortUnicastAddressShowPriv (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
1688void
1689ixEthAccPortMulticastAddressShowPriv(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*/
1731IxEthAccStatus
1732ixEthAccPortDuplexModeSetPriv (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
1803IxEthAccStatus
1804ixEthAccPortDuplexModeGetPriv (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
1850IxEthAccStatus
1851ixEthAccPortTxFrameAppendPaddingEnablePriv (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
1883IxEthAccStatus
1884ixEthAccPortTxFrameAppendPaddingDisablePriv (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
1915IxEthAccStatus
1916ixEthAccPortTxFrameAppendFCSEnablePriv (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
1948IxEthAccStatus
1949ixEthAccPortTxFrameAppendFCSDisablePriv (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
1980IxEthAccStatus
1981ixEthAccPortRxFrameAppendFCSEnablePriv (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
2011IxEthAccStatus
2012ixEthAccPortRxFrameAppendFCSDisablePriv (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
2044PRIVATE void
2045ixEthAccMacNpeStatsMessageCallback (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
2066PRIVATE void
2067ixEthAccMibIIStatsEndianConvert (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
2120IxEthAccStatus
2121ixEthAccMibIIStatsGet (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
2195PRIVATE void
2196ixEthAccMacNpeStatsResetMessageCallback (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
2219IxEthAccStatus
2220ixEthAccMibIIStatsGetClear (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
2290IxEthAccStatus
2291ixEthAccMibIIStatsClear (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 */
2316IxEthAccStatus
2317ixEthAccMacInit(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
2415PRIVATE void
2416ixEthAccMacStateUpdate(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
2503PRIVATE BOOL
2504ixEthAccMacEqual(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
2518PRIVATE void
2519ixEthAccMacPrint(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
2537PRIVATE void
2538ixEthAccMulticastAddressSet(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}
Note: See TracBrowser for help on using the repository browser.