]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/npe/IxEthDBAPISupport.c
imx6 SION bit has to be on for the pins that are used as ENET_REF_CLK
[karo-tx-uboot.git] / drivers / net / npe / IxEthDBAPISupport.c
1 /**
2  * @file IxEthDBAPISupport.c
3  *
4  * @brief Public API support functions
5  *
6  * @par
7  * IXP400 SW Release version 2.0
8  *
9  * -- Copyright Notice --
10  *
11  * @par
12  * Copyright 2001-2005, Intel Corporation.
13  * All rights reserved.
14  *
15  * @par
16  * SPDX-License-Identifier:     BSD-3-Clause
17  * @par
18  * -- End of Copyright Notice --
19  */
20
21 #include <IxEthDB.h>
22 #include <IxNpeMh.h>
23 #include <IxFeatureCtrl.h>
24
25 #include "IxEthDB_p.h"
26 #include "IxEthDBMessages_p.h"
27 #include "IxEthDB_p.h"
28 #include "IxEthDBLog_p.h"
29
30 #ifdef IX_UNIT_TEST
31
32 int dbAccessCounter = 0;
33 int overflowEvent   = 0;
34
35 #endif
36
37 /*
38  * External declaration
39  */
40 extern HashTable dbHashtable;
41
42 /*
43  * Internal declaration
44  */
45 IX_ETH_DB_PUBLIC
46 PortInfo ixEthDBPortInfo[IX_ETH_DB_NUMBER_OF_PORTS];
47
48 IX_ETH_DB_PRIVATE
49 struct
50 {
51     BOOL saved;
52     IxEthDBPriorityTable priorityTable;
53     IxEthDBVlanSet vlanMembership;
54     IxEthDBVlanSet transmitTaggingInfo;
55     IxEthDBFrameFilter frameFilter;
56     IxEthDBTaggingAction taggingAction;
57     IxEthDBFirewallMode firewallMode;
58     BOOL stpBlocked;
59     BOOL srcAddressFilterEnabled;
60     UINT32 maxRxFrameSize;
61     UINT32 maxTxFrameSize;
62 } ixEthDBPortState[IX_ETH_DB_NUMBER_OF_PORTS];
63
64 #define IX_ETH_DB_DEFAULT_FRAME_SIZE (1518)
65
66 /**
67  * @brief initializes a port
68  *
69  * @param portID ID of the port to be initialized
70  *
71  * Note that redundant initializations are silently
72  * dealt with and do not constitute an error
73  *
74  * This function is fully documented in the main
75  * header file, IxEthDB.h
76  */
77 IX_ETH_DB_PUBLIC
78 void ixEthDBPortInit(IxEthDBPortId portID)
79 {
80     PortInfo *portInfo;
81
82     if (portID >= IX_ETH_DB_NUMBER_OF_PORTS)
83     {
84         return;
85     }
86
87     portInfo = &ixEthDBPortInfo[portID];
88
89     if (ixEthDBSingleEthNpeCheck(portID) != IX_ETH_DB_SUCCESS)
90     {
91         WARNING_LOG("EthDB: Unavailable Eth %d: Cannot initialize EthDB Port.\n", (UINT32) portID);
92
93         return;
94     }
95
96     if (portInfo->initialized)
97     {
98         /* redundant */
99         return;
100     }
101
102     /* initialize core fields */
103     portInfo->portID = portID;
104     SET_DEPENDENCY_MAP(portInfo->dependencyPortMap, portID);
105
106     /* default values */
107     portInfo->agingEnabled       = false;
108     portInfo->enabled            = false;
109     portInfo->macAddressUploaded = false;
110     portInfo->maxRxFrameSize     = IX_ETHDB_DEFAULT_FRAME_SIZE;
111     portInfo->maxTxFrameSize     = IX_ETHDB_DEFAULT_FRAME_SIZE;
112
113     /* default update control values */
114     portInfo->updateMethod.searchTree              = NULL;
115     portInfo->updateMethod.searchTreePendingWrite  = false;
116     portInfo->updateMethod.treeInitialized         = false;
117     portInfo->updateMethod.updateEnabled           = false;
118     portInfo->updateMethod.userControlled          = false;
119
120     /* default WiFi parameters */
121     memset(portInfo->bbsid, 0, sizeof (portInfo->bbsid));
122     portInfo->frameControlDurationID = 0;
123
124     /* Ethernet NPE-specific initializations */
125     if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
126     {
127         /* update handler */
128         portInfo->updateMethod.updateHandler = ixEthDBNPEUpdateHandler;
129     }
130
131     /* initialize state save */
132     ixEthDBPortState[portID].saved = false;
133
134     portInfo->initialized = true;
135 }
136
137 /**
138  * @brief enables a port
139  *
140  * @param portID ID of the port to enable
141  *
142  * This function is fully documented in the main
143  * header file, IxEthDB.h
144  *
145  * @return IX_ETH_DB_SUCCESS if enabling was
146  * accomplished, or a meaningful error message otherwise
147  */
148 IX_ETH_DB_PUBLIC
149 IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID)
150 {
151     IxEthDBPortMap triggerPorts;
152     PortInfo *portInfo;
153
154     IX_ETH_DB_CHECK_PORT_EXISTS(portID);
155
156     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
157
158     portInfo = &ixEthDBPortInfo[portID];
159
160     if (portInfo->enabled)
161     {
162         /* redundant */
163         return IX_ETH_DB_SUCCESS;
164     }
165
166     SET_DEPENDENCY_MAP(triggerPorts, portID);
167
168     /* mark as enabled */
169     portInfo->enabled = true;
170
171     /* Operation stops here when Ethernet Learning is not enabled */
172     if(IX_FEATURE_CTRL_SWCONFIG_DISABLED ==
173        ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
174     {
175         return IX_ETH_DB_SUCCESS;
176     }
177
178     if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE && !portInfo->macAddressUploaded)
179     {
180         IX_ETH_DB_SUPPORT_TRACE("DB: (Support) MAC address not set on port %d, enable failed\n", portID);
181
182         /* must use UnicastAddressSet() before enabling an NPE port */
183         return IX_ETH_DB_MAC_UNINITIALIZED;
184     }
185
186     if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
187     {
188         IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Attempting to enable the NPE callback for port %d...\n", portID);
189
190         if (!portInfo->updateMethod.userControlled
191                 && ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0))
192         {
193             portInfo->updateMethod.updateEnabled = true;
194         }
195
196         /* if this is first time initialization then we already have
197            write access to the tree and can AccessRelease directly */
198         if (!portInfo->updateMethod.treeInitialized)
199         {
200             IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Initializing tree for port %d\n", portID);
201
202             /* create an initial tree and release access into it */
203             ixEthDBUpdatePortLearningTrees(triggerPorts);
204
205             /* mark tree as being initialized */
206             portInfo->updateMethod.treeInitialized = true;
207         }
208     }
209
210     if (ixEthDBPortState[portID].saved)
211     {
212         /* previous configuration data stored, restore state */
213         if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
214         {
215             ixEthDBFirewallModeSet(portID, ixEthDBPortState[portID].firewallMode);
216             ixEthDBFirewallInvalidAddressFilterEnable(portID, ixEthDBPortState[portID].srcAddressFilterEnabled);
217         }
218
219 #if 0 /* test-only */
220         if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
221         {
222             ixEthDBAcceptableFrameTypeSet(portID, ixEthDBPortState[portID].frameFilter);
223             ixEthDBIngressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].taggingAction);
224
225             ixEthDBEgressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].transmitTaggingInfo);
226             ixEthDBPortVlanMembershipSet(portID, ixEthDBPortState[portID].vlanMembership);
227
228             ixEthDBPriorityMappingTableSet(portID, ixEthDBPortState[portID].priorityTable);
229         }
230 #endif
231
232         if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
233         {
234             ixEthDBSpanningTreeBlockingStateSet(portID, ixEthDBPortState[portID].stpBlocked);
235         }
236
237         ixEthDBFilteringPortMaximumRxFrameSizeSet(portID, ixEthDBPortState[portID].maxRxFrameSize);
238         ixEthDBFilteringPortMaximumTxFrameSizeSet(portID, ixEthDBPortState[portID].maxTxFrameSize);
239
240         /* discard previous save */
241         ixEthDBPortState[portID].saved = false;
242     }
243
244     IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Enabling succeeded for port %d\n", portID);
245
246     return IX_ETH_DB_SUCCESS;
247 }
248
249 /**
250  * @brief disables a port
251  *
252  * @param portID ID of the port to disable
253  *
254  * This function is fully documented in the
255  * main header file, IxEthDB.h
256  *
257  * @return IX_ETH_DB_SUCCESS if disabling was
258  * successful or an appropriate error message
259  * otherwise
260  */
261 IX_ETH_DB_PUBLIC
262 IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID)
263 {
264     HashIterator iterator;
265     IxEthDBPortMap triggerPorts; /* ports who will have deleted records and therefore will need updating */
266     BOOL result;
267     PortInfo *portInfo;
268     IxEthDBFeature learningEnabled;
269 #if 0 /* test-only */
270     IxEthDBPriorityTable classZeroTable;
271 #endif
272
273     IX_ETH_DB_CHECK_PORT_EXISTS(portID);
274
275     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
276
277     portInfo = &ixEthDBPortInfo[portID];
278
279     if (!portInfo->enabled)
280     {
281         /* redundant */
282         return IX_ETH_DB_SUCCESS;
283     }
284
285     if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
286     {
287         /* save filtering state */
288         ixEthDBPortState[portID].firewallMode            = portInfo->firewallMode;
289         ixEthDBPortState[portID].frameFilter             = portInfo->frameFilter;
290         ixEthDBPortState[portID].taggingAction           = portInfo->taggingAction;
291         ixEthDBPortState[portID].stpBlocked              = portInfo->stpBlocked;
292         ixEthDBPortState[portID].srcAddressFilterEnabled = portInfo->srcAddressFilterEnabled;
293         ixEthDBPortState[portID].maxRxFrameSize          = portInfo->maxRxFrameSize;
294         ixEthDBPortState[portID].maxTxFrameSize          = portInfo->maxTxFrameSize;
295
296         memcpy(ixEthDBPortState[portID].vlanMembership, portInfo->vlanMembership, sizeof (IxEthDBVlanSet));
297         memcpy(ixEthDBPortState[portID].transmitTaggingInfo, portInfo->transmitTaggingInfo, sizeof (IxEthDBVlanSet));
298         memcpy(ixEthDBPortState[portID].priorityTable, portInfo->priorityTable, sizeof (IxEthDBPriorityTable));
299
300         ixEthDBPortState[portID].saved = true;
301
302         /* now turn off all EthDB filtering features on the port */
303
304 #if 0 /* test-only */
305         /* VLAN & QoS */
306         if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
307         {
308             ixEthDBPortVlanMembershipRangeAdd((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID);
309             ixEthDBEgressVlanRangeTaggingEnabledSet((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID, false);
310             ixEthDBAcceptableFrameTypeSet((IxEthDBPortId) portID, IX_ETH_DB_ACCEPT_ALL_FRAMES);
311             ixEthDBIngressVlanTaggingEnabledSet((IxEthDBPortId) portID, IX_ETH_DB_PASS_THROUGH);
312
313             memset(classZeroTable, 0, sizeof (classZeroTable));
314             ixEthDBPriorityMappingTableSet((IxEthDBPortId) portID, classZeroTable);
315         }
316 #endif
317
318         /* STP */
319         if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
320         {
321             ixEthDBSpanningTreeBlockingStateSet((IxEthDBPortId) portID, false);
322         }
323
324         /* Firewall */
325         if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
326         {
327             ixEthDBFirewallModeSet((IxEthDBPortId) portID, IX_ETH_DB_FIREWALL_BLACK_LIST);
328             ixEthDBFirewallTableDownload((IxEthDBPortId) portID);
329             ixEthDBFirewallInvalidAddressFilterEnable((IxEthDBPortId) portID, false);
330         }
331
332         /* Frame size filter */
333         ixEthDBFilteringPortMaximumFrameSizeSet((IxEthDBPortId) portID, IX_ETH_DB_DEFAULT_FRAME_SIZE);
334
335         /* WiFi */
336         if ((portInfo->featureCapability & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0)
337         {
338             ixEthDBWiFiConversionTableDownload((IxEthDBPortId) portID);
339         }
340
341         /* save and disable the learning feature bit */
342         learningEnabled          = portInfo->featureStatus & IX_ETH_DB_LEARNING;
343         portInfo->featureStatus &= ~IX_ETH_DB_LEARNING;
344     }
345     else
346     {
347         /* save the learning feature bit */
348         learningEnabled          = portInfo->featureStatus & IX_ETH_DB_LEARNING;
349     }
350
351     SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
352
353     ixEthDBUpdateLock();
354
355     /* wipe out current entries for this port */
356     BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));
357
358     while (IS_ITERATOR_VALID(&iterator))
359     {
360         MacDescriptor *descriptor =  (MacDescriptor *) iterator.node->data;
361
362         /* check if the port match. If so, remove the entry  */
363         if (descriptor->portID == portID
364                 && (descriptor->type == IX_ETH_DB_FILTERING_RECORD || descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
365                 && !descriptor->recordData.filteringData.staticEntry)
366         {
367             /* delete entry */
368             BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator));
369
370             /* add port to the set of update trigger ports */
371             JOIN_PORT_TO_MAP(triggerPorts, portID);
372         }
373         else
374         {
375             /* move to the next record */
376             BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
377         }
378     }
379
380     if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
381     {
382         if (portInfo->updateMethod.searchTree != NULL)
383         {
384             ixEthDBFreeMacTreeNode(portInfo->updateMethod.searchTree);
385             portInfo->updateMethod.searchTree = NULL;
386         }
387
388         ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_FILTERING_RECORD);
389     }
390
391     /* mark as disabled */
392     portInfo->enabled = false;
393
394     /* disable updates unless the user has specifically altered the default behavior */
395     if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
396     {
397         if (!portInfo->updateMethod.userControlled)
398         {
399             portInfo->updateMethod.updateEnabled = false;
400         }
401
402         /* make sure we re-initialize the NPE learning tree when the port is re-enabled */
403         portInfo->updateMethod.treeInitialized = false;
404     }
405
406     ixEthDBUpdateUnlock();
407
408     /* restore learning feature bit */
409     portInfo->featureStatus |= learningEnabled;
410
411     /* if we've removed any records or lost any events make sure to force an update */
412     IS_EMPTY_DEPENDENCY_MAP(result, triggerPorts);
413
414     if (!result)
415     {
416         ixEthDBUpdatePortLearningTrees(triggerPorts);
417     }
418
419     return IX_ETH_DB_SUCCESS;
420 }
421
422 /**
423  * @brief sends the updated maximum Tx/Rx frame lengths to the NPE
424  *
425  * @param portID ID of the port to update
426  *
427  * @return IX_ETH_DB_SUCCESS if the update completed
428  * successfully or an appropriate error message otherwise
429  *
430  * @internal
431  */
432 IX_ETH_DB_PRIVATE
433 IxEthDBStatus ixEthDBPortFrameLengthsUpdate(IxEthDBPortId portID)
434 {
435     IxNpeMhMessage message;
436     PortInfo *portInfo = &ixEthDBPortInfo[portID];
437     IX_STATUS result;
438
439     FILL_SETMAXFRAMELENGTHS_MSG(message, portID, portInfo->maxRxFrameSize, portInfo->maxTxFrameSize);
440
441     IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
442
443     return result;
444 }
445
446 /**
447  * @brief sets the port maximum Rx frame size
448  *
449  * @param portID ID of the port to set the frame size on
450  * @param maximumRxFrameSize maximum Rx frame size
451  *
452  * This function updates the internal data structures and
453  * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
454  *
455  * This function is fully documented in the main header
456  * file, IxEthDB.h.
457  *
458  * @return IX_ETH_DB_SUCCESS if the operation was
459  * successfull or an appropriate error message otherwise
460  */
461 IX_ETH_DB_PUBLIC
462 IxEthDBStatus ixEthDBFilteringPortMaximumRxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumRxFrameSize)
463 {
464     IX_ETH_DB_CHECK_PORT_EXISTS(portID);
465
466     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
467
468         if (!ixEthDBPortInfo[portID].initialized)
469         {
470                 return IX_ETH_DB_PORT_UNINITIALIZED;
471         }
472
473     if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
474     {
475         if ((maximumRxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
476             (maximumRxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
477         {
478             return IX_ETH_DB_INVALID_ARG;
479         }
480     }
481     else
482     {
483         return IX_ETH_DB_NO_PERMISSION;
484     }
485
486     /* update internal structure */
487     ixEthDBPortInfo[portID].maxRxFrameSize = maximumRxFrameSize;
488
489     /* update the maximum frame size in the NPE */
490     return ixEthDBPortFrameLengthsUpdate(portID);
491 }
492
493 /**
494  * @brief sets the port maximum Tx frame size
495  *
496  * @param portID ID of the port to set the frame size on
497  * @param maximumTxFrameSize maximum Tx frame size
498  *
499  * This function updates the internal data structures and
500  * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
501  *
502  * This function is fully documented in the main header
503  * file, IxEthDB.h.
504  *
505  * @return IX_ETH_DB_SUCCESS if the operation was
506  * successfull or an appropriate error message otherwise
507  */
508 IX_ETH_DB_PUBLIC
509 IxEthDBStatus ixEthDBFilteringPortMaximumTxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumTxFrameSize)
510 {
511     IX_ETH_DB_CHECK_PORT_EXISTS(portID);
512
513     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
514
515         if (!ixEthDBPortInfo[portID].initialized)
516         {
517                 return IX_ETH_DB_PORT_UNINITIALIZED;
518         }
519
520     if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
521     {
522         if ((maximumTxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
523             (maximumTxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
524         {
525             return IX_ETH_DB_INVALID_ARG;
526         }
527     }
528     else
529     {
530         return IX_ETH_DB_NO_PERMISSION;
531     }
532
533     /* update internal structure */
534     ixEthDBPortInfo[portID].maxTxFrameSize = maximumTxFrameSize;
535
536     /* update the maximum frame size in the NPE */
537     return ixEthDBPortFrameLengthsUpdate(portID);
538 }
539
540 /**
541  * @brief sets the port maximum Tx and Rx frame sizes
542  *
543  * @param portID ID of the port to set the frame size on
544  * @param maximumFrameSize maximum Tx and Rx frame sizes
545  *
546  * This function updates the internal data structures and
547  * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
548  *
549  * Note that both the maximum Tx and Rx frame size are set
550  * to the same value. This function is kept for compatibility
551  * reasons.
552  *
553  * This function is fully documented in the main header
554  * file, IxEthDB.h.
555  *
556  * @return IX_ETH_DB_SUCCESS if the operation was
557  * successfull or an appropriate error message otherwise
558  */
559 IX_ETH_DB_PUBLIC
560 IxEthDBStatus ixEthDBFilteringPortMaximumFrameSizeSet(IxEthDBPortId portID, UINT32 maximumFrameSize)
561 {
562     IX_ETH_DB_CHECK_PORT_EXISTS(portID);
563
564     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
565
566     if (!ixEthDBPortInfo[portID].initialized)
567     {
568         return IX_ETH_DB_PORT_UNINITIALIZED;
569     }
570
571     if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
572     {
573         if ((maximumFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
574             (maximumFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
575         {
576             return IX_ETH_DB_INVALID_ARG;
577         }
578     }
579     else
580     {
581         return IX_ETH_DB_NO_PERMISSION;
582     }
583
584     /* update internal structure */
585     ixEthDBPortInfo[portID].maxRxFrameSize = maximumFrameSize;
586     ixEthDBPortInfo[portID].maxTxFrameSize = maximumFrameSize;
587
588     /* update the maximum frame size in the NPE */
589     return ixEthDBPortFrameLengthsUpdate(portID);
590 }
591
592 /**
593  * @brief sets the MAC address of an NPE port
594  *
595  * @param portID port ID to set the MAC address on
596  * @param macAddr pointer to the 6-byte MAC address
597  *
598  * This function is called by the EthAcc
599  * ixEthAccUnicastMacAddressSet() and should not be
600  * manually invoked unless required by special circumstances.
601  *
602  * @return IX_ETH_DB_SUCCESS if the operation succeeded
603  * or an appropriate error message otherwise
604  */
605 IX_ETH_DB_PUBLIC
606 IxEthDBStatus ixEthDBPortAddressSet(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
607 {
608     IxNpeMhMessage message;
609     IX_STATUS result;
610
611     /* use this macro instead CHECK_PORT
612        as the port doesn't need to be enabled */
613     IX_ETH_DB_CHECK_PORT_EXISTS(portID);
614
615     IX_ETH_DB_CHECK_REFERENCE(macAddr);
616
617     if (!ixEthDBPortInfo[portID].initialized)
618     {
619         return IX_ETH_DB_PORT_UNINITIALIZED;
620     }
621
622     /* Operation stops here when Ethernet Learning is not enabled */
623     if(IX_FEATURE_CTRL_SWCONFIG_DISABLED ==
624        ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
625     {
626         return IX_ETH_DB_SUCCESS;
627     }
628
629     IX_ETH_DB_CHECK_SINGLE_NPE(portID);
630
631     /* exit if the port is not an Ethernet NPE */
632     if (ixEthDBPortDefinitions[portID].type != IX_ETH_NPE)
633     {
634         return IX_ETH_DB_INVALID_PORT;
635     }
636
637     /* populate message */
638     FILL_SETPORTADDRESS_MSG(message, portID, macAddr->macAddress);
639
640     IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Sending SetPortAddress on port %d...\n", portID);
641
642     /* send a SetPortAddress message */
643     IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
644
645     if (result == IX_SUCCESS)
646     {
647         ixEthDBPortInfo[portID].macAddressUploaded = true;
648     }
649
650     return result;
651 }