]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/npe/IxEthDBNPEAdaptor.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 / IxEthDBNPEAdaptor.c
1 /**
2  * @file IxEthDBDBNPEAdaptor.c
3  *
4  * @brief Routines that read and write learning/search trees in NPE-specific format
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_p.h"
22 #include "IxEthDBLog_p.h"
23
24 /* forward prototype declarations */
25 IX_ETH_DB_PUBLIC void ixEthDBELTShow(IxEthDBPortId portID);
26 IX_ETH_DB_PUBLIC void ixEthDBShowNpeMsgHistory(void);
27
28 /* data */
29 UINT8* ixEthDBNPEUpdateArea[IX_ETH_DB_NUMBER_OF_PORTS];
30 UINT32 dumpEltSize;
31
32 /* private data */
33 IX_ETH_DB_PRIVATE IxEthDBNoteWriteFn ixEthDBNPENodeWrite[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1];
34
35 #define IX_ETH_DB_MAX_DELTA_ZONES (6) /* at most 6 EP Delta zones, according to NPE FS */
36 IX_ETH_DB_PRIVATE UINT32 ixEthDBEPDeltaOffset[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1][IX_ETH_DB_MAX_DELTA_ZONES]; 
37 IX_ETH_DB_PRIVATE UINT32 ixEthDBEPDelta[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1][IX_ETH_DB_MAX_DELTA_ZONES];
38
39 /**
40  * @brief allocates non-cached or contiguous NPE tree update areas for all the ports
41  *
42  * This function is called only once at initialization time from
43  * @ref ixEthDBInit().
44  *
45  * @warning do not call manually
46  *
47  * @see ixEthDBInit()
48  *
49  * @internal
50  */
51 IX_ETH_DB_PUBLIC
52 void ixEthDBNPEUpdateAreasInit(void)
53 {
54     UINT32 portIndex;
55     PortUpdateMethod *update;
56
57     for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
58     {
59         update = &ixEthDBPortInfo[portIndex].updateMethod;
60
61         if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
62         {
63             update->npeUpdateZone   = IX_OSAL_CACHE_DMA_MALLOC(FULL_ELT_BYTE_SIZE);
64             update->npeGwUpdateZone = IX_OSAL_CACHE_DMA_MALLOC(FULL_GW_BYTE_SIZE);
65             update->vlanUpdateZone  = IX_OSAL_CACHE_DMA_MALLOC(FULL_VLAN_BYTE_SIZE);
66
67             if (update->npeUpdateZone == NULL
68                 || update->npeGwUpdateZone == NULL
69                 || update->vlanUpdateZone == NULL)
70             {
71                 ERROR_LOG("Fatal error: IX_ACC_DRV_DMA_MALLOC() returned NULL, no NPE update zones available\n");
72             }
73             else
74             {
75                 memset(update->npeUpdateZone, 0, FULL_ELT_BYTE_SIZE);
76                 memset(update->npeGwUpdateZone, 0, FULL_GW_BYTE_SIZE);
77                 memset(update->vlanUpdateZone, 0, FULL_VLAN_BYTE_SIZE);
78             }
79         }
80         else
81         {
82             /* unused */
83             update->npeUpdateZone   = NULL;
84             update->npeGwUpdateZone = NULL;
85             update->vlanUpdateZone  = NULL;
86         }
87     }
88 }
89
90 /**
91  * @brief deallocates the NPE update areas for all the ports
92  *
93  * This function is called at component de-initialization time
94  * by @ref ixEthDBUnload().
95  *
96  * @warning do not call manually
97  *
98  * @internal
99  */
100 IX_ETH_DB_PUBLIC
101 void ixEthDBNPEUpdateAreasUnload(void)
102 {
103     UINT32 portIndex;
104
105     for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
106     {
107         if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
108         {
109             IX_OSAL_CACHE_DMA_FREE(ixEthDBPortInfo[portIndex].updateMethod.npeUpdateZone);
110             IX_OSAL_CACHE_DMA_FREE(ixEthDBPortInfo[portIndex].updateMethod.npeGwUpdateZone);
111             IX_OSAL_CACHE_DMA_FREE(ixEthDBPortInfo[portIndex].updateMethod.vlanUpdateZone);
112         }
113     }
114 }
115
116 /**
117  * @brief general-purpose NPE callback function
118  *
119  * @param npeID NPE ID
120  * @param msg NPE message
121  *
122  * This function will unblock the caller by unlocking
123  * the npeAckLock mutex defined for each NPE port
124  *
125  * @internal
126  */
127 IX_ETH_DB_PUBLIC
128 void ixEthDBNpeMsgAck(IxNpeMhNpeId npeID, IxNpeMhMessage msg)
129 {
130     IxEthDBPortId portID = IX_ETH_DB_NPE_TO_PORT_ID(npeID);
131     PortInfo *portInfo;
132
133     if (portID >= IX_ETH_DB_NUMBER_OF_PORTS)
134     {
135         /* invalid port */
136         return;
137     }
138
139     if (ixEthDBPortDefinitions[portID].type != IX_ETH_NPE)
140     {
141         /* not an NPE */
142         return;
143     }
144
145     portInfo = &ixEthDBPortInfo[portID];
146     
147     ixOsalMutexUnlock(&portInfo->npeAckLock);
148 }
149
150 /**
151  * @brief synchronizes the database with tree
152  *
153  * @param portID port ID of the NPE whose tree is to be scanned
154  * @param eltBaseAddress memory base address of the NPE serialized tree
155  * @param eltSize size in bytes of the NPE serialized tree
156  *
157  * Scans the NPE learning tree and resets the age of active database records.
158  *
159  * @internal
160  */
161 IX_ETH_DB_PUBLIC
162 void ixEthDBNPESyncScan(IxEthDBPortId portID, void *eltBaseAddress, UINT32 eltSize)
163 {
164     UINT32 eltEntryOffset;
165     UINT32 entryPortID;
166
167     /* invalidate cache */
168     IX_OSAL_CACHE_INVALIDATE(eltBaseAddress, eltSize);
169
170     for (eltEntryOffset = ELT_ROOT_OFFSET ; eltEntryOffset < eltSize ; eltEntryOffset += ELT_ENTRY_SIZE)
171     {
172         /* (eltBaseAddress + eltEntryOffset) points to a valid NPE tree node
173          *
174          * the format of the node is MAC[6 bytes]:PortID[1 byte]:Reserved[6 bits]:Active[1 bit]:Valid[1 bit]
175          * therefore we can just use the pointer for database searches as only the first 6 bytes are checked
176          */
177         void *eltNodeAddress       = (void *) ((UINT32) eltBaseAddress + eltEntryOffset);
178
179         /* debug */
180         IX_ETH_DB_NPE_VERBOSE_TRACE("DB: (NPEAdaptor) checking node at offset %d...\n", eltEntryOffset / ELT_ENTRY_SIZE);
181
182         if (IX_EDB_NPE_NODE_VALID(eltNodeAddress) != true)
183         {
184             IX_ETH_DB_NPE_VERBOSE_TRACE("\t... node is empty\n");
185         }
186         else if (eltEntryOffset == ELT_ROOT_OFFSET)
187         {
188             IX_ETH_DB_NPE_VERBOSE_TRACE("\t... node is root\n");
189         }
190
191         if (IX_EDB_NPE_NODE_VALID(eltNodeAddress))
192         {
193             entryPortID = IX_ETH_DB_NPE_LOGICAL_ID_TO_PORT_ID(IX_EDB_NPE_NODE_PORT_ID(eltNodeAddress));
194
195             /* check only active entries belonging to this port */
196             if (ixEthDBPortInfo[portID].agingEnabled && IX_EDB_NPE_NODE_ACTIVE(eltNodeAddress) && (portID == entryPortID)
197                 && ((ixEthDBPortDefinitions[portID].capabilities & IX_ETH_ENTRY_AGING) == 0))
198             {
199                 /* search record */
200                 HashNode *node = ixEthDBSearch((IxEthDBMacAddr *) eltNodeAddress, IX_ETH_DB_ALL_FILTERING_RECORDS);
201
202                 /* safety check, maybe user deleted record right before sync? */
203                 if (node != NULL)
204                 {
205                     /* found record */
206                     MacDescriptor *descriptor = (MacDescriptor *) node->data;
207
208                     IX_ETH_DB_NPE_VERBOSE_TRACE("DB: (NPEAdaptor) synced entry [%s] already in the database, updating fields\n", mac2string(eltNodeAddress));
209
210                     /* reset age - set to -1 so that maintenance will restore it to 0 (or more) when incrementing */
211                     if (!descriptor->recordData.filteringData.staticEntry)
212                     {
213                         if (descriptor->type == IX_ETH_DB_FILTERING_RECORD)
214                         {
215                             descriptor->recordData.filteringData.age = AGE_RESET;
216                         }
217                         else if (descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
218                         {
219                             descriptor->recordData.filteringVlanData.age = AGE_RESET;
220                         }
221                     }
222
223                     /* end transaction */
224                     ixEthDBReleaseHashNode(node);
225                 }
226             }
227             else
228             {
229                 IX_ETH_DB_NPE_VERBOSE_TRACE("\t... found portID %d, we check only port %d\n", entryPortID, portID);
230             }
231         }
232     }
233 }
234
235 /**
236  * @brief writes a search tree in NPE format
237  *
238  * @param type type of records to be written into the NPE update zone
239  * @param totalSize maximum size of the linearized tree
240  * @param baseAddress memory base address where to write the NPE tree into
241  * @param tree search tree to write in NPE format
242  * @param blocks number of written 64-byte blocks
243  * @param startIndex optimal binary search start index
244  *
245  * Serializes the given tree in NPE linear format
246  *
247  * @return none
248  *
249  * @internal
250  */
251 IX_ETH_DB_PUBLIC
252 void ixEthDBNPETreeWrite(IxEthDBRecordType type, UINT32 totalSize, void *baseAddress, MacTreeNode *tree, UINT32 *epDelta, UINT32 *blocks)
253 {
254     MacTreeNodeStack *stack;
255     UINT32 maxOffset = 0;
256     UINT32 emptyOffset;
257
258     stack = ixOsalCacheDmaMalloc(sizeof (MacTreeNodeStack));
259     
260     if (stack == NULL)
261     {
262         ERROR_LOG("DB: (NPEAdaptor) failed to allocate the node stack for learning tree linearization, out of memory?\n");
263         return;
264     }
265
266     /* zero out empty root */
267     memset(baseAddress, 0, ELT_ENTRY_SIZE);
268
269     NODE_STACK_INIT(stack);
270
271     if (tree != NULL)
272     {
273         /* push tree root at offset 1 */
274         NODE_STACK_PUSH(stack, tree, 1);
275
276         maxOffset = 1;
277     }
278
279     while (NODE_STACK_NONEMPTY(stack))
280     {
281         MacTreeNode *node;
282         UINT32 offset;
283
284         NODE_STACK_POP(stack, node, offset);
285
286         /* update maximum offset */
287         if (offset > maxOffset)
288         {
289             maxOffset = offset;
290         }
291
292         IX_ETH_DB_NPE_VERBOSE_TRACE("DB: (NPEAdaptor) writing MAC [%s] at offset %d\n", mac2string(node->descriptor->macAddress), offset);
293
294         /* add node to NPE ELT at position indicated by offset */
295         if (offset < MAX_ELT_SIZE)
296         {
297             ixEthDBNPENodeWrite[type]((void *) (((UINT32) baseAddress) + offset * ELT_ENTRY_SIZE), node);
298         }
299
300         if (node->left != NULL)
301         {
302             NODE_STACK_PUSH(stack, node->left, LEFT_CHILD_OFFSET(offset));
303         }
304         else
305         {
306             /* ensure this entry is zeroed */
307             memset((void *) ((UINT32) baseAddress + LEFT_CHILD_OFFSET(offset) * ELT_ENTRY_SIZE), 0, ELT_ENTRY_SIZE);
308         }
309
310         if (node->right != NULL)
311         {
312             NODE_STACK_PUSH(stack, node->right, RIGHT_CHILD_OFFSET(offset));
313         }
314         else
315         {
316             /* ensure this entry is zeroed */
317             memset((void *) ((UINT32) baseAddress + RIGHT_CHILD_OFFSET(offset) * ELT_ENTRY_SIZE), 0, ELT_ENTRY_SIZE);
318         }
319     }
320     
321     emptyOffset = maxOffset + 1;
322
323     /* zero out rest of the tree */
324     IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Emptying tree from offset %d, address 0x%08X, %d bytes\n", 
325         emptyOffset, ((UINT32) baseAddress) + emptyOffset * ELT_ENTRY_SIZE, totalSize - (emptyOffset * ELT_ENTRY_SIZE));
326
327     if (emptyOffset < MAX_ELT_SIZE - 1)
328     {
329         memset((void *) (((UINT32) baseAddress) + (emptyOffset * ELT_ENTRY_SIZE)), 0, totalSize - (emptyOffset * ELT_ENTRY_SIZE));
330     }
331
332     /* flush cache */
333     IX_OSAL_CACHE_FLUSH(baseAddress, totalSize);
334
335     /* debug */
336     IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Ethernet learning/filtering tree XScale wrote at address 0x%08X (max %d bytes):\n\n",
337         (UINT32) baseAddress, FULL_ELT_BYTE_SIZE);
338
339     IX_ETH_DB_NPE_DUMP_ELT(baseAddress, FULL_ELT_BYTE_SIZE);
340     
341     /* compute number of 64-byte blocks */
342     if (blocks != NULL)
343     {
344         *blocks = maxOffset != 0 ? 1 + maxOffset / 8 : 0;
345
346         IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Wrote %d 64-byte blocks\n", *blocks);
347     }
348     
349     /* compute epDelta - start index for binary search */
350     if (epDelta != NULL)
351     {
352         UINT32 deltaIndex = 0;
353
354         *epDelta = 0;
355         
356         for (; deltaIndex < IX_ETH_DB_MAX_DELTA_ZONES ; deltaIndex ++)
357         {
358             if (ixEthDBEPDeltaOffset[type][deltaIndex] >= maxOffset)
359             {
360                 *epDelta = ixEthDBEPDelta[type][deltaIndex];
361                 break;
362             }
363         }
364
365         IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Computed epDelta %d (based on maxOffset %d)\n", *epDelta, maxOffset);
366     }
367
368     ixOsalCacheDmaFree(stack);
369 }
370
371 /**
372  * @brief implements a dummy node serialization function
373  *
374  * @param address address of where the node is to be serialized (unused)
375  * @param node tree node to be serialized (unused)
376  *
377  * This function is registered for safety reasons and should
378  * never be called. It will display an error message if this
379  * function is called.
380  *
381  * @return none
382  *
383  * @internal
384  */
385 IX_ETH_DB_PRIVATE
386 void ixEthDBNullSerialize(void *address, MacTreeNode *node)
387 {
388     IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Warning, the NullSerialize function was called, wrong record type?\n");
389 }
390
391 /**
392  * @brief writes a filtering entry in NPE linear format
393  *
394  * @param address memory address to write node to
395  * @param node node to be written
396  *
397  * Used by @ref ixEthDBNPETreeWrite to liniarize a search tree
398  * in NPE-readable format.
399  *
400  * @internal
401  */
402 IX_ETH_DB_PRIVATE
403 void ixEthDBNPELearningNodeWrite(void *address, MacTreeNode *node)
404 {
405     /* copy mac address */
406     memcpy(address, node->descriptor->macAddress, IX_IEEE803_MAC_ADDRESS_SIZE);
407
408     /* copy port ID */
409     NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_ELT_PORT_ID_OFFSET) = IX_ETH_DB_PORT_ID_TO_NPE_LOGICAL_ID(node->descriptor->portID);
410
411     /* copy flags (valid and not active, as the NPE sets it to active) and clear reserved section (bits 2-7) */
412     NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_ELT_FLAGS_OFFSET) = (UINT8) IX_EDB_FLAGS_INACTIVE_VALID;
413
414     IX_ETH_DB_NPE_VERBOSE_TRACE("DB: (NPEAdaptor) writing ELT node 0x%08x:0x%08x\n", * (UINT32 *) address, * (((UINT32 *) (address)) + 1));
415 }
416
417 /**
418  * @brief writes a WiFi header conversion record in
419  * NPE linear format
420  *
421  * @param address memory address to write node to
422  * @param node node to be written
423  *
424  * Used by @ref ixEthDBNPETreeWrite to liniarize a search tree
425  * in NPE-readable format.
426  *
427  * @internal
428  */
429 IX_ETH_DB_PRIVATE
430 void ixEthDBNPEWiFiNodeWrite(void *address, MacTreeNode *node)
431 {
432     /* copy mac address */
433     memcpy(address, node->descriptor->macAddress, IX_IEEE803_MAC_ADDRESS_SIZE);
434
435     /* copy index */
436     NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_WIFI_INDEX_OFFSET) = node->descriptor->recordData.wifiData.gwAddressIndex;
437
438     /* copy flags (type and valid) */
439     NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_WIFI_FLAGS_OFFSET) = node->descriptor->recordData.wifiData.type << 1 | IX_EDB_FLAGS_VALID;
440 }
441
442 /**
443  * @brief writes a WiFi gateway header conversion record in
444  * NPE linear format
445  *
446  * @param address memory address to write node to
447  * @param node node to be written
448  *
449  * Used by @ref ixEthDBNPETreeWrite to liniarize a search tree
450  * in NPE-readable format.
451  *
452  * @internal
453  */
454 IX_ETH_DB_PUBLIC
455 void ixEthDBNPEGatewayNodeWrite(void *address, MacTreeNode *node)
456 {
457     /* copy mac address */
458     memcpy(address, node->descriptor->recordData.wifiData.gwMacAddress, IX_IEEE803_MAC_ADDRESS_SIZE);
459
460     /* set reserved field, two bytes */
461     NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_FW_RESERVED_OFFSET)     = 0;
462     NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_FW_RESERVED_OFFSET + 1) = 0;
463 }
464
465 /**
466  * @brief writes a firewall record in
467  * NPE linear format
468  *
469  * @param address memory address to write node to
470  * @param node node to be written
471  *
472  * Used by @ref ixEthDBNPETreeWrite to liniarize a search tree
473  * in NPE-readable format.
474  *
475  * @internal
476  */
477 IX_ETH_DB_PRIVATE
478 void ixEthDBNPEFirewallNodeWrite(void *address, MacTreeNode *node)
479 {
480     /* set reserved field */
481     NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_FW_RESERVED_OFFSET) = 0;
482
483     /* set flags */
484     NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_FW_FLAGS_OFFSET) = IX_EDB_FLAGS_VALID;
485
486     /* copy mac address */
487     memcpy((void *) ((UINT32) address + IX_EDB_NPE_NODE_FW_ADDR_OFFSET), node->descriptor->macAddress, IX_IEEE803_MAC_ADDRESS_SIZE);
488 }
489
490 /**
491  * @brief registers the NPE serialization methods
492  *
493  * This functions registers NPE serialization methods
494  * for writing the following types of records in NPE
495  * readable linear format:
496  * - filtering records
497  * - WiFi header conversion records
498  * - WiFi gateway header conversion records
499  * - firewall records
500  *
501  * Note that this function should be called by the
502  * component initialization function.
503  *
504  * @return number of registered record types
505  *
506  * @internal
507  */
508 IX_ETH_DB_PUBLIC
509 UINT32 ixEthDBRecordSerializeMethodsRegister()
510 {
511     int i;
512     
513     /* safety - register a blank method for everybody first */
514     for ( i = 0 ; i < IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1 ; i++)
515     {
516         ixEthDBNPENodeWrite[i] = ixEthDBNullSerialize;
517     }
518     
519     /* register real methods */
520     ixEthDBNPENodeWrite[IX_ETH_DB_FILTERING_RECORD]      = ixEthDBNPELearningNodeWrite;
521     ixEthDBNPENodeWrite[IX_ETH_DB_FILTERING_VLAN_RECORD] = ixEthDBNPELearningNodeWrite;
522     ixEthDBNPENodeWrite[IX_ETH_DB_WIFI_RECORD]           = ixEthDBNPEWiFiNodeWrite;
523     ixEthDBNPENodeWrite[IX_ETH_DB_FIREWALL_RECORD]       = ixEthDBNPEFirewallNodeWrite;
524     ixEthDBNPENodeWrite[IX_ETH_DB_GATEWAY_RECORD]        = ixEthDBNPEGatewayNodeWrite;
525     
526     /* EP Delta arrays */
527     memset(ixEthDBEPDeltaOffset, 0, sizeof (ixEthDBEPDeltaOffset));
528     memset(ixEthDBEPDelta, 0, sizeof (ixEthDBEPDelta));
529     
530     /* filtering records */
531     ixEthDBEPDeltaOffset[IX_ETH_DB_FILTERING_RECORD][0] = 1;
532     ixEthDBEPDelta[IX_ETH_DB_FILTERING_RECORD][0]       = 0;
533     
534     ixEthDBEPDeltaOffset[IX_ETH_DB_FILTERING_RECORD][1] = 3;
535     ixEthDBEPDelta[IX_ETH_DB_FILTERING_RECORD][1]       = 7;
536     
537     ixEthDBEPDeltaOffset[IX_ETH_DB_FILTERING_RECORD][2] = 511;
538     ixEthDBEPDelta[IX_ETH_DB_FILTERING_RECORD][2]       = 14;
539     
540     /* wifi records */
541     ixEthDBEPDeltaOffset[IX_ETH_DB_WIFI_RECORD][0] = 1;
542     ixEthDBEPDelta[IX_ETH_DB_WIFI_RECORD][0]       = 0;
543     
544     ixEthDBEPDeltaOffset[IX_ETH_DB_WIFI_RECORD][1] = 3;
545     ixEthDBEPDelta[IX_ETH_DB_WIFI_RECORD][1]       = 7;
546     
547     ixEthDBEPDeltaOffset[IX_ETH_DB_WIFI_RECORD][2] = 511;
548     ixEthDBEPDelta[IX_ETH_DB_WIFI_RECORD][2]       = 14;
549
550     /* firewall records */
551     ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][0] = 0;
552     ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][0]       = 0;
553     
554     ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][1] = 1;
555     ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][1]       = 5;
556     
557     ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][2] = 3;
558     ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][2]       = 13;
559     
560     ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][3] = 7;
561     ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][3]       = 21;
562     
563     ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][4] = 15;
564     ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][4]       = 29;
565     
566     ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][5] = 31;
567     ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][5]       = 37;
568     
569     return 5; /* 5 methods registered */
570 }
571
572 #ifndef IX_NDEBUG
573
574 IX_ETH_DB_PUBLIC UINT32 npeMsgHistory[IX_ETH_DB_NPE_MSG_HISTORY_DEPTH][2];
575 IX_ETH_DB_PUBLIC UINT32 npeMsgHistoryLen = 0;
576
577 /**
578  * When compiled in DEBUG mode, this function can be used to display
579  * the history of messages sent to the NPEs (up to 100).
580  */
581 IX_ETH_DB_PUBLIC
582 void ixEthDBShowNpeMsgHistory()
583 {
584     UINT32 i = 0;
585     UINT32 base, len;
586
587     if (npeMsgHistoryLen <= IX_ETH_DB_NPE_MSG_HISTORY_DEPTH)
588     {
589         base = 0;
590         len  = npeMsgHistoryLen;
591     }
592     else
593     {
594         base = npeMsgHistoryLen % IX_ETH_DB_NPE_MSG_HISTORY_DEPTH;
595         len  = IX_ETH_DB_NPE_MSG_HISTORY_DEPTH;
596     }
597
598     printf("NPE message history [last %d messages, from least to most recent]:\n", len);
599
600     for (; i < len ; i++)
601     {
602         UINT32 pos = (base + i) % IX_ETH_DB_NPE_MSG_HISTORY_DEPTH;
603         printf("msg[%d]: 0x%08x:0x%08x\n", i, npeMsgHistory[pos][0], npeMsgHistory[pos][1]);
604     }
605 }
606
607 IX_ETH_DB_PUBLIC
608 void ixEthDBELTShow(IxEthDBPortId portID)
609 {
610     IxNpeMhMessage message;
611     IX_STATUS result;
612     
613     /* send EDB_GetMACAddressDatabase message */
614     FILL_GETMACADDRESSDATABASE(message, 
615         0 /* reserved */, 
616         IX_OSAL_MMU_VIRT_TO_PHYS(ixEthDBPortInfo[portID].updateMethod.npeUpdateZone));
617
618     IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
619
620     if (result == IX_SUCCESS)
621     {
622         /* analyze NPE copy */
623         UINT32 eltEntryOffset;
624         UINT32 entryPortID;
625
626         UINT32 eltBaseAddress = (UINT32) ixEthDBPortInfo[portID].updateMethod.npeUpdateZone;
627         UINT32 eltSize        = FULL_ELT_BYTE_SIZE;
628
629         /* invalidate cache */
630         IX_OSAL_CACHE_INVALIDATE((void *) eltBaseAddress, eltSize);
631
632         printf("Listing records in main learning tree for port %d\n", portID);
633
634         for (eltEntryOffset = ELT_ROOT_OFFSET ; eltEntryOffset < eltSize ; eltEntryOffset += ELT_ENTRY_SIZE)
635         {
636             /* (eltBaseAddress + eltEntryOffset) points to a valid NPE tree node
637             *
638             * the format of the node is MAC[6 bytes]:PortID[1 byte]:Reserved[6 bits]:Active[1 bit]:Valid[1 bit]
639             * therefore we can just use the pointer for database searches as only the first 6 bytes are checked
640             */
641             void *eltNodeAddress = (void *) ((UINT32) eltBaseAddress + eltEntryOffset);
642
643             if (IX_EDB_NPE_NODE_VALID(eltNodeAddress))
644             {
645                 HashNode *node;
646
647                 entryPortID = IX_ETH_DB_NPE_LOGICAL_ID_TO_PORT_ID(IX_EDB_NPE_NODE_PORT_ID(eltNodeAddress));
648
649                 /* search record */
650                 node = ixEthDBSearch((IxEthDBMacAddr *) eltNodeAddress, IX_ETH_DB_ALL_RECORD_TYPES);
651
652                 printf("%s - port %d - %s ", mac2string((unsigned char *) eltNodeAddress), entryPortID, 
653                     IX_EDB_NPE_NODE_ACTIVE(eltNodeAddress) ? "active" : "inactive");
654
655                 /* safety check, maybe user deleted record right before sync? */
656                 if (node != NULL)
657                 {
658                     /* found record */
659                     MacDescriptor *descriptor = (MacDescriptor *) node->data;
660
661                     printf("- %s ",
662                         descriptor->type == IX_ETH_DB_FILTERING_RECORD ? "filtering" :
663                         descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD ? "vlan" :
664                         descriptor->type == IX_ETH_DB_WIFI_RECORD ? "wifi" : "other (check main DB)");
665
666                     if (descriptor->type == IX_ETH_DB_FILTERING_RECORD) printf("- age %d - %s ", 
667                         descriptor->recordData.filteringData.age,
668                         descriptor->recordData.filteringData.staticEntry ? "static" : "dynamic");
669
670                     if (descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD) printf("- age %d - %s - tci %d ",
671                         descriptor->recordData.filteringVlanData.age,
672                         descriptor->recordData.filteringVlanData.staticEntry ? "static" : "dynamic",
673                         descriptor->recordData.filteringVlanData.ieee802_1qTag);
674
675                     /* end transaction */
676                     ixEthDBReleaseHashNode(node);
677                 }
678                 else
679                 {
680                     printf("- not synced");
681                 }
682
683                 printf("\n");
684             }
685         }
686     }
687     else
688     {
689         ixOsalLog(IX_OSAL_LOG_LVL_FATAL, IX_OSAL_LOG_DEV_STDOUT, 
690             "EthDB: (ShowELT) Could not complete action (communication failure)\n",
691             portID, 0, 0, 0, 0, 0);
692     }
693 }
694
695 #endif