blob: 65113448d27b7a732a4dd0efde1d28d8b78a0fdc [file] [log] [blame]
Wolfgang Denk4646d2a2006-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
Wolfgang Denkc57eadc2013-07-28 22:12:47 +020021 * SPDX-License-Identifier: BSD-3-Clause
Wolfgang Denk4646d2a2006-05-30 15:56:48 +020022 * @par
23 * -- End of Copyright Notice --
24 */
25
26#include "IxOsal.h"
27#include "IxNpeMh.h"
28#ifdef CONFIG_IXP425_COMPONENT_ETHDB
29#include "IxEthDB.h"
30#endif
31#include "IxEthDBPortDefs.h"
32#include "IxEthNpe.h"
33#include "IxEthAcc.h"
34#include "IxEthAccDataPlane_p.h"
35#include "IxEthAcc_p.h"
36#include "IxEthAccMac_p.h"
37
38/* Maximum number of retries during ixEthAccPortDisable, which
39 * is approximately 10 seconds
40*/
41#define IX_ETH_ACC_MAX_RETRY 500
42
43/* Maximum number of retries during ixEthAccPortDisable when expecting
44 * timeout
45 */
46#define IX_ETH_ACC_MAX_RETRY_TIMEOUT 5
47
48#define IX_ETH_ACC_VALIDATE_PORT_ID(portId) \
49 do \
50 { \
51 if(!IX_ETH_ACC_IS_PORT_VALID(portId)) \
52 { \
53 return IX_ETH_ACC_INVALID_PORT; \
54 } \
55 } while(0)
56
57PUBLIC IxEthAccMacState ixEthAccMacState[IX_ETH_ACC_NUMBER_OF_PORTS];
58
59PRIVATE UINT32 ixEthAccMacBase[IX_ETH_ACC_NUMBER_OF_PORTS];
60
61/*Forward function declarations*/
62PRIVATE void
63ixEthAccPortDisableRx (IxEthAccPortId portId,
64 IX_OSAL_MBUF * mBufPtr,
65 BOOL useMultiBufferCallback);
66
67PRIVATE void
68ixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId,
69 IX_OSAL_MBUF * mBufPtr,
70 BOOL useMultiBufferCallback);
71
72PRIVATE void
73ixEthAccPortDisableTxDone (UINT32 cbTag,
74 IX_OSAL_MBUF *mbuf);
75
76PRIVATE void
77ixEthAccPortDisableTxDoneAndSubmit (UINT32 cbTag,
78 IX_OSAL_MBUF *mbuf);
79
80PRIVATE void
81ixEthAccPortDisableRxCallback (UINT32 cbTag,
82 IX_OSAL_MBUF * mBufPtr,
83 UINT32 learnedPortId);
84
85PRIVATE void
86ixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag,
87 IX_OSAL_MBUF **mBufPtr);
88
89PRIVATE IxEthAccStatus
90ixEthAccPortDisableTryTransmit(UINT32 portId);
91
92PRIVATE IxEthAccStatus
93ixEthAccPortDisableTryReplenish(UINT32 portId);
94
95PRIVATE IxEthAccStatus
96ixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId,
97 IxEthAccMacAddr *macAddr);
98
99PRIVATE IxEthAccStatus
100ixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId,
101 IxEthAccMacAddr *macAddr);
102
103PRIVATE void
104ixEthAccMacNpeStatsMessageCallback (IxNpeMhNpeId npeId,
105 IxNpeMhMessage msg);
106
107PRIVATE void
108ixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId,
109 IxNpeMhMessage msg);
110
111PRIVATE void
112ixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId,
113 IxNpeMhMessage msg);
114
115PRIVATE void
116ixEthAccMulticastAddressSet(IxEthAccPortId portId);
117
118PRIVATE BOOL
119ixEthAccMacEqual(IxEthAccMacAddr *macAddr1,
120 IxEthAccMacAddr *macAddr2);
121
122PRIVATE void
123ixEthAccMacPrint(IxEthAccMacAddr *m);
124
125PRIVATE void
126ixEthAccMacStateUpdate(IxEthAccPortId portId);
127
128IxEthAccStatus
129ixEthAccMacMemInit(void)
130{
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);
137#ifdef __ixp46X
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)
142 {
143 ixOsalLog(IX_OSAL_LOG_LVL_FATAL,
144 IX_OSAL_LOG_DEV_STDOUT,
145 "EthAcc: Could not map MAC I/O memory\n",
146 0, 0, 0, 0, 0 ,0);
147
148 return IX_ETH_ACC_FAIL;
149 }
150#endif
151
152 if (ixEthAccMacBase[IX_ETH_PORT_1] == 0
153 || ixEthAccMacBase[IX_ETH_PORT_2] == 0)
154 {
155 ixOsalLog(IX_OSAL_LOG_LVL_FATAL,
156 IX_OSAL_LOG_DEV_STDOUT,
157 "EthAcc: Could not map MAC I/O memory\n",
158 0, 0, 0, 0, 0 ,0);
159
160 return IX_ETH_ACC_FAIL;
161 }
162
163 return IX_ETH_ACC_SUCCESS;
164}
165
166void
167ixEthAccMacUnload(void)
168{
169 IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_1]);
170 IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_2]);
171#ifdef __ixp46X
172 IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_3]);
173 ixEthAccMacBase[IX_ETH_PORT_3] = 0;
174#endif
175 ixEthAccMacBase[IX_ETH_PORT_2] = 0;
176 ixEthAccMacBase[IX_ETH_PORT_1] = 0;
177}
178
179IxEthAccStatus
180ixEthAccPortEnablePriv(IxEthAccPortId portId)
181{
182 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
183
184 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
185 {
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 ;
188 }
189
190 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
191 {
192 printf("EthAcc: (Mac) cannot enable port %d, port not initialized\n", portId);
193 return (IX_ETH_ACC_PORT_UNINITIALIZED);
194 }
195
196 if (ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn == NULL)
197 {
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);
201 }
202
203 if ((ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn == NULL)
204 && (ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn == NULL))
205 {
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);
209 }
210
211 if(!ixEthAccMacState[portId].initDone)
212 {
213 printf("EthAcc: (Mac) cannot enable port %d, MAC address not set\n", portId);
214 return (IX_ETH_ACC_MAC_UNINITIALIZED);
215 }
216
217 /* if the state is being set to what it is already at, do nothing*/
218 if (ixEthAccMacState[portId].enabled)
219 {
220 return IX_ETH_ACC_SUCCESS;
221 }
222
223#ifdef CONFIG_IXP425_COMPONENT_ETHDB
224 /* enable ethernet database for this port */
225 if (ixEthDBPortEnable(portId) != IX_ETH_DB_SUCCESS)
226 {
227 printf("EthAcc: (Mac) cannot enable port %d, EthDB failure\n", portId);
228 return IX_ETH_ACC_FAIL;
229 }
230#endif
231
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);
236
237 REG_WRITE(ixEthAccMacBase[portId],
238 IX_ETH_ACC_MAC_RANDOM_SEED,
239 IX_ETH_ACC_RANDOM_SEED_DEFAULT);
240
241 REG_WRITE(ixEthAccMacBase[portId],
242 IX_ETH_ACC_MAC_THRESH_P_EMPTY,
243 IX_ETH_ACC_MAC_THRESH_P_EMPTY_DEFAULT);
244
245 REG_WRITE(ixEthAccMacBase[portId],
246 IX_ETH_ACC_MAC_THRESH_P_FULL,
247 IX_ETH_ACC_MAC_THRESH_P_FULL_DEFAULT);
248
249 REG_WRITE(ixEthAccMacBase[portId],
250 IX_ETH_ACC_MAC_TX_DEFER,
251 IX_ETH_ACC_MAC_TX_DEFER_DEFAULT);
252
253 REG_WRITE(ixEthAccMacBase[portId],
254 IX_ETH_ACC_MAC_TX_TWO_DEFER_1,
255 IX_ETH_ACC_MAC_TX_TWO_DEFER_1_DEFAULT);
256
257 REG_WRITE(ixEthAccMacBase[portId],
258 IX_ETH_ACC_MAC_TX_TWO_DEFER_2,
259 IX_ETH_ACC_MAC_TX_TWO_DEFER_2_DEFAULT);
260
261 REG_WRITE(ixEthAccMacBase[portId],
262 IX_ETH_ACC_MAC_SLOT_TIME,
263 IX_ETH_ACC_MAC_SLOT_TIME_DEFAULT);
264
265 REG_WRITE(ixEthAccMacBase[portId],
266 IX_ETH_ACC_MAC_INT_CLK_THRESH,
267 IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
268
269 REG_WRITE(ixEthAccMacBase[portId],
270 IX_ETH_ACC_MAC_BUF_SIZE_TX,
271 IX_ETH_ACC_MAC_BUF_SIZE_TX_DEFAULT);
272
273 REG_WRITE(ixEthAccMacBase[portId],
274 IX_ETH_ACC_MAC_TX_CNTRL1,
275 IX_ETH_ACC_TX_CNTRL1_DEFAULT);
276
277 REG_WRITE(ixEthAccMacBase[portId],
278 IX_ETH_ACC_MAC_RX_CNTRL1,
279 IX_ETH_ACC_RX_CNTRL1_DEFAULT);
280
281 /* set the global state */
282 ixEthAccMacState[portId].portDisableState = ACTIVE;
York Sun4a598092013-04-01 11:29:11 -0700283 ixEthAccMacState[portId].enabled = true;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200284
285 /* rewrite the setup (including mac filtering) depending
286 * on current options
287 */
288 ixEthAccMacStateUpdate(portId);
289
290 return IX_ETH_ACC_SUCCESS;
291}
292
293/*
294 * PortDisable local variables. They contain the intermediate steps
295 * while the port is being disabled and the buffers being drained out
296 * of the NPE.
297 */
298typedef void (*IxEthAccPortDisableRx)(IxEthAccPortId portId,
299 IX_OSAL_MBUF * mBufPtr,
300 BOOL useMultiBufferCallback);
301static IxEthAccPortRxCallback
302ixEthAccPortDisableFn[IX_ETH_ACC_NUMBER_OF_PORTS];
303static IxEthAccPortMultiBufferRxCallback
304ixEthAccPortDisableMultiBufferFn[IX_ETH_ACC_NUMBER_OF_PORTS];
305static IxEthAccPortDisableRx
306ixEthAccPortDisableRxTable[IX_ETH_ACC_NUMBER_OF_PORTS];
307static UINT32
308ixEthAccPortDisableCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
309static UINT32
310ixEthAccPortDisableMultiBufferCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
311
312static IxEthAccPortTxDoneCallback
313ixEthAccPortDisableTxDoneFn[IX_ETH_ACC_NUMBER_OF_PORTS];
314static UINT32
315ixEthAccPortDisableTxDoneCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];
316
317static UINT32
318ixEthAccPortDisableUserBufferCount[IX_ETH_ACC_NUMBER_OF_PORTS];
319
320/*
321 * PortDisable private callbacks functions. They handle the user
322 * traffic, and the special buffers (one for tx, one for rx) used
323 * in portDisable.
324 */
325PRIVATE void
326ixEthAccPortDisableTxDone(UINT32 cbTag,
327 IX_OSAL_MBUF *mbuf)
328{
329 IxEthAccPortId portId = (IxEthAccPortId)cbTag;
330 volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState;
331
332 /* check for the special mbuf used in portDisable */
333 if (mbuf == ixEthAccMacState[portId].portDisableTxMbufPtr)
334 {
335 *txState = TRANSMIT_DONE;
336 }
337 else
338 {
339 /* increment the count of user traffic during portDisable */
340 ixEthAccPortDisableUserBufferCount[portId]++;
341
342 /* call client TxDone function */
343 ixEthAccPortDisableTxDoneFn[portId](ixEthAccPortDisableTxDoneCbTag[portId], mbuf);
344 }
345}
346
347PRIVATE IxEthAccStatus
348ixEthAccPortDisableTryTransmit(UINT32 portId)
349{
350 int key;
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
357 * maximum rate.
358 */
359 key = ixOsalIrqLock();
360 if (*txState == TRANSMIT_DONE)
361 {
362 IX_OSAL_MBUF *mbufTxPtr = ixEthAccMacState[portId].portDisableTxMbufPtr;
363 *txState = TRANSMIT;
364 status = ixEthAccPortTxFrameSubmit(portId,
365 mbufTxPtr,
366 IX_ETH_ACC_TX_DEFAULT_PRIORITY);
367 }
368 ixOsalIrqUnlock(key);
369
370 return status;
371}
372
373PRIVATE void
374ixEthAccPortDisableTxDoneAndSubmit(UINT32 cbTag,
375 IX_OSAL_MBUF *mbuf)
376{
377 IxEthAccPortId portId = (IxEthAccPortId)cbTag;
378
379 /* call the callback which forwards the traffic to the client */
380 ixEthAccPortDisableTxDone(cbTag, mbuf);
381
382 /* try to transmit the buffer used in portDisable
383 * if seen in TxDone
384 */
385 ixEthAccPortDisableTryTransmit(portId);
386}
387
388PRIVATE void
389ixEthAccPortDisableRx (IxEthAccPortId portId,
390 IX_OSAL_MBUF * mBufPtr,
391 BOOL useMultiBufferCallback)
392{
393 volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState;
394 IX_OSAL_MBUF *mNextPtr;
395
396 while (mBufPtr)
397 {
398 mNextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr);
399 IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr) = NULL;
400
401 /* check for the special mbuf used in portDisable */
402 if (mBufPtr == ixEthAccMacState[portId].portDisableRxMbufPtr)
403 {
404 *rxState = RECEIVE;
405 }
406 else
407 {
408 /* increment the count of user traffic during portDisable */
409 ixEthAccPortDisableUserBufferCount[portId]++;
410
411 /* reset the received payload length during portDisable */
412 IX_OSAL_MBUF_MLEN(mBufPtr) = 0;
413 IX_OSAL_MBUF_PKT_LEN(mBufPtr) = 0;
414
415 if (useMultiBufferCallback)
416 {
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.
421 */
422 IX_OSAL_MBUF *mBufPtrArray[2];
423
424 mBufPtrArray[0] = mBufPtr;
425 mBufPtrArray[1] = NULL;
426 ixEthAccPortDisableMultiBufferFn[portId](
427 ixEthAccPortDisableMultiBufferCbTag[portId],
428 mBufPtrArray);
429 }
430 else
431 {
432 /* call the user callback with a unchained
433 * buffer, without payload and the destination port is
434 * unknown.
435 */
436 ixEthAccPortDisableFn[portId](
437 ixEthAccPortDisableCbTag[portId],
438 mBufPtr,
439 IX_ETH_DB_UNKNOWN_PORT /* port not found */);
440 }
441 }
442
443 mBufPtr = mNextPtr;
444 }
445}
446
447PRIVATE IxEthAccStatus
448ixEthAccPortDisableTryReplenish(UINT32 portId)
449{
450 int key;
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
457 * maximum rate.
458 */
459 key = ixOsalIrqLock();
460 if (*rxState == RECEIVE)
461 {
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);
466 }
467 ixOsalIrqUnlock(key);
468
469 return status;
470}
471
472PRIVATE void
473ixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId,
474 IX_OSAL_MBUF * mBufPtr,
475 BOOL useMultiBufferCallback)
476{
477 /* call the callback which forwards the traffic to the client */
478 ixEthAccPortDisableRx(portId, mBufPtr, useMultiBufferCallback);
479
480 /* try to replenish with the buffer used in portDisable
481 * if seen in Rx
482 */
483 ixEthAccPortDisableTryReplenish(portId);
484}
485
486PRIVATE void
487ixEthAccPortDisableRxCallback (UINT32 cbTag,
488 IX_OSAL_MBUF * mBufPtr,
489 UINT32 learnedPortId)
490{
491 IxEthAccPortId portId = (IxEthAccPortId)cbTag;
492
493 /* call the portDisable receive callback */
York Sun4a598092013-04-01 11:29:11 -0700494 (ixEthAccPortDisableRxTable[portId])(portId, mBufPtr, false);
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200495}
496
497PRIVATE void
498ixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag,
499 IX_OSAL_MBUF **mBufPtr)
500{
501 IxEthAccPortId portId = (IxEthAccPortId)cbTag;
502
503 while (*mBufPtr)
504 {
505 /* call the portDisable receive callback with one buffer at a time */
York Sun4a598092013-04-01 11:29:11 -0700506 (ixEthAccPortDisableRxTable[portId])(portId, *mBufPtr++, true);
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200507 }
508}
509
510IxEthAccStatus
511ixEthAccPortDisablePriv(IxEthAccPortId portId)
512{
513 IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
514 int key;
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;
519
520 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
521
522 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
523 {
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 ;
526 }
527
528 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
529 {
530 return (IX_ETH_ACC_PORT_UNINITIALIZED);
531 }
532
533 /* if the state is being set to what it is already at, do nothing */
534 if (!ixEthAccMacState[portId].enabled)
535 {
536 return IX_ETH_ACC_SUCCESS;
537 }
538
539 *state = DISABLED;
540
541 /* disable MAC receive first */
542 ixEthAccPortRxDisablePriv(portId);
543
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
547 */
548 if (ixEthDBPortDisable(portId) != IX_ETH_DB_SUCCESS)
549 {
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);
552 }
553#endif
554
555 /* enter the critical section */
556 key = ixOsalIrqLock();
557
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;
566
567 /* register temporary callbacks */
568 ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn = ixEthAccPortDisableRxCallback;
569 ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag = portId;
570
571 ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = ixEthAccPortDisableMultiBufferRxCallback;
572 ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = portId;
573
574 ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn = ixEthAccPortDisableTxDone;
575 ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag = portId;
576
577 /* initialise the Rx state and Tx states */
578 *txState = TRANSMIT_DONE;
579 *rxState = RECEIVE;
580
581 /* exit the critical section */
582 ixOsalIrqUnlock(key);
583
584 /* enable a NPE loopback */
585 if (ixEthAccNpeLoopbackEnablePriv(portId) != IX_ETH_ACC_SUCCESS)
586 {
587 status = IX_ETH_ACC_FAIL;
588 }
589
590 if (status == IX_ETH_ACC_SUCCESS)
591 {
592 retry = 0;
593
594 /* Step 1 : Drain Tx traffic and TxDone queues :
595 *
596 * Transmit and replenish at least once with the
597 * special buffers until both of them are seen
598 * in the callback hook
599 *
600 * (the receive callback keeps replenishing, so once we see
601 * the special Tx buffer, we can be sure that Tx drain is complete)
602 */
603 ixEthAccPortDisableRxTable[portId]
604 = ixEthAccPortDisableRxAndReplenish;
605 ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn
606 = ixEthAccPortDisableTxDone;
607
608 do
609 {
610 /* keep replenishing */
611 status = ixEthAccPortDisableTryReplenish(portId);
612 if (status == IX_ETH_ACC_SUCCESS)
613 {
614 /* keep transmitting */
615 status = ixEthAccPortDisableTryTransmit(portId);
616 }
617 if (status == IX_ETH_ACC_SUCCESS)
618 {
619 /* wait for some traffic being processed */
620 ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
621 }
622 }
623 while ((status == IX_ETH_ACC_SUCCESS)
624 && (retry++ < IX_ETH_ACC_MAX_RETRY)
625 && (*txState == TRANSMIT));
626
627 /* Step 2 : Drain Rx traffic, RxFree and Rx queues :
628 *
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
634 * is complete)
635 *
636 * The nested loop helps to retry if the user was keeping
637 * replenishing or transmitting during portDisable.
638 *
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.
646 */
647 ixEthAccPortDisableRxTable[portId]
648 = ixEthAccPortDisableRx;
649 ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn
650 = ixEthAccPortDisableTxDoneAndSubmit;
651
652 do
653 {
654 do
655 {
656 ixEthAccPortDisableUserBufferCount[portId] = 0;
657
658 /* keep replenishing */
659 status = ixEthAccPortDisableTryReplenish(portId);
660 if (status == IX_ETH_ACC_SUCCESS)
661 {
662 /* keep transmitting */
663 status = ixEthAccPortDisableTryTransmit(portId);
664 }
665 if (status == IX_ETH_ACC_SUCCESS)
666 {
667 /* wait for some traffic being processed */
668 ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
669 }
670 }
671 while ((status == IX_ETH_ACC_SUCCESS)
672 && (retry++ < IX_ETH_ACC_MAX_RETRY)
673 && ((ixEthAccPortDisableUserBufferCount[portId] != 0)
674 || (*rxState == REPLENISH)));
675
676 /* After the first iteration, change the receive callbacks,
677 * to process only 1 buffer at a time
678 */
679 ixEthAccPortDisableRxTable[portId]
680 = ixEthAccPortDisableRx;
681 ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn
682 = ixEthAccPortDisableTxDone;
683
684 /* repeat the whole process while user traffic is seen in TxDone
685 *
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
692 */
693 }
694 while ((status == IX_ETH_ACC_SUCCESS)
695 && (retry < IX_ETH_ACC_MAX_RETRY)
696 && (*txState == TRANSMIT));
697
698 /* check the loop exit conditions. The NPE should not hold
699 * the special buffers.
700 */
701 if ((*rxState == REPLENISH) || (*txState == TRANSMIT))
702 {
703 status = IX_ETH_ACC_FAIL;
704 }
705
706 if (status == IX_ETH_ACC_SUCCESS)
707 {
708 /* Step 3 : Replenish without transmitting until a timeout
709 * occurs, in order to drain the internal NPE fifos
710 *
711 * we can expect a few frames srill held
712 * in the NPE.
713 *
714 * The 2 nested loops take care about the NPE dropping traffic
715 * (including loopback traffic) when the Rx queue is full.
716 *
717 * The timeout value is very conservative
718 * since the loopback used keeps replenishhing.
719 *
720 */
721 do
722 {
723 ixEthAccPortDisableRxTable[portId] = ixEthAccPortDisableRxAndReplenish;
724 ixEthAccPortDisableUserBufferCount[portId] = 0;
725 retryTimeout = 0;
726 do
727 {
728 /* keep replenishing */
729 status = ixEthAccPortDisableTryReplenish(portId);
730 if (status == IX_ETH_ACC_SUCCESS)
731 {
732 /* wait for some traffic being processed */
733 ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
734 }
735 }
736 while ((status == IX_ETH_ACC_SUCCESS)
737 && (retryTimeout++ < IX_ETH_ACC_MAX_RETRY_TIMEOUT));
738
739 /* Step 4 : Transmit once. Stop replenish
740 *
741 * After the Rx timeout, we are sure that the NPE does not
742 * hold any frame in its internal NPE fifos.
743 *
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.
748 *
749 */
750 ixEthAccPortDisableRxTable[portId] = ixEthAccPortDisableRx;
751 status = ixEthAccPortDisableTryTransmit(portId);
752
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)
756 */
757 if (status == IX_ETH_ACC_SUCCESS)
758 {
759 retryTimeout = 0;
760 do
761 {
762 ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);
763 }
764 while ((*rxState == REPLENISH)
765 && (retryTimeout++ < IX_ETH_ACC_MAX_RETRY_TIMEOUT));
766 }
767
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.
771 */
772 }
773 while ((status == IX_ETH_ACC_SUCCESS)
774 && (retry++ < IX_ETH_ACC_MAX_RETRY)
775 && ((*txState == TRANSMIT)
776 || (*rxState == REPLENISH)
777 || (ixEthAccPortDisableUserBufferCount[portId] != 0)));
778
779 /* Step 5 : check the final states : the NPE has
780 * no buffer left, nor in Tx , nor in Rx directions.
781 */
782 if ((*rxState == REPLENISH) || (*txState == TRANSMIT))
783 {
784 status = IX_ETH_ACC_FAIL;
785 }
786 }
787
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.
791 */
792 if (ixEthAccNpeLoopbackDisablePriv(portId) != IX_ETH_ACC_SUCCESS)
793 {
794 status = IX_ETH_ACC_FAIL;
795 }
796 }
797
798 /* disable MAC Tx and Rx services */
York Sun4a598092013-04-01 11:29:11 -0700799 ixEthAccMacState[portId].enabled = false;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200800 ixEthAccMacStateUpdate(portId);
801
802 /* restore the Rx and TxDone callbacks (within a critical section) */
803 key = ixOsalIrqLock();
804
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];
811
812 ixOsalIrqUnlock(key);
813
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.
817 */
818 REG_WRITE(ixEthAccMacBase[portId],
819 IX_ETH_ACC_MAC_CORE_CNTRL,
820 IX_ETH_ACC_CORE_RESET);
821
822 ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY);
823
824 /* rewrite all parameters to their current value */
825 ixEthAccMacStateUpdate(portId);
826
827 REG_WRITE(ixEthAccMacBase[portId],
828 IX_ETH_ACC_MAC_INT_CLK_THRESH,
829 IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
830
831 REG_WRITE(ixEthAccMacBase[portId],
832 IX_ETH_ACC_MAC_CORE_CNTRL,
833 IX_ETH_ACC_CORE_MDC_EN);
834
835 return status;
836}
837
838IxEthAccStatus
839ixEthAccPortEnabledQueryPriv(IxEthAccPortId portId, BOOL *enabled)
840{
841 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
842
843 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
844 {
845 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable port.\n",(INT32)portId,0,0,0,0,0);
846
847 /* Since Eth NPE is not available, port must be disabled */
York Sun4a598092013-04-01 11:29:11 -0700848 *enabled = false ;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200849 return IX_ETH_ACC_SUCCESS ;
850 }
851
852 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
853 {
854 /* Since Eth NPE is not available, port must be disabled */
York Sun4a598092013-04-01 11:29:11 -0700855 *enabled = false ;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200856 return (IX_ETH_ACC_PORT_UNINITIALIZED);
857 }
858
859 *enabled = ixEthAccMacState[portId].enabled;
860
861 return IX_ETH_ACC_SUCCESS;
862}
863
864IxEthAccStatus
865ixEthAccPortMacResetPriv(IxEthAccPortId portId)
866{
867 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
868
869 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
870 {
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 ;
873 }
874
875 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
876 {
877 return (IX_ETH_ACC_PORT_UNINITIALIZED);
878 }
879
880 REG_WRITE(ixEthAccMacBase[portId],
881 IX_ETH_ACC_MAC_CORE_CNTRL,
882 IX_ETH_ACC_CORE_RESET);
883
884 ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY);
885
886 /* rewrite all parameters to their current value */
887 ixEthAccMacStateUpdate(portId);
888
889 REG_WRITE(ixEthAccMacBase[portId],
890 IX_ETH_ACC_MAC_INT_CLK_THRESH,
891 IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
892
893 REG_WRITE(ixEthAccMacBase[portId],
894 IX_ETH_ACC_MAC_CORE_CNTRL,
895 IX_ETH_ACC_CORE_MDC_EN);
896
897 return IX_ETH_ACC_SUCCESS;
898}
899
900IxEthAccStatus
901ixEthAccPortLoopbackEnable(IxEthAccPortId portId)
902{
903 UINT32 regval;
904
905 /* Turn off promiscuous mode */
906 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
907
908 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
909 {
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 ;
912 }
913
914 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
915 {
916 return (IX_ETH_ACC_PORT_UNINITIALIZED);
917 }
918
919 /* read register */
920 REG_READ(ixEthAccMacBase[portId],
921 IX_ETH_ACC_MAC_RX_CNTRL1,
922 regval);
923
924 /* update register */
925 REG_WRITE(ixEthAccMacBase[portId],
926 IX_ETH_ACC_MAC_RX_CNTRL1,
927 regval | IX_ETH_ACC_RX_CNTRL1_LOOP_EN);
928
929 return IX_ETH_ACC_SUCCESS;
930}
931
932PRIVATE void
933ixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId,
934 IxNpeMhMessage msg)
935{
936 IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
937
938#ifndef NDEBUG
939 /* Prudent to at least check the port is within range */
940 if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)
941 {
942 IX_ETH_ACC_FATAL_LOG("IXETHACC:ixEthAccPortDisableMessageCallback: Illegal port: %u\n",
943 (UINT32) portId, 0, 0, 0, 0, 0);
944
945 return;
946 }
947#endif
948
949 /* unlock message reception mutex */
950 ixOsalMutexUnlock(&ixEthAccMacState[portId].npeLoopbackMessageLock);
951}
952
953IxEthAccStatus
954ixEthAccNpeLoopbackEnablePriv(IxEthAccPortId portId)
955{
956 IX_STATUS npeMhStatus;
957 IxNpeMhMessage message;
958 IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
959
960 /* Turn off promiscuous mode */
961 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
962
963 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
964 {
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 ;
967 }
968
969 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
970 {
971 return (IX_ETH_ACC_PORT_UNINITIALIZED);
972 }
973
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)
976 | 0x01;
977 message.data[1] = 0;
978
979 npeMhStatus = ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
980 message,
981 IX_ETHNPE_SETLOOPBACK_MODE_ACK,
982 ixEthAccNpeLoopbackMessageCallback,
983 IX_NPEMH_SEND_RETRIES_DEFAULT);
984
985 if (npeMhStatus != IX_SUCCESS)
986 {
987 status = IX_ETH_ACC_FAIL;
988 }
989 else
990 {
991 /* wait for NPE loopbackEnable response */
992 if (ixOsalMutexLock(&ixEthAccMacState[portId]. npeLoopbackMessageLock,
993 IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS)
994 != IX_SUCCESS)
995 {
996 status = IX_ETH_ACC_FAIL;
997 }
998 }
999
1000 return status;
1001}
1002
1003IxEthAccStatus
1004ixEthAccPortTxEnablePriv(IxEthAccPortId portId)
1005{
1006 UINT32 regval;
1007
1008 /* Turn off promiscuous mode */
1009 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1010
1011 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1012 {
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 ;
1015 }
1016
1017 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1018 {
1019 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1020 }
1021
1022 /* read register */
1023 REG_READ(ixEthAccMacBase[portId],
1024 IX_ETH_ACC_MAC_TX_CNTRL1,
1025 regval);
1026
1027 /* update register */
1028 REG_WRITE(ixEthAccMacBase[portId],
1029 IX_ETH_ACC_MAC_TX_CNTRL1,
1030 regval | IX_ETH_ACC_TX_CNTRL1_TX_EN);
1031
1032 return IX_ETH_ACC_SUCCESS;
1033}
1034
1035IxEthAccStatus
1036ixEthAccPortRxEnablePriv(IxEthAccPortId portId)
1037{
1038 UINT32 regval;
1039
1040 /* Turn off promiscuous mode */
1041 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1042
1043 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1044 {
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 ;
1047 }
1048
1049 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1050 {
1051 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1052 }
1053
1054 /* read register */
1055 REG_READ(ixEthAccMacBase[portId],
1056 IX_ETH_ACC_MAC_RX_CNTRL1,
1057 regval);
1058
1059 /* update register */
1060 REG_WRITE(ixEthAccMacBase[portId],
1061 IX_ETH_ACC_MAC_RX_CNTRL1,
1062 regval | IX_ETH_ACC_RX_CNTRL1_RX_EN);
1063
1064 return IX_ETH_ACC_SUCCESS;
1065}
1066
1067IxEthAccStatus
1068ixEthAccPortLoopbackDisable(IxEthAccPortId portId)
1069{
1070 UINT32 regval;
1071
1072 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1073
1074 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1075 {
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 ;
1078 }
1079
1080 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1081 {
1082 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1083 }
1084
1085 /*disable MAC loopabck */
1086 REG_READ(ixEthAccMacBase[portId],
1087 IX_ETH_ACC_MAC_RX_CNTRL1,
1088 regval);
1089
1090 REG_WRITE(ixEthAccMacBase[portId],
1091 IX_ETH_ACC_MAC_RX_CNTRL1,
1092 (regval & ~IX_ETH_ACC_RX_CNTRL1_LOOP_EN));
1093
1094 return IX_ETH_ACC_SUCCESS;
1095}
1096
1097IxEthAccStatus
1098ixEthAccNpeLoopbackDisablePriv(IxEthAccPortId portId)
1099{
1100 IX_STATUS npeMhStatus;
1101 IxNpeMhMessage message;
1102 IxEthAccStatus status = IX_ETH_ACC_SUCCESS;
1103
1104 /* Turn off promiscuous mode */
1105 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1106
1107 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1108 {
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 ;
1111 }
1112
1113 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1114 {
1115 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1116 }
1117
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;
1121
1122 npeMhStatus = ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
1123 message,
1124 IX_ETHNPE_SETLOOPBACK_MODE_ACK,
1125 ixEthAccNpeLoopbackMessageCallback,
1126 IX_NPEMH_SEND_RETRIES_DEFAULT);
1127
1128 if (npeMhStatus != IX_SUCCESS)
1129 {
1130 status = IX_ETH_ACC_FAIL;
1131 }
1132 else
1133 {
1134 /* wait for NPE loopbackEnable response */
1135 if (ixOsalMutexLock(&ixEthAccMacState[portId].npeLoopbackMessageLock,
1136 IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS)
1137 != IX_SUCCESS)
1138 {
1139 status = IX_ETH_ACC_FAIL;
1140 }
1141 }
1142
1143 return status;
1144}
1145
1146IxEthAccStatus
1147ixEthAccPortTxDisablePriv(IxEthAccPortId portId)
1148{
1149 UINT32 regval;
1150
1151 /* Turn off promiscuous mode */
1152 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1153
1154 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1155 {
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 ;
1158 }
1159
1160 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1161 {
1162 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1163 }
1164
1165 /* read register */
1166 REG_READ(ixEthAccMacBase[portId],
1167 IX_ETH_ACC_MAC_TX_CNTRL1,
1168 regval);
1169
1170 /* update register */
1171 REG_WRITE(ixEthAccMacBase[portId],
1172 IX_ETH_ACC_MAC_TX_CNTRL1,
1173 (regval & ~IX_ETH_ACC_TX_CNTRL1_TX_EN));
1174
1175 return IX_ETH_ACC_SUCCESS;
1176}
1177
1178IxEthAccStatus
1179ixEthAccPortRxDisablePriv(IxEthAccPortId portId)
1180{
1181 UINT32 regval;
1182
1183 /* Turn off promiscuous mode */
1184 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1185
1186 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1187 {
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 ;
1190 }
1191
1192 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1193 {
1194 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1195 }
1196
1197 /* read register */
1198 REG_READ(ixEthAccMacBase[portId],
1199 IX_ETH_ACC_MAC_RX_CNTRL1,
1200 regval);
1201
1202 /* update register */
1203 REG_WRITE(ixEthAccMacBase[portId],
1204 IX_ETH_ACC_MAC_RX_CNTRL1,
1205 (regval & ~IX_ETH_ACC_RX_CNTRL1_RX_EN));
1206
1207 return IX_ETH_ACC_SUCCESS;
1208}
1209
1210IxEthAccStatus
1211ixEthAccPortPromiscuousModeClearPriv(IxEthAccPortId portId)
1212{
1213 UINT32 regval;
1214
1215 /* Turn off promiscuous mode */
1216 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1217
1218 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1219 {
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 ;
1222 }
1223
1224 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1225 {
1226 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1227 }
1228
1229 /*set bit 5 of Rx control 1 - enable address filtering*/
1230 REG_READ(ixEthAccMacBase[portId],
1231 IX_ETH_ACC_MAC_RX_CNTRL1,
1232 regval);
1233
1234 REG_WRITE(ixEthAccMacBase[portId],
1235 IX_ETH_ACC_MAC_RX_CNTRL1,
1236 regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN);
1237
York Sun4a598092013-04-01 11:29:11 -07001238 ixEthAccMacState[portId].promiscuous = false;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001239
1240 ixEthAccMulticastAddressSet(portId);
1241
1242 return IX_ETH_ACC_SUCCESS;
1243}
1244
1245IxEthAccStatus
1246ixEthAccPortPromiscuousModeSetPriv(IxEthAccPortId portId)
1247{
1248 UINT32 regval;
1249
1250 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1251
1252 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1253 {
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 ;
1256 }
1257
1258 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1259 {
1260 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1261 }
1262
1263 /*
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.
1267 */
1268 REG_READ(ixEthAccMacBase[portId],
1269 IX_ETH_ACC_MAC_RX_CNTRL1,
1270 regval);
1271
1272 REG_WRITE(ixEthAccMacBase[portId],
1273 IX_ETH_ACC_MAC_RX_CNTRL1,
1274 regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN);
1275
York Sun4a598092013-04-01 11:29:11 -07001276 ixEthAccMacState[portId].promiscuous = true;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001277
1278 ixEthAccMulticastAddressSet(portId);
1279
1280 return IX_ETH_ACC_SUCCESS;
1281}
1282
1283IxEthAccStatus
1284ixEthAccPortUnicastMacAddressSetPriv (IxEthAccPortId portId,
1285 IxEthAccMacAddr *macAddr)
1286{
1287 UINT32 i;
1288
1289 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1290
1291 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1292 {
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 ;
1295 }
1296
1297 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1298 {
1299 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1300 }
1301
1302
1303 if (macAddr == NULL)
1304 {
1305 return IX_ETH_ACC_FAIL;
1306 }
1307
1308 if ( macAddr->macAddress[0] & IX_ETH_ACC_ETH_MAC_BCAST_MCAST_BIT )
1309 {
1310 /* This is a multicast/broadcast address cant set it ! */
1311 return IX_ETH_ACC_FAIL;
1312 }
1313
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 )
1320 {
1321 /* This is an invalid mac address cant set it ! */
1322 return IX_ETH_ACC_FAIL;
1323 }
1324
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)
1328 {
1329 return IX_ETH_ACC_FAIL;
1330 }
1331#endif
1332
1333 /*Set the Unicast MAC to the specified value*/
1334 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1335 {
1336 REG_WRITE(ixEthAccMacBase[portId],
1337 IX_ETH_ACC_MAC_UNI_ADDR_1 + i*sizeof(UINT32),
1338 macAddr->macAddress[i]);
1339 }
York Sun4a598092013-04-01 11:29:11 -07001340 ixEthAccMacState[portId].initDone = true;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001341
1342 return IX_ETH_ACC_SUCCESS;
1343}
1344
1345IxEthAccStatus
1346ixEthAccPortUnicastMacAddressGetPriv (IxEthAccPortId portId,
1347 IxEthAccMacAddr *macAddr)
1348{
1349 /*Return the current value of the Unicast MAC from h/w
1350 for the specified port*/
1351 UINT32 i;
1352
1353 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1354
1355 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1356 {
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++)
1360 {
1361 macAddr->macAddress[i] = 0;
1362 }
1363 return IX_ETH_ACC_SUCCESS ;
1364 }
1365
1366 if(!ixEthAccMacState[portId].initDone)
1367 {
1368 return (IX_ETH_ACC_MAC_UNINITIALIZED);
1369 }
1370
1371 if (macAddr == NULL)
1372 {
1373 return IX_ETH_ACC_FAIL;
1374 }
1375
1376
1377 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1378 {
1379 REG_READ(ixEthAccMacBase[portId],
1380 IX_ETH_ACC_MAC_UNI_ADDR_1 + i*sizeof(UINT32),
1381 macAddr->macAddress[i]);
1382 }
1383 return IX_ETH_ACC_SUCCESS;
1384}
1385
1386PRIVATE IxEthAccStatus
1387ixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId,
1388 IxEthAccMacAddr *macAddr)
1389{
1390 /*Return the current value of the Multicast MAC from h/w
1391 for the specified port*/
1392 UINT32 i;
1393
1394 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1395 {
1396
1397 REG_READ(ixEthAccMacBase[portId],
1398 IX_ETH_ACC_MAC_ADDR_1 + i*sizeof(UINT32),
1399 macAddr->macAddress[i]);
1400 }
1401
1402 return IX_ETH_ACC_SUCCESS;
1403}
1404
1405PRIVATE IxEthAccStatus
1406ixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId,
1407 IxEthAccMacAddr *macAddr)
1408{
1409 /*Return the current value of the Multicast MAC from h/w
1410 for the specified port*/
1411 UINT32 i;
1412
1413 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
1414 {
1415
1416 REG_READ(ixEthAccMacBase[portId],
1417 IX_ETH_ACC_MAC_ADDR_MASK_1 + i*sizeof(UINT32),
1418 macAddr->macAddress[i]);
1419 }
1420 return IX_ETH_ACC_SUCCESS;
1421}
1422
1423IxEthAccStatus
1424ixEthAccPortMulticastAddressJoinPriv (IxEthAccPortId portId,
1425 IxEthAccMacAddr *macAddr)
1426{
1427 UINT32 i;
1428 IxEthAccMacAddr broadcastAddr = {{0xff,0xff,0xff,0xff,0xff,0xff}};
1429
1430 /*Check that the port parameter is valid*/
1431 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1432
1433 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1434 {
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 ;
1437 }
1438
1439 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1440 {
1441 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1442 }
1443
1444 /*Check that the mac address is valid*/
1445 if(macAddr == NULL)
1446 {
1447 return IX_ETH_ACC_FAIL;
1448 }
1449
1450 /* Check that this is a multicast address */
1451 if (!(macAddr->macAddress[0] & IX_ETH_ACC_ETH_MAC_BCAST_MCAST_BIT))
1452 {
1453 return IX_ETH_ACC_FAIL;
1454 }
1455
1456 /* We don't add the Broadcast address */
1457 if(ixEthAccMacEqual(&broadcastAddr, macAddr))
1458 {
1459 return IX_ETH_ACC_FAIL;
1460 }
1461
1462 for (i = 0;
1463 i<ixEthAccMacState[portId].mcastAddrIndex;
1464 i++)
1465 {
1466 /*Check if the current entry already match an existing matches*/
1467 if(ixEthAccMacEqual(&ixEthAccMacState[portId].mcastAddrsTable[i], macAddr))
1468 {
1469 /* Address found in the list and already configured,
1470 * return a success status
1471 */
1472 return IX_ETH_ACC_SUCCESS;
1473 }
1474 }
1475
1476 /* check for availability at the end of the current table */
1477 if(ixEthAccMacState[portId].mcastAddrIndex >= IX_ETH_ACC_MAX_MULTICAST_ADDRESSES)
1478 {
1479 return IX_ETH_ACC_FAIL;
1480 }
1481
1482 /*First add the address to the multicast table for the
1483 specified port*/
1484 i=ixEthAccMacState[portId].mcastAddrIndex;
1485
1486 memcpy(&ixEthAccMacState[portId].mcastAddrsTable[i],
1487 &macAddr->macAddress,
1488 IX_IEEE803_MAC_ADDRESS_SIZE);
1489
1490 /*Increment the index into the table, this must be done here
1491 as MulticastAddressSet below needs to know about the latest
1492 entry.
1493 */
1494 ixEthAccMacState[portId].mcastAddrIndex++;
1495
1496 /*Then calculate the new value to be written to the address and
1497 address mask registers*/
1498 ixEthAccMulticastAddressSet(portId);
1499
1500 return IX_ETH_ACC_SUCCESS;
1501}
1502
1503
1504IxEthAccStatus
1505ixEthAccPortMulticastAddressJoinAllPriv (IxEthAccPortId portId)
1506{
1507 IxEthAccMacAddr mcastMacAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}};
1508
1509 /*Check that the port parameter is valid*/
1510 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1511
1512 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1513 {
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 ;
1516 }
1517
1518 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1519 {
1520 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1521 }
1522
1523 /* remove all entries from the database and
1524 * insert a multicast entry
1525 */
1526 memcpy(&ixEthAccMacState[portId].mcastAddrsTable[0],
1527 &mcastMacAddr.macAddress,
1528 IX_IEEE803_MAC_ADDRESS_SIZE);
1529
1530 ixEthAccMacState[portId].mcastAddrIndex = 1;
York Sun4a598092013-04-01 11:29:11 -07001531 ixEthAccMacState[portId].joinAll = true;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001532
1533 ixEthAccMulticastAddressSet(portId);
1534
1535 return IX_ETH_ACC_SUCCESS;
1536}
1537
1538IxEthAccStatus
1539ixEthAccPortMulticastAddressLeavePriv (IxEthAccPortId portId,
1540 IxEthAccMacAddr *macAddr)
1541{
1542 UINT32 i;
1543 IxEthAccMacAddr mcastMacAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}};
1544
1545 /*Check that the port parameter is valid*/
1546 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1547
1548 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1549 {
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 ;
1552 }
1553
1554 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1555 {
1556 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1557 }
1558
1559 /*Check that the mac address is valid*/
1560 if(macAddr == NULL)
1561 {
1562 return IX_ETH_ACC_FAIL;
1563 }
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
1567 */
1568 i=0;
1569
1570 while(i<ixEthAccMacState[portId].mcastAddrIndex)
1571 {
1572 /*Check if the current entry matches*/
1573 if(ixEthAccMacEqual(&ixEthAccMacState[portId].mcastAddrsTable[i],
1574 macAddr))
1575 {
1576 if(ixEthAccMacEqual(macAddr, &mcastMacAddr))
1577 {
York Sun4a598092013-04-01 11:29:11 -07001578 ixEthAccMacState[portId].joinAll = false;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001579 }
1580 /*Decrement the index into the multicast address table
1581 for the current port*/
1582 ixEthAccMacState[portId].mcastAddrIndex--;
1583
1584 /*Copy down all entries above the current entry*/
1585 while(i<ixEthAccMacState[portId].mcastAddrIndex)
1586 {
1587 memcpy(&ixEthAccMacState[portId].mcastAddrsTable[i],
1588 &ixEthAccMacState[portId].mcastAddrsTable[i+1],
1589 IX_IEEE803_MAC_ADDRESS_SIZE);
1590 i++;
1591 }
1592 /*recalculate the mask and write it to the MAC*/
1593 ixEthAccMulticastAddressSet(portId);
1594
1595 return IX_ETH_ACC_SUCCESS;
1596 }
1597 /* search the next entry */
1598 i++;
1599 }
1600 /* no matching entry found */
1601 return IX_ETH_ACC_NO_SUCH_ADDR;
1602}
1603
1604IxEthAccStatus
1605ixEthAccPortMulticastAddressLeaveAllPriv (IxEthAccPortId portId)
1606{
1607 /*Check that the port parameter is valid*/
1608 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1609
1610 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1611 {
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 ;
1614 }
1615
1616 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1617 {
1618 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1619 }
1620
1621 ixEthAccMacState[portId].mcastAddrIndex = 0;
York Sun4a598092013-04-01 11:29:11 -07001622 ixEthAccMacState[portId].joinAll = false;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001623
1624 ixEthAccMulticastAddressSet(portId);
1625
1626 return IX_ETH_ACC_SUCCESS;
1627}
1628
1629
1630IxEthAccStatus
1631ixEthAccPortUnicastAddressShowPriv (IxEthAccPortId portId)
1632{
1633 IxEthAccMacAddr macAddr;
1634
1635 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1636
1637 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1638 {
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 ;
1641 }
1642
1643 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1644 {
1645 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1646 }
1647
1648 /*Get the MAC (UINICAST) address from hardware*/
1649 if(ixEthAccPortUnicastMacAddressGetPriv(portId, &macAddr) != IX_ETH_ACC_SUCCESS)
1650 {
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;
1654 }
1655
1656 /*print it out*/
1657 ixEthAccMacPrint(&macAddr);
1658 printf("\n");
1659 return IX_ETH_ACC_SUCCESS;
1660}
1661
1662
1663
1664void
1665ixEthAccPortMulticastAddressShowPriv(IxEthAccPortId portId)
1666{
1667 IxEthAccMacAddr macAddr;
1668 UINT32 i;
1669
1670 if(!IX_ETH_ACC_IS_PORT_VALID(portId))
1671 {
1672 return;
1673 }
1674
1675 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1676 {
1677 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot show Multicast Address.\n",(INT32)portId,0,0,0,0,0);
1678 return ;
1679 }
1680
1681 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1682 {
1683 return;
1684 }
1685
1686 printf("Multicast MAC: ");
1687 /*Get the MAC (MULTICAST) address from hardware*/
1688 ixEthAccPortMulticastMacAddressGet(portId, &macAddr);
1689 /*print it out*/
1690 ixEthAccMacPrint(&macAddr);
1691 /*Get the MAC (MULTICAST) filter from hardware*/
1692 ixEthAccPortMulticastMacFilterGet(portId, &macAddr);
1693 /*print it out*/
1694 printf(" ( ");
1695 ixEthAccMacPrint(&macAddr);
1696 printf(" )\n");
1697 printf("Constituent Addresses:\n");
1698 for(i=0;i<ixEthAccMacState[portId].mcastAddrIndex;i++)
1699 {
1700 ixEthAccMacPrint(&ixEthAccMacState[portId].mcastAddrsTable[i]);
1701 printf("\n");
1702 }
1703 return;
1704}
1705
1706/*Set the duplex mode*/
1707IxEthAccStatus
1708ixEthAccPortDuplexModeSetPriv (IxEthAccPortId portId,
1709 IxEthAccDuplexMode mode)
1710{
1711 UINT32 txregval;
1712 UINT32 rxregval;
1713
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);
1717
1718 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1719 {
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 ;
1722 }
1723
1724 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1725 {
1726 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1727 }
1728
1729 REG_READ(ixEthAccMacBase[portId],
1730 IX_ETH_ACC_MAC_TX_CNTRL1,
1731 txregval);
1732
1733 REG_READ(ixEthAccMacBase[portId],
1734 IX_ETH_ACC_MAC_RX_CNTRL1,
1735 rxregval);
1736
1737 if (mode == IX_ETH_ACC_FULL_DUPLEX)
1738 {
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);
1743
1744 /*We must set the pause enable in the receive logic when in
1745 full duplex mode*/
1746 REG_WRITE(ixEthAccMacBase[portId],
1747 IX_ETH_ACC_MAC_RX_CNTRL1,
1748 rxregval | IX_ETH_ACC_RX_CNTRL1_PAUSE_EN);
York Sun4a598092013-04-01 11:29:11 -07001749 ixEthAccMacState[portId].fullDuplex = true;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001750
1751 }
1752 else if (mode == IX_ETH_ACC_HALF_DUPLEX)
1753 {
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);
1758
1759 /*We must clear pause enable in the receive logic when in
1760 half duplex mode*/
1761 REG_WRITE(ixEthAccMacBase[portId],
1762 IX_ETH_ACC_MAC_RX_CNTRL1,
1763 rxregval & ~IX_ETH_ACC_RX_CNTRL1_PAUSE_EN);
1764
York Sun4a598092013-04-01 11:29:11 -07001765 ixEthAccMacState[portId].fullDuplex = false;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001766 }
1767 else
1768 {
1769 return IX_ETH_ACC_FAIL;
1770 }
1771
1772
1773 return IX_ETH_ACC_SUCCESS;
1774
1775}
1776
1777
1778
1779IxEthAccStatus
1780ixEthAccPortDuplexModeGetPriv (IxEthAccPortId portId,
1781 IxEthAccDuplexMode *mode)
1782{
1783 /*Return the duplex mode for the specified port*/
1784 UINT32 regval;
1785
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);
1789
1790 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1791 {
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 ;
1796 }
1797
1798 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1799 {
1800 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1801 }
1802
1803 if (mode == NULL)
1804 {
1805 return (IX_ETH_ACC_FAIL);
1806 }
1807
1808 REG_READ(ixEthAccMacBase[portId],
1809 IX_ETH_ACC_MAC_TX_CNTRL1,
1810 regval);
1811
1812 if( regval & IX_ETH_ACC_TX_CNTRL1_DUPLEX)
1813 {
1814 *mode = IX_ETH_ACC_HALF_DUPLEX;
1815 }
1816 else
1817 {
1818 *mode = IX_ETH_ACC_FULL_DUPLEX;
1819 }
1820
1821 return IX_ETH_ACC_SUCCESS;
1822}
1823
1824
1825
1826IxEthAccStatus
1827ixEthAccPortTxFrameAppendPaddingEnablePriv (IxEthAccPortId portId)
1828{
1829 UINT32 regval;
1830 /*Enable FCS computation by the MAC and appending to the
1831 frame*/
1832
1833 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1834
1835 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1836 {
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 ;
1839 }
1840
1841 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1842 {
1843 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1844 }
1845
1846 REG_READ(ixEthAccMacBase[portId],
1847 IX_ETH_ACC_MAC_TX_CNTRL1,
1848 regval);
1849
1850 REG_WRITE(ixEthAccMacBase[portId],
1851 IX_ETH_ACC_MAC_TX_CNTRL1,
1852 regval |
1853 IX_ETH_ACC_TX_CNTRL1_PAD_EN);
1854
York Sun4a598092013-04-01 11:29:11 -07001855 ixEthAccMacState[portId].txPADAppend = true;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001856 return IX_ETH_ACC_SUCCESS;
1857}
1858
1859IxEthAccStatus
1860ixEthAccPortTxFrameAppendPaddingDisablePriv (IxEthAccPortId portId)
1861{
1862 UINT32 regval;
1863
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);
1867
1868 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1869 {
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 ;
1872 }
1873
1874 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1875 {
1876 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1877 }
1878
1879 REG_READ(ixEthAccMacBase[portId],
1880 IX_ETH_ACC_MAC_TX_CNTRL1,
1881 regval);
1882
1883 REG_WRITE(ixEthAccMacBase[portId],
1884 IX_ETH_ACC_MAC_TX_CNTRL1,
1885 regval & ~IX_ETH_ACC_TX_CNTRL1_PAD_EN);
1886
York Sun4a598092013-04-01 11:29:11 -07001887 ixEthAccMacState[portId].txPADAppend = false;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001888 return IX_ETH_ACC_SUCCESS;
1889}
1890
1891IxEthAccStatus
1892ixEthAccPortTxFrameAppendFCSEnablePriv (IxEthAccPortId portId)
1893{
1894 UINT32 regval;
1895
1896 /*Enable FCS computation by the MAC and appending to the
1897 frame*/
1898
1899 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1900
1901 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1902 {
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 ;
1905 }
1906
1907 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1908 {
1909 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1910 }
1911
1912 REG_READ(ixEthAccMacBase[portId],
1913 IX_ETH_ACC_MAC_TX_CNTRL1,
1914 regval);
1915
1916 REG_WRITE(ixEthAccMacBase[portId],
1917 IX_ETH_ACC_MAC_TX_CNTRL1,
1918 regval | IX_ETH_ACC_TX_CNTRL1_FCS_EN);
1919
York Sun4a598092013-04-01 11:29:11 -07001920 ixEthAccMacState[portId].txFCSAppend = true;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001921 return IX_ETH_ACC_SUCCESS;
1922}
1923
1924IxEthAccStatus
1925ixEthAccPortTxFrameAppendFCSDisablePriv (IxEthAccPortId portId)
1926{
1927 UINT32 regval;
1928
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);
1932
1933 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1934 {
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 ;
1937 }
1938
1939 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1940 {
1941 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1942 }
1943
1944 REG_READ(ixEthAccMacBase[portId],
1945 IX_ETH_ACC_MAC_TX_CNTRL1,
1946 regval);
1947
1948 REG_WRITE(ixEthAccMacBase[portId],
1949 IX_ETH_ACC_MAC_TX_CNTRL1,
1950 regval & ~IX_ETH_ACC_TX_CNTRL1_FCS_EN);
1951
York Sun4a598092013-04-01 11:29:11 -07001952 ixEthAccMacState[portId].txFCSAppend = false;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001953 return IX_ETH_ACC_SUCCESS;
1954}
1955
1956IxEthAccStatus
1957ixEthAccPortRxFrameAppendFCSEnablePriv (IxEthAccPortId portId)
1958{
1959 /*Set bit 2 of Rx control 1*/
1960 UINT32 regval;
1961
1962 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1963
1964 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1965 {
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 ;
1968 }
1969
1970 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
1971 {
1972 return (IX_ETH_ACC_PORT_UNINITIALIZED);
1973 }
1974
1975 REG_READ(ixEthAccMacBase[portId],
1976 IX_ETH_ACC_MAC_RX_CNTRL1,
1977 regval);
1978
1979 REG_WRITE(ixEthAccMacBase[portId],
1980 IX_ETH_ACC_MAC_RX_CNTRL1,
1981 regval | IX_ETH_ACC_RX_CNTRL1_CRC_EN);
1982
York Sun4a598092013-04-01 11:29:11 -07001983 ixEthAccMacState[portId].rxFCSAppend = true;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001984 return IX_ETH_ACC_SUCCESS;
1985}
1986
1987IxEthAccStatus
1988ixEthAccPortRxFrameAppendFCSDisablePriv (IxEthAccPortId portId)
1989{
1990 UINT32 regval;
1991
1992 /*Clear bit 2 of Rx control 1*/
1993 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
1994
1995 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
1996 {
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 ;
1999 }
2000
2001 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
2002 {
2003 return (IX_ETH_ACC_PORT_UNINITIALIZED);
2004 }
2005
2006 REG_READ(ixEthAccMacBase[portId],
2007 IX_ETH_ACC_MAC_RX_CNTRL1,
2008 regval);
2009
2010 REG_WRITE(ixEthAccMacBase[portId],
2011 IX_ETH_ACC_MAC_RX_CNTRL1,
2012 regval & ~IX_ETH_ACC_RX_CNTRL1_CRC_EN);
2013
York Sun4a598092013-04-01 11:29:11 -07002014 ixEthAccMacState[portId].rxFCSAppend = false;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002015 return IX_ETH_ACC_SUCCESS;
2016}
2017
2018
2019
2020PRIVATE void
2021ixEthAccMacNpeStatsMessageCallback (IxNpeMhNpeId npeId,
2022 IxNpeMhMessage msg)
2023{
2024 IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
2025
2026#ifndef NDEBUG
2027 /* Prudent to at least check the port is within range */
2028 if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)
2029 {
2030 IX_ETH_ACC_FATAL_LOG(
2031 "IXETHACC:ixEthAccMacNpeStatsMessageCallback: Illegal port: %u\n",
2032 (UINT32)portId, 0, 0, 0, 0, 0);
2033 return;
2034 }
2035#endif
2036
2037 /*Unblock Stats Get call*/
2038 ixOsalMutexUnlock(&ixEthAccMacState[portId].ackMIBStatsLock);
2039
2040}
2041
2042PRIVATE void
2043ixEthAccMibIIStatsEndianConvert (IxEthEthObjStats *retStats)
2044{
2045 /* endianness conversion */
2046
2047 /* Rx stats */
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);
2074
2075 /* Tx stats */
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);
2094}
2095
2096IxEthAccStatus
2097ixEthAccMibIIStatsGet (IxEthAccPortId portId,
2098 IxEthEthObjStats *retStats )
2099{
2100 IxNpeMhMessage message;
2101
2102 if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
2103 {
2104 printf("EthAcc: ixEthAccMibIIStatsGet (Mac) EthAcc service is not initialized\n");
2105 return (IX_ETH_ACC_FAIL);
2106 }
2107
2108 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2109
2110 if (retStats == NULL)
2111 {
2112 printf("EthAcc: ixEthAccMibIIStatsGet (Mac) NULL argument\n");
2113 return (IX_ETH_ACC_FAIL);
2114 }
2115
2116 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2117 {
2118 printf("EthAcc: ixEthAccMibIIStatsGet (Mac) NPE for port %d is not available\n", portId);
2119
2120 IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get MIB II Stats.\n",(INT32)portId,0,0,0,0,0);
2121
2122 /* Return all zero stats */
2123 IX_ETH_ACC_MEMSET(retStats, 0, sizeof(IxEthEthObjStats));
2124
2125 return IX_ETH_ACC_SUCCESS ;
2126 }
2127
2128 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
2129 {
2130 printf("EthAcc: ixEthAccMibIIStatsGet (Mac) port %d is not initialized\n", portId);
2131 return (IX_ETH_ACC_PORT_UNINITIALIZED);
2132 }
2133
2134 IX_OSAL_CACHE_INVALIDATE(retStats, sizeof(IxEthEthObjStats));
2135
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);
2138
2139 /* Permit only one task to request MIB statistics Get operation
2140 at a time */
2141 ixOsalMutexLock(&ixEthAccMacState[portId].MIBStatsGetAccessLock, IX_OSAL_WAIT_FOREVER);
2142
2143 if(ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
2144 message,
2145 IX_ETHNPE_GETSTATS,
2146 ixEthAccMacNpeStatsMessageCallback,
2147 IX_NPEMH_SEND_RETRIES_DEFAULT)
2148 != IX_SUCCESS)
2149 {
2150 ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetAccessLock);
2151
2152 printf("EthAcc: (Mac) StatsGet failed to send NPE message\n");
2153
2154 return IX_ETH_ACC_FAIL;
2155 }
2156
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);
2161
2162 /* Permit other tasks to perform MIB statistics Get operation */
2163 ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetAccessLock);
2164
2165 ixEthAccMibIIStatsEndianConvert (retStats);
2166
2167 return IX_ETH_ACC_SUCCESS;
2168}
2169
2170
2171PRIVATE void
2172ixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId,
2173 IxNpeMhMessage msg)
2174{
2175 IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
2176
2177#ifndef NDEBUG
2178 /* Prudent to at least check the port is within range */
2179 if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)
2180 {
2181 IX_ETH_ACC_FATAL_LOG(
2182 "IXETHACC:ixEthAccMacNpeStatsResetMessageCallback: Illegal port: %u\n",
2183 (UINT32)portId, 0, 0, 0, 0, 0);
2184 return;
2185 }
2186#endif
2187
2188 /*Unblock Stats Get & reset call*/
2189 ixOsalMutexUnlock(&ixEthAccMacState[portId].ackMIBStatsResetLock);
2190
2191}
2192
2193
2194
2195IxEthAccStatus
2196ixEthAccMibIIStatsGetClear (IxEthAccPortId portId,
2197 IxEthEthObjStats *retStats)
2198{
2199 IxNpeMhMessage message;
2200
2201 if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
2202 {
2203 printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) EthAcc service is not initialized\n");
2204 return (IX_ETH_ACC_FAIL);
2205 }
2206
2207 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2208
2209 if (retStats == NULL)
2210 {
2211 printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) NULL argument\n");
2212 return (IX_ETH_ACC_FAIL);
2213 }
2214
2215 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2216 {
2217 printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) NPE for port %d is not available\n", portId);
2218
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);
2220
2221 /* Return all zero stats */
2222 IX_ETH_ACC_MEMSET(retStats, 0, sizeof(IxEthEthObjStats));
2223
2224 return IX_ETH_ACC_SUCCESS ;
2225 }
2226
2227 if (!IX_ETH_IS_PORT_INITIALIZED(portId))
2228 {
2229 printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) port %d is not initialized\n", portId);
2230 return (IX_ETH_ACC_PORT_UNINITIALIZED);
2231 }
2232
2233 IX_OSAL_CACHE_INVALIDATE(retStats, sizeof(IxEthEthObjStats));
2234
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);
2237
2238 /* Permit only one task to request MIB statistics Get-Reset operation at a time */
2239 ixOsalMutexLock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock, IX_OSAL_WAIT_FOREVER);
2240
2241 if(ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId),
2242 message,
2243 IX_ETHNPE_RESETSTATS,
2244 ixEthAccMacNpeStatsResetMessageCallback,
2245 IX_NPEMH_SEND_RETRIES_DEFAULT)
2246 != IX_SUCCESS)
2247 {
2248 ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock);
2249
2250 printf("EthAcc: (Mac) ixEthAccMibIIStatsGetClear failed to send NPE message\n");
2251
2252 return IX_ETH_ACC_FAIL;
2253 }
2254
2255 /* Wait for callback invocation indicating response to this request */
2256 ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsResetLock, IX_ETH_ACC_MIB_STATS_DELAY_MSECS);
2257
2258 /* permit other tasks to get and reset MIB stats*/
2259 ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock);
2260
2261 ixEthAccMibIIStatsEndianConvert(retStats);
2262
2263 return IX_ETH_ACC_SUCCESS;
2264}
2265
2266IxEthAccStatus
2267ixEthAccMibIIStatsClear (IxEthAccPortId portId)
2268{
2269 static IxEthEthObjStats retStats;
2270 IxEthAccStatus status;
2271
2272 if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
2273 {
2274 return (IX_ETH_ACC_FAIL);
2275 }
2276
2277 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2278
2279 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2280 {
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 ;
2283 }
2284
2285 /* there is no reset operation without a corresponding Get */
2286 status = ixEthAccMibIIStatsGetClear(portId, &retStats);
2287
2288 return status;
2289}
2290
2291/* Initialize the ethernet MAC settings */
2292IxEthAccStatus
2293ixEthAccMacInit(IxEthAccPortId portId)
2294{
2295 IX_OSAL_MBUF_POOL* portDisablePool;
2296 UINT8 *data;
2297
2298 IX_ETH_ACC_VALIDATE_PORT_ID(portId);
2299
2300 if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
2301 {
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 ;
2304 }
2305
York Sun4a598092013-04-01 11:29:11 -07002306 if(ixEthAccMacState[portId].macInitialised == false)
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002307 {
York Sun4a598092013-04-01 11:29:11 -07002308 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;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002317
2318 /* initialize MIB stats mutexes */
2319 ixOsalMutexInit(&ixEthAccMacState[portId].ackMIBStatsLock);
2320 ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsLock, IX_OSAL_WAIT_FOREVER);
2321
2322 ixOsalMutexInit(&ixEthAccMacState[portId].ackMIBStatsResetLock);
2323 ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsResetLock, IX_OSAL_WAIT_FOREVER);
2324
2325 ixOsalMutexInit(&ixEthAccMacState[portId].MIBStatsGetAccessLock);
2326
2327 ixOsalMutexInit(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock);
2328
2329 ixOsalMutexInit(&ixEthAccMacState[portId].npeLoopbackMessageLock);
2330
2331 ixEthAccMacState[portId].portDisableRxMbufPtr = NULL;
2332 ixEthAccMacState[portId].portDisableTxMbufPtr = NULL;
2333
2334 portDisablePool = IX_OSAL_MBUF_POOL_INIT(2,
2335 IX_ETHACC_RX_MBUF_MIN_SIZE,
2336 "portDisable Pool");
2337
2338 IX_OSAL_ENSURE(portDisablePool != NULL, "Failed to initialize PortDisable pool");
2339
2340 ixEthAccMacState[portId].portDisableRxMbufPtr = IX_OSAL_MBUF_POOL_GET(portDisablePool);
2341 ixEthAccMacState[portId].portDisableTxMbufPtr = IX_OSAL_MBUF_POOL_GET(portDisablePool);
2342
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;
2349
2350 memset(IX_OSAL_MBUF_MDATA(ixEthAccMacState[portId].portDisableRxMbufPtr),
2351 0xAA,
2352 IX_ETHACC_RX_MBUF_MIN_SIZE);
2353
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;
2357
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 */
2364
2365 IX_OSAL_CACHE_FLUSH(data, 64);
2366 }
2367
2368 IX_OSAL_ASSERT (ixEthAccMacBase[portId] != 0);
2369
2370 REG_WRITE(ixEthAccMacBase[portId],
2371 IX_ETH_ACC_MAC_CORE_CNTRL,
2372 IX_ETH_ACC_CORE_RESET);
2373
2374 ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY);
2375
2376 REG_WRITE(ixEthAccMacBase[portId],
2377 IX_ETH_ACC_MAC_CORE_CNTRL,
2378 IX_ETH_ACC_CORE_MDC_EN);
2379
2380 REG_WRITE(ixEthAccMacBase[portId],
2381 IX_ETH_ACC_MAC_INT_CLK_THRESH,
2382 IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);
2383
2384 ixEthAccMacStateUpdate(portId);
2385
2386 return IX_ETH_ACC_SUCCESS;
2387}
2388
2389/* PRIVATE Functions*/
2390
2391PRIVATE void
2392ixEthAccMacStateUpdate(IxEthAccPortId portId)
2393{
2394 UINT32 regval;
2395
York Sun4a598092013-04-01 11:29:11 -07002396 if ( ixEthAccMacState[portId].enabled == false )
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002397 {
2398 /* Just disable both the transmitter and reciver in the MAC. */
2399 REG_READ(ixEthAccMacBase[portId],
2400 IX_ETH_ACC_MAC_RX_CNTRL1,
2401 regval);
Wolfgang Denka1be4762008-05-20 16:00:29 +02002402 REG_WRITE(ixEthAccMacBase[portId],
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002403 IX_ETH_ACC_MAC_RX_CNTRL1,
2404 regval & ~IX_ETH_ACC_RX_CNTRL1_RX_EN);
2405
2406 REG_READ(ixEthAccMacBase[portId],
2407 IX_ETH_ACC_MAC_TX_CNTRL1,
2408 regval);
Wolfgang Denka1be4762008-05-20 16:00:29 +02002409 REG_WRITE(ixEthAccMacBase[portId],
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002410 IX_ETH_ACC_MAC_TX_CNTRL1,
2411 regval & ~IX_ETH_ACC_TX_CNTRL1_TX_EN);
2412 }
2413
2414 if(ixEthAccMacState[portId].fullDuplex)
2415 {
2416 ixEthAccPortDuplexModeSetPriv (portId, IX_ETH_ACC_FULL_DUPLEX);
2417 }
2418 else
2419 {
2420 ixEthAccPortDuplexModeSetPriv (portId, IX_ETH_ACC_HALF_DUPLEX);
2421 }
2422
2423 if(ixEthAccMacState[portId].rxFCSAppend)
2424 {
2425 ixEthAccPortRxFrameAppendFCSEnablePriv (portId);
2426 }
2427 else
2428 {
2429 ixEthAccPortRxFrameAppendFCSDisablePriv (portId);
2430 }
2431
2432 if(ixEthAccMacState[portId].txFCSAppend)
2433 {
2434 ixEthAccPortTxFrameAppendFCSEnablePriv (portId);
2435 }
2436 else
2437 {
2438 ixEthAccPortTxFrameAppendFCSDisablePriv (portId);
2439 }
2440
2441 if(ixEthAccMacState[portId].txPADAppend)
2442 {
2443 ixEthAccPortTxFrameAppendPaddingEnablePriv (portId);
2444 }
2445 else
2446 {
2447 ixEthAccPortTxFrameAppendPaddingDisablePriv (portId);
2448 }
2449
2450 if(ixEthAccMacState[portId].promiscuous)
2451 {
2452 ixEthAccPortPromiscuousModeSetPriv(portId);
2453 }
2454 else
2455 {
2456 ixEthAccPortPromiscuousModeClearPriv(portId);
2457 }
2458
York Sun4a598092013-04-01 11:29:11 -07002459 if ( ixEthAccMacState[portId].enabled == true )
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002460 {
2461 /* Enable both the transmitter and reciver in the MAC. */
2462 REG_READ(ixEthAccMacBase[portId],
2463 IX_ETH_ACC_MAC_RX_CNTRL1,
2464 regval);
2465 REG_WRITE(ixEthAccMacBase[portId],
2466 IX_ETH_ACC_MAC_RX_CNTRL1,
2467 regval | IX_ETH_ACC_RX_CNTRL1_RX_EN);
2468
2469 REG_READ(ixEthAccMacBase[portId],
2470 IX_ETH_ACC_MAC_TX_CNTRL1,
2471 regval);
Wolfgang Denka1be4762008-05-20 16:00:29 +02002472 REG_WRITE(ixEthAccMacBase[portId],
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002473 IX_ETH_ACC_MAC_TX_CNTRL1,
2474 regval | IX_ETH_ACC_TX_CNTRL1_TX_EN);
2475 }
2476}
2477
2478
2479PRIVATE BOOL
2480ixEthAccMacEqual(IxEthAccMacAddr *macAddr1,
2481 IxEthAccMacAddr *macAddr2)
2482{
2483 UINT32 i;
2484 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE; i++)
2485 {
2486 if(macAddr1->macAddress[i] != macAddr2->macAddress[i])
2487 {
York Sun4a598092013-04-01 11:29:11 -07002488 return false;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002489 }
2490 }
York Sun4a598092013-04-01 11:29:11 -07002491 return true;
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002492}
2493
2494PRIVATE void
2495ixEthAccMacPrint(IxEthAccMacAddr *m)
2496{
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]);
2501}
2502
2503/* Set the multicast address and address mask registers
2504 *
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.
2508 *
2509 * A bit in the address register must be set if all multicast
2510 * addresses have that bit set, otherwise, it should be cleared
2511 */
2512
2513PRIVATE void
2514ixEthAccMulticastAddressSet(IxEthAccPortId portId)
2515{
2516 UINT32 i;
2517 UINT32 j;
2518 IxEthAccMacAddr addressMask;
2519 IxEthAccMacAddr address;
2520 IxEthAccMacAddr alwaysClearBits;
2521 IxEthAccMacAddr alwaysSetBits;
2522
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
2527 *
2528 * alwaysSetBits is calculated by ANDing all
2529 * multicast addresses, those bits that are always set
2530 * are set in the result
2531 */
2532
York Sun4a598092013-04-01 11:29:11 -07002533 if (ixEthAccMacState[portId].promiscuous == true)
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002534 {
2535 /* Promiscuous Mode is set, and filtering
2536 * allow all packets, and enable the mcast and
2537 * bcast detection.
2538 */
2539 memset(&addressMask.macAddress,
2540 0,
2541 IX_IEEE803_MAC_ADDRESS_SIZE);
2542 memset(&address.macAddress,
2543 0,
2544 IX_IEEE803_MAC_ADDRESS_SIZE);
2545 }
2546 else
2547 {
York Sun4a598092013-04-01 11:29:11 -07002548 if(ixEthAccMacState[portId].joinAll == true)
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02002549 {
2550 /* Join all is set. The mask and address are
2551 * the multicast settings.
2552 */
2553 IxEthAccMacAddr macAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}};
2554
2555 memcpy(addressMask.macAddress,
2556 macAddr.macAddress,
2557 IX_IEEE803_MAC_ADDRESS_SIZE);
2558 memcpy(address.macAddress,
2559 macAddr.macAddress,
2560 IX_IEEE803_MAC_ADDRESS_SIZE);
2561 }
2562 else if(ixEthAccMacState[portId].mcastAddrIndex == 0)
2563 {
2564 /* No entry in the filtering database,
2565 * Promiscuous Mode is cleared, Broadcast filtering
2566 * is configured.
2567 */
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);
2574 }
2575 else
2576 {
2577 /* build a mask and an address which mix all entreis
2578 * from the list of multicast addresses
2579 */
2580 memset(alwaysClearBits.macAddress,
2581 0,
2582 IX_IEEE803_MAC_ADDRESS_SIZE);
2583 memset(alwaysSetBits.macAddress,
2584 IX_ETH_ACC_MAC_ALL_BITS_SET,
2585 IX_IEEE803_MAC_ADDRESS_SIZE);
2586
2587 for(i=0;i<ixEthAccMacState[portId].mcastAddrIndex;i++)
2588 {
2589 for(j=0;j<IX_IEEE803_MAC_ADDRESS_SIZE;j++)
2590 {
2591 alwaysClearBits.macAddress[j] |=
2592 ixEthAccMacState[portId].mcastAddrsTable[i].macAddress[j];
2593 alwaysSetBits.macAddress[j] &=
2594 ixEthAccMacState[portId].mcastAddrsTable[i].macAddress[j];
2595 }
2596 }
2597
2598 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
2599 {
2600 addressMask.macAddress[i] = alwaysSetBits.macAddress[i]
2601 | ~alwaysClearBits.macAddress[i];
2602 address.macAddress[i] = alwaysSetBits.macAddress[i];
2603 }
2604 }
2605 }
2606
2607 /*write the new addr filtering to h/w*/
2608 for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++)
2609 {
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]);
2616 }
2617}