1/*
2 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
3 * Permission to use, copy, modify, and/or distribute this software for
4 * any purpose with or without fee is hereby granted, provided that the
5 * above copyright notice and this permission notice appear in all copies.
6 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
7 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
8 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
9 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
10 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
11 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
12 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
13 */
14
15
16/**
17 * @defgroup horus_fdb HORUS_FDB
18 * @{
19 */
20#include "sw.h"
21#include "hsl.h"
22#include "hsl_dev.h"
23#include "hsl_port_prop.h"
24#include "horus_fdb.h"
25#include "horus_reg.h"
26
27#define ARL_FLUSH_ALL             1
28#define ARL_LOAD_ENTRY            2
29#define ARL_PURGE_ENTRY           3
30#define ARL_FLUSH_ALL_UNLOCK      4
31#define ARL_FLUSH_PORT_UNICAST    5
32#define ARL_NEXT_ENTRY            6
33#define ARL_FIND_ENTRY            7
34
35#define ARL_FIRST_ENTRY           1001
36#define ARL_FLUSH_PORT_NO_STATIC  1002
37#define ARL_FLUSH_PORT_AND_STATIC 1003
38
39static a_bool_t
40horus_fdb_is_zeroaddr(fal_mac_addr_t addr)
41{
42    a_uint32_t i;
43
44    for (i = 0; i < 6; i++)
45    {
46        if (addr.uc[i])
47        {
48            return A_FALSE;
49        }
50    }
51
52    return A_TRUE;
53}
54
55static void
56horus_fdb_fill_addr(fal_mac_addr_t addr, a_uint32_t * reg0, a_uint32_t * reg1)
57{
58    SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_ADDR_BYTE0, addr.uc[0], *reg1);
59    SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_ADDR_BYTE1, addr.uc[1], *reg1);
60    SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_ADDR_BYTE2, addr.uc[2], *reg1);
61    SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_ADDR_BYTE3, addr.uc[3], *reg1);
62
63    SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_ADDR_BYTE4, addr.uc[4], *reg0);
64    SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_ADDR_BYTE5, addr.uc[5], *reg0);
65
66    return;
67}
68
69static sw_error_t
70horus_atu_sw_to_hw(a_uint32_t dev_id, const fal_fdb_entry_t * entry,
71                   a_uint32_t reg[])
72{
73    a_uint32_t port;
74
75    if (A_FALSE == entry->portmap_en)
76    {
77        if (A_TRUE !=
78                hsl_port_prop_check(dev_id, entry->port.id, HSL_PP_INCL_CPU))
79        {
80            return SW_BAD_PARAM;
81        }
82
83        port = 0x1UL << entry->port.id;
84    }
85    else
86    {
87        if (A_FALSE ==
88                hsl_mports_prop_check(dev_id, entry->port.map, HSL_PP_INCL_CPU))
89        {
90            return SW_BAD_PARAM;
91        }
92
93        port = entry->port.map;
94    }
95
96    if (FAL_MAC_CPY_TO_CPU == entry->dacmd)
97    {
98        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, COPY_TO_CPU, 1, reg[2]);
99    }
100    else if (FAL_MAC_RDT_TO_CPU == entry->dacmd)
101    {
102        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, REDRCT_TO_CPU, 1, reg[2]);
103    }
104    else if (FAL_MAC_FRWRD != entry->dacmd)
105    {
106        return SW_NOT_SUPPORTED;
107    }
108
109    if (FAL_MAC_DROP == entry->sacmd)
110    {
111        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, SA_DROP_EN, 1, reg[2]);
112    }
113    else if (FAL_MAC_FRWRD != entry->sacmd)
114    {
115        return SW_NOT_SUPPORTED;
116    }
117
118    if (A_TRUE == entry->leaky_en)
119    {
120        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, LEAKY_EN, 1, reg[2]);
121    }
122    else
123    {
124        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, LEAKY_EN, 0, reg[2]);
125    }
126
127    if (A_TRUE == entry->static_en)
128    {
129        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_STATUS, 15, reg[2]);
130    }
131    else
132    {
133        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_STATUS, 7, reg[2]);
134    }
135
136    if (A_TRUE == entry->mirror_en)
137    {
138        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, MIRROR_EN, 1, reg[2]);
139    }
140
141    if (A_TRUE == entry->clone_en)
142    {
143        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, CLONE_EN, 1, reg[2]);
144    }
145
146    if (A_TRUE == entry->cross_pt_state)
147    {
148        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, CROSS_PT, 1, reg[2]);
149    }
150
151    if (A_TRUE == entry->da_pri_en)
152    {
153        hsl_dev_t *p_dev;
154
155        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_PRI_EN, 1, reg[2]);
156
157        SW_RTN_ON_NULL(p_dev = hsl_dev_ptr_get(dev_id));
158
159        if (entry->da_queue > (p_dev->nr_queue - 1))
160            return SW_BAD_PARAM;
161
162        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_PRI, entry->da_queue, reg[2]);
163    }
164
165    SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, DES_PORT, port, reg[2]);
166    horus_fdb_fill_addr(entry->addr, &reg[0], &reg[1]);
167
168    return SW_OK;
169}
170
171static void
172horus_atu_hw_to_sw(const a_uint32_t reg[], fal_fdb_entry_t * entry)
173{
174    a_uint32_t i, data;
175
176    aos_mem_zero(entry, sizeof (fal_fdb_entry_t));
177
178    entry->dacmd = FAL_MAC_FRWRD;
179    SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, COPY_TO_CPU, data, reg[2]);
180    if (1 == data)
181    {
182        entry->dacmd = FAL_MAC_CPY_TO_CPU;
183    }
184
185    SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, REDRCT_TO_CPU, data, reg[2]);
186    if (1 == data)
187    {
188        entry->dacmd = FAL_MAC_RDT_TO_CPU;
189    }
190
191    entry->sacmd = FAL_MAC_FRWRD;
192    SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, SA_DROP_EN, data, reg[2]);
193    if (1 == data)
194    {
195        entry->sacmd = FAL_MAC_DROP;
196    }
197
198    entry->leaky_en = A_FALSE;
199    SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, LEAKY_EN, data, reg[2]);
200    if (1 == data)
201    {
202        entry->leaky_en = A_TRUE;
203    }
204
205    entry->static_en = A_FALSE;
206    SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, AT_STATUS, data, reg[2]);
207    if (0xf == data)
208    {
209        entry->static_en = A_TRUE;
210    }
211
212    entry->mirror_en = A_FALSE;
213    SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, MIRROR_EN, data, reg[2]);
214    if (1 == data)
215    {
216        entry->mirror_en = A_TRUE;
217    }
218
219    entry->clone_en = A_FALSE;
220    SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, CLONE_EN, data, reg[2]);
221    if (1 == data)
222    {
223        entry->clone_en = A_TRUE;
224    }
225
226    entry->da_pri_en = A_FALSE;
227    SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, AT_PRI_EN, data, reg[2]);
228    if (1 == data)
229    {
230        SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, AT_PRI, data, reg[2]);
231        entry->da_pri_en = A_TRUE;
232        entry->da_queue = data & 0x3;
233    }
234
235    entry->cross_pt_state = A_FALSE;
236    SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, CROSS_PT, data, reg[2]);
237    if (1 == data)
238    {
239        entry->cross_pt_state = A_TRUE;
240    }
241
242    SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, DES_PORT, data, reg[2]);
243
244    entry->portmap_en = A_TRUE;
245    entry->port.map = data;
246
247    for (i = 0; i < 4; i++)
248    {
249        entry->addr.uc[i] = (reg[1] >> ((3 - i) << 3)) & 0xff;
250    }
251
252    for (i = 4; i < 6; i++)
253    {
254        entry->addr.uc[i] = (reg[0] >> ((7 - i) << 3)) & 0xff;
255    }
256
257    return;
258}
259
260static sw_error_t
261horus_fdb_commit(a_uint32_t dev_id, a_uint32_t op)
262{
263    sw_error_t rv;
264    a_uint32_t busy = 1;
265    a_uint32_t full_vio;
266    a_uint32_t i = 1000;
267    a_uint32_t entry;
268    a_uint32_t hwop = op;
269
270    while (busy && --i)
271    {
272        HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_FUNC0, 0, AT_BUSY,
273                          (a_uint8_t *) (&busy), sizeof (a_uint32_t));
274        SW_RTN_ON_ERROR(rv);
275        aos_udelay(5);
276    }
277
278    if (0 == i)
279    {
280        return SW_BUSY;
281    }
282
283    HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC0, 0,
284                      (a_uint8_t *) (&entry), sizeof (a_uint32_t));
285    SW_RTN_ON_ERROR(rv);
286
287    SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_BUSY, 1, entry);
288
289    if (ARL_FLUSH_PORT_AND_STATIC == hwop)
290    {
291        hwop = ARL_FLUSH_PORT_UNICAST;
292        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, FLUSH_ST_EN, 1, entry);
293    }
294
295    if (ARL_FLUSH_PORT_NO_STATIC == hwop)
296    {
297        hwop = ARL_FLUSH_PORT_UNICAST;
298        SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, FLUSH_ST_EN, 0, entry);
299    }
300
301    SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_FUNC, hwop, entry);
302
303    HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0,
304                      (a_uint8_t *) (&entry), sizeof (a_uint32_t));
305    SW_RTN_ON_ERROR(rv);
306
307    busy = 1;
308    i = 1000;
309    while (busy && --i)
310    {
311        HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_FUNC0, 0, AT_BUSY,
312                          (a_uint8_t *) (&busy), sizeof (a_uint32_t));
313        SW_RTN_ON_ERROR(rv);
314        aos_udelay(5);
315    }
316
317    if (0 == i)
318    {
319        return SW_FAIL;
320    }
321
322    HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_FUNC0, 0, AT_FULL_VIO,
323                      (a_uint8_t *) (&full_vio), sizeof (a_uint32_t));
324    SW_RTN_ON_ERROR(rv);
325
326    if (full_vio)
327    {
328        /* must clear AT_FULL_VOI bit */
329        entry = 0x1000;
330        HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0,
331                          (a_uint8_t *) (&entry), sizeof (a_uint32_t));
332        SW_RTN_ON_ERROR(rv);
333
334        if (ARL_LOAD_ENTRY == hwop)
335        {
336            return SW_FULL;
337        }
338        else if ((ARL_PURGE_ENTRY == hwop)
339                 || (ARL_FLUSH_PORT_UNICAST == hwop))
340        {
341            return SW_NOT_FOUND;
342        }
343        else
344        {
345            return SW_FAIL;
346        }
347    }
348
349    return SW_OK;
350}
351
352static sw_error_t
353horus_atu_get(a_uint32_t dev_id, fal_fdb_entry_t * entry, a_uint32_t op)
354{
355    sw_error_t rv;
356    a_uint32_t reg[3] = { 0 };
357    a_uint32_t status = 0;
358    a_uint32_t hwop = op;
359
360    if ((ARL_NEXT_ENTRY == op)
361            || (ARL_FIND_ENTRY == op))
362    {
363        horus_fdb_fill_addr(entry->addr, &reg[0], &reg[1]);
364    }
365
366    HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0,
367                      (a_uint8_t *) (&reg[0]), sizeof (a_uint32_t));
368    SW_RTN_ON_ERROR(rv);
369
370    HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC1, 0,
371                      (a_uint8_t *) (&reg[1]), sizeof (a_uint32_t));
372    SW_RTN_ON_ERROR(rv);
373
374    /* set status not zero */
375    if (ARL_NEXT_ENTRY == op)
376    {
377        reg[2] = 0xf0000;
378    }
379
380    if (ARL_FIRST_ENTRY == op)
381    {
382        hwop = ARL_NEXT_ENTRY;
383    }
384
385    HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC2, 0,
386                      (a_uint8_t *) (&reg[2]), sizeof (a_uint32_t));
387    SW_RTN_ON_ERROR(rv);
388
389    rv = horus_fdb_commit(dev_id, hwop);
390    SW_RTN_ON_ERROR(rv);
391
392    /* get hardware enrety */
393    HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC0, 0,
394                      (a_uint8_t *) (&reg[0]), sizeof (a_uint32_t));
395
396    SW_RTN_ON_ERROR(rv);
397
398    HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC1, 0,
399                      (a_uint8_t *) (&reg[1]), sizeof (a_uint32_t));
400
401    SW_RTN_ON_ERROR(rv);
402
403    HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC2, 0,
404                      (a_uint8_t *) (&reg[2]), sizeof (a_uint32_t));
405
406    SW_RTN_ON_ERROR(rv);
407
408    SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, AT_STATUS, status, reg[2]);
409
410    horus_atu_hw_to_sw(reg, entry);
411
412    /* If hardware return back with address and status all zero,
413       that means no other next valid entry in fdb table */
414    if ((A_TRUE == horus_fdb_is_zeroaddr(entry->addr))
415            && (0 == status))
416    {
417        if (ARL_NEXT_ENTRY == op)
418        {
419            return SW_NO_MORE;
420        }
421        else if ((ARL_FIND_ENTRY == op)
422                 || (ARL_FIRST_ENTRY == op))
423        {
424            return SW_NOT_FOUND;
425        }
426        else
427        {
428            return SW_FAIL;
429        }
430    }
431    else
432    {
433        return SW_OK;
434    }
435}
436
437static sw_error_t
438_horus_fdb_add(a_uint32_t dev_id, const fal_fdb_entry_t * entry)
439{
440    sw_error_t rv;
441    a_uint32_t reg[3] = { 0, 0, 0 };
442
443    HSL_DEV_ID_CHECK(dev_id);
444
445    rv = horus_atu_sw_to_hw(dev_id, entry, reg);
446    SW_RTN_ON_ERROR(rv);
447
448    HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC2, 0,
449                      (a_uint8_t *) (&reg[2]), sizeof (a_uint32_t));
450    SW_RTN_ON_ERROR(rv);
451
452    HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC1, 0, (a_uint8_t *) (&reg[1]),
453                      sizeof (a_uint32_t));
454    SW_RTN_ON_ERROR(rv);
455
456    HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0, (a_uint8_t *) (&reg[0]),
457                      sizeof (a_uint32_t));
458    SW_RTN_ON_ERROR(rv);
459
460    rv = horus_fdb_commit(dev_id, ARL_LOAD_ENTRY);
461
462    return rv;
463}
464
465static sw_error_t
466_horus_fdb_del_all(a_uint32_t dev_id, a_uint32_t flag)
467{
468    sw_error_t rv;
469
470    HSL_DEV_ID_CHECK(dev_id);
471
472    if (FAL_FDB_DEL_STATIC & flag)
473    {
474        rv = horus_fdb_commit(dev_id, ARL_FLUSH_ALL);
475    }
476    else
477    {
478        rv = horus_fdb_commit(dev_id, ARL_FLUSH_ALL_UNLOCK);
479    }
480
481    return rv;
482}
483
484static sw_error_t
485_horus_fdb_del_by_port(a_uint32_t dev_id, fal_port_t port_id, a_uint32_t flag)
486{
487    sw_error_t rv;
488    a_uint32_t reg = 0;
489
490    HSL_DEV_ID_CHECK(dev_id);
491
492    if (A_FALSE == hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU))
493    {
494        return SW_BAD_PARAM;
495    }
496
497    SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_PORT_NUM, port_id, reg);
498
499    HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0, (a_uint8_t *) (&reg),
500                      sizeof (a_uint32_t));
501    SW_RTN_ON_ERROR(rv);
502
503    if (FAL_FDB_DEL_STATIC & flag)
504    {
505        rv = horus_fdb_commit(dev_id, ARL_FLUSH_PORT_AND_STATIC);
506    }
507    else
508    {
509        rv = horus_fdb_commit(dev_id, ARL_FLUSH_PORT_NO_STATIC);
510    }
511
512    return rv;
513}
514
515static sw_error_t
516_horus_fdb_del_by_mac(a_uint32_t dev_id, const fal_fdb_entry_t * entry)
517{
518    sw_error_t rv;
519    a_uint32_t reg0 = 0, reg1 = 0;
520
521    HSL_DEV_ID_CHECK(dev_id);
522
523    horus_fdb_fill_addr(entry->addr, &reg0, &reg1);
524
525    HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC1, 0, (a_uint8_t *) (&reg1),
526                      sizeof (a_uint32_t));
527    SW_RTN_ON_ERROR(rv);
528
529    HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0, (a_uint8_t *) (&reg0),
530                      sizeof (a_uint32_t));
531    SW_RTN_ON_ERROR(rv);
532
533    rv = horus_fdb_commit(dev_id, ARL_PURGE_ENTRY);
534    return rv;
535}
536
537static sw_error_t
538_horus_fdb_next(a_uint32_t dev_id, fal_fdb_entry_t * entry)
539{
540    sw_error_t rv;
541
542    HSL_DEV_ID_CHECK(dev_id);
543
544    rv = horus_atu_get(dev_id, entry, ARL_NEXT_ENTRY);
545    return rv;
546}
547
548static sw_error_t
549_horus_fdb_first(a_uint32_t dev_id, fal_fdb_entry_t * entry)
550{
551    sw_error_t rv;
552
553    HSL_DEV_ID_CHECK(dev_id);
554
555    rv = horus_atu_get(dev_id, entry, ARL_FIRST_ENTRY);
556    return rv;
557}
558
559static sw_error_t
560_horus_fdb_find(a_uint32_t dev_id, fal_fdb_entry_t * entry)
561{
562    sw_error_t rv;
563
564    HSL_DEV_ID_CHECK(dev_id);
565
566    rv = horus_atu_get(dev_id, entry, ARL_FIND_ENTRY);
567    return rv;
568}
569
570static sw_error_t
571_horus_fdb_port_learn_set(a_uint32_t dev_id, fal_port_t port_id,
572                          a_bool_t enable)
573{
574    a_uint32_t data;
575    sw_error_t rv;
576
577    HSL_DEV_ID_CHECK(dev_id);
578
579    if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU))
580    {
581        return SW_BAD_PARAM;
582    }
583
584    if (A_TRUE == enable)
585    {
586        data = 1;
587    }
588    else if (A_FALSE == enable)
589    {
590        data = 0;
591    }
592    else
593    {
594        return SW_BAD_PARAM;
595    }
596
597    HSL_REG_FIELD_SET(rv, dev_id, PORT_CTL, port_id, LEARN_EN,
598                      (a_uint8_t *) (&data), sizeof (a_uint32_t));
599    return rv;
600}
601
602static sw_error_t
603_horus_fdb_port_learn_get(a_uint32_t dev_id, fal_port_t port_id,
604                          a_bool_t *enable)
605{
606    a_uint32_t data;
607    sw_error_t rv;
608
609    HSL_DEV_ID_CHECK(dev_id);
610
611    if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU))
612    {
613        return SW_BAD_PARAM;
614    }
615
616    HSL_REG_FIELD_GET(rv, dev_id, PORT_CTL, port_id, LEARN_EN,
617                      (a_uint8_t *) (&data), sizeof (a_uint32_t));
618    SW_RTN_ON_ERROR(rv);
619
620    if (1 == data)
621    {
622        *enable = A_TRUE;
623    }
624    else
625    {
626        *enable = A_FALSE;
627    }
628
629    return SW_OK;
630}
631
632static sw_error_t
633_horus_fdb_age_ctrl_set(a_uint32_t dev_id, a_bool_t enable)
634{
635    a_uint32_t data;
636    sw_error_t rv;
637
638    HSL_DEV_ID_CHECK(dev_id);
639
640    if (A_TRUE == enable)
641    {
642        data = 1;
643    }
644    else if (A_FALSE == enable)
645    {
646        data = 0;
647    }
648    else
649    {
650        return SW_BAD_PARAM;
651    }
652
653    HSL_REG_FIELD_SET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_EN,
654                      (a_uint8_t *) (&data), sizeof (a_uint32_t));
655    return rv;
656}
657
658static sw_error_t
659_horus_fdb_age_ctrl_get(a_uint32_t dev_id, a_bool_t *enable)
660{
661    a_uint32_t data;
662    sw_error_t rv;
663
664    HSL_DEV_ID_CHECK(dev_id);
665
666    HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_EN,
667                      (a_uint8_t *) (&data), sizeof (a_uint32_t));
668    SW_RTN_ON_ERROR(rv);
669
670    if (1 == data)
671    {
672        *enable = A_TRUE;
673    }
674    else
675    {
676        *enable = A_FALSE;
677    }
678
679    return SW_OK;
680}
681
682static sw_error_t
683_horus_fdb_age_time_set(a_uint32_t dev_id, a_uint32_t * time)
684{
685    a_uint32_t data;
686    sw_error_t rv;
687
688    HSL_DEV_ID_CHECK(dev_id);
689
690    if ((65535 * 7 < *time) || (7 > *time))
691    {
692        return SW_BAD_PARAM;
693    }
694    data = *time / 7;
695    *time = data * 7;
696    HSL_REG_FIELD_SET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_TIME,
697                      (a_uint8_t *) (&data), sizeof (a_uint32_t));
698    return rv;
699}
700
701static sw_error_t
702_horus_fdb_age_time_get(a_uint32_t dev_id, a_uint32_t *time)
703{
704    a_uint32_t data;
705    sw_error_t rv;
706
707    HSL_DEV_ID_CHECK(dev_id);
708
709    HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_TIME,
710                      (a_uint8_t *) (&data), sizeof (a_uint32_t));
711    SW_RTN_ON_ERROR(rv);
712
713    *time = data * 7;
714    return SW_OK;
715}
716
717/**
718 * @brief Add a Fdb entry
719 * @param[in] dev_id device id
720 * @param[in] entry fdb entry
721 * @return SW_OK or error code
722 */
723HSL_LOCAL sw_error_t
724horus_fdb_add(a_uint32_t dev_id, const fal_fdb_entry_t * entry)
725{
726    sw_error_t rv;
727
728    HSL_API_LOCK;
729    rv = _horus_fdb_add(dev_id, entry);
730    HSL_API_UNLOCK;
731    return rv;
732}
733
734/**
735 * @brief Delete all Fdb entries
736 *   @details   Comments:
737 *         If set FAL_FDB_DEL_STATIC bit in flag which means delete all fdb
738 *       entries otherwise only delete dynamic entries.
739 * @param[in] dev_id device id
740 * @param[in] flag delete operation option
741 * @return SW_OK or error code
742 */
743HSL_LOCAL sw_error_t
744horus_fdb_del_all(a_uint32_t dev_id, a_uint32_t flag)
745{
746    sw_error_t rv;
747
748    HSL_API_LOCK;
749    rv = _horus_fdb_del_all(dev_id, flag);
750    HSL_API_UNLOCK;
751    return rv;
752}
753
754/**
755 * @brief Delete Fdb entries on a particular port
756 *   @details   Comments:
757 *       If set FAL_FDB_DEL_STATIC bit in flag which means delete all fdb
758 *       entries otherwise only delete dynamic entries.
759 * @param[in] dev_id device id
760 * @param[in] port_id port id
761 * @param[in] flag delete operation option
762 * @return SW_OK or error code
763 */
764HSL_LOCAL sw_error_t
765horus_fdb_del_by_port(a_uint32_t dev_id, fal_port_t port_id, a_uint32_t flag)
766{
767    sw_error_t rv;
768
769    HSL_API_LOCK;
770    rv = _horus_fdb_del_by_port(dev_id, port_id, flag);
771    HSL_API_UNLOCK;
772    return rv;
773}
774
775/**
776 * @brief Delete a particular Fdb entry through mac address
777 *   @details   Comments:
778 *       Only addr field in entry is meaning. For IVL learning vid or fid field
779 *       also is meaning.
780 * @param[in] dev_id device id
781 * @param[in] entry fdb entry
782 * @return SW_OK or error code
783 */
784HSL_LOCAL sw_error_t
785horus_fdb_del_by_mac(a_uint32_t dev_id, const fal_fdb_entry_t * entry)
786{
787    sw_error_t rv;
788
789    HSL_API_LOCK;
790    rv = _horus_fdb_del_by_mac(dev_id, entry);
791    HSL_API_UNLOCK;
792    return rv;
793}
794
795/**
796 * @brief Get next Fdb entry from particular device
797 *   @details   Comments:
798 *    For input parameter only addr field in entry is meaning.
799 * @param[in] dev_id device id
800 * @param entry fdb entry
801 * @return SW_OK or error code
802 */
803HSL_LOCAL sw_error_t
804horus_fdb_next(a_uint32_t dev_id, fal_fdb_entry_t * entry)
805{
806    sw_error_t rv;
807
808    HSL_API_LOCK;
809    rv = _horus_fdb_next(dev_id, entry);
810    HSL_API_UNLOCK;
811    return rv;
812}
813
814/**
815 * @brief Get first Fdb entry from particular device
816 * @param[in] dev_id device id
817 * @param[out] entry fdb entry
818 * @return SW_OK or error code
819 */
820HSL_LOCAL sw_error_t
821horus_fdb_first(a_uint32_t dev_id, fal_fdb_entry_t * entry)
822{
823    sw_error_t rv;
824
825    HSL_API_LOCK;
826    rv = _horus_fdb_first(dev_id, entry);
827    HSL_API_UNLOCK;
828    return rv;
829}
830
831/**
832 * @brief Find a particular Fdb entry from device through mac address.
833 *    @details  Comments:
834    For input parameter only addr field in entry is meaning.
835 * @param[in] dev_id device id
836 * @param[in] entry fdb entry
837 * @param[out] entry fdb entry
838 * @return SW_OK or error code
839 */
840HSL_LOCAL sw_error_t
841horus_fdb_find(a_uint32_t dev_id, fal_fdb_entry_t * entry)
842{
843    sw_error_t rv;
844
845    HSL_API_LOCK;
846    rv = _horus_fdb_find(dev_id, entry);
847    HSL_API_UNLOCK;
848    return rv;
849}
850
851/**
852 * @brief Set dynamic address learning status on a particular port.
853 *    @details  Comments:
854 *       This operation will enable or disable dynamic address learning
855 *       feature on a particular port.
856 * @param[in] dev_id device id
857 * @param[in] port_id port id
858 * @param[in] enable enable or disable
859 * @return SW_OK or error code
860 */
861HSL_LOCAL sw_error_t
862horus_fdb_port_learn_set(a_uint32_t dev_id, fal_port_t port_id,
863                         a_bool_t enable)
864{
865    sw_error_t rv;
866
867    HSL_API_LOCK;
868    rv = _horus_fdb_port_learn_set(dev_id, port_id, enable);
869    HSL_API_UNLOCK;
870    return rv;
871}
872
873/**
874 * @brief Get dynamic address learning status on a particular port.
875 * @param[in] dev_id device id
876 * @param[in] port_id port id
877 * @param[out] enable A_TRUE or A_FALSE
878 * @return SW_OK or error code
879 */
880HSL_LOCAL sw_error_t
881horus_fdb_port_learn_get(a_uint32_t dev_id, fal_port_t port_id,
882                         a_bool_t *enable)
883{
884    sw_error_t rv;
885
886    HSL_API_LOCK;
887    rv = _horus_fdb_port_learn_get(dev_id, port_id, enable);
888    HSL_API_UNLOCK;
889    return rv;
890}
891
892/**
893 * @brief Set dynamic address aging status on particular device.
894 *   @details  Comments:
895 *       This operation will enable or disable dynamic address aging
896 *       feature on particular device.
897 * @param[in] dev_id device id
898 * @param[in] enable enable or disable
899 * @return SW_OK or error code
900 */
901HSL_LOCAL sw_error_t
902horus_fdb_age_ctrl_set(a_uint32_t dev_id, a_bool_t enable)
903{
904    sw_error_t rv;
905
906    HSL_API_LOCK;
907    rv = _horus_fdb_age_ctrl_set(dev_id, enable);
908    HSL_API_UNLOCK;
909    return rv;
910}
911
912/**
913 * @brief Get dynamic address aging status on particular device.
914 * @param[in] dev_id device id
915 * @param[in] enable enable or disable
916 * @return SW_OK or error code
917 */
918HSL_LOCAL sw_error_t
919horus_fdb_age_ctrl_get(a_uint32_t dev_id, a_bool_t *enable)
920{
921    sw_error_t rv;
922
923    HSL_API_LOCK;
924    rv = _horus_fdb_age_ctrl_get(dev_id, enable);
925    HSL_API_UNLOCK;
926    return rv;
927}
928
929/**
930 * @brief Set dynamic address aging time on a particular device.
931 * @details   Comments:
932 *       This operation will set dynamic address aging time on a particular device.
933 *       The unit of time is second. Because different device has differnet
934 *       hardware granularity function will return actual time in hardware.
935 * @param[in] dev_id device id
936 * @param time aging time
937 * @return SW_OK or error code
938 */
939HSL_LOCAL sw_error_t
940horus_fdb_age_time_set(a_uint32_t dev_id, a_uint32_t * time)
941{
942    sw_error_t rv;
943
944    HSL_API_LOCK;
945    rv = _horus_fdb_age_time_set(dev_id, time);
946    HSL_API_UNLOCK;
947    return rv;
948}
949
950/**
951 * @brief Get dynamic address aging time on a particular device.
952 * @param[in] dev_id device id
953 * @param[out] time aging time
954 * @return SW_OK or error code
955 */
956HSL_LOCAL sw_error_t
957horus_fdb_age_time_get(a_uint32_t dev_id, a_uint32_t *time)
958{
959    sw_error_t rv;
960
961    HSL_API_LOCK;
962    rv = _horus_fdb_age_time_get(dev_id, time);
963    HSL_API_UNLOCK;
964    return rv;
965}
966
967sw_error_t
968horus_fdb_init(a_uint32_t dev_id)
969{
970    HSL_DEV_ID_CHECK(dev_id);
971
972#ifndef HSL_STANDALONG
973    {
974        hsl_api_t *p_api;
975
976        SW_RTN_ON_NULL(p_api = hsl_api_ptr_get(dev_id));
977
978        p_api->fdb_add = horus_fdb_add;
979        p_api->fdb_del_all = horus_fdb_del_all;
980        p_api->fdb_del_by_port = horus_fdb_del_by_port;
981        p_api->fdb_del_by_mac = horus_fdb_del_by_mac;
982        p_api->fdb_first = horus_fdb_first;
983        p_api->fdb_next = horus_fdb_next;
984        p_api->fdb_find = horus_fdb_find;
985        p_api->port_learn_set = horus_fdb_port_learn_set;
986        p_api->port_learn_get = horus_fdb_port_learn_get;
987        p_api->age_ctrl_set = horus_fdb_age_ctrl_set;
988        p_api->age_ctrl_get = horus_fdb_age_ctrl_get;
989        p_api->age_time_set = horus_fdb_age_time_set;
990        p_api->age_time_get = horus_fdb_age_time_get;
991    }
992#endif
993
994    return SW_OK;
995}
996
997/**
998 * @}
999 */
1000