4 * @author Intel Corporation
7 * @brief MAC control functions
12 * IXP400 SW Release version 2.0
14 * -- Copyright Notice --
17 * Copyright 2001-2005, Intel Corporation.
18 * All rights reserved.
21 * SPDX-License-Identifier: BSD-3-Clause
23 * -- End of Copyright Notice --
28 #ifdef CONFIG_IXP425_COMPONENT_ETHDB
31 #include "IxEthDBPortDefs.h"
34 #include "IxEthAccDataPlane_p.h"
35 #include "IxEthAcc_p.h"
36 #include "IxEthAccMac_p.h"
38 /* Maximum number of retries during ixEthAccPortDisable, which
39 * is approximately 10 seconds
41 #define IX_ETH_ACC_MAX_RETRY 500
43 /* Maximum number of retries during ixEthAccPortDisable when expecting
46 #define IX_ETH_ACC_MAX_RETRY_TIMEOUT 5
48 #define IX_ETH_ACC_VALIDATE_PORT_ID(portId) \
51 if(!IX_ETH_ACC_IS_PORT_VALID(portId)) \
53 return IX_ETH_ACC_INVALID_PORT; \
57 PUBLIC IxEthAccMacState ixEthAccMacState[IX_ETH_ACC_NUMBER_OF_PORTS];
59 PRIVATE UINT32 ixEthAccMacBase[IX_ETH_ACC_NUMBER_OF_PORTS];
61 /*Forward function declarations*/
63 ixEthAccPortDisableRx (IxEthAccPortId portId,
64 IX_OSAL_MBUF * mBufPtr,
65 BOOL useMultiBufferCallback);
68 ixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId,
69 IX_OSAL_MBUF * mBufPtr,
70 BOOL useMultiBufferCallback);
73 ixEthAccPortDisableTxDone (UINT32 cbTag,
77 ixEthAccPortDisableTxDoneAndSubmit (UINT32 cbTag,
81 ixEthAccPortDisableRxCallback (UINT32 cbTag,
82 IX_OSAL_MBUF * mBufPtr,
83 UINT32 learnedPortId);
86 ixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag,
87 IX_OSAL_MBUF **mBufPtr);
89 PRIVATE IxEthAccStatus
90 ixEthAccPortDisableTryTransmit(UINT32 portId);
92 PRIVATE IxEthAccStatus
93 ixEthAccPortDisableTryReplenish(UINT32 portId);
95 PRIVATE IxEthAccStatus
96 ixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId,
97 IxEthAccMacAddr *macAddr);
99 PRIVATE IxEthAccStatus
100 ixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId,
101 IxEthAccMacAddr *macAddr);
104 ixEthAccMacNpeStatsMessageCallback (IxNpeMhNpeId npeId,
108 ixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId,
112 ixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId,
116 ixEthAccMulticastAddressSet(IxEthAccPortId portId);
119 ixEthAccMacEqual(IxEthAccMacAddr *macAddr1,
120 IxEthAccMacAddr *macAddr2);
123 ixEthAccMacPrint(IxEthAccMacAddr *m);
126 ixEthAccMacStateUpdate(IxEthAccPortId portId);
129 ixEthAccMacMemInit(void)
131 ixEthAccMacBase[IX_ETH_PORT_1] =
132 (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_0_BASE,
133 IX_OSAL_IXP400_ETHA_MAP_SIZE);
134 ixEthAccMacBase[IX_ETH_PORT_2] =
135 (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_1_BASE,
136 IX_OSAL_IXP400_ETHB_MAP_SIZE);
138 ixEthAccMacBase[IX_ETH_PORT_3] =
139 (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_2_BASE,
140 IX_OSAL_IXP400_ETH_NPEA_MAP_SIZE);
141 if (ixEthAccMacBase[IX_ETH_PORT_3] == 0)
143 ixOsalLog(IX_OSAL_LOG_LVL_FATAL,
144 IX_OSAL_LOG_DEV_STDOUT,
145 "EthAcc: Could not map MAC I/O memory\n",
148 return IX_ETH_ACC_FAIL;
152 if (ixEthAccMacBase[IX_ETH_PORT_1] == 0
153 || ixEthAccMacBase[IX_ETH_PORT_2] == 0)
155 ixOsalLog(IX_OSAL_LOG_LVL_FATAL,
156 IX_OSAL_LOG_DEV_STDOUT,
157 "EthAcc: Could not map MAC I/O memory\n",
160 return IX_ETH_ACC_FAIL;
163 return IX_ETH_ACC_SUCCESS;
167 ixEthAccMacUnload(void)
169 IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_1]);
170 IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_2]);
172 IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_3]);
173 ixEthAccMacBase[IX_ETH_PORT_3] = 0;
175 ixEthAccMacBase[IX_ETH_PORT_2] = 0;
176 ixEthAccMacBase[IX_ETH_PORT_1] = 0;
180 ixEthAccPortEnablePriv(IxEthAccPortId portId)
182 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
184 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
186 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable port.\n",(INT32)portId,0,0,0,0,0);
187 return IX_ETH_ACC_SUCCESS ;
190 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
192 printf("EthAcc: (Mac) cannot enable port %d, port not initialized\n", portId);
193 return (IX_ETH_ACC_PORT_UNINITIALIZED);
196 if (ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn == NULL)
198 /* TxDone callback not registered */
199 printf("EthAcc: (Mac) cannot enable port %d, TxDone callback not registered\n", portId);
200 return (IX_ETH_ACC_PORT_UNINITIALIZED);
203 if ((ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn == NULL)
204 && (ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn == NULL))
206 /* Receive callback not registered */
207 printf("EthAcc: (Mac) cannot enable port %d, Rx callback not registered\n", portId);
208 return (IX_ETH_ACC_PORT_UNINITIALIZED);
211 if(!ixEthAccMacState[portId].initDone)
213 printf("EthAcc: (Mac) cannot enable port %d, MAC address not set\n", portId);
214 return (IX_ETH_ACC_MAC_UNINITIALIZED);
217 /* if the state is being set to what it is already at, do nothing*/
218 if (ixEthAccMacState[portId].enabled)
220 return IX_ETH_ACC_SUCCESS;
223 #ifdef CONFIG_IXP425_COMPONENT_ETHDB
224 /* enable ethernet database for this port */
225 if (ixEthDBPortEnable(portId) != IX_ETH_DB_SUCCESS)
227 printf("EthAcc: (Mac) cannot enable port %d, EthDB failure\n", portId);
228 return IX_ETH_ACC_FAIL;
232 /* set the MAC core registers */
233 REG_WRITE(ixEthAccMacBase[portId],
234 IX_ETH_ACC_MAC_TX_CNTRL2,
235 IX_ETH_ACC_TX_CNTRL2_RETRIES_MASK);
237 REG_WRITE(ixEthAccMacBase[portId],
238 IX_ETH_ACC_MAC_RANDOM_SEED,
239 IX_ETH_ACC_RANDOM_SEED_DEFAULT);
241 REG_WRITE(ixEthAccMacBase[portId],
242 IX_ETH_ACC_MAC_THRESH_P_EMPTY,
243 IX_ETH_ACC_MAC_THRESH_P_EMPTY_DEFAULT);
245 REG_WRITE(ixEthAccMacBase[portId],
246 IX_ETH_ACC_MAC_THRESH_P_FULL,
247 IX_ETH_ACC_MAC_THRESH_P_FULL_DEFAULT);
249 REG_WRITE(ixEthAccMacBase[portId],
250 IX_ETH_ACC_MAC_TX_DEFER,
251 IX_ETH_ACC_MAC_TX_DEFER_DEFAULT);
253 REG_WRITE(ixEthAccMacBase[portId],
254 IX_ETH_ACC_MAC_TX_TWO_DEFER_1,
255 IX_ETH_ACC_MAC_TX_TWO_DEFER_1_DEFAULT);
257 REG_WRITE(ixEthAccMacBase[portId],
258 IX_ETH_ACC_MAC_TX_TWO_DEFER_2,
259 IX_ETH_ACC_MAC_TX_TWO_DEFER_2_DEFAULT);
261 REG_WRITE(ixEthAccMacBase[portId],
262 IX_ETH_ACC_MAC_SLOT_TIME,
263 IX_ETH_ACC_MAC_SLOT_TIME_DEFAULT);
265 REG_WRITE(ixEthAccMacBase[portId],
266 IX_ETH_ACC_MAC_INT_CLK_THRESH,
267 IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
269 REG_WRITE(ixEthAccMacBase[portId],
270 IX_ETH_ACC_MAC_BUF_SIZE_TX,
271 IX_ETH_ACC_MAC_BUF_SIZE_TX_DEFAULT);
273 REG_WRITE(ixEthAccMacBase[portId],
274 IX_ETH_ACC_MAC_TX_CNTRL1,
275 IX_ETH_ACC_TX_CNTRL1_DEFAULT);
277 REG_WRITE(ixEthAccMacBase[portId],
278 IX_ETH_ACC_MAC_RX_CNTRL1,
279 IX_ETH_ACC_RX_CNTRL1_DEFAULT);
281 /* set the global state */
282 ixEthAccMacState[portId].portDisableState = ACTIVE;
283 ixEthAccMacState[portId].enabled = true;
285 /* rewrite the setup (including mac filtering) depending
288 ixEthAccMacStateUpdate(portId);
290 return IX_ETH_ACC_SUCCESS;
294 * PortDisable local variables. They contain the intermediate steps
295 * while the port is being disabled and the buffers being drained out
298 typedef void (*IxEthAccPortDisableRx)(IxEthAccPortId portId,
299 IX_OSAL_MBUF * mBufPtr,
300 BOOL useMultiBufferCallback);
301 static IxEthAccPortRxCallback
302 ixEthAccPortDisableFn[IX_ETH_ACC_NUMBER_OF_PORTS];
303 static IxEthAccPortMultiBufferRxCallback
304 ixEthAccPortDisableMultiBufferFn[IX_ETH_ACC_NUMBER_OF_PORTS];
305 static IxEthAccPortDisableRx
306 ixEthAccPortDisableRxTable[IX_ETH_ACC_NUMBER_OF_PORTS];
308 ixEthAccPortDisableCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
310 ixEthAccPortDisableMultiBufferCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
312 static IxEthAccPortTxDoneCallback
313 ixEthAccPortDisableTxDoneFn[IX_ETH_ACC_NUMBER_OF_PORTS];
315 ixEthAccPortDisableTxDoneCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
318 ixEthAccPortDisableUserBufferCount[IX_ETH_ACC_NUMBER_OF_PORTS];
321 * PortDisable private callbacks functions. They handle the user
322 * traffic, and the special buffers (one for tx, one for rx) used
326 ixEthAccPortDisableTxDone(UINT32 cbTag,
329 IxEthAccPortId portId = (IxEthAccPortId)cbTag;
330 volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState;
332 /* check for the special mbuf used in portDisable */
333 if (mbuf == ixEthAccMacState[portId].portDisableTxMbufPtr)
335 *txState = TRANSMIT_DONE;
339 /* increment the count of user traffic during portDisable */
340 ixEthAccPortDisableUserBufferCount[portId]++;
342 /* call client TxDone function */
343 ixEthAccPortDisableTxDoneFn[portId](ixEthAccPortDisableTxDoneCbTag[portId], mbuf);
347 PRIVATE IxEthAccStatus
348 ixEthAccPortDisableTryTransmit(UINT32 portId)
351 IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
352 volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState;
353 /* transmit the special buffer again if it is transmitted
354 * and update the txState
355 * This section is protected because the portDisable context
356 * run an identical code, so the system keeps transmitting at the
359 key = ixOsalIrqLock();
360 if (*txState == TRANSMIT_DONE)
362 IX_OSAL_MBUF *mbufTxPtr = ixEthAccMacState[portId].portDisableTxMbufPtr;
364 status = ixEthAccPortTxFrameSubmit(portId,
366 IX_ETH_ACC_TX_DEFAULT_PRIORITY);
368 ixOsalIrqUnlock(key);
374 ixEthAccPortDisableTxDoneAndSubmit(UINT32 cbTag,
377 IxEthAccPortId portId = (IxEthAccPortId)cbTag;
379 /* call the callback which forwards the traffic to the client */
380 ixEthAccPortDisableTxDone(cbTag, mbuf);
382 /* try to transmit the buffer used in portDisable
385 ixEthAccPortDisableTryTransmit(portId);
389 ixEthAccPortDisableRx (IxEthAccPortId portId,
390 IX_OSAL_MBUF * mBufPtr,
391 BOOL useMultiBufferCallback)
393 volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState;
394 IX_OSAL_MBUF *mNextPtr;
398 mNextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr);
399 IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr) = NULL;
401 /* check for the special mbuf used in portDisable */
402 if (mBufPtr == ixEthAccMacState[portId].portDisableRxMbufPtr)
408 /* increment the count of user traffic during portDisable */
409 ixEthAccPortDisableUserBufferCount[portId]++;
411 /* reset the received payload length during portDisable */
412 IX_OSAL_MBUF_MLEN(mBufPtr) = 0;
413 IX_OSAL_MBUF_PKT_LEN(mBufPtr) = 0;
415 if (useMultiBufferCallback)
417 /* call the user callback with one unchained
418 * buffer, without payload. A small array is built
419 * to be used as a parameter (the user callback expects
420 * to receive an array ended by a NULL pointer.
422 IX_OSAL_MBUF *mBufPtrArray[2];
424 mBufPtrArray[0] = mBufPtr;
425 mBufPtrArray[1] = NULL;
426 ixEthAccPortDisableMultiBufferFn[portId](
427 ixEthAccPortDisableMultiBufferCbTag[portId],
432 /* call the user callback with a unchained
433 * buffer, without payload and the destination port is
436 ixEthAccPortDisableFn[portId](
437 ixEthAccPortDisableCbTag[portId],
439 IX_ETH_DB_UNKNOWN_PORT /* port not found */);
447 PRIVATE IxEthAccStatus
448 ixEthAccPortDisableTryReplenish(UINT32 portId)
451 IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
452 volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState;
453 /* replenish with the special buffer again if it is received
454 * and update the rxState
455 * This section is protected because the portDisable context
456 * run an identical code, so the system keeps replenishing at the
459 key = ixOsalIrqLock();
460 if (*rxState == RECEIVE)
462 IX_OSAL_MBUF *mbufRxPtr = ixEthAccMacState[portId].portDisableRxMbufPtr;
463 *rxState = REPLENISH;
464 IX_OSAL_MBUF_MLEN(mbufRxPtr) = IX_ETHACC_RX_MBUF_MIN_SIZE;
465 status = ixEthAccPortRxFreeReplenish(portId, mbufRxPtr);
467 ixOsalIrqUnlock(key);
473 ixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId,
474 IX_OSAL_MBUF * mBufPtr,
475 BOOL useMultiBufferCallback)
477 /* call the callback which forwards the traffic to the client */
478 ixEthAccPortDisableRx(portId, mBufPtr, useMultiBufferCallback);
480 /* try to replenish with the buffer used in portDisable
483 ixEthAccPortDisableTryReplenish(portId);
487 ixEthAccPortDisableRxCallback (UINT32 cbTag,
488 IX_OSAL_MBUF * mBufPtr,
489 UINT32 learnedPortId)
491 IxEthAccPortId portId = (IxEthAccPortId)cbTag;
493 /* call the portDisable receive callback */
494 (ixEthAccPortDisableRxTable[portId])(portId, mBufPtr, false);
498 ixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag,
499 IX_OSAL_MBUF **mBufPtr)
501 IxEthAccPortId portId = (IxEthAccPortId)cbTag;
505 /* call the portDisable receive callback with one buffer at a time */
506 (ixEthAccPortDisableRxTable[portId])(portId, *mBufPtr++, true);
511 ixEthAccPortDisablePriv(IxEthAccPortId portId)
513 IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
515 int retry, retryTimeout;
516 volatile IxEthAccPortDisableState *state = &ixEthAccMacState[portId].portDisableState;
517 volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState;
518 volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState;
520 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
522 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
524 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disable port.\n",(INT32)portId,0,0,0,0,0);
525 return IX_ETH_ACC_SUCCESS ;
528 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
530 return (IX_ETH_ACC_PORT_UNINITIALIZED);
533 /* if the state is being set to what it is already at, do nothing */
534 if (!ixEthAccMacState[portId].enabled)
536 return IX_ETH_ACC_SUCCESS;
541 /* disable MAC receive first */
542 ixEthAccPortRxDisablePriv(portId);
544 #ifdef CONFIG_IXP425_COMPONENT_ETHDB
545 /* disable ethernet database for this port - It is done now to avoid
546 * issuing ELT maintenance after requesting 'port disable' in an NPE
548 if (ixEthDBPortDisable(portId) != IX_ETH_DB_SUCCESS)
550 status = IX_ETH_ACC_FAIL;
551 IX_ETH_ACC_FATAL_LOG("ixEthAccPortDisable: failed to disable EthDB for this port\n", 0, 0, 0, 0, 0, 0);
555 /* enter the critical section */
556 key = ixOsalIrqLock();
558 /* swap the Rx and TxDone callbacks */
559 ixEthAccPortDisableFn[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn;
560 ixEthAccPortDisableMultiBufferFn[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn;
561 ixEthAccPortDisableCbTag[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag;
562 ixEthAccPortDisableMultiBufferCbTag[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag;
563 ixEthAccPortDisableTxDoneFn[portId] = ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn;
564 ixEthAccPortDisableTxDoneCbTag[portId] = ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag;
565 ixEthAccPortDisableRxTable[portId] = ixEthAccPortDisableRx;
567 /* register temporary callbacks */
568 ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn = ixEthAccPortDisableRxCallback;
569 ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag = portId;
571 ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = ixEthAccPortDisableMultiBufferRxCallback;
572 ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = portId;
574 ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn = ixEthAccPortDisableTxDone;
575 ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag = portId;
577 /* initialise the Rx state and Tx states */
578 *txState = TRANSMIT_DONE;
581 /* exit the critical section */
582 ixOsalIrqUnlock(key);
584 /* enable a NPE loopback */
585 if (ixEthAccNpeLoopbackEnablePriv(portId) != IX_ETH_ACC_SUCCESS)
587 status = IX_ETH_ACC_FAIL;
590 if (status == IX_ETH_ACC_SUCCESS)
594 /* Step 1 : Drain Tx traffic and TxDone queues :
596 * Transmit and replenish at least once with the
597 * special buffers until both of them are seen
598 * in the callback hook
600 * (the receive callback keeps replenishing, so once we see
601 * the special Tx buffer, we can be sure that Tx drain is complete)
603 ixEthAccPortDisableRxTable[portId]
604 = ixEthAccPortDisableRxAndReplenish;
605 ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn
606 = ixEthAccPortDisableTxDone;
610 /* keep replenishing */
611 status = ixEthAccPortDisableTryReplenish(portId);
612 if (status == IX_ETH_ACC_SUCCESS)
614 /* keep transmitting */
615 status = ixEthAccPortDisableTryTransmit(portId);
617 if (status == IX_ETH_ACC_SUCCESS)
619 /* wait for some traffic being processed */
620 ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
623 while ((status == IX_ETH_ACC_SUCCESS)
624 && (retry++ < IX_ETH_ACC_MAX_RETRY)
625 && (*txState == TRANSMIT));
627 /* Step 2 : Drain Rx traffic, RxFree and Rx queues :
629 * Transmit and replenish at least once with the
630 * special buffers until both of them are seen
631 * in the callback hook
632 * (the transmit callback keeps transmitting, and when we see
633 * the special Rx buffer, we can be sure that rxFree drain
636 * The nested loop helps to retry if the user was keeping
637 * replenishing or transmitting during portDisable.
639 * The 2 nested loops ensure more retries if user traffic is
640 * seen during portDisable : the user should not replenish
641 * or transmit while portDisable is running. However, because of
642 * the queueing possibilities in ethAcc dataplane, it is possible
643 * that a lot of traffic is left in the queues (e.g. when
644 * transmitting over a low speed link) and therefore, more
645 * retries are allowed to help flushing the buffers out.
647 ixEthAccPortDisableRxTable[portId]
648 = ixEthAccPortDisableRx;
649 ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn
650 = ixEthAccPortDisableTxDoneAndSubmit;
656 ixEthAccPortDisableUserBufferCount[portId] = 0;
658 /* keep replenishing */
659 status = ixEthAccPortDisableTryReplenish(portId);
660 if (status == IX_ETH_ACC_SUCCESS)
662 /* keep transmitting */
663 status = ixEthAccPortDisableTryTransmit(portId);
665 if (status == IX_ETH_ACC_SUCCESS)
667 /* wait for some traffic being processed */
668 ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
671 while ((status == IX_ETH_ACC_SUCCESS)
672 && (retry++ < IX_ETH_ACC_MAX_RETRY)
673 && ((ixEthAccPortDisableUserBufferCount[portId] != 0)
674 || (*rxState == REPLENISH)));
676 /* After the first iteration, change the receive callbacks,
677 * to process only 1 buffer at a time
679 ixEthAccPortDisableRxTable[portId]
680 = ixEthAccPortDisableRx;
681 ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn
682 = ixEthAccPortDisableTxDone;
684 /* repeat the whole process while user traffic is seen in TxDone
686 * The conditions to stop the loop are
687 * - Xscale has both Rx and Tx special buffers
688 * (txState = transmit, rxState = receive)
689 * - any error in txSubmit or rxReplenish
690 * - no user traffic seen
691 * - an excessive amount of retries
694 while ((status == IX_ETH_ACC_SUCCESS)
695 && (retry < IX_ETH_ACC_MAX_RETRY)
696 && (*txState == TRANSMIT));
698 /* check the loop exit conditions. The NPE should not hold
699 * the special buffers.
701 if ((*rxState == REPLENISH) || (*txState == TRANSMIT))
703 status = IX_ETH_ACC_FAIL;
706 if (status == IX_ETH_ACC_SUCCESS)
708 /* Step 3 : Replenish without transmitting until a timeout
709 * occurs, in order to drain the internal NPE fifos
711 * we can expect a few frames srill held
714 * The 2 nested loops take care about the NPE dropping traffic
715 * (including loopback traffic) when the Rx queue is full.
717 * The timeout value is very conservative
718 * since the loopback used keeps replenishhing.
723 ixEthAccPortDisableRxTable[portId] = ixEthAccPortDisableRxAndReplenish;
724 ixEthAccPortDisableUserBufferCount[portId] = 0;
728 /* keep replenishing */
729 status = ixEthAccPortDisableTryReplenish(portId);
730 if (status == IX_ETH_ACC_SUCCESS)
732 /* wait for some traffic being processed */
733 ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
736 while ((status == IX_ETH_ACC_SUCCESS)
737 && (retryTimeout++ < IX_ETH_ACC_MAX_RETRY_TIMEOUT));
739 /* Step 4 : Transmit once. Stop replenish
741 * After the Rx timeout, we are sure that the NPE does not
742 * hold any frame in its internal NPE fifos.
744 * At this point, the NPE still holds the last rxFree buffer.
745 * By transmitting a single frame, this should unblock the
746 * last rxFree buffer. This code just transmit once and
747 * wait for both frames seen in TxDone and in rxFree.
750 ixEthAccPortDisableRxTable[portId] = ixEthAccPortDisableRx;
751 status = ixEthAccPortDisableTryTransmit(portId);
753 /* the NPE should immediatelyt release
754 * the last Rx buffer and the last transmitted buffer
755 * unless the last Tx frame was dropped (rx queue full)
757 if (status == IX_ETH_ACC_SUCCESS)
762 ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
764 while ((*rxState == REPLENISH)
765 && (retryTimeout++ < IX_ETH_ACC_MAX_RETRY_TIMEOUT));
768 /* the NPE may have dropped the traffic because of Rx
769 * queue being full. This code ensures that the last
770 * Tx and Rx frames are both received.
773 while ((status == IX_ETH_ACC_SUCCESS)
774 && (retry++ < IX_ETH_ACC_MAX_RETRY)
775 && ((*txState == TRANSMIT)
776 || (*rxState == REPLENISH)
777 || (ixEthAccPortDisableUserBufferCount[portId] != 0)));
779 /* Step 5 : check the final states : the NPE has
780 * no buffer left, nor in Tx , nor in Rx directions.
782 if ((*rxState == REPLENISH) || (*txState == TRANSMIT))
784 status = IX_ETH_ACC_FAIL;
788 /* now all the buffers are drained, disable NPE loopback
789 * This is done regardless of the logic to drain the queues and
790 * the internal buffers held by the NPE.
792 if (ixEthAccNpeLoopbackDisablePriv(portId) != IX_ETH_ACC_SUCCESS)
794 status = IX_ETH_ACC_FAIL;
798 /* disable MAC Tx and Rx services */
799 ixEthAccMacState[portId].enabled = false;
800 ixEthAccMacStateUpdate(portId);
802 /* restore the Rx and TxDone callbacks (within a critical section) */
803 key = ixOsalIrqLock();
805 ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn = ixEthAccPortDisableFn[portId];
806 ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag = ixEthAccPortDisableCbTag[portId];
807 ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = ixEthAccPortDisableMultiBufferFn[portId];
808 ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = ixEthAccPortDisableMultiBufferCbTag[portId];
809 ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn = ixEthAccPortDisableTxDoneFn[portId];
810 ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag = ixEthAccPortDisableTxDoneCbTag[portId];
812 ixOsalIrqUnlock(key);
814 /* the MAC core rx/tx disable may left the MAC hardware in an
815 * unpredictable state. A hw reset is executed before resetting
816 * all the MAC parameters to a known value.
818 REG_WRITE(ixEthAccMacBase[portId],
819 IX_ETH_ACC_MAC_CORE_CNTRL,
820 IX_ETH_ACC_CORE_RESET);
822 ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY);
824 /* rewrite all parameters to their current value */
825 ixEthAccMacStateUpdate(portId);
827 REG_WRITE(ixEthAccMacBase[portId],
828 IX_ETH_ACC_MAC_INT_CLK_THRESH,
829 IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
831 REG_WRITE(ixEthAccMacBase[portId],
832 IX_ETH_ACC_MAC_CORE_CNTRL,
833 IX_ETH_ACC_CORE_MDC_EN);
839 ixEthAccPortEnabledQueryPriv(IxEthAccPortId portId, BOOL *enabled)
841 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
843 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
845 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable port.\n",(INT32)portId,0,0,0,0,0);
847 /* Since Eth NPE is not available, port must be disabled */
849 return IX_ETH_ACC_SUCCESS ;
852 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
854 /* Since Eth NPE is not available, port must be disabled */
856 return (IX_ETH_ACC_PORT_UNINITIALIZED);
859 *enabled = ixEthAccMacState[portId].enabled;
861 return IX_ETH_ACC_SUCCESS;
865 ixEthAccPortMacResetPriv(IxEthAccPortId portId)
867 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
869 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
871 IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot reset Ethernet coprocessor.\n",(INT32)portId,0,0,0,0,0);
872 return IX_ETH_ACC_SUCCESS ;
875 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
877 return (IX_ETH_ACC_PORT_UNINITIALIZED);
880 REG_WRITE(ixEthAccMacBase[portId],
881 IX_ETH_ACC_MAC_CORE_CNTRL,
882 IX_ETH_ACC_CORE_RESET);
884 ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY);
886 /* rewrite all parameters to their current value */
887 ixEthAccMacStateUpdate(portId);
889 REG_WRITE(ixEthAccMacBase[portId],
890 IX_ETH_ACC_MAC_INT_CLK_THRESH,
891 IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
893 REG_WRITE(ixEthAccMacBase[portId],
894 IX_ETH_ACC_MAC_CORE_CNTRL,
895 IX_ETH_ACC_CORE_MDC_EN);
897 return IX_ETH_ACC_SUCCESS;
901 ixEthAccPortLoopbackEnable(IxEthAccPortId portId)
905 /* Turn off promiscuous mode */
906 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
908 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
910 IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable loopback.\n",(INT32)portId,0,0,0,0,0);
911 return IX_ETH_ACC_SUCCESS ;
914 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
916 return (IX_ETH_ACC_PORT_UNINITIALIZED);
920 REG_READ(ixEthAccMacBase[portId],
921 IX_ETH_ACC_MAC_RX_CNTRL1,
924 /* update register */
925 REG_WRITE(ixEthAccMacBase[portId],
926 IX_ETH_ACC_MAC_RX_CNTRL1,
927 regval | IX_ETH_ACC_RX_CNTRL1_LOOP_EN);
929 return IX_ETH_ACC_SUCCESS;
933 ixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId,
936 IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
939 /* Prudent to at least check the port is within range */
940 if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)
942 IX_ETH_ACC_FATAL_LOG("IXETHACC:ixEthAccPortDisableMessageCallback: Illegal port: %u\n",
943 (UINT32) portId, 0, 0, 0, 0, 0);
949 /* unlock message reception mutex */
950 ixOsalMutexUnlock(&ixEthAccMacState[portId].npeLoopbackMessageLock);
954 ixEthAccNpeLoopbackEnablePriv(IxEthAccPortId portId)
956 IX_STATUS npeMhStatus;
957 IxNpeMhMessage message;
958 IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
960 /* Turn off promiscuous mode */
961 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
963 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
965 IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable NPE loopback.\n",(INT32)portId,0,0,0,0,0);
966 return IX_ETH_ACC_SUCCESS ;
969 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
971 return (IX_ETH_ACC_PORT_UNINITIALIZED);
974 /* enable NPE loopback (lsb of the message contains the value 1) */
975 message.data[0] = (IX_ETHNPE_SETLOOPBACK_MODE << IX_ETH_ACC_MAC_MSGID_SHL)
979 npeMhStatus = ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
981 IX_ETHNPE_SETLOOPBACK_MODE_ACK,
982 ixEthAccNpeLoopbackMessageCallback,
983 IX_NPEMH_SEND_RETRIES_DEFAULT);
985 if (npeMhStatus != IX_SUCCESS)
987 status = IX_ETH_ACC_FAIL;
991 /* wait for NPE loopbackEnable response */
992 if (ixOsalMutexLock(&ixEthAccMacState[portId]. npeLoopbackMessageLock,
993 IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS)
996 status = IX_ETH_ACC_FAIL;
1004 ixEthAccPortTxEnablePriv(IxEthAccPortId portId)
1008 /* Turn off promiscuous mode */
1009 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1011 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1013 IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable TX.\n",(INT32)portId,0,0,0,0,0);
1014 return IX_ETH_ACC_SUCCESS ;
1017 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1019 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1023 REG_READ(ixEthAccMacBase[portId],
1024 IX_ETH_ACC_MAC_TX_CNTRL1,
1027 /* update register */
1028 REG_WRITE(ixEthAccMacBase[portId],
1029 IX_ETH_ACC_MAC_TX_CNTRL1,
1030 regval | IX_ETH_ACC_TX_CNTRL1_TX_EN);
1032 return IX_ETH_ACC_SUCCESS;
1036 ixEthAccPortRxEnablePriv(IxEthAccPortId portId)
1040 /* Turn off promiscuous mode */
1041 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1043 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1045 IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable RX.\n",(INT32)portId,0,0,0,0,0);
1046 return IX_ETH_ACC_SUCCESS ;
1049 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1051 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1055 REG_READ(ixEthAccMacBase[portId],
1056 IX_ETH_ACC_MAC_RX_CNTRL1,
1059 /* update register */
1060 REG_WRITE(ixEthAccMacBase[portId],
1061 IX_ETH_ACC_MAC_RX_CNTRL1,
1062 regval | IX_ETH_ACC_RX_CNTRL1_RX_EN);
1064 return IX_ETH_ACC_SUCCESS;
1068 ixEthAccPortLoopbackDisable(IxEthAccPortId portId)
1072 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1074 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1076 IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable loopback.\n",(INT32)portId,0,0,0,0,0);
1077 return IX_ETH_ACC_SUCCESS ;
1080 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1082 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1085 /*disable MAC loopabck */
1086 REG_READ(ixEthAccMacBase[portId],
1087 IX_ETH_ACC_MAC_RX_CNTRL1,
1090 REG_WRITE(ixEthAccMacBase[portId],
1091 IX_ETH_ACC_MAC_RX_CNTRL1,
1092 (regval & ~IX_ETH_ACC_RX_CNTRL1_LOOP_EN));
1094 return IX_ETH_ACC_SUCCESS;
1098 ixEthAccNpeLoopbackDisablePriv(IxEthAccPortId portId)
1100 IX_STATUS npeMhStatus;
1101 IxNpeMhMessage message;
1102 IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
1104 /* Turn off promiscuous mode */
1105 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1107 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1109 IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable NPE loopback.\n",(INT32)portId,0,0,0,0,0);
1110 return IX_ETH_ACC_SUCCESS ;
1113 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1115 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1118 /* disable NPE loopback (lsb of the message contains the value 0) */
1119 message.data[0] = (IX_ETHNPE_SETLOOPBACK_MODE << IX_ETH_ACC_MAC_MSGID_SHL);
1120 message.data[1] = 0;
1122 npeMhStatus = ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
1124 IX_ETHNPE_SETLOOPBACK_MODE_ACK,
1125 ixEthAccNpeLoopbackMessageCallback,
1126 IX_NPEMH_SEND_RETRIES_DEFAULT);
1128 if (npeMhStatus != IX_SUCCESS)
1130 status = IX_ETH_ACC_FAIL;
1134 /* wait for NPE loopbackEnable response */
1135 if (ixOsalMutexLock(&ixEthAccMacState[portId].npeLoopbackMessageLock,
1136 IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS)
1139 status = IX_ETH_ACC_FAIL;
1147 ixEthAccPortTxDisablePriv(IxEthAccPortId portId)
1151 /* Turn off promiscuous mode */
1152 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1154 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1156 IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable TX.\n", (INT32)portId,0,0,0,0,0);
1157 return IX_ETH_ACC_SUCCESS ;
1160 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1162 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1166 REG_READ(ixEthAccMacBase[portId],
1167 IX_ETH_ACC_MAC_TX_CNTRL1,
1170 /* update register */
1171 REG_WRITE(ixEthAccMacBase[portId],
1172 IX_ETH_ACC_MAC_TX_CNTRL1,
1173 (regval & ~IX_ETH_ACC_TX_CNTRL1_TX_EN));
1175 return IX_ETH_ACC_SUCCESS;
1179 ixEthAccPortRxDisablePriv(IxEthAccPortId portId)
1183 /* Turn off promiscuous mode */
1184 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1186 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1188 IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable RX.\n", (INT32)portId,0,0,0,0,0);
1189 return IX_ETH_ACC_SUCCESS ;
1192 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1194 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1198 REG_READ(ixEthAccMacBase[portId],
1199 IX_ETH_ACC_MAC_RX_CNTRL1,
1202 /* update register */
1203 REG_WRITE(ixEthAccMacBase[portId],
1204 IX_ETH_ACC_MAC_RX_CNTRL1,
1205 (regval & ~IX_ETH_ACC_RX_CNTRL1_RX_EN));
1207 return IX_ETH_ACC_SUCCESS;
1211 ixEthAccPortPromiscuousModeClearPriv(IxEthAccPortId portId)
1215 /* Turn off promiscuous mode */
1216 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1218 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1220 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot clear promiscuous mode.\n",(INT32)portId,0,0,0,0,0);
1221 return IX_ETH_ACC_SUCCESS ;
1224 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1226 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1229 /*set bit 5 of Rx control 1 - enable address filtering*/
1230 REG_READ(ixEthAccMacBase[portId],
1231 IX_ETH_ACC_MAC_RX_CNTRL1,
1234 REG_WRITE(ixEthAccMacBase[portId],
1235 IX_ETH_ACC_MAC_RX_CNTRL1,
1236 regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN);
1238 ixEthAccMacState[portId].promiscuous = false;
1240 ixEthAccMulticastAddressSet(portId);
1242 return IX_ETH_ACC_SUCCESS;
1246 ixEthAccPortPromiscuousModeSetPriv(IxEthAccPortId portId)
1250 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1252 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1254 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot set promiscuous mode.\n",(INT32)portId,0,0,0,0,0);
1255 return IX_ETH_ACC_SUCCESS ;
1258 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1260 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1264 * Set bit 5 of Rx control 1 - We enable address filtering even in
1265 * promiscuous mode because we want the MAC to set the appropriate
1266 * bits in m_flags which doesn't happen if we turn off filtering.
1268 REG_READ(ixEthAccMacBase[portId],
1269 IX_ETH_ACC_MAC_RX_CNTRL1,
1272 REG_WRITE(ixEthAccMacBase[portId],
1273 IX_ETH_ACC_MAC_RX_CNTRL1,
1274 regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN);
1276 ixEthAccMacState[portId].promiscuous = true;
1278 ixEthAccMulticastAddressSet(portId);
1280 return IX_ETH_ACC_SUCCESS;
1284 ixEthAccPortUnicastMacAddressSetPriv (IxEthAccPortId portId,
1285 IxEthAccMacAddr *macAddr)
1289 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1291 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1293 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot set Unicast Mac Address.\n",(INT32)portId,0,0,0,0,0);
1294 return IX_ETH_ACC_SUCCESS ;
1297 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1299 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1303 if (macAddr == NULL)
1305 return IX_ETH_ACC_FAIL;
1308 if ( macAddr->macAddress[0] & IX_ETH_ACC_ETH_MAC_BCAST_MCAST_BIT )
1310 /* This is a multicast/broadcast address cant set it ! */
1311 return IX_ETH_ACC_FAIL;
1314 if ( macAddr->macAddress[0] == 0 &&
1315 macAddr->macAddress[1] == 0 &&
1316 macAddr->macAddress[2] == 0 &&
1317 macAddr->macAddress[3] == 0 &&
1318 macAddr->macAddress[4] == 0 &&
1319 macAddr->macAddress[5] == 0 )
1321 /* This is an invalid mac address cant set it ! */
1322 return IX_ETH_ACC_FAIL;
1325 #ifdef CONFIG_IXP425_COMPONENT_ETHDB
1326 /* update the MAC address in the ethernet database */
1327 if (ixEthDBPortAddressSet(portId, (IxEthDBMacAddr *) macAddr) != IX_ETH_DB_SUCCESS)
1329 return IX_ETH_ACC_FAIL;
1333 /*Set the Unicast MAC to the specified value*/
1334 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1336 REG_WRITE(ixEthAccMacBase[portId],
1337 IX_ETH_ACC_MAC_UNI_ADDR_1 + i*sizeof(UINT32),
1338 macAddr->macAddress[i]);
1340 ixEthAccMacState[portId].initDone = true;
1342 return IX_ETH_ACC_SUCCESS;
1346 ixEthAccPortUnicastMacAddressGetPriv (IxEthAccPortId portId,
1347 IxEthAccMacAddr *macAddr)
1349 /*Return the current value of the Unicast MAC from h/w
1350 for the specified port*/
1353 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1355 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1357 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get Unicast Mac Address.\n",(INT32)portId,0,0,0,0,0);
1358 /* Since Eth Npe is unavailable, return invalid MAC Address = 00:00:00:00:00:00 */
1359 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1361 macAddr->macAddress[i] = 0;
1363 return IX_ETH_ACC_SUCCESS ;
1366 if(!ixEthAccMacState[portId].initDone)
1368 return (IX_ETH_ACC_MAC_UNINITIALIZED);
1371 if (macAddr == NULL)
1373 return IX_ETH_ACC_FAIL;
1377 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1379 REG_READ(ixEthAccMacBase[portId],
1380 IX_ETH_ACC_MAC_UNI_ADDR_1 + i*sizeof(UINT32),
1381 macAddr->macAddress[i]);
1383 return IX_ETH_ACC_SUCCESS;
1386 PRIVATE IxEthAccStatus
1387 ixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId,
1388 IxEthAccMacAddr *macAddr)
1390 /*Return the current value of the Multicast MAC from h/w
1391 for the specified port*/
1394 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1397 REG_READ(ixEthAccMacBase[portId],
1398 IX_ETH_ACC_MAC_ADDR_1 + i*sizeof(UINT32),
1399 macAddr->macAddress[i]);
1402 return IX_ETH_ACC_SUCCESS;
1405 PRIVATE IxEthAccStatus
1406 ixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId,
1407 IxEthAccMacAddr *macAddr)
1409 /*Return the current value of the Multicast MAC from h/w
1410 for the specified port*/
1413 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1416 REG_READ(ixEthAccMacBase[portId],
1417 IX_ETH_ACC_MAC_ADDR_MASK_1 + i*sizeof(UINT32),
1418 macAddr->macAddress[i]);
1420 return IX_ETH_ACC_SUCCESS;
1424 ixEthAccPortMulticastAddressJoinPriv (IxEthAccPortId portId,
1425 IxEthAccMacAddr *macAddr)
1428 IxEthAccMacAddr broadcastAddr = {{0xff,0xff,0xff,0xff,0xff,0xff}};
1430 /*Check that the port parameter is valid*/
1431 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1433 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1435 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot join Multicast Mac Address.\n",(INT32)portId,0,0,0,0,0);
1436 return IX_ETH_ACC_SUCCESS ;
1439 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1441 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1444 /*Check that the mac address is valid*/
1447 return IX_ETH_ACC_FAIL;
1450 /* Check that this is a multicast address */
1451 if (!(macAddr->macAddress[0] & IX_ETH_ACC_ETH_MAC_BCAST_MCAST_BIT))
1453 return IX_ETH_ACC_FAIL;
1456 /* We don't add the Broadcast address */
1457 if(ixEthAccMacEqual(&broadcastAddr, macAddr))
1459 return IX_ETH_ACC_FAIL;
1463 i<ixEthAccMacState[portId].mcastAddrIndex;
1466 /*Check if the current entry already match an existing matches*/
1467 if(ixEthAccMacEqual(&ixEthAccMacState[portId].mcastAddrsTable[i], macAddr))
1469 /* Address found in the list and already configured,
1470 * return a success status
1472 return IX_ETH_ACC_SUCCESS;
1476 /* check for availability at the end of the current table */
1477 if(ixEthAccMacState[portId].mcastAddrIndex >= IX_ETH_ACC_MAX_MULTICAST_ADDRESSES)
1479 return IX_ETH_ACC_FAIL;
1482 /*First add the address to the multicast table for the
1484 i=ixEthAccMacState[portId].mcastAddrIndex;
1486 memcpy(&ixEthAccMacState[portId].mcastAddrsTable[i],
1487 &macAddr->macAddress,
1488 IX_IEEE803_MAC_ADDRESS_SIZE);
1490 /*Increment the index into the table, this must be done here
1491 as MulticastAddressSet below needs to know about the latest
1494 ixEthAccMacState[portId].mcastAddrIndex++;
1496 /*Then calculate the new value to be written to the address and
1497 address mask registers*/
1498 ixEthAccMulticastAddressSet(portId);
1500 return IX_ETH_ACC_SUCCESS;
1505 ixEthAccPortMulticastAddressJoinAllPriv (IxEthAccPortId portId)
1507 IxEthAccMacAddr mcastMacAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}};
1509 /*Check that the port parameter is valid*/
1510 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1512 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1514 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot join all Multicast Address.\n",(INT32)portId,0,0,0,0,0);
1515 return IX_ETH_ACC_SUCCESS ;
1518 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1520 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1523 /* remove all entries from the database and
1524 * insert a multicast entry
1526 memcpy(&ixEthAccMacState[portId].mcastAddrsTable[0],
1527 &mcastMacAddr.macAddress,
1528 IX_IEEE803_MAC_ADDRESS_SIZE);
1530 ixEthAccMacState[portId].mcastAddrIndex = 1;
1531 ixEthAccMacState[portId].joinAll = true;
1533 ixEthAccMulticastAddressSet(portId);
1535 return IX_ETH_ACC_SUCCESS;
1539 ixEthAccPortMulticastAddressLeavePriv (IxEthAccPortId portId,
1540 IxEthAccMacAddr *macAddr)
1543 IxEthAccMacAddr mcastMacAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}};
1545 /*Check that the port parameter is valid*/
1546 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1548 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1550 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot leave Multicast Address.\n",(INT32)portId,0,0,0,0,0);
1551 return IX_ETH_ACC_SUCCESS ;
1554 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1556 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1559 /*Check that the mac address is valid*/
1562 return IX_ETH_ACC_FAIL;
1564 /* Remove this mac address from the mask for the specified port
1565 * we copy down all entries above the blanked entry, and
1566 * decrement the index
1570 while(i<ixEthAccMacState[portId].mcastAddrIndex)
1572 /*Check if the current entry matches*/
1573 if(ixEthAccMacEqual(&ixEthAccMacState[portId].mcastAddrsTable[i],
1576 if(ixEthAccMacEqual(macAddr, &mcastMacAddr))
1578 ixEthAccMacState[portId].joinAll = false;
1580 /*Decrement the index into the multicast address table
1581 for the current port*/
1582 ixEthAccMacState[portId].mcastAddrIndex--;
1584 /*Copy down all entries above the current entry*/
1585 while(i<ixEthAccMacState[portId].mcastAddrIndex)
1587 memcpy(&ixEthAccMacState[portId].mcastAddrsTable[i],
1588 &ixEthAccMacState[portId].mcastAddrsTable[i+1],
1589 IX_IEEE803_MAC_ADDRESS_SIZE);
1592 /*recalculate the mask and write it to the MAC*/
1593 ixEthAccMulticastAddressSet(portId);
1595 return IX_ETH_ACC_SUCCESS;
1597 /* search the next entry */
1600 /* no matching entry found */
1601 return IX_ETH_ACC_NO_SUCH_ADDR;
1605 ixEthAccPortMulticastAddressLeaveAllPriv (IxEthAccPortId portId)
1607 /*Check that the port parameter is valid*/
1608 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1610 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1612 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot leave all Multicast Address.\n",(INT32)portId,0,0,0,0,0);
1613 return IX_ETH_ACC_SUCCESS ;
1616 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1618 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1621 ixEthAccMacState[portId].mcastAddrIndex = 0;
1622 ixEthAccMacState[portId].joinAll = false;
1624 ixEthAccMulticastAddressSet(portId);
1626 return IX_ETH_ACC_SUCCESS;
1631 ixEthAccPortUnicastAddressShowPriv (IxEthAccPortId portId)
1633 IxEthAccMacAddr macAddr;
1635 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1637 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1639 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot show Unicast Address.\n",(INT32)portId,0,0,0,0,0);
1640 return IX_ETH_ACC_SUCCESS ;
1643 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1645 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1648 /*Get the MAC (UINICAST) address from hardware*/
1649 if(ixEthAccPortUnicastMacAddressGetPriv(portId, &macAddr) != IX_ETH_ACC_SUCCESS)
1651 IX_ETH_ACC_WARNING_LOG("EthAcc: MAC address uninitialised port %u\n",
1652 (INT32)portId,0,0,0,0,0);
1653 return IX_ETH_ACC_MAC_UNINITIALIZED;
1657 ixEthAccMacPrint(&macAddr);
1659 return IX_ETH_ACC_SUCCESS;
1665 ixEthAccPortMulticastAddressShowPriv(IxEthAccPortId portId)
1667 IxEthAccMacAddr macAddr;
1670 if(!IX_ETH_ACC_IS_PORT_VALID(portId))
1675 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1677 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot show Multicast Address.\n",(INT32)portId,0,0,0,0,0);
1681 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1686 printf("Multicast MAC: ");
1687 /*Get the MAC (MULTICAST) address from hardware*/
1688 ixEthAccPortMulticastMacAddressGet(portId, &macAddr);
1690 ixEthAccMacPrint(&macAddr);
1691 /*Get the MAC (MULTICAST) filter from hardware*/
1692 ixEthAccPortMulticastMacFilterGet(portId, &macAddr);
1695 ixEthAccMacPrint(&macAddr);
1697 printf("Constituent Addresses:\n");
1698 for(i=0;i<ixEthAccMacState[portId].mcastAddrIndex;i++)
1700 ixEthAccMacPrint(&ixEthAccMacState[portId].mcastAddrsTable[i]);
1706 /*Set the duplex mode*/
1708 ixEthAccPortDuplexModeSetPriv (IxEthAccPortId portId,
1709 IxEthAccDuplexMode mode)
1714 /*This is bit 1 of the transmit control reg, set to 1 for half
1715 duplex, 0 for full duplex*/
1716 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1718 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1720 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot set Duplex Mode.\n",(INT32)portId,0,0,0,0,0);
1721 return IX_ETH_ACC_SUCCESS ;
1724 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1726 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1729 REG_READ(ixEthAccMacBase[portId],
1730 IX_ETH_ACC_MAC_TX_CNTRL1,
1733 REG_READ(ixEthAccMacBase[portId],
1734 IX_ETH_ACC_MAC_RX_CNTRL1,
1737 if (mode == IX_ETH_ACC_FULL_DUPLEX)
1739 /*Clear half duplex bit in TX*/
1740 REG_WRITE(ixEthAccMacBase[portId],
1741 IX_ETH_ACC_MAC_TX_CNTRL1,
1742 txregval & ~IX_ETH_ACC_TX_CNTRL1_DUPLEX);
1744 /*We must set the pause enable in the receive logic when in
1746 REG_WRITE(ixEthAccMacBase[portId],
1747 IX_ETH_ACC_MAC_RX_CNTRL1,
1748 rxregval | IX_ETH_ACC_RX_CNTRL1_PAUSE_EN);
1749 ixEthAccMacState[portId].fullDuplex = true;
1752 else if (mode == IX_ETH_ACC_HALF_DUPLEX)
1754 /*Set half duplex bit in TX*/
1755 REG_WRITE(ixEthAccMacBase[portId],
1756 IX_ETH_ACC_MAC_TX_CNTRL1,
1757 txregval | IX_ETH_ACC_TX_CNTRL1_DUPLEX);
1759 /*We must clear pause enable in the receive logic when in
1761 REG_WRITE(ixEthAccMacBase[portId],
1762 IX_ETH_ACC_MAC_RX_CNTRL1,
1763 rxregval & ~IX_ETH_ACC_RX_CNTRL1_PAUSE_EN);
1765 ixEthAccMacState[portId].fullDuplex = false;
1769 return IX_ETH_ACC_FAIL;
1773 return IX_ETH_ACC_SUCCESS;
1780 ixEthAccPortDuplexModeGetPriv (IxEthAccPortId portId,
1781 IxEthAccDuplexMode *mode)
1783 /*Return the duplex mode for the specified port*/
1786 /*This is bit 1 of the transmit control reg, set to 1 for half
1787 duplex, 0 for full duplex*/
1788 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1790 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1792 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get Duplex Mode.\n",(INT32)portId,0,0,0,0,0);
1793 /* return hald duplex */
1794 *mode = IX_ETH_ACC_HALF_DUPLEX ;
1795 return IX_ETH_ACC_SUCCESS ;
1798 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1800 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1805 return (IX_ETH_ACC_FAIL);
1808 REG_READ(ixEthAccMacBase[portId],
1809 IX_ETH_ACC_MAC_TX_CNTRL1,
1812 if( regval & IX_ETH_ACC_TX_CNTRL1_DUPLEX)
1814 *mode = IX_ETH_ACC_HALF_DUPLEX;
1818 *mode = IX_ETH_ACC_FULL_DUPLEX;
1821 return IX_ETH_ACC_SUCCESS;
1827 ixEthAccPortTxFrameAppendPaddingEnablePriv (IxEthAccPortId portId)
1830 /*Enable FCS computation by the MAC and appending to the
1833 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1835 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1837 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable Tx Frame Append Padding.\n",(INT32)portId,0,0,0,0,0);
1838 return IX_ETH_ACC_SUCCESS ;
1841 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1843 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1846 REG_READ(ixEthAccMacBase[portId],
1847 IX_ETH_ACC_MAC_TX_CNTRL1,
1850 REG_WRITE(ixEthAccMacBase[portId],
1851 IX_ETH_ACC_MAC_TX_CNTRL1,
1853 IX_ETH_ACC_TX_CNTRL1_PAD_EN);
1855 ixEthAccMacState[portId].txPADAppend = true;
1856 return IX_ETH_ACC_SUCCESS;
1860 ixEthAccPortTxFrameAppendPaddingDisablePriv (IxEthAccPortId portId)
1864 /*disable FCS computation and appending*/
1865 /*Set bit 4 of Tx control register one to zero*/
1866 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1868 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1870 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disble Tx Frame Append Padding.\n",(INT32)portId,0,0,0,0,0);
1871 return IX_ETH_ACC_SUCCESS ;
1874 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1876 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1879 REG_READ(ixEthAccMacBase[portId],
1880 IX_ETH_ACC_MAC_TX_CNTRL1,
1883 REG_WRITE(ixEthAccMacBase[portId],
1884 IX_ETH_ACC_MAC_TX_CNTRL1,
1885 regval & ~IX_ETH_ACC_TX_CNTRL1_PAD_EN);
1887 ixEthAccMacState[portId].txPADAppend = false;
1888 return IX_ETH_ACC_SUCCESS;
1892 ixEthAccPortTxFrameAppendFCSEnablePriv (IxEthAccPortId portId)
1896 /*Enable FCS computation by the MAC and appending to the
1899 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1901 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1903 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable Tx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0);
1904 return IX_ETH_ACC_SUCCESS ;
1907 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1909 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1912 REG_READ(ixEthAccMacBase[portId],
1913 IX_ETH_ACC_MAC_TX_CNTRL1,
1916 REG_WRITE(ixEthAccMacBase[portId],
1917 IX_ETH_ACC_MAC_TX_CNTRL1,
1918 regval | IX_ETH_ACC_TX_CNTRL1_FCS_EN);
1920 ixEthAccMacState[portId].txFCSAppend = true;
1921 return IX_ETH_ACC_SUCCESS;
1925 ixEthAccPortTxFrameAppendFCSDisablePriv (IxEthAccPortId portId)
1929 /*disable FCS computation and appending*/
1930 /*Set bit 4 of Tx control register one to zero*/
1931 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1933 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1935 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disable Tx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0);
1936 return IX_ETH_ACC_SUCCESS ;
1939 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1941 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1944 REG_READ(ixEthAccMacBase[portId],
1945 IX_ETH_ACC_MAC_TX_CNTRL1,
1948 REG_WRITE(ixEthAccMacBase[portId],
1949 IX_ETH_ACC_MAC_TX_CNTRL1,
1950 regval & ~IX_ETH_ACC_TX_CNTRL1_FCS_EN);
1952 ixEthAccMacState[portId].txFCSAppend = false;
1953 return IX_ETH_ACC_SUCCESS;
1957 ixEthAccPortRxFrameAppendFCSEnablePriv (IxEthAccPortId portId)
1959 /*Set bit 2 of Rx control 1*/
1962 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1964 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1966 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable Rx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0);
1967 return IX_ETH_ACC_SUCCESS ;
1970 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1972 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1975 REG_READ(ixEthAccMacBase[portId],
1976 IX_ETH_ACC_MAC_RX_CNTRL1,
1979 REG_WRITE(ixEthAccMacBase[portId],
1980 IX_ETH_ACC_MAC_RX_CNTRL1,
1981 regval | IX_ETH_ACC_RX_CNTRL1_CRC_EN);
1983 ixEthAccMacState[portId].rxFCSAppend = true;
1984 return IX_ETH_ACC_SUCCESS;
1988 ixEthAccPortRxFrameAppendFCSDisablePriv (IxEthAccPortId portId)
1992 /*Clear bit 2 of Rx control 1*/
1993 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1995 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1997 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disable Rx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0);
1998 return IX_ETH_ACC_SUCCESS ;
2001 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
2003 return (IX_ETH_ACC_PORT_UNINITIALIZED);
2006 REG_READ(ixEthAccMacBase[portId],
2007 IX_ETH_ACC_MAC_RX_CNTRL1,
2010 REG_WRITE(ixEthAccMacBase[portId],
2011 IX_ETH_ACC_MAC_RX_CNTRL1,
2012 regval & ~IX_ETH_ACC_RX_CNTRL1_CRC_EN);
2014 ixEthAccMacState[portId].rxFCSAppend = false;
2015 return IX_ETH_ACC_SUCCESS;
2021 ixEthAccMacNpeStatsMessageCallback (IxNpeMhNpeId npeId,
2024 IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
2027 /* Prudent to at least check the port is within range */
2028 if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)
2030 IX_ETH_ACC_FATAL_LOG(
2031 "IXETHACC:ixEthAccMacNpeStatsMessageCallback: Illegal port: %u\n",
2032 (UINT32)portId, 0, 0, 0, 0, 0);
2037 /*Unblock Stats Get call*/
2038 ixOsalMutexUnlock(&ixEthAccMacState[portId].ackMIBStatsLock);
2043 ixEthAccMibIIStatsEndianConvert (IxEthEthObjStats *retStats)
2045 /* endianness conversion */
2048 retStats->dot3StatsAlignmentErrors =
2049 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsAlignmentErrors);
2050 retStats->dot3StatsFCSErrors =
2051 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsFCSErrors);
2052 retStats->dot3StatsInternalMacReceiveErrors =
2053 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsInternalMacReceiveErrors);
2054 retStats->RxOverrunDiscards =
2055 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxOverrunDiscards);
2056 retStats->RxLearnedEntryDiscards =
2057 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxLearnedEntryDiscards);
2058 retStats->RxLargeFramesDiscards =
2059 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxLargeFramesDiscards);
2060 retStats->RxSTPBlockedDiscards =
2061 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxSTPBlockedDiscards);
2062 retStats->RxVLANTypeFilterDiscards =
2063 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxVLANTypeFilterDiscards);
2064 retStats->RxVLANIdFilterDiscards =
2065 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxVLANIdFilterDiscards);
2066 retStats->RxInvalidSourceDiscards =
2067 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxInvalidSourceDiscards);
2068 retStats->RxBlackListDiscards =
2069 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxBlackListDiscards);
2070 retStats->RxWhiteListDiscards =
2071 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxWhiteListDiscards);
2072 retStats->RxUnderflowEntryDiscards =
2073 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxUnderflowEntryDiscards);
2076 retStats->dot3StatsSingleCollisionFrames =
2077 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsSingleCollisionFrames);
2078 retStats->dot3StatsMultipleCollisionFrames =
2079 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsMultipleCollisionFrames);
2080 retStats->dot3StatsDeferredTransmissions =
2081 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsDeferredTransmissions);
2082 retStats->dot3StatsLateCollisions =
2083 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsLateCollisions);
2084 retStats->dot3StatsExcessiveCollsions =
2085 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsExcessiveCollsions);
2086 retStats->dot3StatsInternalMacTransmitErrors =
2087 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsInternalMacTransmitErrors);
2088 retStats->dot3StatsCarrierSenseErrors =
2089 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsCarrierSenseErrors);
2090 retStats->TxLargeFrameDiscards =
2091 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->TxLargeFrameDiscards);
2092 retStats->TxVLANIdFilterDiscards =
2093 IX_OSAL_SWAP_BE_SHARED_LONG(retStats->TxVLANIdFilterDiscards);
2097 ixEthAccMibIIStatsGet (IxEthAccPortId portId,
2098 IxEthEthObjStats *retStats )
2100 IxNpeMhMessage message;
2102 if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
2104 printf("EthAcc: ixEthAccMibIIStatsGet (Mac) EthAcc service is not initialized\n");
2105 return (IX_ETH_ACC_FAIL);
2108 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2110 if (retStats == NULL)
2112 printf("EthAcc: ixEthAccMibIIStatsGet (Mac) NULL argument\n");
2113 return (IX_ETH_ACC_FAIL);
2116 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2118 printf("EthAcc: ixEthAccMibIIStatsGet (Mac) NPE for port %d is not available\n", portId);
2120 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get MIB II Stats.\n",(INT32)portId,0,0,0,0,0);
2122 /* Return all zero stats */
2123 IX_ETH_ACC_MEMSET(retStats, 0, sizeof(IxEthEthObjStats));
2125 return IX_ETH_ACC_SUCCESS ;
2128 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
2130 printf("EthAcc: ixEthAccMibIIStatsGet (Mac) port %d is not initialized\n", portId);
2131 return (IX_ETH_ACC_PORT_UNINITIALIZED);
2134 IX_OSAL_CACHE_INVALIDATE(retStats, sizeof(IxEthEthObjStats));
2136 message.data[0] = IX_ETHNPE_GETSTATS << IX_ETH_ACC_MAC_MSGID_SHL;
2137 message.data[1] = (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS(retStats);
2139 /* Permit only one task to request MIB statistics Get operation
2141 ixOsalMutexLock(&ixEthAccMacState[portId].MIBStatsGetAccessLock, IX_OSAL_WAIT_FOREVER);
2143 if(ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
2146 ixEthAccMacNpeStatsMessageCallback,
2147 IX_NPEMH_SEND_RETRIES_DEFAULT)
2150 ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetAccessLock);
2152 printf("EthAcc: (Mac) StatsGet failed to send NPE message\n");
2154 return IX_ETH_ACC_FAIL;
2157 /* Wait for callback invocation indicating response to
2158 this request - we need this mutex in order to ensure
2159 that the return from this function is synchronous */
2160 ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsLock, IX_ETH_ACC_MIB_STATS_DELAY_MSECS);
2162 /* Permit other tasks to perform MIB statistics Get operation */
2163 ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetAccessLock);
2165 ixEthAccMibIIStatsEndianConvert (retStats);
2167 return IX_ETH_ACC_SUCCESS;
2172 ixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId,
2175 IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
2178 /* Prudent to at least check the port is within range */
2179 if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)
2181 IX_ETH_ACC_FATAL_LOG(
2182 "IXETHACC:ixEthAccMacNpeStatsResetMessageCallback: Illegal port: %u\n",
2183 (UINT32)portId, 0, 0, 0, 0, 0);
2188 /*Unblock Stats Get & reset call*/
2189 ixOsalMutexUnlock(&ixEthAccMacState[portId].ackMIBStatsResetLock);
2196 ixEthAccMibIIStatsGetClear (IxEthAccPortId portId,
2197 IxEthEthObjStats *retStats)
2199 IxNpeMhMessage message;
2201 if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
2203 printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) EthAcc service is not initialized\n");
2204 return (IX_ETH_ACC_FAIL);
2207 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2209 if (retStats == NULL)
2211 printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) NULL argument\n");
2212 return (IX_ETH_ACC_FAIL);
2215 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2217 printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) NPE for port %d is not available\n", portId);
2219 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get and clear MIB II Stats.\n", (INT32)portId, 0, 0, 0, 0, 0);
2221 /* Return all zero stats */
2222 IX_ETH_ACC_MEMSET(retStats, 0, sizeof(IxEthEthObjStats));
2224 return IX_ETH_ACC_SUCCESS ;
2227 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
2229 printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) port %d is not initialized\n", portId);
2230 return (IX_ETH_ACC_PORT_UNINITIALIZED);
2233 IX_OSAL_CACHE_INVALIDATE(retStats, sizeof(IxEthEthObjStats));
2235 message.data[0] = IX_ETHNPE_RESETSTATS << IX_ETH_ACC_MAC_MSGID_SHL;
2236 message.data[1] = (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS(retStats);
2238 /* Permit only one task to request MIB statistics Get-Reset operation at a time */
2239 ixOsalMutexLock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock, IX_OSAL_WAIT_FOREVER);
2241 if(ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
2243 IX_ETHNPE_RESETSTATS,
2244 ixEthAccMacNpeStatsResetMessageCallback,
2245 IX_NPEMH_SEND_RETRIES_DEFAULT)
2248 ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock);
2250 printf("EthAcc: (Mac) ixEthAccMibIIStatsGetClear failed to send NPE message\n");
2252 return IX_ETH_ACC_FAIL;
2255 /* Wait for callback invocation indicating response to this request */
2256 ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsResetLock, IX_ETH_ACC_MIB_STATS_DELAY_MSECS);
2258 /* permit other tasks to get and reset MIB stats*/
2259 ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock);
2261 ixEthAccMibIIStatsEndianConvert(retStats);
2263 return IX_ETH_ACC_SUCCESS;
2267 ixEthAccMibIIStatsClear (IxEthAccPortId portId)
2269 static IxEthEthObjStats retStats;
2270 IxEthAccStatus status;
2272 if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
2274 return (IX_ETH_ACC_FAIL);
2277 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2279 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2281 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot clear MIB II Stats.\n",(INT32)portId,0,0,0,0,0);
2282 return IX_ETH_ACC_SUCCESS ;
2285 /* there is no reset operation without a corresponding Get */
2286 status = ixEthAccMibIIStatsGetClear(portId, &retStats);
2291 /* Initialize the ethernet MAC settings */
2293 ixEthAccMacInit(IxEthAccPortId portId)
2295 IX_OSAL_MBUF_POOL* portDisablePool;
2298 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2300 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2302 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot initialize Mac.\n",(INT32)portId,0,0,0,0,0);
2303 return IX_ETH_ACC_SUCCESS ;
2306 if(ixEthAccMacState[portId].macInitialised == false)
2308 ixEthAccMacState[portId].fullDuplex = true;
2309 ixEthAccMacState[portId].rxFCSAppend = true;
2310 ixEthAccMacState[portId].txFCSAppend = true;
2311 ixEthAccMacState[portId].txPADAppend = true;
2312 ixEthAccMacState[portId].enabled = false;
2313 ixEthAccMacState[portId].promiscuous = true;
2314 ixEthAccMacState[portId].joinAll = false;
2315 ixEthAccMacState[portId].initDone = false;
2316 ixEthAccMacState[portId].macInitialised = true;
2318 /* initialize MIB stats mutexes */
2319 ixOsalMutexInit(&ixEthAccMacState[portId].ackMIBStatsLock);
2320 ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsLock, IX_OSAL_WAIT_FOREVER);
2322 ixOsalMutexInit(&ixEthAccMacState[portId].ackMIBStatsResetLock);
2323 ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsResetLock, IX_OSAL_WAIT_FOREVER);
2325 ixOsalMutexInit(&ixEthAccMacState[portId].MIBStatsGetAccessLock);
2327 ixOsalMutexInit(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock);
2329 ixOsalMutexInit(&ixEthAccMacState[portId].npeLoopbackMessageLock);
2331 ixEthAccMacState[portId].portDisableRxMbufPtr = NULL;
2332 ixEthAccMacState[portId].portDisableTxMbufPtr = NULL;
2334 portDisablePool = IX_OSAL_MBUF_POOL_INIT(2,
2335 IX_ETHACC_RX_MBUF_MIN_SIZE,
2336 "portDisable Pool");
2338 IX_OSAL_ENSURE(portDisablePool != NULL, "Failed to initialize PortDisable pool");
2340 ixEthAccMacState[portId].portDisableRxMbufPtr = IX_OSAL_MBUF_POOL_GET(portDisablePool);
2341 ixEthAccMacState[portId].portDisableTxMbufPtr = IX_OSAL_MBUF_POOL_GET(portDisablePool);
2343 IX_OSAL_ENSURE(ixEthAccMacState[portId].portDisableRxMbufPtr != NULL,
2344 "Pool allocation failed");
2345 IX_OSAL_ENSURE(ixEthAccMacState[portId].portDisableTxMbufPtr != NULL,
2346 "Pool allocation failed");
2347 /* fill the payload of the Rx mbuf used in portDisable */
2348 IX_OSAL_MBUF_MLEN(ixEthAccMacState[portId].portDisableRxMbufPtr) = IX_ETHACC_RX_MBUF_MIN_SIZE;
2350 memset(IX_OSAL_MBUF_MDATA(ixEthAccMacState[portId].portDisableRxMbufPtr),
2352 IX_ETHACC_RX_MBUF_MIN_SIZE);
2354 /* fill the payload of the Tx mbuf used in portDisable (64 bytes) */
2355 IX_OSAL_MBUF_MLEN(ixEthAccMacState[portId].portDisableTxMbufPtr) = 64;
2356 IX_OSAL_MBUF_PKT_LEN(ixEthAccMacState[portId].portDisableTxMbufPtr) = 64;
2358 data = (UINT8 *) IX_OSAL_MBUF_MDATA(ixEthAccMacState[portId].portDisableTxMbufPtr);
2359 memset(data, 0xBB, 64);
2360 data[0] = 0x00; /* unicast destination MAC address */
2361 data[6] = 0x00; /* unicast source MAC address */
2362 data[12] = 0x08; /* typelength : IP frame */
2363 data[13] = 0x00; /* typelength : IP frame */
2365 IX_OSAL_CACHE_FLUSH(data, 64);
2368 IX_OSAL_ASSERT (ixEthAccMacBase[portId] != 0);
2370 REG_WRITE(ixEthAccMacBase[portId],
2371 IX_ETH_ACC_MAC_CORE_CNTRL,
2372 IX_ETH_ACC_CORE_RESET);
2374 ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY);
2376 REG_WRITE(ixEthAccMacBase[portId],
2377 IX_ETH_ACC_MAC_CORE_CNTRL,
2378 IX_ETH_ACC_CORE_MDC_EN);
2380 REG_WRITE(ixEthAccMacBase[portId],
2381 IX_ETH_ACC_MAC_INT_CLK_THRESH,
2382 IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
2384 ixEthAccMacStateUpdate(portId);
2386 return IX_ETH_ACC_SUCCESS;
2389 /* PRIVATE Functions*/
2392 ixEthAccMacStateUpdate(IxEthAccPortId portId)
2396 if ( ixEthAccMacState[portId].enabled == false )
2398 /* Just disable both the transmitter and reciver in the MAC. */
2399 REG_READ(ixEthAccMacBase[portId],
2400 IX_ETH_ACC_MAC_RX_CNTRL1,
2402 REG_WRITE(ixEthAccMacBase[portId],
2403 IX_ETH_ACC_MAC_RX_CNTRL1,
2404 regval & ~IX_ETH_ACC_RX_CNTRL1_RX_EN);
2406 REG_READ(ixEthAccMacBase[portId],
2407 IX_ETH_ACC_MAC_TX_CNTRL1,
2409 REG_WRITE(ixEthAccMacBase[portId],
2410 IX_ETH_ACC_MAC_TX_CNTRL1,
2411 regval & ~IX_ETH_ACC_TX_CNTRL1_TX_EN);
2414 if(ixEthAccMacState[portId].fullDuplex)
2416 ixEthAccPortDuplexModeSetPriv (portId, IX_ETH_ACC_FULL_DUPLEX);
2420 ixEthAccPortDuplexModeSetPriv (portId, IX_ETH_ACC_HALF_DUPLEX);
2423 if(ixEthAccMacState[portId].rxFCSAppend)
2425 ixEthAccPortRxFrameAppendFCSEnablePriv (portId);
2429 ixEthAccPortRxFrameAppendFCSDisablePriv (portId);
2432 if(ixEthAccMacState[portId].txFCSAppend)
2434 ixEthAccPortTxFrameAppendFCSEnablePriv (portId);
2438 ixEthAccPortTxFrameAppendFCSDisablePriv (portId);
2441 if(ixEthAccMacState[portId].txPADAppend)
2443 ixEthAccPortTxFrameAppendPaddingEnablePriv (portId);
2447 ixEthAccPortTxFrameAppendPaddingDisablePriv (portId);
2450 if(ixEthAccMacState[portId].promiscuous)
2452 ixEthAccPortPromiscuousModeSetPriv(portId);
2456 ixEthAccPortPromiscuousModeClearPriv(portId);
2459 if ( ixEthAccMacState[portId].enabled == true )
2461 /* Enable both the transmitter and reciver in the MAC. */
2462 REG_READ(ixEthAccMacBase[portId],
2463 IX_ETH_ACC_MAC_RX_CNTRL1,
2465 REG_WRITE(ixEthAccMacBase[portId],
2466 IX_ETH_ACC_MAC_RX_CNTRL1,
2467 regval | IX_ETH_ACC_RX_CNTRL1_RX_EN);
2469 REG_READ(ixEthAccMacBase[portId],
2470 IX_ETH_ACC_MAC_TX_CNTRL1,
2472 REG_WRITE(ixEthAccMacBase[portId],
2473 IX_ETH_ACC_MAC_TX_CNTRL1,
2474 regval | IX_ETH_ACC_TX_CNTRL1_TX_EN);
2480 ixEthAccMacEqual(IxEthAccMacAddr *macAddr1,
2481 IxEthAccMacAddr *macAddr2)
2484 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE; i++)
2486 if(macAddr1->macAddress[i] != macAddr2->macAddress[i])
2495 ixEthAccMacPrint(IxEthAccMacAddr *m)
2497 printf("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
2498 m->macAddress[0], m->macAddress[1],
2499 m->macAddress[2], m->macAddress[3],
2500 m->macAddress[4], m->macAddress[5]);
2503 /* Set the multicast address and address mask registers
2505 * A bit in the address mask register must be set if
2506 * all multicast addresses always have that bit set, or if
2507 * all multicast addresses always have that bit cleared.
2509 * A bit in the address register must be set if all multicast
2510 * addresses have that bit set, otherwise, it should be cleared
2514 ixEthAccMulticastAddressSet(IxEthAccPortId portId)
2518 IxEthAccMacAddr addressMask;
2519 IxEthAccMacAddr address;
2520 IxEthAccMacAddr alwaysClearBits;
2521 IxEthAccMacAddr alwaysSetBits;
2523 /* calculate alwaysClearBits and alwaysSetBits:
2524 * alwaysClearBits is calculated by ORing all
2525 * multicast addresses, those bits that are always
2526 * clear are clear in the result
2528 * alwaysSetBits is calculated by ANDing all
2529 * multicast addresses, those bits that are always set
2530 * are set in the result
2533 if (ixEthAccMacState[portId].promiscuous == true)
2535 /* Promiscuous Mode is set, and filtering
2536 * allow all packets, and enable the mcast and
2539 memset(&addressMask.macAddress,
2541 IX_IEEE803_MAC_ADDRESS_SIZE);
2542 memset(&address.macAddress,
2544 IX_IEEE803_MAC_ADDRESS_SIZE);
2548 if(ixEthAccMacState[portId].joinAll == true)
2550 /* Join all is set. The mask and address are
2551 * the multicast settings.
2553 IxEthAccMacAddr macAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}};
2555 memcpy(addressMask.macAddress,
2557 IX_IEEE803_MAC_ADDRESS_SIZE);
2558 memcpy(address.macAddress,
2560 IX_IEEE803_MAC_ADDRESS_SIZE);
2562 else if(ixEthAccMacState[portId].mcastAddrIndex == 0)
2564 /* No entry in the filtering database,
2565 * Promiscuous Mode is cleared, Broadcast filtering
2568 memset(addressMask.macAddress,
2569 IX_ETH_ACC_MAC_ALL_BITS_SET,
2570 IX_IEEE803_MAC_ADDRESS_SIZE);
2571 memset(address.macAddress,
2572 IX_ETH_ACC_MAC_ALL_BITS_SET,
2573 IX_IEEE803_MAC_ADDRESS_SIZE);
2577 /* build a mask and an address which mix all entreis
2578 * from the list of multicast addresses
2580 memset(alwaysClearBits.macAddress,
2582 IX_IEEE803_MAC_ADDRESS_SIZE);
2583 memset(alwaysSetBits.macAddress,
2584 IX_ETH_ACC_MAC_ALL_BITS_SET,
2585 IX_IEEE803_MAC_ADDRESS_SIZE);
2587 for(i=0;i<ixEthAccMacState[portId].mcastAddrIndex;i++)
2589 for(j=0;j<IX_IEEE803_MAC_ADDRESS_SIZE;j++)
2591 alwaysClearBits.macAddress[j] |=
2592 ixEthAccMacState[portId].mcastAddrsTable[i].macAddress[j];
2593 alwaysSetBits.macAddress[j] &=
2594 ixEthAccMacState[portId].mcastAddrsTable[i].macAddress[j];
2598 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
2600 addressMask.macAddress[i] = alwaysSetBits.macAddress[i]
2601 | ~alwaysClearBits.macAddress[i];
2602 address.macAddress[i] = alwaysSetBits.macAddress[i];
2607 /*write the new addr filtering to h/w*/
2608 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
2610 REG_WRITE(ixEthAccMacBase[portId],
2611 IX_ETH_ACC_MAC_ADDR_MASK_1+i*sizeof(UINT32),
2612 addressMask.macAddress[i]);
2613 REG_WRITE(ixEthAccMacBase[portId],
2614 IX_ETH_ACC_MAC_ADDR_1+i*sizeof(UINT32),
2615 address.macAddress[i]);