uboot/drivers/net/npe/IxEthAccMac.c
<<
>>
Prefs
   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}
2642