blob: d57e71678efe6e4e8b39c930063bf65ab3bf15fd [file] [log] [blame]
Wolfgang Denkba94a1b2006-05-30 15:56:48 +02001/**
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}