blob: 4745cf580c361d4b69e41a538ddb9e4bd2fa240d [file] [log] [blame]
developerfd40db22021-04-29 10:08:25 +08001/*
2* switch_fun.c: switch function sets
3*/
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <string.h>
8#include <stdbool.h>
9#include <sys/ioctl.h>
10#include <sys/socket.h>
11#include <linux/if.h>
12#include <stdbool.h>
13#include <time.h>
developer997ed6b2024-03-26 14:03:42 +080014#include <errno.h>
developerfd40db22021-04-29 10:08:25 +080015
16#include "switch_extend.h"
17#include "switch_netlink.h"
18#include "switch_ioctl.h"
19#include "switch_fun.h"
20
21#define leaky_bucket 0
22
developerbe40a9e2024-03-07 21:44:26 +080023struct switch_func_s mt753x_switch_func = {
24 .pf_table_dump = table_dump,
25 .pf_table_clear = table_clear,
26 .pf_switch_reset = switch_reset,
27 .pf_doArlAging = doArlAging,
28 .pf_read_mib_counters = read_mib_counters,
29 .pf_clear_mib_counters = clear_mib_counters,
30 .pf_read_output_queue_counters = read_output_queue_counters,
31 .pf_read_free_page_counters = read_free_page_counters,
32 .pf_rate_control = rate_control,
33 .pf_igress_rate_set = ingress_rate_set,
34 .pf_egress_rate_set = egress_rate_set,
35 .pf_table_add = table_add,
36 .pf_table_del_fid = table_del_fid,
37 .pf_table_del_vid = table_del_vid,
38 .pf_table_search_mac_fid = table_search_mac_fid,
39 .pf_table_search_mac_vid = table_search_mac_vid,
40 .pf_global_set_mac_fc = global_set_mac_fc,
41 .pf_set_mac_pfc = set_mac_pfc,
42 .pf_qos_sch_select = qos_sch_select,
43 .pf_qos_set_base = qos_set_base,
44 .pf_qos_wfq_set_weight = qos_wfq_set_weight,
45 .pf_qos_set_portpri = qos_set_portpri,
46 .pf_qos_set_dscppri = qos_set_dscppri,
47 .pf_qos_pri_mapping_queue = qos_pri_mapping_queue,
48 .pf_doStp = doStp,
49 .pf_sip_dump = sip_dump,
50 .pf_sip_add = sip_add,
51 .pf_sip_del = sip_del,
52 .pf_sip_clear = sip_clear,
53 .pf_dip_dump = dip_dump,
54 .pf_dip_add = dip_add,
55 .pf_dip_del = dip_del,
56 .pf_dip_clear = dip_clear,
57 .pf_set_mirror_to = set_mirror_to,
58 .pf_set_mirror_from = set_mirror_from,
59 .pf_doMirrorEn = doMirrorEn,
60 .pf_doMirrorPortBased = doMirrorPortBased,
61 .pf_acl_dip_add = acl_dip_add,
62 .pf_acl_dip_modify = acl_dip_modify,
63 .pf_acl_dip_pppoe = acl_dip_pppoe,
64 .pf_acl_dip_trtcm = acl_dip_trtcm,
65 .pf_acl_dip_meter = acl_dip_meter,
66 .pf_acl_mac_add = acl_mac_add,
67 .pf_acl_ethertype = acl_ethertype,
68 .pf_acl_sp_add = acl_sp_add,
69 .pf_acl_l4_add = acl_l4_add,
70 .pf_acl_port_enable = acl_port_enable,
71 .pf_acl_table_add = acl_table_add,
72 .pf_acl_mask_table_add = acl_mask_table_add,
73 .pf_acl_rule_table_add = acl_rule_table_add,
74 .pf_acl_rate_table_add = acl_rate_table_add,
75 .pf_vlan_dump = vlan_dump,
76 .pf_vlan_set = vlan_set,
77 .pf_vlan_clear = vlan_clear,
78 .pf_doVlanSetVid = doVlanSetVid,
79 .pf_doVlanSetPvid = doVlanSetPvid,
80 .pf_doVlanSetAccFrm = doVlanSetAccFrm,
81 .pf_doVlanSetPortAttr = doVlanSetPortAttr,
82 .pf_doVlanSetPortMode = doVlanSetPortMode,
83 .pf_doVlanSetEgressTagPCR = doVlanSetEgressTagPCR,
84 .pf_doVlanSetEgressTagPVC = doVlanSetEgressTagPVC,
85 .pf_igmp_on = igmp_on,
86 .pf_igmp_off = igmp_off,
87 .pf_igmp_enable = igmp_enable,
88 .pf_igmp_disable = igmp_disable,
89 .pf_collision_pool_enable = collision_pool_enable,
90 .pf_collision_pool_mac_dump = collision_pool_mac_dump,
91 .pf_collision_pool_dip_dump = collision_pool_dip_dump,
92 .pf_collision_pool_sip_dump = collision_pool_sip_dump,
93 .pf_pfc_get_rx_counter = pfc_get_rx_counter,
94 .pf_pfc_get_tx_counter = pfc_get_tx_counter,
95 .pf_eee_enable = eee_enable,
96 .pf_eee_dump = eee_dump,
97};
98
developerfd40db22021-04-29 10:08:25 +080099static int getnext(char *src, int separator, char *dest)
100{
101 char *c;
102 int len;
103
104 if ((src == NULL) || (dest == NULL))
105 return -1;
106
107 c = strchr(src, separator);
108 if (c == NULL)
109 return -1;
110
111 len = c - src;
112 strncpy(dest, src, len);
113 dest[len] = '\0';
114 return len + 1;
115}
116
117static int str_to_ip(unsigned int *ip, char *str)
118{
119 int i;
120 int len;
121 char *ptr = str;
122 char buf[128];
123 unsigned char c[4];
124
125 for (i = 0; i < 3; ++i) {
126 if ((len = getnext(ptr, '.', buf)) == -1)
127 return 1;
128 c[i] = atoi(buf);
129 ptr += len;
130 }
131 c[3] = atoi(ptr);
132 *ip = (c[0] << 24) + (c[1] << 16) + (c[2] << 8) + c[3];
133 return 0;
134}
135
136/*convert IP address from number to string */
developer546b2792024-06-15 20:31:38 +0800137static void ip_to_str(char *str, size_t size, unsigned int ip)
developerfd40db22021-04-29 10:08:25 +0800138{
139 unsigned char *ptr = (unsigned char *)&ip;
140 unsigned char c[4];
developer546b2792024-06-15 20:31:38 +0800141 int ret;
142
143 if (str == NULL || size == 0) {
144 printf("convert IP address failed\n");
145 return;
146 }
developerfd40db22021-04-29 10:08:25 +0800147
148 c[0] = *(ptr);
149 c[1] = *(ptr + 1);
150 c[2] = *(ptr + 2);
151 c[3] = *(ptr + 3);
developer546b2792024-06-15 20:31:38 +0800152
153 ret = snprintf(str, size, "%d.%d.%d.%d", c[3], c[2], c[1], c[0]);
154 if (ret < 0) {
155 printf("Encoding error in snprintf\n");
156 return;
157 } else if ((size_t)ret >= size) {
158 printf("Required size %d, provided size %zu\n", ret, size);
159 return;
160 }
developerfd40db22021-04-29 10:08:25 +0800161}
162
163int reg_read(unsigned int offset, unsigned int *value)
164{
165 int ret = -1;
166
167 if (nl_init_flag == true) {
168 ret = reg_read_netlink(attres, offset, value);
169 } else {
170 if (attres->dev_id == -1)
171 ret = reg_read_ioctl(offset, value);
172 }
173 if (ret < 0) {
174 printf("Read fail\n");
175 *value = 0;
176 return ret;
177 }
178
179 return 0;
180}
181
182int reg_write(unsigned int offset, unsigned int value)
183{
184 int ret = -1;
185
186 if (nl_init_flag == true) {
187 ret = reg_write_netlink(attres, offset, value);
188 } else {
189 if (attres->dev_id == -1)
190 ret = reg_write_ioctl(offset, value);
191 }
192 if (ret < 0) {
193 printf("Write fail\n");
194 exit_free();
195 exit(0);
196 }
197 return 0;
198}
199
200int mii_mgr_read(unsigned int port_num, unsigned int reg, unsigned int *value)
201{
202 int ret;
203
204 if (port_num > 31) {
205 printf("Invalid Port or PHY addr \n");
206 return -1;
207 }
208
209 if (nl_init_flag == true)
210 ret = phy_cl22_read_netlink(attres, port_num, reg, value);
211 else
212 ret = mii_mgr_cl22_read_ioctl(port_num, reg, value);
213
214 if (ret < 0) {
developer06979e42021-05-28 16:48:10 +0800215 printf("Phy cl22 read fail\n");
developerfd40db22021-04-29 10:08:25 +0800216 exit_free();
217 exit(0);
218 }
219
220 return 0;
221}
222
223int mii_mgr_write(unsigned int port_num, unsigned int reg, unsigned int value)
224{
225 int ret;
226
227 if (port_num > 31) {
228 printf("Invalid Port or PHY addr \n");
229 return -1;
230 }
231
232 if (nl_init_flag == true)
233 ret = phy_cl22_write_netlink(attres, port_num, reg, value);
234 else
235 ret = mii_mgr_cl22_write_ioctl(port_num, reg, value);
236
237 if (ret < 0) {
developer06979e42021-05-28 16:48:10 +0800238 printf("Phy cl22 write fail\n");
developerfd40db22021-04-29 10:08:25 +0800239 exit_free();
240 exit(0);
241 }
242
243 return 0;
244}
245
developerbe40a9e2024-03-07 21:44:26 +0800246int mii_mgr_c45_read(unsigned int port_num, unsigned int dev, unsigned int reg,
247 unsigned int *value)
developerfd40db22021-04-29 10:08:25 +0800248{
249 int ret;
250
251 if (port_num > 31) {
252 printf("Invalid Port or PHY addr \n");
253 return -1;
254 }
255
256 if (nl_init_flag == true)
257 ret = phy_cl45_read_netlink(attres, port_num, dev, reg, value);
258 else
259 ret = mii_mgr_cl45_read_ioctl(port_num, dev, reg, value);
260
261 if (ret < 0) {
developer06979e42021-05-28 16:48:10 +0800262 printf("Phy cl45 read fail\n");
developerfd40db22021-04-29 10:08:25 +0800263 exit_free();
264 exit(0);
265 }
266
267 return 0;
268}
269
developerbe40a9e2024-03-07 21:44:26 +0800270int mii_mgr_c45_write(unsigned int port_num, unsigned int dev, unsigned int reg,
271 unsigned int value)
developerfd40db22021-04-29 10:08:25 +0800272{
273 int ret;
274
275 if (port_num > 31) {
276 printf("Invalid Port or PHY addr \n");
277 return -1;
278 }
279
280 if (nl_init_flag == true)
281 ret = phy_cl45_write_netlink(attres, port_num, dev, reg, value);
282 else
283 ret = mii_mgr_cl45_write_ioctl(port_num, dev, reg, value);
284
285 if (ret < 0) {
developer06979e42021-05-28 16:48:10 +0800286 printf("Phy cl45 write fail\n");
developerfd40db22021-04-29 10:08:25 +0800287 exit_free();
288 exit(0);
289 }
290
291 return 0;
292}
293
developerfd40db22021-04-29 10:08:25 +0800294int phy_dump(int phy_addr)
295{
296 int ret;
297
298 if (nl_init_flag == true)
299 ret = phy_dump_netlink(attres, phy_addr);
300 else
301 ret = phy_dump_ioctl(phy_addr);
302
303 if (ret < 0) {
304 printf("Phy dump fail\n");
305 exit_free();
306 exit(0);
307 }
308
309 return 0;
310}
311
312void phy_crossover(int argc, char *argv[])
313{
314 unsigned int port_num = strtoul(argv[2], NULL, 10);
developerbe40a9e2024-03-07 21:44:26 +0800315 unsigned int value = 0;
developerfd40db22021-04-29 10:08:25 +0800316 int ret;
317
318 if (port_num > 4) {
319 printf("invaild value, port_name:0~4\n");
320 return;
321 }
322
323 if (nl_init_flag == true)
developerbe40a9e2024-03-07 21:44:26 +0800324 ret =
325 phy_cl45_read_netlink(attres, port_num, 0x1E,
326 MT7530_T10_TEST_CONTROL, &value);
developerfd40db22021-04-29 10:08:25 +0800327 else
developerbe40a9e2024-03-07 21:44:26 +0800328 ret =
329 mii_mgr_cl45_read_ioctl(port_num, 0x1E,
330 MT7530_T10_TEST_CONTROL, &value);
developerfd40db22021-04-29 10:08:25 +0800331 if (ret < 0) {
332 printf("phy_cl45 read fail\n");
333 exit_free();
334 exit(0);
335 }
336
337 printf("mii_mgr_cl45:");
developerbe40a9e2024-03-07 21:44:26 +0800338 printf("Read: port#=%d, device=0x%x, reg=0x%x, value=0x%x\n", port_num,
339 0x1E, MT7530_T10_TEST_CONTROL, value);
developerfd40db22021-04-29 10:08:25 +0800340
developerbe40a9e2024-03-07 21:44:26 +0800341 if (!strncmp(argv[3], "auto", 5)) {
developerfd40db22021-04-29 10:08:25 +0800342 value &= (~(0x3 << 3));
343 } else if (!strncmp(argv[3], "mdi", 4)) {
344 value &= (~(0x3 << 3));
345 value |= (0x2 << 3);
346 } else if (!strncmp(argv[3], "mdix", 5)) {
347 value |= (0x3 << 3);
348 } else {
349 printf("invaild parameter\n");
350 return;
351 }
developerbe40a9e2024-03-07 21:44:26 +0800352 printf("Write: port#=%d, device=0x%x, reg=0x%x. value=0x%x\n", port_num,
353 0x1E, MT7530_T10_TEST_CONTROL, value);
developerfd40db22021-04-29 10:08:25 +0800354
355 if (nl_init_flag == true)
developerbe40a9e2024-03-07 21:44:26 +0800356 ret =
357 phy_cl45_write_netlink(attres, port_num, 0x1E,
358 MT7530_T10_TEST_CONTROL, value);
developerfd40db22021-04-29 10:08:25 +0800359 else
developerbe40a9e2024-03-07 21:44:26 +0800360 ret =
361 mii_mgr_cl45_write_ioctl(port_num, 0x1E,
362 MT7530_T10_TEST_CONTROL, value);
developerfd40db22021-04-29 10:08:25 +0800363
364 if (ret < 0) {
365 printf("phy_cl45 write fail\n");
366 exit_free();
367 exit(0);
368 }
369}
370
371int rw_phy_token_ring(int argc, char *argv[])
372{
373 int ch_addr, node_addr, data_addr;
374 unsigned int tr_reg_control;
375 unsigned int val_l = 0;
376 unsigned int val_h = 0;
377 unsigned int port_num;
developer2fdae312024-06-15 20:36:12 +0800378 char *endptr;
developerfd40db22021-04-29 10:08:25 +0800379
380 if (argc < 4)
381 return -1;
382
383 if (argv[2][0] == 'r') {
384 if (argc != 7)
385 return -1;
developerbe40a9e2024-03-07 21:44:26 +0800386 mii_mgr_write(0, 0x1f, 0x52b5); // r31 = 0x52b5
developer2fdae312024-06-15 20:36:12 +0800387
388 errno = 0;
389 port_num = strtoul(argv[3], &endptr, 10);
390 if (errno != 0 || *endptr != '\0' || port_num > MAX_PORT) {
developerfd40db22021-04-29 10:08:25 +0800391 printf("Illegal port index and port:0~6\n");
392 return -1;
393 }
developer2fdae312024-06-15 20:36:12 +0800394
395 errno = 0;
396 ch_addr = strtoul(argv[4], &endptr, 10);
397 if (errno != 0 || *endptr != '\0')
398 goto error;
399
400 errno = 0;
401 node_addr = strtoul(argv[5], &endptr, 16);
402 if (errno != 0 || *endptr != '\0')
403 goto error;
404
405 errno = 0;
406 data_addr = strtoul(argv[6], &endptr, 16);
407 if (errno != 0 || *endptr != '\0')
408 goto error;
409
developerbe40a9e2024-03-07 21:44:26 +0800410 printf("port = %x, ch_addr = %x, node_addr=%x, data_addr=%x\n",
411 port_num, ch_addr, node_addr, data_addr);
412 tr_reg_control =
413 (1 << 15) | (1 << 13) | (ch_addr << 11) | (node_addr << 7) |
414 (data_addr << 1);
415 mii_mgr_write(port_num, 16, tr_reg_control); // r16 = tr_reg_control
developerfd40db22021-04-29 10:08:25 +0800416 mii_mgr_read(port_num, 17, &val_l);
417 mii_mgr_read(port_num, 18, &val_h);
developerbe40a9e2024-03-07 21:44:26 +0800418 printf
419 ("switch trreg read tr_reg_control=%x, value_H=%x, value_L=%x\n",
420 tr_reg_control, val_h, val_l);
developerfd40db22021-04-29 10:08:25 +0800421 } else if (argv[2][0] == 'w') {
422 if (argc != 9)
423 return -1;
developerbe40a9e2024-03-07 21:44:26 +0800424 mii_mgr_write(0, 0x1f, 0x52b5); // r31 = 0x52b5
developer2fdae312024-06-15 20:36:12 +0800425
426 errno = 0;
427 port_num = strtoul(argv[3], &endptr, 10);
428 if (errno != 0 || *endptr != '\0' || port_num > MAX_PORT) {
429 printf("Illegal port index and port:0~6\n");
developerfd40db22021-04-29 10:08:25 +0800430 return -1;
431 }
developer2fdae312024-06-15 20:36:12 +0800432
433 errno = 0;
434 ch_addr = strtoul(argv[4], &endptr, 10);
435 if (errno != 0 || *endptr != '\0')
436 goto error;
437
438 errno = 0;
439 node_addr = strtoul(argv[5], &endptr, 16);
440 if (errno != 0 || *endptr != '\0')
441 goto error;
442
443 errno = 0;
444 data_addr = strtoul(argv[6], &endptr, 16);
445 if (errno != 0 || *endptr != '\0')
446 goto error;
447
448 errno = 0;
449 val_h = strtoul(argv[7], &endptr, 16);
450 if (errno != 0 || *endptr != '\0')
451 goto error;
452
453 errno = 0;
454 val_l = strtoul(argv[8], &endptr, 16);
455 if (errno != 0 || *endptr != '\0')
456 goto error;
457
developerbe40a9e2024-03-07 21:44:26 +0800458 printf("port = %x, ch_addr = %x, node_addr=%x, data_addr=%x\n",
459 port_num, ch_addr, node_addr, data_addr);
460 tr_reg_control =
461 (1 << 15) | (0 << 13) | (ch_addr << 11) | (node_addr << 7) |
462 (data_addr << 1);
developerfd40db22021-04-29 10:08:25 +0800463 mii_mgr_write(port_num, 17, val_l);
464 mii_mgr_write(port_num, 18, val_h);
developerbe40a9e2024-03-07 21:44:26 +0800465 mii_mgr_write(port_num, 16, tr_reg_control); // r16 = tr_reg_control
466 printf
467 ("switch trreg Write tr_reg_control=%x, value_H=%x, value_L=%x\n",
468 tr_reg_control, val_h, val_l);
developerfd40db22021-04-29 10:08:25 +0800469 } else
470 return -1;
developer2fdae312024-06-15 20:36:12 +0800471
developerfd40db22021-04-29 10:08:25 +0800472 return 0;
developer2fdae312024-06-15 20:36:12 +0800473
474error:
475 printf("\n**Illegal parameters\n");
476 return -1;
developerfd40db22021-04-29 10:08:25 +0800477}
478
developerbe40a9e2024-03-07 21:44:26 +0800479void write_acl_table(unsigned char tbl_idx, unsigned int vawd1,
480 unsigned int vawd2)
developerfd40db22021-04-29 10:08:25 +0800481{
developerbe40a9e2024-03-07 21:44:26 +0800482 unsigned int value = 0, reg = 0;
developerfd40db22021-04-29 10:08:25 +0800483 unsigned int max_index;
484
developer8c3871b2022-07-01 14:07:53 +0800485 if (chip_name == 0x7531 || chip_name == 0x7988)
developerfd40db22021-04-29 10:08:25 +0800486 max_index = 256;
487 else
488 max_index = 64;
489
490 printf("Pattern_acl_tbl_idx:%d\n", tbl_idx);
491
492 if (tbl_idx >= max_index) {
493 printf(HELP_ACL_ACL_TBL_ADD);
494 return;
495 }
496
497 reg = REG_VTCR_ADDR;
developerbe40a9e2024-03-07 21:44:26 +0800498 while (1) { // wait until not busy
developerfd40db22021-04-29 10:08:25 +0800499 reg_read(reg, &value);
500 if ((value & REG_VTCR_BUSY_MASK) == 0) {
501 break;
502 }
503 }
504 reg_write(REG_VAWD1_ADDR, vawd1);
505 printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
506 reg_write(REG_VAWD2_ADDR, vawd2);
507 printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
508 reg = REG_VTCR_ADDR;
509 value = REG_VTCR_BUSY_MASK | (0x05 << REG_VTCR_FUNC_OFFT) | tbl_idx;
510 reg_write(reg, value);
511 printf("write reg: %x, value: %x\n", reg, value);
512
developerbe40a9e2024-03-07 21:44:26 +0800513 while (1) { // wait until not busy
developerfd40db22021-04-29 10:08:25 +0800514 reg_read(reg, &value);
515 if ((value & REG_VTCR_BUSY_MASK) == 0)
516 break;
517 }
518}
519
520void acl_table_add(int argc, char *argv[])
521{
developerbe40a9e2024-03-07 21:44:26 +0800522 unsigned int vawd1 = 0, vawd2 = 0;
523 unsigned char tbl_idx = 0;
developer546b2792024-06-15 20:31:38 +0800524 char *endptr;
developerfd40db22021-04-29 10:08:25 +0800525
developer546b2792024-06-15 20:31:38 +0800526 errno = 0;
527 tbl_idx = strtoul(argv[3], &endptr, 10);
528 if (errno != 0 || *endptr != '\0') {
529 printf("Error: wrong ACL rule table index\n");
530 return;
531 }
532
533 errno = 0;
534 vawd1 = strtoul(argv[4], &endptr, 16);
535 if (errno != 0 || *endptr != '\0') {
536 printf("Error: wrong ACL rule table write data 1\n");
537 return;
538 }
539
540 errno = 0;
541 vawd2 = strtoul(argv[5], &endptr, 16);
542 if (errno != 0 || *endptr != '\0') {
543 printf("Error: wrong ACL rule table write data 2\n");
544 return;
545 }
546
developerfd40db22021-04-29 10:08:25 +0800547 write_acl_table(tbl_idx, vawd1, vawd2);
548}
549
developerbe40a9e2024-03-07 21:44:26 +0800550void write_acl_mask_table(unsigned char tbl_idx, unsigned int vawd1,
551 unsigned int vawd2)
developerfd40db22021-04-29 10:08:25 +0800552{
developerbe40a9e2024-03-07 21:44:26 +0800553 unsigned int value = 0, reg = 0;
554 unsigned int max_index = 0;
developerfd40db22021-04-29 10:08:25 +0800555
developer8c3871b2022-07-01 14:07:53 +0800556 if (chip_name == 0x7531 || chip_name == 0x7988)
developerfd40db22021-04-29 10:08:25 +0800557 max_index = 128;
558 else
559 max_index = 32;
560
561 printf("Rule_mask_tbl_idx:%d\n", tbl_idx);
562
563 if (tbl_idx >= max_index) {
564 printf(HELP_ACL_MASK_TBL_ADD);
565 return;
566 }
567 reg = REG_VTCR_ADDR;
developerbe40a9e2024-03-07 21:44:26 +0800568 while (1) { // wait until not busy
developerfd40db22021-04-29 10:08:25 +0800569 reg_read(reg, &value);
570 if ((value & REG_VTCR_BUSY_MASK) == 0)
571 break;
572 }
573 reg_write(REG_VAWD1_ADDR, vawd1);
574 printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
575 reg_write(REG_VAWD2_ADDR, vawd2);
576 printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
577 reg = REG_VTCR_ADDR;
578 value = REG_VTCR_BUSY_MASK | (0x09 << REG_VTCR_FUNC_OFFT) | tbl_idx;
579 reg_write(reg, value);
580 printf("write reg: %x, value: %x\n", reg, value);
developerbe40a9e2024-03-07 21:44:26 +0800581 while (1) { // wait until not busy
developerfd40db22021-04-29 10:08:25 +0800582 reg_read(reg, &value);
583 if ((value & REG_VTCR_BUSY_MASK) == 0)
584 break;
585 }
586}
587
588void acl_mask_table_add(int argc, char *argv[])
589{
developerbe40a9e2024-03-07 21:44:26 +0800590 unsigned int vawd1 = 0, vawd2 = 0;
591 unsigned char tbl_idx = 0;
developer546b2792024-06-15 20:31:38 +0800592 char *endptr;
developerfd40db22021-04-29 10:08:25 +0800593
developer546b2792024-06-15 20:31:38 +0800594 errno = 0;
595 tbl_idx = strtoul(argv[3], &endptr, 10);
596 if (errno != 0 || *endptr != '\0') {
597 printf("Error: wrong ACL mask table index\n");
598 return;
599 }
600
601 errno = 0;
602 vawd1 = strtoul(argv[4], &endptr, 16);
603 if (errno != 0 || *endptr != '\0') {
604 printf("Error: wrong ACL mask table write data 1\n");
605 return;
606 }
607
608 errno = 0;
609 vawd2 = strtoul(argv[5], &endptr, 16);
610 if (errno != 0 || *endptr != '\0') {
611 printf("Error: wrong ACL mask table write data 2\n");
612 return;
613 }
614
developerfd40db22021-04-29 10:08:25 +0800615 write_acl_mask_table(tbl_idx, vawd1, vawd2);
616}
617
developerbe40a9e2024-03-07 21:44:26 +0800618void write_acl_rule_table(unsigned char tbl_idx, unsigned int vawd1,
619 unsigned int vawd2)
developerfd40db22021-04-29 10:08:25 +0800620{
developerbe40a9e2024-03-07 21:44:26 +0800621 unsigned int value = 0, reg = 0;
622 unsigned int max_index = 0;
developerfd40db22021-04-29 10:08:25 +0800623
developer8c3871b2022-07-01 14:07:53 +0800624 if (chip_name == 0x7531 || chip_name == 0x7988)
developerfd40db22021-04-29 10:08:25 +0800625 max_index = 128;
626 else
627 max_index = 32;
628
629 printf("Rule_control_tbl_idx:%d\n", tbl_idx);
630
developerbe40a9e2024-03-07 21:44:26 +0800631 if (tbl_idx >= max_index) { /* Check the input parameters is right or not. */
developerfd40db22021-04-29 10:08:25 +0800632 printf(HELP_ACL_RULE_TBL_ADD);
633 return;
634 }
635 reg = REG_VTCR_ADDR;
636
developerbe40a9e2024-03-07 21:44:26 +0800637 while (1) { // wait until not busy
developerfd40db22021-04-29 10:08:25 +0800638 reg_read(reg, &value);
639 if ((value & REG_VTCR_BUSY_MASK) == 0) {
640 break;
641 }
642 }
643 reg_write(REG_VAWD1_ADDR, vawd1);
644 printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
645 reg_write(REG_VAWD2_ADDR, vawd2);
646 printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
647 reg = REG_VTCR_ADDR;
648 value = REG_VTCR_BUSY_MASK | (0x0B << REG_VTCR_FUNC_OFFT) | tbl_idx;
649 reg_write(reg, value);
650 printf("write reg: %x, value: %x\n", reg, value);
651
developerbe40a9e2024-03-07 21:44:26 +0800652 while (1) { // wait until not busy
developerfd40db22021-04-29 10:08:25 +0800653 reg_read(reg, &value);
654 if ((value & REG_VTCR_BUSY_MASK) == 0) {
655 break;
656 }
657 }
658}
659
660void acl_rule_table_add(int argc, char *argv[])
661{
developerbe40a9e2024-03-07 21:44:26 +0800662 unsigned int vawd1 = 0, vawd2 = 0;
663 unsigned char tbl_idx = 0;
developer546b2792024-06-15 20:31:38 +0800664 char *endptr;
665
666 errno = 0;
667 tbl_idx = strtoul(argv[3], &endptr, 10);
668 if (errno != 0 || *endptr != '\0') {
669 printf("Error: wrong ACL rule control table index\n");
670 return;
671 }
672
673 errno = 0;
674 vawd1 = strtoul(argv[4], &endptr, 16);
675 if (errno != 0 || *endptr != '\0') {
676 printf("Error: wrong ACL rule control table write data 1\n");
677 return;
678 }
679
680 errno = 0;
681 vawd2 = strtoul(argv[5], &endptr, 16);
682 if (errno != 0 || *endptr != '\0') {
683 printf("Error: wrong ACL rule control table write data 2\n");
684 return;
685 }
developerfd40db22021-04-29 10:08:25 +0800686
developerfd40db22021-04-29 10:08:25 +0800687 write_acl_rule_table(tbl_idx, vawd1, vawd2);
688}
689
developerbe40a9e2024-03-07 21:44:26 +0800690void write_rate_table(unsigned char tbl_idx, unsigned int vawd1,
691 unsigned int vawd2)
developerfd40db22021-04-29 10:08:25 +0800692{
developerbe40a9e2024-03-07 21:44:26 +0800693 unsigned int value = 0, reg = 0;
developerfd40db22021-04-29 10:08:25 +0800694 unsigned int max_index = 32;
695
696 printf("Rule_action_tbl_idx:%d\n", tbl_idx);
697
698 if (tbl_idx >= max_index) {
699 printf(HELP_ACL_RATE_TBL_ADD);
700 return;
701 }
702
703 reg = REG_VTCR_ADDR;
developerbe40a9e2024-03-07 21:44:26 +0800704 while (1) { // wait until not busy
developerfd40db22021-04-29 10:08:25 +0800705 reg_read(reg, &value);
706 if ((value & REG_VTCR_BUSY_MASK) == 0)
707 break;
708 }
709
710 reg_write(REG_VAWD1_ADDR, vawd1);
711 printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
712 reg_write(REG_VAWD2_ADDR, vawd2);
713 printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
714 reg = REG_VTCR_ADDR;
715 value = REG_VTCR_BUSY_MASK | (0x0D << REG_VTCR_FUNC_OFFT) | tbl_idx;
716 reg_write(reg, value);
717 printf("write reg: %x, value: %x\n", reg, value);
718
developerbe40a9e2024-03-07 21:44:26 +0800719 while (1) { // wait until not busy
developerfd40db22021-04-29 10:08:25 +0800720 reg_read(reg, &value);
721 if ((value & REG_VTCR_BUSY_MASK) == 0)
722 break;
723 }
724}
725
726void acl_rate_table_add(int argc, char *argv[])
727{
developerbe40a9e2024-03-07 21:44:26 +0800728 unsigned int vawd1 = 0, vawd2 = 0;
729 unsigned char tbl_idx = 0;
developer546b2792024-06-15 20:31:38 +0800730 char *endptr;
developerfd40db22021-04-29 10:08:25 +0800731
developer546b2792024-06-15 20:31:38 +0800732 errno = 0;
733 tbl_idx = strtoul(argv[3], &endptr, 10);
734 if (errno != 0 || *endptr != '\0') {
735 printf("Error: wrong ACL rate control table index\n");
736 return;
737 }
738
739 errno = 0;
740 vawd1 = strtoul(argv[4], &endptr, 16);
741 if (errno != 0 || *endptr != '\0') {
742 printf("Error: wrong ACL rate control table write data 1\n");
743 return;
744 }
745
746 errno = 0;
747 vawd2 = strtoul(argv[5], &endptr, 16);
748 if (errno != 0 || *endptr != '\0') {
749 printf("Error: wrong ACL rate control table write data 2\n");
750 return;
751 }
developerfd40db22021-04-29 10:08:25 +0800752
753 write_rate_table(tbl_idx, vawd1, vawd2);
754}
755
developerbe40a9e2024-03-07 21:44:26 +0800756void write_trTCM_table(unsigned char tbl_idx, unsigned int vawd1,
757 unsigned int vawd2)
developerfd40db22021-04-29 10:08:25 +0800758{
developerbe40a9e2024-03-07 21:44:26 +0800759 unsigned int value = 0, reg = 0;
developerfd40db22021-04-29 10:08:25 +0800760 unsigned int max_index = 32;
761
762 printf("trTCM_tbl_idx:%d\n", tbl_idx);
763
764 if (tbl_idx >= max_index) {
765 printf(HELP_ACL_TRTCM_TBL_ADD);
766 return;
767 }
768
769 reg = REG_VTCR_ADDR;
developerbe40a9e2024-03-07 21:44:26 +0800770 while (1) { // wait until not busy
developerfd40db22021-04-29 10:08:25 +0800771 reg_read(reg, &value);
772 if ((value & REG_VTCR_BUSY_MASK) == 0)
773 break;
774 }
775
776 reg_write(REG_VAWD1_ADDR, vawd1);
777 printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
778 reg_write(REG_VAWD2_ADDR, vawd2);
779 printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
780 reg = REG_VTCR_ADDR;
781 value = REG_VTCR_BUSY_MASK | (0x07 << REG_VTCR_FUNC_OFFT) | tbl_idx;
782 reg_write(reg, value);
783 printf("write reg: %x, value: %x\n", reg, value);
784
developerbe40a9e2024-03-07 21:44:26 +0800785 while (1) { // wait until not busy
developerfd40db22021-04-29 10:08:25 +0800786 reg_read(reg, &value);
787 if ((value & REG_VTCR_BUSY_MASK) == 0)
788 break;
789 }
790}
791
developerbe40a9e2024-03-07 21:44:26 +0800792int acl_parameters_pre_del(int len1, int len2, int argc, char *argv[],
793 int *port)
developerfd40db22021-04-29 10:08:25 +0800794{
developerbe40a9e2024-03-07 21:44:26 +0800795 int i = 0;
developerfd40db22021-04-29 10:08:25 +0800796
797 *port = 0;
798 if (argc < len1) {
799 printf("insufficient arguments!\n");
800 return -1;
801 }
802
developerbe40a9e2024-03-07 21:44:26 +0800803 if (len2 == 12) {
developerfd40db22021-04-29 10:08:25 +0800804 if (!argv[4] || strlen(argv[4]) != len2) {
developerbe40a9e2024-03-07 21:44:26 +0800805 printf
806 ("The [%s] format error, should be of length %d\n",
807 argv[4], len2);
developerfd40db22021-04-29 10:08:25 +0800808 return -1;
809 }
810 }
811
812 if (!argv[5] || strlen(argv[5]) != 8) {
813 printf("portsmap format error, should be of length 7\n");
814 return -1;
815 }
816
817 for (i = 0; i < 7; i++) {
818 if (argv[5][i] != '0' && argv[5][i] != '1') {
developerbe40a9e2024-03-07 21:44:26 +0800819 printf
820 ("portmap format error, should be of combination of 0 or 1\n");
developerfd40db22021-04-29 10:08:25 +0800821 return -1;
822 }
823 *port += (argv[5][i] - '0') * (1 << i);
824 }
825 return 0;
826}
827
developerbe40a9e2024-03-07 21:44:26 +0800828void acl_compare_pattern(int ports, int comparion, int base, int word,
829 unsigned char table_index)
developerfd40db22021-04-29 10:08:25 +0800830{
developerbe40a9e2024-03-07 21:44:26 +0800831 unsigned int value = 0;
developerfd40db22021-04-29 10:08:25 +0800832
developerbe40a9e2024-03-07 21:44:26 +0800833 comparion |= 0xffff0000; //compare mask
developerfd40db22021-04-29 10:08:25 +0800834
developerbe40a9e2024-03-07 21:44:26 +0800835 value = ports << 8; //w_port_map
836 value |= 0x1 << 19; //enable
837 value |= base << 16; //mac header
838 value |= word << 1; //word offset
developerfd40db22021-04-29 10:08:25 +0800839
840 write_acl_table(table_index, comparion, value);
841}
842
843void acl_mac_add(int argc, char *argv[])
844{
developerbe40a9e2024-03-07 21:44:26 +0800845 unsigned int value = 0;
846 int ports = 0;
developerfd40db22021-04-29 10:08:25 +0800847 char tmpstr[5];
848 int ret;
developer546b2792024-06-15 20:31:38 +0800849 char *endptr;
developerfd40db22021-04-29 10:08:25 +0800850
851 ret = acl_parameters_pre_del(6, 12, argc, argv, &ports);
852 if (ret < 0)
853 return;
developerbe40a9e2024-03-07 21:44:26 +0800854 /* Set pattern */
developerfd40db22021-04-29 10:08:25 +0800855 strncpy(tmpstr, argv[4], 4);
856 tmpstr[4] = '\0';
developer546b2792024-06-15 20:31:38 +0800857 errno = 0;
858 value = strtoul(tmpstr, &endptr, 16);
859 if (errno != 0 || *endptr != '\0')
860 goto error;
861
developerfd40db22021-04-29 10:08:25 +0800862 acl_compare_pattern(ports, value, 0x0, 0, 0);
863
864 strncpy(tmpstr, argv[4] + 4, 4);
865 tmpstr[4] = '\0';
developer546b2792024-06-15 20:31:38 +0800866 errno = 0;
867 value = strtoul(tmpstr, &endptr, 16);
868 if (errno != 0 || *endptr != '\0')
869 goto error;
developerfd40db22021-04-29 10:08:25 +0800870 acl_compare_pattern(ports, value, 0x0, 1, 1);
871
872 strncpy(tmpstr, argv[4] + 8, 4);
873 tmpstr[4] = '\0';
developer546b2792024-06-15 20:31:38 +0800874 errno = 0;
875 value = strtoul(tmpstr, &endptr, 16);
876 if (errno != 0 || *endptr != '\0')
877 goto error;
developerfd40db22021-04-29 10:08:25 +0800878 acl_compare_pattern(ports, value, 0x0, 2, 2);
879
880 //set mask
developerbe40a9e2024-03-07 21:44:26 +0800881 write_acl_mask_table(0, 0x7, 0);
developerfd40db22021-04-29 10:08:25 +0800882
883 //set action
developerbe40a9e2024-03-07 21:44:26 +0800884 value = 0x7; //drop
885 value |= 1 << 28; //acl intterupt enable
886 value |= 1 << 27; //acl hit count
887 value |= 2 << 24; //acl hit count group index (0~3)
888 write_acl_rule_table(0, value, 0);
developer546b2792024-06-15 20:31:38 +0800889 return;
890
891error:
892 printf("Error: string converting\n");
893 return;
developerfd40db22021-04-29 10:08:25 +0800894}
895
896void acl_dip_meter(int argc, char *argv[])
897{
developerbe40a9e2024-03-07 21:44:26 +0800898 unsigned int value = 0, ip_value = 0, meter = 0;
899 int ports = 0;
developerfd40db22021-04-29 10:08:25 +0800900 int ret;
901
902 ip_value = 0;
903 ret = acl_parameters_pre_del(7, -1, argc, argv, &ports);
904 if (ret < 0)
905 return;
906
907 str_to_ip(&ip_value, argv[4]);
908 //set pattern
909 value = (ip_value >> 16);
910 acl_compare_pattern(ports, value, 0x2, 0x8, 0);
911
912 //set pattern
913 value = (ip_value & 0xffff);
914 acl_compare_pattern(ports, value, 0x2, 0x9, 1);
915
916 //set mask
developerbe40a9e2024-03-07 21:44:26 +0800917 write_acl_mask_table(0, 0x3, 0);
developerfd40db22021-04-29 10:08:25 +0800918
919 //set action
920 meter = strtoul(argv[6], NULL, 0);
921 if (((chip_name == 0x7530) && (meter > 1000000)) ||
developerbe40a9e2024-03-07 21:44:26 +0800922 ((chip_name == 0x7531) && (meter > 2500000)) ||
923 ((chip_name == 0x7988) && (meter > 4000000))) {
developer8c3871b2022-07-01 14:07:53 +0800924 printf("\n**Illegal meter input, and 7530: 0~1000000Kpbs, 7531: 0~2500000Kpbs, 7988: 0~4000000Kpbs**\n");
developerfd40db22021-04-29 10:08:25 +0800925 return;
926 }
developer8c3871b2022-07-01 14:07:53 +0800927 if (((chip_name == 0x7531 || chip_name == 0x7988) && (meter > 1000000))) {
developerbe40a9e2024-03-07 21:44:26 +0800928 reg_read(0xc, &value);
developerfd40db22021-04-29 10:08:25 +0800929 value |= 0x1 << 30;
developerbe40a9e2024-03-07 21:44:26 +0800930 reg_write(0xC, value);
931 printf("AGC: 0x%x\n", value);
932 value = meter / 1000; //uint is 1Mbps
developerfd40db22021-04-29 10:08:25 +0800933 } else {
developerbe40a9e2024-03-07 21:44:26 +0800934 reg_read(0xc, &value);
developerfd40db22021-04-29 10:08:25 +0800935 value &= ~(0x1 << 30);
developerbe40a9e2024-03-07 21:44:26 +0800936 reg_write(0xC, value);
937 printf("AGC: 0x%x\n", value);
938 value = meter >> 6; //uint is 64Kbps
developerfd40db22021-04-29 10:08:25 +0800939 }
developerbe40a9e2024-03-07 21:44:26 +0800940 value |= 0x1 << 15; //enable rate control
941 printf("Acl rate control:0x%x\n", value);
developerfd40db22021-04-29 10:08:25 +0800942 write_rate_table(0, value, 0);
943}
944
945void acl_dip_trtcm(int argc, char *argv[])
946{
947 unsigned int value, value2, ip_value;
948 unsigned int CIR, CBS, PIR, PBS;
949 int ports;
950 int ret;
951
952 ip_value = 0;
953 ret = acl_parameters_pre_del(10, -1, argc, argv, &ports);
954 if (ret < 0)
955 return;
956
957 str_to_ip(&ip_value, argv[4]);
958 //set pattern
959 value = (ip_value >> 16);
960 acl_compare_pattern(ports, value, 0x2, 0x8, 0);
961
962 //set pattern
963 value = (ip_value & 0xffff);
964 acl_compare_pattern(ports, value, 0x2, 0x9, 1);
965
966 //set CBS PBS
967 CIR = strtoul(argv[6], NULL, 0);
968 CBS = strtoul(argv[7], NULL, 0);
969 PIR = strtoul(argv[8], NULL, 0);
970 PBS = strtoul(argv[9], NULL, 0);
971
developerbe40a9e2024-03-07 21:44:26 +0800972 if (CIR > 65535 * 64 || CBS > 65535 || PIR > 65535 * 64 || PBS > 65535) {
developerfd40db22021-04-29 10:08:25 +0800973 printf("\n**Illegal input parameters**\n");
974 return;
975 }
976
developerbe40a9e2024-03-07 21:44:26 +0800977 value = CBS << 16; //bit16~31
978 value |= PBS; //bit0~15
979 //value |= 1;//valid
developerfd40db22021-04-29 10:08:25 +0800980 CIR = CIR >> 6;
981 PIR = PIR >> 6;
982
developerbe40a9e2024-03-07 21:44:26 +0800983 value2 = CIR << 16; //bit16~31
984 value2 |= PIR; //bit0~15
985 write_trTCM_table(0, value, value2);
developerfd40db22021-04-29 10:08:25 +0800986
987 //set pattern
developerbe40a9e2024-03-07 21:44:26 +0800988 write_acl_mask_table(0, 0x3, 0);
developerfd40db22021-04-29 10:08:25 +0800989
990 //set action
developerbe40a9e2024-03-07 21:44:26 +0800991 value = 0x1 << (11 + 1); //TrTCM green meter#0 Low drop
992 value |= 0x2 << (8 + 1); //TrTCM yellow meter#0 Med drop
993 value |= 0x3 << (5 + 1); //TrTCM red meter#0 Hig drop
994 value |= 0x1 << 0; //TrTCM drop pcd select
995 write_acl_rule_table(0, 0, value);
developerfd40db22021-04-29 10:08:25 +0800996}
997
998void acl_ethertype(int argc, char *argv[])
999{
1000 unsigned int value, ethertype;
1001 int ports;
1002 int ret;
1003
1004 ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
1005 if (ret < 0)
1006 return;
developerbe40a9e2024-03-07 21:44:26 +08001007 printf("ports:0x%x\n", ports);
developerfd40db22021-04-29 10:08:25 +08001008 ethertype = strtoul(argv[4], NULL, 16);
1009 //set pattern
1010 value = ethertype;
1011 acl_compare_pattern(ports, value, 0x0, 0x6, 0);
1012
1013 //set pattern
developerbe40a9e2024-03-07 21:44:26 +08001014 write_acl_mask_table(0, 0x1, 0);
developerfd40db22021-04-29 10:08:25 +08001015
1016 //set action(drop)
developerbe40a9e2024-03-07 21:44:26 +08001017 value = 0x7; //default. Nodrop
1018 value |= 1 << 28; //acl intterupt enable
1019 value |= 1 << 27; //acl hit count
developerfd40db22021-04-29 10:08:25 +08001020
developerbe40a9e2024-03-07 21:44:26 +08001021 write_acl_rule_table(0, value, 0);
developerfd40db22021-04-29 10:08:25 +08001022}
1023
1024void acl_dip_modify(int argc, char *argv[])
1025{
1026 unsigned int value, ip_value;
1027 int ports;
1028 int priority;
1029 int ret;
1030
1031 ip_value = 0;
1032 priority = strtoul(argv[6], NULL, 16);
1033 if (priority < 0 || priority > 7) {
1034 printf("\n**Illegal priority value!**\n");
1035 return;
1036 }
1037
1038 ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
1039 if (ret < 0)
1040 return;
1041
1042 str_to_ip(&ip_value, argv[4]);
1043 //set pattern
1044 value = (ip_value >> 16);
1045 acl_compare_pattern(ports, value, 0x2, 0x8, 0);
1046
1047 //set pattern
1048 value = (ip_value & 0xffff);
1049 acl_compare_pattern(ports, value, 0x2, 0x9, 1);
1050
1051 //set pattern
developerbe40a9e2024-03-07 21:44:26 +08001052 write_acl_mask_table(0, 0x3, 0);
developerfd40db22021-04-29 10:08:25 +08001053
1054 //set action
developerbe40a9e2024-03-07 21:44:26 +08001055 value = 0x0; //default. Nodrop
1056 value |= 1 << 28; //acl intterupt enable
1057 value |= 1 << 27; //acl hit count
1058 value |= priority << 4; //acl UP
1059 write_acl_rule_table(0, value, 0);
developerfd40db22021-04-29 10:08:25 +08001060}
1061
1062void acl_dip_pppoe(int argc, char *argv[])
1063{
1064 unsigned int value, ip_value;
1065 int ports;
1066 int ret;
1067
1068 ip_value = 0;
1069 ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
1070 if (ret < 0)
1071 return;
1072
1073 str_to_ip(&ip_value, argv[4]);
1074 //set pattern
1075 value = (ip_value >> 16);
1076 acl_compare_pattern(ports, value, 0x2, 0x8, 0);
1077
1078 //set pattern
1079 value = (ip_value & 0xffff);
1080 acl_compare_pattern(ports, value, 0x2, 0x9, 1);
1081
1082 //set pattern
developerbe40a9e2024-03-07 21:44:26 +08001083 write_acl_mask_table(0, 0x3, 0);
developerfd40db22021-04-29 10:08:25 +08001084
1085 //set action
developerbe40a9e2024-03-07 21:44:26 +08001086 value = 0x0; //default. Nodrop
1087 value |= 1 << 28; //acl intterupt enable
1088 value |= 1 << 27; //acl hit count
1089 value |= 1 << 20; //pppoe header remove
1090 value |= 1 << 21; //SA MAC SWAP
1091 value |= 1 << 22; //DA MAC SWAP
1092 write_acl_rule_table(0, value, 7);
developerfd40db22021-04-29 10:08:25 +08001093}
1094
1095void acl_dip_add(int argc, char *argv[])
1096{
1097 unsigned int value, ip_value;
1098 int ports;
1099 int ret;
1100
1101 ip_value = 0;
1102 ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
1103 if (ret < 0)
1104 return;
1105
1106 str_to_ip(&ip_value, argv[4]);
1107 //set pattern
1108 value = (ip_value >> 16);
1109 acl_compare_pattern(ports, value, 0x2, 0x8, 0);
1110
1111 //set pattern
1112 value = (ip_value & 0xffff);
1113 acl_compare_pattern(ports, value, 0x2, 0x9, 1);
1114
1115 //set pattern
developerbe40a9e2024-03-07 21:44:26 +08001116 write_acl_mask_table(0, 0x3, 0);
developerfd40db22021-04-29 10:08:25 +08001117
1118 //set action
1119 //value = 0x0; //default
developerbe40a9e2024-03-07 21:44:26 +08001120 value = 0x7; //drop
1121 value |= 1 << 28; //acl intterupt enable
1122 value |= 1 << 27; //acl hit count
1123 value |= 2 << 24; //acl hit count group index (0~3)
1124 write_acl_rule_table(0, value, 0);
developerfd40db22021-04-29 10:08:25 +08001125}
1126
1127void acl_l4_add(int argc, char *argv[])
1128{
developerbe40a9e2024-03-07 21:44:26 +08001129 unsigned int value = 0;
developerfd40db22021-04-29 10:08:25 +08001130 int ports;
1131 int ret;
1132
1133 ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
1134 if (ret < 0)
1135 return;
1136
1137 //set pattern
1138 value = strtoul(argv[4], NULL, 16);
1139 acl_compare_pattern(ports, value, 0x5, 0x0, 0);
1140
1141 //set rue mask
developerbe40a9e2024-03-07 21:44:26 +08001142 write_acl_mask_table(0, 0x1, 0);
developerfd40db22021-04-29 10:08:25 +08001143 //set action
developerbe40a9e2024-03-07 21:44:26 +08001144 value = 0x7; //drop
1145 //value |= 1;//valid
1146 write_acl_rule_table(0, value, 0);
developerfd40db22021-04-29 10:08:25 +08001147}
1148
1149void acl_sp_add(int argc, char *argv[])
1150{
developerbe40a9e2024-03-07 21:44:26 +08001151 unsigned int value = 0;
developerfd40db22021-04-29 10:08:25 +08001152 int ports;
1153 int ret;
1154
1155 ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
1156 if (ret < 0)
1157 return;
1158 //set pattern
1159 value = strtoul(argv[4], NULL, 0);
1160 acl_compare_pattern(ports, value, 0x4, 0x0, 0);
1161
1162 //set rue mask
developerbe40a9e2024-03-07 21:44:26 +08001163 write_acl_mask_table(0, 0x1, 0);
developerfd40db22021-04-29 10:08:25 +08001164
1165 //set action
developerbe40a9e2024-03-07 21:44:26 +08001166 value = 0x7; //drop
1167 //value |= 1;//valid
1168 write_acl_rule_table(0, value, 0);
developerfd40db22021-04-29 10:08:25 +08001169}
1170
1171void acl_port_enable(int argc, char *argv[])
1172{
developerbe40a9e2024-03-07 21:44:26 +08001173 unsigned int value = 0, reg = 0;
1174 unsigned char acl_port = 0, acl_en = 0;
developer546b2792024-06-15 20:31:38 +08001175 char *endptr;
developerfd40db22021-04-29 10:08:25 +08001176
developer546b2792024-06-15 20:31:38 +08001177 errno = 0;
1178 acl_port = strtoul(argv[3], &endptr, 10);
1179 if (errno != 0 || *endptr != '\0' || acl_port > MAX_PORT) {
1180 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
1181 return;
1182 }
developerfd40db22021-04-29 10:08:25 +08001183
developer546b2792024-06-15 20:31:38 +08001184 errno = 0;
1185 acl_en = strtoul(argv[4], &endptr, 10);
1186 if (errno != 0 || *endptr != '\0' || acl_en > 1) {
developerfd40db22021-04-29 10:08:25 +08001187 printf(HELP_ACL_SETPORTEN);
1188 return;
1189 }
1190
developer546b2792024-06-15 20:31:38 +08001191 printf("acl_port:%d, acl_en:%d\n", acl_port, acl_en);
1192
developerbe40a9e2024-03-07 21:44:26 +08001193 reg = REG_PCR_P0_ADDR + (0x100 * acl_port); // 0x2004[10]
developerfd40db22021-04-29 10:08:25 +08001194 reg_read(reg, &value);
1195 value &= (~REG_PORT_ACL_EN_MASK);
1196 value |= (acl_en << REG_PORT_ACL_EN_OFFT);
1197
1198 printf("write reg: %x, value: %x\n", reg, value);
1199 reg_write(reg, value);
1200}
1201
1202static void dip_dump_internal(int type)
1203{
1204 unsigned int i, j, value, mac, mac2, value2;
developerbe40a9e2024-03-07 21:44:26 +08001205 char tmpstr[16] = { 0 };
developerfd40db22021-04-29 10:08:25 +08001206 int table_size = 0;
1207 int hit_value1 = 0;
1208 int hit_value2 = 0;
1209
developerbe40a9e2024-03-07 21:44:26 +08001210 if (type == GENERAL_TABLE) {
developerfd40db22021-04-29 10:08:25 +08001211 table_size = 0x800;
developerbe40a9e2024-03-07 21:44:26 +08001212 reg_write(REG_ATC_ADDR, 0x8104); //dip search command
1213 } else {
developerfd40db22021-04-29 10:08:25 +08001214 table_size = 0x40;
developerbe40a9e2024-03-07 21:44:26 +08001215 reg_write(REG_ATC_ADDR, 0x811c); //dip search command
developerfd40db22021-04-29 10:08:25 +08001216 }
developerbe40a9e2024-03-07 21:44:26 +08001217 printf
1218 ("hash port(0:6) rsp_cnt flag timer dip-address ATRD\n");
developerfd40db22021-04-29 10:08:25 +08001219 for (i = 0; i < table_size; i++) {
developerbe40a9e2024-03-07 21:44:26 +08001220 while (1) {
developerfd40db22021-04-29 10:08:25 +08001221 reg_read(REG_ATC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08001222 if (type == GENERAL_TABLE) {
developerfd40db22021-04-29 10:08:25 +08001223 hit_value1 = value & (0x1 << 13);
1224 hit_value2 = 1;
developerbe40a9e2024-03-07 21:44:26 +08001225 } else {
developerfd40db22021-04-29 10:08:25 +08001226 hit_value1 = value & (0x1 << 13);
1227 hit_value2 = value & (0x1 << 28);
1228 }
1229
developerbe40a9e2024-03-07 21:44:26 +08001230 if (hit_value1 && hit_value2) { //search_rdy
developerfd40db22021-04-29 10:08:25 +08001231 reg_read(REG_ATRD_ADDR, &value2);
1232 //printf("REG_ATRD_ADDR=0x%x\n\r",value2);
1233
developerbe40a9e2024-03-07 21:44:26 +08001234 printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
1235 j = (value2 >> 4) & 0xff; //r_port_map
developerfd40db22021-04-29 10:08:25 +08001236 printf("%c", (j & 0x01) ? '1' : '-');
1237 printf("%c", (j & 0x02) ? '1' : '-');
1238 printf("%c", (j & 0x04) ? '1' : '-');
1239 printf("%c ", (j & 0x08) ? '1' : '-');
1240 printf("%c", (j & 0x10) ? '1' : '-');
1241 printf("%c", (j & 0x20) ? '1' : '-');
1242 printf("%c", (j & 0x40) ? '1' : '-');
1243
1244 reg_read(REG_TSRA2_ADDR, &mac2);
1245
developerbe40a9e2024-03-07 21:44:26 +08001246 printf(" 0x%4x", (mac2 & 0xffff)); //RESP_CNT
1247 printf(" 0x%2x", ((mac2 >> 16) & 0xff)); //RESP_FLAG
1248 printf(" %3d", ((mac2 >> 24) & 0xff)); //RESP_TIMER
1249 //printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
developerfd40db22021-04-29 10:08:25 +08001250 reg_read(REG_TSRA1_ADDR, &mac);
developer546b2792024-06-15 20:31:38 +08001251 ip_to_str(tmpstr, sizeof(tmpstr), mac);
developerfd40db22021-04-29 10:08:25 +08001252 printf(" %s", tmpstr);
developerbe40a9e2024-03-07 21:44:26 +08001253 printf(" 0x%8x\n", value2); //ATRD
1254 //printf("%04x", ((mac2 >> 16) & 0xffff));
1255 //printf(" %c\n", (((value2 >> 20) & 0x03)== 0x03)? 'y':'-');
developerfd40db22021-04-29 10:08:25 +08001256 if (value & 0x4000) {
1257 printf("end of table %d\n", i);
1258 return;
1259 }
1260 break;
developerbe40a9e2024-03-07 21:44:26 +08001261 } else if (value & 0x4000) { //at_table_end
1262 printf("found the last entry %d (not ready)\n",
1263 i);
developerfd40db22021-04-29 10:08:25 +08001264 return;
1265 }
1266 usleep(5000);
1267 }
1268
developerbe40a9e2024-03-07 21:44:26 +08001269 if (type == GENERAL_TABLE)
1270 reg_write(REG_ATC_ADDR, 0x8105); //search for next dip address
developerfd40db22021-04-29 10:08:25 +08001271 else
developerbe40a9e2024-03-07 21:44:26 +08001272 reg_write(REG_ATC_ADDR, 0x811d); //search for next dip address
developerfd40db22021-04-29 10:08:25 +08001273 usleep(5000);
1274 }
1275}
1276
developerbe40a9e2024-03-07 21:44:26 +08001277void dip_dump(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08001278{
1279 dip_dump_internal(GENERAL_TABLE);
1280
1281}
1282
1283void dip_add(int argc, char *argv[])
1284{
1285 unsigned int value = 0;
developerbe40a9e2024-03-07 21:44:26 +08001286 unsigned int i = 0, j = 0;
developerfd40db22021-04-29 10:08:25 +08001287
1288 value = 0;
1289
1290 str_to_ip(&value, argv[3]);
1291
1292 reg_write(REG_ATA1_ADDR, value);
1293 printf("REG_ATA1_ADDR is 0x%x\n\r", value);
1294
1295#if 0
1296 reg_write(REG_ATA2_ADDR, value);
1297 printf("REG_ATA2_ADDR is 0x%x\n\r", value);
1298#endif
1299 if (!argv[4] || strlen(argv[4]) != 8) {
1300 printf("portmap format error, should be of length 7\n");
1301 return;
1302 }
1303 j = 0;
1304 for (i = 0; i < 7; i++) {
1305 if (argv[4][i] != '0' && argv[4][i] != '1') {
developerbe40a9e2024-03-07 21:44:26 +08001306 printf
1307 ("portmap format error, should be of combination of 0 or 1\n");
developerfd40db22021-04-29 10:08:25 +08001308 return;
1309 }
1310 j += (argv[4][i] - '0') * (1 << i);
1311 }
developerbe40a9e2024-03-07 21:44:26 +08001312 value = j << 4; //w_port_map
1313 value |= (0x3 << 2); //static
developerfd40db22021-04-29 10:08:25 +08001314
1315 reg_write(REG_ATWD_ADDR, value);
1316
1317 usleep(5000);
1318 reg_read(REG_ATWD_ADDR, &value);
1319 printf("REG_ATWD_ADDR is 0x%x\n\r", value);
1320
developerbe40a9e2024-03-07 21:44:26 +08001321 value = 0x8011; //single w_dip_cmd
developerfd40db22021-04-29 10:08:25 +08001322 reg_write(REG_ATC_ADDR, value);
1323
1324 usleep(1000);
1325
1326 for (i = 0; i < 20; i++) {
1327 reg_read(REG_ATC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08001328 if ((value & 0x8000) == 0) { //mac address busy
developerfd40db22021-04-29 10:08:25 +08001329 printf("done.\n");
1330 return;
1331 }
1332 usleep(1000);
1333 }
1334 if (i == 20)
1335 printf("timeout.\n");
1336}
1337
1338void dip_del(int argc, char *argv[])
1339{
1340 unsigned int i, value;
1341
1342 value = 0;
1343 str_to_ip(&value, argv[3]);
1344
1345 reg_write(REG_ATA1_ADDR, value);
1346
1347 value = 0;
1348 reg_write(REG_ATA2_ADDR, value);
1349
developerbe40a9e2024-03-07 21:44:26 +08001350 value = 0; //STATUS=0, delete dip
developerfd40db22021-04-29 10:08:25 +08001351 reg_write(REG_ATWD_ADDR, value);
1352
developerbe40a9e2024-03-07 21:44:26 +08001353 value = 0x8011; //w_dip_cmd
developerfd40db22021-04-29 10:08:25 +08001354 reg_write(REG_ATC_ADDR, value);
1355
1356 for (i = 0; i < 20; i++) {
1357 reg_read(REG_ATC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08001358 if ((value & 0x8000) == 0) { //mac address busy
developerfd40db22021-04-29 10:08:25 +08001359 if (argv[1] != NULL)
1360 printf("done.\n");
1361 return;
1362 }
1363 usleep(1000);
1364 }
1365 if (i == 20)
1366 printf("timeout.\n");
1367}
1368
developerbe40a9e2024-03-07 21:44:26 +08001369void dip_clear(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08001370{
1371
developerbe40a9e2024-03-07 21:44:26 +08001372 unsigned int value = 0;
developerfd40db22021-04-29 10:08:25 +08001373
developerbe40a9e2024-03-07 21:44:26 +08001374 reg_write(REG_ATC_ADDR, 0x8102); //clear all dip
developerfd40db22021-04-29 10:08:25 +08001375 usleep(5000);
1376 reg_read(REG_ATC_ADDR, &value);
1377 printf("REG_ATC_ADDR is 0x%x\n\r", value);
1378}
1379
1380static void sip_dump_internal(int type)
1381{
developerbe40a9e2024-03-07 21:44:26 +08001382 unsigned int i = 0, j = 0, value = 0, mac = 0, mac2 = 0, value2 = 0;
developerfd40db22021-04-29 10:08:25 +08001383 int table_size = 0;
1384 int hit_value1 = 0;
1385 int hit_value2 = 0;
developerbe40a9e2024-03-07 21:44:26 +08001386 char tmpstr[16] = { 0 };
developerfd40db22021-04-29 10:08:25 +08001387
1388 if (type == GENERAL_TABLE) {
1389 table_size = 0x800;
developerbe40a9e2024-03-07 21:44:26 +08001390 reg_write(REG_ATC_ADDR, 0x8204); //sip search command
1391 } else {
developerfd40db22021-04-29 10:08:25 +08001392 table_size = 0x40;
developerbe40a9e2024-03-07 21:44:26 +08001393 reg_write(REG_ATC_ADDR, 0x822c); //sip search command
developerfd40db22021-04-29 10:08:25 +08001394 }
1395 printf("hash port(0:6) dip-address sip-address ATRD\n");
1396 for (i = 0; i < table_size; i++) {
developerbe40a9e2024-03-07 21:44:26 +08001397 while (1) {
developerfd40db22021-04-29 10:08:25 +08001398 reg_read(REG_ATC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08001399 if (type == GENERAL_TABLE) {
developerfd40db22021-04-29 10:08:25 +08001400 hit_value1 = value & (0x1 << 13);
1401 hit_value2 = 1;
1402 } else {
1403 hit_value1 = value & (0x1 << 13);
1404 hit_value2 = value & (0x1 << 28);
1405 }
1406
developerbe40a9e2024-03-07 21:44:26 +08001407 if (hit_value1 && hit_value2) { //search_rdy
developerfd40db22021-04-29 10:08:25 +08001408 reg_read(REG_ATRD_ADDR, &value2);
1409 //printf("REG_ATRD_ADDR=0x%x\n\r",value2);
1410
developerbe40a9e2024-03-07 21:44:26 +08001411 printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
1412 j = (value2 >> 4) & 0xff; //r_port_map
developerfd40db22021-04-29 10:08:25 +08001413 printf("%c", (j & 0x01) ? '1' : '-');
1414 printf("%c", (j & 0x02) ? '1' : '-');
1415 printf("%c", (j & 0x04) ? '1' : '-');
1416 printf("%c", (j & 0x08) ? '1' : '-');
1417 printf(" %c", (j & 0x10) ? '1' : '-');
1418 printf("%c", (j & 0x20) ? '1' : '-');
1419 printf("%c", (j & 0x40) ? '1' : '-');
1420
1421 reg_read(REG_TSRA2_ADDR, &mac2);
1422
developer546b2792024-06-15 20:31:38 +08001423 ip_to_str(tmpstr, sizeof(tmpstr), mac2);
developerfd40db22021-04-29 10:08:25 +08001424 printf(" %s", tmpstr);
1425
1426 //printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
1427 reg_read(REG_TSRA1_ADDR, &mac);
developer546b2792024-06-15 20:31:38 +08001428 ip_to_str(tmpstr, sizeof(tmpstr), mac);
developerfd40db22021-04-29 10:08:25 +08001429 printf(" %s", tmpstr);
1430 printf(" 0x%x\n", value2);
1431 //printf("%04x", ((mac2 >> 16) & 0xffff));
1432 //printf(" %c\n", (((value2 >> 20) & 0x03)== 0x03)? 'y':'-');
1433 if (value & 0x4000) {
1434 printf("end of table %d\n", i);
1435 return;
1436 }
1437 break;
developerbe40a9e2024-03-07 21:44:26 +08001438 } else if (value & 0x4000) { //at_table_end
1439 printf("found the last entry %d (not ready)\n",
1440 i);
developerfd40db22021-04-29 10:08:25 +08001441 return;
1442 }
1443 usleep(5000);
1444 }
1445
developerbe40a9e2024-03-07 21:44:26 +08001446 if (type == GENERAL_TABLE)
1447 reg_write(REG_ATC_ADDR, 0x8205); //search for next sip address
1448 else
1449 reg_write(REG_ATC_ADDR, 0x822d); //search for next sip address
1450 usleep(5000);
developerfd40db22021-04-29 10:08:25 +08001451 }
1452}
1453
developerbe40a9e2024-03-07 21:44:26 +08001454void sip_dump(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08001455{
1456
1457 sip_dump_internal(GENERAL_TABLE);
1458
1459}
1460
developerfd40db22021-04-29 10:08:25 +08001461void sip_add(int argc, char *argv[])
1462{
developerbe40a9e2024-03-07 21:44:26 +08001463 unsigned int i = 0, j = 0, value = 0;
developerfd40db22021-04-29 10:08:25 +08001464
1465 value = 0;
developerbe40a9e2024-03-07 21:44:26 +08001466 str_to_ip(&value, argv[3]); //SIP
developerfd40db22021-04-29 10:08:25 +08001467
1468 reg_write(REG_ATA2_ADDR, value);
1469 printf("REG_ATA2_ADDR is 0x%x\n\r", value);
1470
1471 value = 0;
1472
developerbe40a9e2024-03-07 21:44:26 +08001473 str_to_ip(&value, argv[4]); //DIP
developerfd40db22021-04-29 10:08:25 +08001474 reg_write(REG_ATA1_ADDR, value);
1475 printf("REG_ATA1_ADDR is 0x%x\n\r", value);
1476
1477 if (!argv[5] || strlen(argv[5]) != 8) {
1478 printf("portmap format error, should be of length 7\n");
1479 return;
1480 }
1481 j = 0;
1482 for (i = 0; i < 7; i++) {
1483 if (argv[5][i] != '0' && argv[5][i] != '1') {
developerbe40a9e2024-03-07 21:44:26 +08001484 printf
1485 ("portmap format error, should be of combination of 0 or 1\n");
developerfd40db22021-04-29 10:08:25 +08001486 return;
1487 }
1488 j += (argv[5][i] - '0') * (1 << i);
1489 }
developerbe40a9e2024-03-07 21:44:26 +08001490 value = j << 4; //w_port_map
1491 value |= (0x3 << 2); //static
developerfd40db22021-04-29 10:08:25 +08001492
1493 reg_write(REG_ATWD_ADDR, value);
1494
1495 usleep(5000);
1496 reg_read(REG_ATWD_ADDR, &value);
1497 printf("REG_ATWD_ADDR is 0x%x\n\r", value);
1498
developerbe40a9e2024-03-07 21:44:26 +08001499 value = 0x8021; //single w_sip_cmd
developerfd40db22021-04-29 10:08:25 +08001500 reg_write(REG_ATC_ADDR, value);
1501
1502 usleep(1000);
1503
1504 for (i = 0; i < 20; i++) {
1505 reg_read(REG_ATC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08001506 if ((value & 0x8000) == 0) { //mac address busy
developerfd40db22021-04-29 10:08:25 +08001507 printf("done.\n");
1508 return;
1509 }
1510 usleep(1000);
1511 }
1512 if (i == 20)
1513 printf("timeout.\n");
1514}
1515
1516void sip_del(int argc, char *argv[])
1517{
developerbe40a9e2024-03-07 21:44:26 +08001518 unsigned int i = 0, value = 0;
developerfd40db22021-04-29 10:08:25 +08001519
1520 value = 0;
1521 str_to_ip(&value, argv[3]);
1522
developerbe40a9e2024-03-07 21:44:26 +08001523 reg_write(REG_ATA2_ADDR, value); //SIP
developerfd40db22021-04-29 10:08:25 +08001524
1525 str_to_ip(&value, argv[4]);
developerbe40a9e2024-03-07 21:44:26 +08001526 reg_write(REG_ATA1_ADDR, value); //DIP
developerfd40db22021-04-29 10:08:25 +08001527
developerbe40a9e2024-03-07 21:44:26 +08001528 value = 0; //STATUS=0, delete sip
developerfd40db22021-04-29 10:08:25 +08001529 reg_write(REG_ATWD_ADDR, value);
1530
developerbe40a9e2024-03-07 21:44:26 +08001531 value = 0x8021; //w_sip_cmd
developerfd40db22021-04-29 10:08:25 +08001532 reg_write(REG_ATC_ADDR, value);
1533
1534 for (i = 0; i < 20; i++) {
1535 reg_read(REG_ATC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08001536 if ((value & 0x8000) == 0) { //mac address busy
developerfd40db22021-04-29 10:08:25 +08001537 if (argv[1] != NULL)
1538 printf("done.\n");
1539 return;
1540 }
1541 usleep(1000);
1542 }
1543 if (i == 20)
1544 printf("timeout.\n");
1545}
1546
developerbe40a9e2024-03-07 21:44:26 +08001547void sip_clear(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08001548{
developerbe40a9e2024-03-07 21:44:26 +08001549 unsigned int value = 0;
developerfd40db22021-04-29 10:08:25 +08001550
developerbe40a9e2024-03-07 21:44:26 +08001551 reg_write(REG_ATC_ADDR, 0x8202); //clear all sip
developerfd40db22021-04-29 10:08:25 +08001552 usleep(5000);
1553 reg_read(REG_ATC_ADDR, &value);
1554 printf("REG_ATC_ADDR is 0x%x\n\r", value);
1555}
1556
1557static void table_dump_internal(int type)
1558{
developerbe40a9e2024-03-07 21:44:26 +08001559 unsigned int i = 0, j = 0, value = 0, mac = 0, mac2 = 0, value2 = 0;
developerfd40db22021-04-29 10:08:25 +08001560 int table_size = 0;
1561 int table_end = 0;
1562 int hit_value1 = 0;
1563 int hit_value2 = 0;
1564
developerbe40a9e2024-03-07 21:44:26 +08001565 if (type == GENERAL_TABLE) {
developerfd40db22021-04-29 10:08:25 +08001566 table_size = 0x800;
1567 table_end = 0x7FF;
1568 reg_write(REG_ATC_ADDR, 0x8004);
1569 } else {
1570 table_size = 0x40;
1571 table_end = 0x3F;
1572 reg_write(REG_ATC_ADDR, 0x800C);
1573 }
developerbe40a9e2024-03-07 21:44:26 +08001574 printf
1575 ("hash port(0:6) fid vid age(s) mac-address filter my_mac\n");
developerfd40db22021-04-29 10:08:25 +08001576 for (i = 0; i < table_size; i++) {
developerbe40a9e2024-03-07 21:44:26 +08001577 while (1) {
developerfd40db22021-04-29 10:08:25 +08001578 reg_read(REG_ATC_ADDR, &value);
1579 //printf("ATC = 0x%x\n", value);
developerbe40a9e2024-03-07 21:44:26 +08001580 if (type == GENERAL_TABLE) {
developerfd40db22021-04-29 10:08:25 +08001581 hit_value1 = value & (0x1 << 13);
1582 hit_value2 = 1;
1583 } else {
1584 hit_value1 = value & (0x1 << 13);
1585 hit_value2 = value & (0x1 << 28);
1586 }
1587
developerbe40a9e2024-03-07 21:44:26 +08001588 if (hit_value1 && hit_value2
1589 && (((value >> 15) & 0x1) == 0)) {
developerfd40db22021-04-29 10:08:25 +08001590 printf("%03x: ", (value >> 16) & 0xfff);
1591 reg_read(REG_ATRD_ADDR, &value2);
developerbe40a9e2024-03-07 21:44:26 +08001592 j = (value2 >> 4) & 0xff; //r_port_map
developerfd40db22021-04-29 10:08:25 +08001593 printf("%c", (j & 0x01) ? '1' : '-');
1594 printf("%c", (j & 0x02) ? '1' : '-');
1595 printf("%c", (j & 0x04) ? '1' : '-');
1596 printf("%c", (j & 0x08) ? '1' : '-');
1597 printf("%c", (j & 0x10) ? '1' : '-');
1598 printf("%c", (j & 0x20) ? '1' : '-');
1599 printf("%c", (j & 0x40) ? '1' : '-');
1600 printf("%c", (j & 0x80) ? '1' : '-');
1601
1602 reg_read(REG_TSRA2_ADDR, &mac2);
1603
developerbe40a9e2024-03-07 21:44:26 +08001604 printf(" %2d", (mac2 >> 12) & 0x7); //FID
developerfd40db22021-04-29 10:08:25 +08001605 printf(" %4d", (mac2 & 0xfff));
1606 if (((value2 >> 24) & 0xff) == 0xFF)
developerbe40a9e2024-03-07 21:44:26 +08001607 printf(" --- "); //r_age_field:static
developerfd40db22021-04-29 10:08:25 +08001608 else
developerbe40a9e2024-03-07 21:44:26 +08001609 printf(" %5d ", (((value2 >> 24) & 0xff) + 1) * 2); //r_age_field
developerfd40db22021-04-29 10:08:25 +08001610 reg_read(REG_TSRA1_ADDR, &mac);
1611 printf(" %08x", mac);
1612 printf("%04x", ((mac2 >> 16) & 0xffff));
developerbe40a9e2024-03-07 21:44:26 +08001613 printf(" %c",
1614 (((value2 >> 20) & 0x03) ==
1615 0x03) ? 'y' : '-');
1616 printf(" %c\n",
1617 (((value2 >> 23) & 0x01) ==
1618 0x01) ? 'y' : '-');
1619 if ((value & 0x4000)
1620 && (((value >> 16) & 0xfff) == table_end)) {
developerfd40db22021-04-29 10:08:25 +08001621 printf("end of table %d\n", i);
1622 return;
1623 }
1624 break;
developerbe40a9e2024-03-07 21:44:26 +08001625 } else if ((value & 0x4000) && (((value >> 15) & 0x1) == 0) && (((value >> 16) & 0xfff) == table_end)) { //at_table_end
1626 printf("found the last entry %d (not ready)\n",
1627 i);
developerfd40db22021-04-29 10:08:25 +08001628 return;
developerbe40a9e2024-03-07 21:44:26 +08001629 } else
developerfd40db22021-04-29 10:08:25 +08001630 usleep(5);
1631 }
1632
developerbe40a9e2024-03-07 21:44:26 +08001633 if (type == GENERAL_TABLE)
1634 reg_write(REG_ATC_ADDR, 0x8005); //search for next address
1635 else
1636 reg_write(REG_ATC_ADDR, 0x800d); //search for next address
developerfd40db22021-04-29 10:08:25 +08001637 usleep(5);
1638 }
1639}
1640
developerbe40a9e2024-03-07 21:44:26 +08001641void table_dump(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08001642{
1643 table_dump_internal(GENERAL_TABLE);
1644
1645}
1646
developerfd40db22021-04-29 10:08:25 +08001647void table_add(int argc, char *argv[])
1648{
developerbe40a9e2024-03-07 21:44:26 +08001649 unsigned int i = 0, j = 0, value = 0, is_filter = 0, is_mymac = 0;
developerfd40db22021-04-29 10:08:25 +08001650 char tmpstr[9];
developer621433d2024-06-15 20:40:10 +08001651 char *endptr;
developerfd40db22021-04-29 10:08:25 +08001652
1653 is_filter = (argv[1][0] == 'f') ? 1 : 0;
1654 is_mymac = (argv[1][0] == 'm') ? 1 : 0;
1655 if (!argv[2] || strlen(argv[2]) != 12) {
1656 printf("MAC address format error, should be of length 12\n");
1657 return;
1658 }
1659 strncpy(tmpstr, argv[2], 8);
1660 tmpstr[8] = '\0';
developer621433d2024-06-15 20:40:10 +08001661 errno = 0;
1662 value = strtoul(tmpstr, &endptr, 16);
1663 if (errno != 0 || *endptr != '\0') {
1664 printf("Error: string converting\n");
1665 return;
1666 }
developerfd40db22021-04-29 10:08:25 +08001667 reg_write(REG_ATA1_ADDR, value);
1668 printf("REG_ATA1_ADDR is 0x%x\n\r", value);
1669
1670 strncpy(tmpstr, argv[2] + 8, 4);
1671 tmpstr[4] = '\0';
developer621433d2024-06-15 20:40:10 +08001672 errno = 0;
1673 value = strtoul(tmpstr, &endptr, 16);
1674 if (errno != 0 || *endptr != '\0') {
1675 printf("Error: string converting\n");
1676 return;
1677 }
developerfd40db22021-04-29 10:08:25 +08001678 value = (value << 16);
developerbe40a9e2024-03-07 21:44:26 +08001679 value |= (1 << 15); //IVL=1
developerfd40db22021-04-29 10:08:25 +08001680
1681 if (argc > 4) {
developer621433d2024-06-15 20:40:10 +08001682 errno = 0;
1683 j = strtoul(argv[4], &endptr, 10);
1684 if (errno != 0 || *endptr != '\0' || j > 4095) {
developerfd40db22021-04-29 10:08:25 +08001685 printf("wrong vid range, should be within 0~4095\n");
1686 return;
1687 }
developerbe40a9e2024-03-07 21:44:26 +08001688 value |= j; //vid
developerfd40db22021-04-29 10:08:25 +08001689 }
1690
1691 reg_write(REG_ATA2_ADDR, value);
1692 printf("REG_ATA2_ADDR is 0x%x\n\r", value);
1693
1694 if (!argv[3] || strlen(argv[3]) != 8) {
1695 if (is_filter)
1696 argv[3] = "11111111";
1697 else {
1698 printf("portmap format error, should be of length 8\n");
1699 return;
1700 }
1701 }
1702 j = 0;
1703 for (i = 0; i < 7; i++) {
1704 if (argv[3][i] != '0' && argv[3][i] != '1') {
developerbe40a9e2024-03-07 21:44:26 +08001705 printf
1706 ("portmap format error, should be of combination of 0 or 1\n");
developerfd40db22021-04-29 10:08:25 +08001707 return;
1708 }
1709 j += (argv[3][i] - '0') * (1 << i);
1710 }
developerbe40a9e2024-03-07 21:44:26 +08001711 value = j << 4; //w_port_map
developerfd40db22021-04-29 10:08:25 +08001712
1713 if (argc > 5) {
developer621433d2024-06-15 20:40:10 +08001714 errno = 0;
1715 j = strtoul(argv[5], &endptr, 10);
1716 if (errno != 0 || *endptr != '\0' || j < 1 || 255 < j) {
developerfd40db22021-04-29 10:08:25 +08001717 printf("wrong age range, should be within 1~255\n");
1718 return;
1719 }
developerbe40a9e2024-03-07 21:44:26 +08001720 value |= (j << 24); //w_age_field
1721 value |= (0x1 << 2); //dynamic
developerfd40db22021-04-29 10:08:25 +08001722 } else {
developerbe40a9e2024-03-07 21:44:26 +08001723 value |= (0xff << 24); //w_age_field
1724 value |= (0x3 << 2); //static
developerfd40db22021-04-29 10:08:25 +08001725 }
1726
1727 if (argc > 6) {
developer621433d2024-06-15 20:40:10 +08001728 errno = 0;
1729 j = strtoul(argv[6], &endptr, 10);
1730 if (errno != 0 || *endptr != '\0' || j > 7) {
developerfd40db22021-04-29 10:08:25 +08001731 printf("wrong eg-tag range, should be within 0~7\n");
1732 return;
1733 }
developerbe40a9e2024-03-07 21:44:26 +08001734 value |= (j << 13); //EG_TAG
developerfd40db22021-04-29 10:08:25 +08001735 }
1736
1737 if (is_filter)
developerbe40a9e2024-03-07 21:44:26 +08001738 value |= (7 << 20); //sa_filter
developerfd40db22021-04-29 10:08:25 +08001739
1740 if (is_mymac)
1741 value |= (1 << 23);
1742
1743 reg_write(REG_ATWD_ADDR, value);
1744
1745 usleep(5000);
1746 reg_read(REG_ATWD_ADDR, &value);
1747 printf("REG_ATWD_ADDR is 0x%x\n\r", value);
1748
developerbe40a9e2024-03-07 21:44:26 +08001749 value = 0x8001; //w_mac_cmd
developerfd40db22021-04-29 10:08:25 +08001750 reg_write(REG_ATC_ADDR, value);
1751
1752 usleep(1000);
1753
1754 for (i = 0; i < 20; i++) {
1755 reg_read(REG_ATC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08001756 if ((value & 0x8000) == 0) { //mac address busy
developerfd40db22021-04-29 10:08:25 +08001757 printf("done.\n");
1758 return;
1759 }
1760 usleep(1000);
1761 }
1762 if (i == 20)
1763 printf("timeout.\n");
1764}
1765
1766void table_search_mac_vid(int argc, char *argv[])
1767{
developerbe40a9e2024-03-07 21:44:26 +08001768 unsigned int i = 0, j = 0, value = 0, mac = 0, mac2 = 0, value2 = 0;
developerfd40db22021-04-29 10:08:25 +08001769 char tmpstr[9];
developer621433d2024-06-15 20:40:10 +08001770 char *endptr;
developerfd40db22021-04-29 10:08:25 +08001771
1772 if (!argv[3] || strlen(argv[3]) != 12) {
1773 printf("MAC address format error, should be of length 12\n");
1774 return;
1775 }
1776 strncpy(tmpstr, argv[3], 8);
1777 tmpstr[8] = '\0';
developer621433d2024-06-15 20:40:10 +08001778 errno = 0;
1779 value = strtoul(tmpstr, &endptr, 16);
1780 if (errno != 0 || *endptr != '\0') {
1781 printf("Error: string converting\n");
1782 return;
1783 }
developerfd40db22021-04-29 10:08:25 +08001784 reg_write(REG_ATA1_ADDR, value);
1785 //printf("REG_ATA1_ADDR is 0x%x\n\r",value);
1786
1787 strncpy(tmpstr, argv[3] + 8, 4);
1788 tmpstr[4] = '\0';
1789
developer621433d2024-06-15 20:40:10 +08001790 errno = 0;
1791 value = strtoul(tmpstr, &endptr, 16);
1792 if (errno != 0 || *endptr != '\0') {
1793 printf("Error: string converting\n");
1794 return;
1795 }
developerfd40db22021-04-29 10:08:25 +08001796 value = (value << 16);
developerbe40a9e2024-03-07 21:44:26 +08001797 value |= (1 << 15); //IVL=1
developerfd40db22021-04-29 10:08:25 +08001798
developer621433d2024-06-15 20:40:10 +08001799 errno = 0;
1800 j = strtoul(argv[5], &endptr, 10);
1801 if (errno != 0 || *endptr != '\0' || j > 4095) {
developerfd40db22021-04-29 10:08:25 +08001802 printf("wrong vid range, should be within 0~4095\n");
1803 return;
1804 }
developer621433d2024-06-15 20:40:10 +08001805
developerbe40a9e2024-03-07 21:44:26 +08001806 value |= j; //vid
developerfd40db22021-04-29 10:08:25 +08001807
1808 reg_write(REG_ATA2_ADDR, value);
1809 //printf("REG_ATA2_ADDR is 0x%x\n\r",value);
1810
developerbe40a9e2024-03-07 21:44:26 +08001811 value = 0x8000; //w_mac_cmd
developerfd40db22021-04-29 10:08:25 +08001812 reg_write(REG_ATC_ADDR, value);
1813
1814 usleep(1000);
1815
1816 for (i = 0; i < 20; i++) {
1817 reg_read(REG_ATC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08001818 if ((value & 0x8000) == 0) { //mac address busy
developerfd40db22021-04-29 10:08:25 +08001819 break;
1820 }
1821 usleep(1000);
1822 }
1823 if (i == 20) {
1824 printf("search timeout.\n");
1825 return;
1826 }
1827
1828 if (value & 0x1000) {
1829 printf("search no entry.\n");
1830 return;
1831 }
1832
1833 printf("search done.\n");
developerbe40a9e2024-03-07 21:44:26 +08001834 printf
1835 ("hash port(0:6) fid vid age mac-address filter my_mac\n");
developerfd40db22021-04-29 10:08:25 +08001836
developerbe40a9e2024-03-07 21:44:26 +08001837 printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
developerfd40db22021-04-29 10:08:25 +08001838 reg_read(REG_ATRD_ADDR, &value2);
developerbe40a9e2024-03-07 21:44:26 +08001839 j = (value2 >> 4) & 0xff; //r_port_map
developerfd40db22021-04-29 10:08:25 +08001840 printf("%c", (j & 0x01) ? '1' : '-');
1841 printf("%c", (j & 0x02) ? '1' : '-');
1842 printf("%c", (j & 0x04) ? '1' : '-');
1843 printf("%c ", (j & 0x08) ? '1' : '-');
1844 printf("%c", (j & 0x10) ? '1' : '-');
1845 printf("%c", (j & 0x20) ? '1' : '-');
1846 printf("%c", (j & 0x40) ? '1' : '-');
1847 printf("%c", (j & 0x80) ? '1' : '-');
1848
1849 reg_read(REG_TSRA2_ADDR, &mac2);
1850
developerbe40a9e2024-03-07 21:44:26 +08001851 printf(" %2d", (mac2 >> 12) & 0x7); //FID
developerfd40db22021-04-29 10:08:25 +08001852 printf(" %4d", (mac2 & 0xfff));
developerbe40a9e2024-03-07 21:44:26 +08001853 printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
developerfd40db22021-04-29 10:08:25 +08001854 reg_read(REG_TSRA1_ADDR, &mac);
1855 printf(" %08x", mac);
1856 printf("%04x", ((mac2 >> 16) & 0xffff));
1857 printf(" %c", (((value2 >> 20) & 0x03) == 0x03) ? 'y' : '-');
1858 printf(" %c\n", (((value2 >> 23) & 0x01) == 0x01) ? 'y' : '-');
1859}
1860
1861void table_search_mac_fid(int argc, char *argv[])
1862{
developerbe40a9e2024-03-07 21:44:26 +08001863 unsigned int i = 0, j = 0, value = 0, mac = 0, mac2 = 0, value2 = 0;
developerfd40db22021-04-29 10:08:25 +08001864 char tmpstr[9];
developer621433d2024-06-15 20:40:10 +08001865 char *endptr;
developerfd40db22021-04-29 10:08:25 +08001866
1867 if (!argv[3] || strlen(argv[3]) != 12) {
1868 printf("MAC address format error, should be of length 12\n");
1869 return;
1870 }
1871 strncpy(tmpstr, argv[3], 8);
1872 tmpstr[8] = '\0';
developer621433d2024-06-15 20:40:10 +08001873 errno = 0;
1874 value = strtoul(tmpstr, &endptr, 16);
1875 if (errno != 0 || *endptr != '\0') {
1876 printf("Error: string converting\n");
1877 return;
1878 }
developerfd40db22021-04-29 10:08:25 +08001879 reg_write(REG_ATA1_ADDR, value);
1880 //printf("REG_ATA1_ADDR is 0x%x\n\r",value);
1881
1882 strncpy(tmpstr, argv[3] + 8, 4);
1883 tmpstr[4] = '\0';
developer621433d2024-06-15 20:40:10 +08001884 errno = 0;
1885 value = strtoul(tmpstr, &endptr, 16);
1886 if (errno != 0 || *endptr != '\0') {
1887 printf("Error: string converting\n");
1888 return;
1889 }
developerfd40db22021-04-29 10:08:25 +08001890 value = (value << 16);
developerbe40a9e2024-03-07 21:44:26 +08001891 value &= ~(1 << 15); //IVL=0
developerfd40db22021-04-29 10:08:25 +08001892
developer621433d2024-06-15 20:40:10 +08001893 errno = 0;
1894 j = strtoul(argv[5], &endptr, 10);
1895 if (errno != 0 || *endptr != '\0' || j > 7) {
developerfd40db22021-04-29 10:08:25 +08001896 printf("wrong fid range, should be within 0~7\n");
1897 return;
1898 }
developer621433d2024-06-15 20:40:10 +08001899
developerbe40a9e2024-03-07 21:44:26 +08001900 value |= (j << 12); //vid
developerfd40db22021-04-29 10:08:25 +08001901
1902 reg_write(REG_ATA2_ADDR, value);
1903 //printf("REG_ATA2_ADDR is 0x%x\n\r",value);
1904
developerbe40a9e2024-03-07 21:44:26 +08001905 value = 0x8000; //w_mac_cmd
developerfd40db22021-04-29 10:08:25 +08001906 reg_write(REG_ATC_ADDR, value);
1907
1908 usleep(1000);
1909
1910 for (i = 0; i < 20; i++) {
1911 reg_read(REG_ATC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08001912 if ((value & 0x8000) == 0) { //mac address busy
developerfd40db22021-04-29 10:08:25 +08001913 break;
1914 }
1915 usleep(1000);
1916 }
1917 if (i == 20) {
1918 printf("search timeout.\n");
1919 return;
1920 }
1921
1922 if (value & 0x1000) {
1923 printf("search no entry.\n");
1924 return;
1925 }
1926
1927 printf("search done.\n");
developerbe40a9e2024-03-07 21:44:26 +08001928 printf
1929 ("hash port(0:6) fid vid age mac-address filter my_mac\n");
developerfd40db22021-04-29 10:08:25 +08001930
developerbe40a9e2024-03-07 21:44:26 +08001931 printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
developerfd40db22021-04-29 10:08:25 +08001932 reg_read(REG_ATRD_ADDR, &value2);
developerbe40a9e2024-03-07 21:44:26 +08001933 j = (value2 >> 4) & 0xff; //r_port_map
developerfd40db22021-04-29 10:08:25 +08001934 printf("%c", (j & 0x01) ? '1' : '-');
1935 printf("%c", (j & 0x02) ? '1' : '-');
1936 printf("%c", (j & 0x04) ? '1' : '-');
1937 printf("%c ", (j & 0x08) ? '1' : '-');
1938 printf("%c", (j & 0x10) ? '1' : '-');
1939 printf("%c", (j & 0x20) ? '1' : '-');
1940 printf("%c", (j & 0x40) ? '1' : '-');
1941 printf("%c", (j & 0x80) ? '1' : '-');
1942
1943 reg_read(REG_TSRA2_ADDR, &mac2);
1944
developerbe40a9e2024-03-07 21:44:26 +08001945 printf(" %2d", (mac2 >> 12) & 0x7); //FID
developerfd40db22021-04-29 10:08:25 +08001946 printf(" %4d", (mac2 & 0xfff));
developerbe40a9e2024-03-07 21:44:26 +08001947 printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
developerfd40db22021-04-29 10:08:25 +08001948 reg_read(REG_TSRA1_ADDR, &mac);
1949 printf(" %08x", mac);
1950 printf("%04x", ((mac2 >> 16) & 0xffff));
1951 printf(" %c", (((value2 >> 20) & 0x03) == 0x03) ? 'y' : '-');
1952 printf(" %c\n", (((value2 >> 23) & 0x01) == 0x01) ? 'y' : '-');
1953}
1954
1955void table_del_fid(int argc, char *argv[])
1956{
developerbe40a9e2024-03-07 21:44:26 +08001957 unsigned int i = 0, j = 0, value = 0;
developerfd40db22021-04-29 10:08:25 +08001958 char tmpstr[9];
developer621433d2024-06-15 20:40:10 +08001959 char *endptr;
developerfd40db22021-04-29 10:08:25 +08001960
1961 if (!argv[3] || strlen(argv[3]) != 12) {
1962 printf("MAC address format error, should be of length 12\n");
1963 return;
1964 }
1965 strncpy(tmpstr, argv[3], 8);
1966 tmpstr[8] = '\0';
developer621433d2024-06-15 20:40:10 +08001967 errno = 0;
1968 value = strtoul(tmpstr, &endptr, 16);
1969 if (errno != 0 || *endptr != '\0') {
1970 printf("Error: string converting\n");
1971 return;
1972 }
developerfd40db22021-04-29 10:08:25 +08001973 reg_write(REG_ATA1_ADDR, value);
developer621433d2024-06-15 20:40:10 +08001974
developerfd40db22021-04-29 10:08:25 +08001975 strncpy(tmpstr, argv[3] + 8, 4);
1976 tmpstr[4] = '\0';
developer621433d2024-06-15 20:40:10 +08001977 errno = 0;
1978 value = strtoul(tmpstr, &endptr, 16);
1979 if (errno != 0 || *endptr != '\0') {
1980 printf("Error: string converting\n");
1981 return;
1982 }
developerfd40db22021-04-29 10:08:25 +08001983 value = (value << 16);
1984
1985 if (argc > 5) {
developer621433d2024-06-15 20:40:10 +08001986 errno = 0;
1987 j = strtoul(argv[5], &endptr, 10);
1988 if (errno != 0 || *endptr != '\0' || j > 7) {
developerfd40db22021-04-29 10:08:25 +08001989 printf("wrong fid range, should be within 0~7\n");
1990 return;
1991 }
developerbe40a9e2024-03-07 21:44:26 +08001992 value |= (j << 12); /* fid */
developerfd40db22021-04-29 10:08:25 +08001993 }
1994
1995 reg_write(REG_ATA2_ADDR, value);
1996
developerbe40a9e2024-03-07 21:44:26 +08001997 value = 0; /* STATUS=0, delete mac */
developerfd40db22021-04-29 10:08:25 +08001998 reg_write(REG_ATWD_ADDR, value);
1999
developerbe40a9e2024-03-07 21:44:26 +08002000 value = 0x8001; //w_mac_cmd
developerfd40db22021-04-29 10:08:25 +08002001 reg_write(REG_ATC_ADDR, value);
2002
2003 for (i = 0; i < 20; i++) {
2004 reg_read(REG_ATC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08002005 if ((value & 0x8000) == 0) { /* mac address busy */
developerfd40db22021-04-29 10:08:25 +08002006 if (argv[1] != NULL)
2007 printf("done.\n");
2008 return;
2009 }
2010 usleep(1000);
2011 }
2012 if (i == 20)
2013 printf("timeout.\n");
2014}
2015
2016void table_del_vid(int argc, char *argv[])
2017{
developerbe40a9e2024-03-07 21:44:26 +08002018 unsigned int i = 0, j = 0, value = 0;
developerfd40db22021-04-29 10:08:25 +08002019 char tmpstr[9];
developer621433d2024-06-15 20:40:10 +08002020 char *endptr;
developerfd40db22021-04-29 10:08:25 +08002021
2022 if (!argv[3] || strlen(argv[3]) != 12) {
2023 printf("MAC address format error, should be of length 12\n");
2024 return;
2025 }
2026 strncpy(tmpstr, argv[3], 8);
2027 tmpstr[8] = '\0';
developer621433d2024-06-15 20:40:10 +08002028 errno = 0;
2029 value = strtoul(tmpstr, &endptr, 16);
2030 if (errno != 0 || *endptr != '\0') {
2031 printf("Error: string converting\n");
2032 return;
2033 }
developerfd40db22021-04-29 10:08:25 +08002034 reg_write(REG_ATA1_ADDR, value);
2035
2036 strncpy(tmpstr, argv[3] + 8, 4);
2037 tmpstr[4] = '\0';
developer621433d2024-06-15 20:40:10 +08002038 errno = 0;
2039 value = strtoul(tmpstr, &endptr, 16);
2040 if (errno != 0 || *endptr != '\0') {
2041 printf("Error: string converting\n");
2042 return;
2043 }
developerfd40db22021-04-29 10:08:25 +08002044 value = (value << 16);
2045
developer621433d2024-06-15 20:40:10 +08002046 errno = 0;
2047 j = strtoul(argv[5], &endptr, 10);
2048 if (errno != 0 || *endptr != '\0' || j > 4095) {
developerfd40db22021-04-29 10:08:25 +08002049 printf("wrong fid range, should be within 0~4095\n");
2050 return;
2051 }
developer621433d2024-06-15 20:40:10 +08002052
developerbe40a9e2024-03-07 21:44:26 +08002053 value |= j; //vid
developerfd40db22021-04-29 10:08:25 +08002054 value |= 1 << 15;
2055 reg_write(REG_ATA2_ADDR, value);
2056
developerbe40a9e2024-03-07 21:44:26 +08002057 value = 0; //STATUS=0, delete mac
developerfd40db22021-04-29 10:08:25 +08002058 reg_write(REG_ATWD_ADDR, value);
2059
developerbe40a9e2024-03-07 21:44:26 +08002060 value = 0x8001; //w_mac_cmd
developerfd40db22021-04-29 10:08:25 +08002061 reg_write(REG_ATC_ADDR, value);
2062
2063 for (i = 0; i < 20; i++) {
2064 reg_read(REG_ATC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08002065 if ((value & 0x8000) == 0) { //mac address busy
developerfd40db22021-04-29 10:08:25 +08002066 if (argv[1] != NULL)
2067 printf("done.\n");
2068 return;
2069 }
2070 usleep(1000);
2071 }
2072 if (i == 20)
2073 printf("timeout.\n");
2074}
2075
developerbe40a9e2024-03-07 21:44:26 +08002076void table_clear(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08002077{
developerbe40a9e2024-03-07 21:44:26 +08002078 unsigned int value = 0;
2079
developerfd40db22021-04-29 10:08:25 +08002080 reg_write(REG_ATC_ADDR, 0x8002);
2081 usleep(5000);
2082 reg_read(REG_ATC_ADDR, &value);
2083
2084 printf("REG_ATC_ADDR is 0x%x\n\r", value);
2085}
2086
2087void set_mirror_to(int argc, char *argv[])
2088{
developerbe40a9e2024-03-07 21:44:26 +08002089 unsigned int value = 0;
2090 int idx = 0;
developerfd40db22021-04-29 10:08:25 +08002091
2092 idx = strtoul(argv[3], NULL, 0);
2093 if (idx < 0 || MAX_PORT < idx) {
2094 printf("wrong port member, should be within 0~%d\n", MAX_PORT);
2095 return;
2096 }
2097 if (chip_name == 0x7530) {
2098
2099 reg_read(REG_MFC_ADDR, &value);
2100 value |= 0x1 << 3;
2101 value &= 0xfffffff8;
2102 value |= idx << 0;
2103
2104 reg_write(REG_MFC_ADDR, value);
2105 } else {
2106
2107 reg_read(REG_CFC_ADDR, &value);
2108 value &= (~REG_CFC_MIRROR_EN_MASK);
2109 value |= (1 << REG_CFC_MIRROR_EN_OFFT);
2110 value &= (~REG_CFC_MIRROR_PORT_MASK);
2111 value |= (idx << REG_CFC_MIRROR_PORT_OFFT);
2112 reg_write(REG_CFC_ADDR, value);
2113 }
2114}
2115
2116void set_mirror_from(int argc, char *argv[])
2117{
developerbe40a9e2024-03-07 21:44:26 +08002118 unsigned int offset = 0, value = 0;
developer546b2792024-06-15 20:31:38 +08002119 unsigned int idx = 0, mirror = 0;
2120 char *endptr;
developerfd40db22021-04-29 10:08:25 +08002121
developer546b2792024-06-15 20:31:38 +08002122 errno = 0;
2123 idx = strtoul(argv[3], &endptr, 0);
2124 if (errno != 0 || *endptr != '\0' || idx > MAX_PORT) {
2125 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
developerfd40db22021-04-29 10:08:25 +08002126 return;
2127 }
2128
developer546b2792024-06-15 20:31:38 +08002129 errno = 0;
2130 mirror = strtoul(argv[4], &endptr, 0);
2131
2132 if (errno != 0 || *endptr != '\0' || mirror > 3) {
developerfd40db22021-04-29 10:08:25 +08002133 printf("wrong mirror setting, should be within 0~3\n");
2134 return;
2135 }
2136
2137 offset = (0x2004 | (idx << 8));
2138 reg_read(offset, &value);
2139
2140 value &= 0xfffffcff;
2141 value |= mirror << 8;
2142
2143 reg_write(offset, value);
2144}
2145
2146void vlan_dump(int argc, char *argv[])
2147{
developerbe40a9e2024-03-07 21:44:26 +08002148 unsigned int i = 0, j = 0, value = 0, value2 = 0;
developerfd40db22021-04-29 10:08:25 +08002149 int eg_tag = 0;
2150
2151 if (argc == 4) {
2152 if (!strncmp(argv[3], "egtag", 6))
2153 eg_tag = 1;
2154 }
2155
2156 if (eg_tag)
developerbe40a9e2024-03-07 21:44:26 +08002157 printf
2158 (" vid fid portmap s-tag\teg_tag(0:untagged 2:tagged)\n");
developerfd40db22021-04-29 10:08:25 +08002159 else
2160 printf(" vid fid portmap s-tag\n");
2161
2162 for (i = 1; i < 4095; i++) {
developerbe40a9e2024-03-07 21:44:26 +08002163 value = (0x80000000 + i); //r_vid_cmd
developerfd40db22021-04-29 10:08:25 +08002164 reg_write(REG_VTCR_ADDR, value);
2165
2166 for (j = 0; j < 20; j++) {
2167 reg_read(REG_VTCR_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08002168 if ((value & 0x80000000) == 0) { //mac address busy
developerfd40db22021-04-29 10:08:25 +08002169 break;
2170 }
2171 usleep(1000);
2172 }
2173 if (j == 20)
2174 printf("timeout.\n");
2175
2176 reg_read(REG_VAWD1_ADDR, &value);
2177 reg_read(REG_VAWD2_ADDR, &value2);
2178 //printf("REG_VAWD1_ADDR value%d is 0x%x\n\r", i, value);
2179 //printf("REG_VAWD2_ADDR value%d is 0x%x\n\r", i, value2);
2180
2181 if ((value & 0x01) != 0) {
2182 printf(" %4d ", i);
2183 printf(" %2d ", ((value & 0xe) >> 1));
2184 printf(" %c", (value & 0x00010000) ? '1' : '-');
2185 printf("%c", (value & 0x00020000) ? '1' : '-');
2186 printf("%c", (value & 0x00040000) ? '1' : '-');
2187 printf("%c", (value & 0x00080000) ? '1' : '-');
2188 printf("%c", (value & 0x00100000) ? '1' : '-');
2189 printf("%c", (value & 0x00200000) ? '1' : '-');
2190 printf("%c", (value & 0x00400000) ? '1' : '-');
2191 printf("%c", (value & 0x00800000) ? '1' : '-');
2192 printf(" %4d", ((value & 0xfff0) >> 4));
2193 if (eg_tag) {
2194 printf("\t");
2195 if ((value & (0x3 << 28)) == (0x3 << 28)) {
2196 /* VTAG_EN=1 and EG_CON=1 */
2197 printf("CONSISTENT");
2198 } else if (value & (0x1 << 28)) {
2199 /* VTAG_EN=1 */
2200 printf("%d", (value2 & 0x0003) >> 0);
2201 printf("%d", (value2 & 0x000c) >> 2);
2202 printf("%d", (value2 & 0x0030) >> 4);
2203 printf("%d", (value2 & 0x00c0) >> 6);
2204 printf("%d", (value2 & 0x0300) >> 8);
2205 printf("%d", (value2 & 0x0c00) >> 10);
2206 printf("%d", (value2 & 0x3000) >> 12);
2207 printf("%d", (value2 & 0xc000) >> 14);
2208 } else {
2209 /* VTAG_EN=0 */
2210 printf("DISABLED");
2211 }
2212 }
2213 printf("\n");
2214 } else {
developerbe40a9e2024-03-07 21:44:26 +08002215 /*print 16 vid for reference information */
developerfd40db22021-04-29 10:08:25 +08002216 if (i <= 16) {
2217 printf(" %4d ", i);
2218 printf(" %2d ", ((value & 0xe) >> 1));
2219 printf(" invalid\n");
2220 }
2221 }
2222 }
2223}
2224
developerfd40db22021-04-29 10:08:25 +08002225static long timespec_diff_us(struct timespec start, struct timespec end)
2226{
2227 struct timespec temp;
2228 unsigned long duration = 0;
2229
2230 if ((end.tv_nsec - start.tv_nsec) < 0) {
2231 temp.tv_sec = end.tv_sec - start.tv_sec - 1;
2232 temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
2233 } else {
2234 temp.tv_sec = end.tv_sec - start.tv_sec;
2235 temp.tv_nsec = end.tv_nsec - start.tv_nsec;
2236 }
developerbe40a9e2024-03-07 21:44:26 +08002237 /* calculate second part */
developerfd40db22021-04-29 10:08:25 +08002238 duration += temp.tv_sec * 1000000;
developerbe40a9e2024-03-07 21:44:26 +08002239 /* calculate ns part */
developerfd40db22021-04-29 10:08:25 +08002240 duration += temp.tv_nsec >> 10;
2241
2242 return duration;
2243}
2244
developerfd40db22021-04-29 10:08:25 +08002245void vlan_clear(int argc, char *argv[])
2246{
developerbe40a9e2024-03-07 21:44:26 +08002247 unsigned int value = 0;
2248 int vid = 0;
developerfd40db22021-04-29 10:08:25 +08002249 unsigned long duration_us = 0;
2250 struct timespec start, end;
2251
2252 for (vid = 0; vid < 4096; vid++) {
2253 clock_gettime(CLOCK_REALTIME, &start);
developerbe40a9e2024-03-07 21:44:26 +08002254 value = 0; //invalid
developerfd40db22021-04-29 10:08:25 +08002255 reg_write(REG_VAWD1_ADDR, value);
2256
developerbe40a9e2024-03-07 21:44:26 +08002257 value = (0x80001000 + vid); //w_vid_cmd
developerfd40db22021-04-29 10:08:25 +08002258 reg_write(REG_VTCR_ADDR, value);
2259 while (duration_us <= 1000) {
2260 reg_read(REG_VTCR_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08002261 if ((value & 0x80000000) == 0) { //table busy
developerfd40db22021-04-29 10:08:25 +08002262 break;
2263 }
2264 clock_gettime(CLOCK_REALTIME, &end);
2265 duration_us = timespec_diff_us(start, end);
2266 }
2267 if (duration_us > 1000)
2268 printf("config vlan timeout: %ld.\n", duration_us);
2269 }
2270}
2271
2272void vlan_set(int argc, char *argv[])
2273{
2274 unsigned int vlan_mem = 0;
2275 unsigned int value = 0;
2276 unsigned int value2 = 0;
developerbe40a9e2024-03-07 21:44:26 +08002277 int i = 0, vid = 0, fid = 0;
developerfd40db22021-04-29 10:08:25 +08002278 int stag = 0;
2279 unsigned long eg_con = 0;
2280 unsigned int eg_tag = 0;
2281
2282 if (argc < 5) {
2283 printf("insufficient arguments!\n");
2284 return;
2285 }
2286
2287 fid = strtoul(argv[3], NULL, 0);
2288 if (fid < 0 || fid > 7) {
2289 printf("wrong filtering db id range, should be within 0~7\n");
2290 return;
2291 }
2292 value |= (fid << 1);
2293
2294 vid = strtoul(argv[4], NULL, 0);
2295 if (vid < 0 || 0xfff < vid) {
2296 printf("wrong vlan id range, should be within 0~4095\n");
2297 return;
2298 }
2299
2300 if (strlen(argv[5]) != 8) {
2301 printf("portmap format error, should be of length 7\n");
2302 return;
2303 }
2304
2305 vlan_mem = 0;
2306 for (i = 0; i < 8; i++) {
2307 if (argv[5][i] != '0' && argv[5][i] != '1') {
developerbe40a9e2024-03-07 21:44:26 +08002308 printf
2309 ("portmap format error, should be of combination of 0 or 1\n");
developerfd40db22021-04-29 10:08:25 +08002310 return;
2311 }
2312 vlan_mem += (argv[5][i] - '0') * (1 << i);
2313 }
2314
2315 /* VLAN stag */
2316 if (argc > 6) {
2317 stag = strtoul(argv[6], NULL, 16);
2318 if (stag < 0 || 0xfff < stag) {
developerbe40a9e2024-03-07 21:44:26 +08002319 printf
2320 ("wrong stag id range, should be within 0~4095\n");
developerfd40db22021-04-29 10:08:25 +08002321 return;
2322 }
2323 //printf("STAG is 0x%x\n", stag);
2324 }
2325
2326 /* set vlan member */
2327 value |= (vlan_mem << 16);
developerbe40a9e2024-03-07 21:44:26 +08002328 value |= (1 << 30); //IVL=1
2329 value |= ((stag & 0xfff) << 4); //stag
2330 value |= 1; //valid
developerfd40db22021-04-29 10:08:25 +08002331
2332 if (argc > 7) {
2333 eg_con = strtoul(argv[7], NULL, 2);
2334 eg_con = !!eg_con;
developerbe40a9e2024-03-07 21:44:26 +08002335 value |= (eg_con << 29); //eg_con
2336 value |= (1 << 28); //eg tag control enable
developerfd40db22021-04-29 10:08:25 +08002337 }
2338
2339 if (argc > 8 && !eg_con) {
2340 if (strlen(argv[8]) != 8) {
developerbe40a9e2024-03-07 21:44:26 +08002341 printf
2342 ("egtag portmap format error, should be of length 7\n");
developerfd40db22021-04-29 10:08:25 +08002343 return;
2344 }
2345
2346 for (i = 0; i < 8; i++) {
2347 if (argv[8][i] < '0' || argv[8][i] > '3') {
developerbe40a9e2024-03-07 21:44:26 +08002348 printf
2349 ("egtag portmap format error, should be of combination of 0 or 3\n");
developerfd40db22021-04-29 10:08:25 +08002350 return;
2351 }
2352 //eg_tag += (argv[8][i] - '0') * (1 << i * 2);
2353 eg_tag |= (argv[8][i] - '0') << (i * 2);
2354 }
2355
developerbe40a9e2024-03-07 21:44:26 +08002356 value |= (1 << 28); //eg tag control enable
developerfd40db22021-04-29 10:08:25 +08002357 value2 &= ~(0xffff);
2358 value2 |= eg_tag;
2359 }
2360 reg_write(REG_VAWD1_ADDR, value);
2361 reg_write(REG_VAWD2_ADDR, value2);
2362 //printf("VAWD1=0x%08x VAWD2=0x%08x ", value, value2);
2363
developerbe40a9e2024-03-07 21:44:26 +08002364 value = (0x80001000 + vid); //w_vid_cmd
developerfd40db22021-04-29 10:08:25 +08002365 reg_write(REG_VTCR_ADDR, value);
2366 //printf("VTCR=0x%08x\n", value);
2367
2368 for (i = 0; i < 300; i++) {
2369 usleep(1000);
2370 reg_read(REG_VTCR_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08002371 if ((value & 0x80000000) == 0) //table busy
developerfd40db22021-04-29 10:08:25 +08002372 break;
2373 }
2374
2375 if (i == 300)
2376 printf("config vlan timeout.\n");
2377}
2378
2379void igmp_on(int argc, char *argv[])
2380{
2381 unsigned int leaky_en = 0;
2382 unsigned int wan_num = 4;
developerbe40a9e2024-03-07 21:44:26 +08002383 unsigned int port = 0, offset = 0, value = 0;
developerfd40db22021-04-29 10:08:25 +08002384 char cmd[80];
2385 int ret;
developer2fdae312024-06-15 20:36:12 +08002386 char *endptr;
developerfd40db22021-04-29 10:08:25 +08002387
developer2fdae312024-06-15 20:36:12 +08002388 if (argc > 3) {
2389 errno = 0;
2390 leaky_en = strtoul(argv[3], &endptr, 10);
2391 if (errno != 0 || *endptr != '\0') {
2392 printf("Error: string converting\n");
2393 return;
2394 }
2395 }
2396 if (argc > 4) {
2397 errno = 0;
2398 wan_num = strtoul(argv[4], &endptr, 10);
2399 if (errno != 0 || *endptr != '\0') {
2400 printf("Error: string converting\n");
2401 return;
2402 }
2403 }
developerfd40db22021-04-29 10:08:25 +08002404
2405 if (leaky_en == 1) {
2406 if (wan_num == 4) {
2407 /* reg_write(0x2410, 0x810000c8); */
2408 reg_read(0x2410, &value);
2409 reg_write(0x2410, value | (1 << 3));
2410 /* reg_write(0x2010, 0x810000c0); */
2411 reg_read(0x2010, &value);
2412 reg_write(0x2010, value & (~(1 << 3)));
2413 reg_write(REG_ISC_ADDR, 0x10027d10);
2414 } else {
2415 /* reg_write(0x2010, 0x810000c8); */
2416 reg_read(0x2010, &value);
2417 reg_write(0x2010, value | (1 << 3));
2418 /* reg_write(0x2410, 0x810000c0); */
2419 reg_read(0x2410, &value);
2420 reg_write(0x2410, value & (~(1 << 3)));
2421 reg_write(REG_ISC_ADDR, 0x01027d01);
2422 }
developerbe40a9e2024-03-07 21:44:26 +08002423 } else
developerfd40db22021-04-29 10:08:25 +08002424 reg_write(REG_ISC_ADDR, 0x10027d60);
2425
2426 reg_write(0x1c, 0x08100810);
2427 reg_write(0x2008, 0xb3ff);
2428 reg_write(0x2108, 0xb3ff);
2429 reg_write(0x2208, 0xb3ff);
2430 reg_write(0x2308, 0xb3ff);
2431 reg_write(0x2408, 0xb3ff);
2432 reg_write(0x2608, 0xb3ff);
2433 /* Enable Port ACL
developerbe40a9e2024-03-07 21:44:26 +08002434 * reg_write(0x2P04, 0xff0403);
2435 */
developerfd40db22021-04-29 10:08:25 +08002436 for (port = 0; port <= 6; port++) {
2437 offset = 0x2004 + port * 0x100;
2438 reg_read(offset, &value);
2439 reg_write(offset, value | (1 << 10));
2440 }
2441
developerbe40a9e2024-03-07 21:44:26 +08002442 /*IGMP query only p4 -> p5 */
developerfd40db22021-04-29 10:08:25 +08002443 reg_write(0x94, 0x00ff0002);
2444 if (wan_num == 4)
2445 reg_write(0x98, 0x000a1008);
2446 else
2447 reg_write(0x98, 0x000a0108);
2448 reg_write(0x90, 0x80005000);
2449 reg_write(0x94, 0xff001100);
2450 if (wan_num == 4)
2451 reg_write(0x98, 0x000B1000);
2452 else
2453 reg_write(0x98, 0x000B0100);
2454 reg_write(0x90, 0x80005001);
2455 reg_write(0x94, 0x3);
2456 reg_write(0x98, 0x0);
2457 reg_write(0x90, 0x80009000);
2458 reg_write(0x94, 0x1a002080);
2459 reg_write(0x98, 0x0);
2460 reg_write(0x90, 0x8000b000);
2461
developerbe40a9e2024-03-07 21:44:26 +08002462 /*IGMP p5 -> p4 */
developerfd40db22021-04-29 10:08:25 +08002463 reg_write(0x94, 0x00ff0002);
2464 reg_write(0x98, 0x000a2008);
2465 reg_write(0x90, 0x80005002);
2466 reg_write(0x94, 0x4);
2467 reg_write(0x98, 0x0);
2468 reg_write(0x90, 0x80009001);
2469 if (wan_num == 4)
2470 reg_write(0x94, 0x1a001080);
2471 else
2472 reg_write(0x94, 0x1a000180);
2473 reg_write(0x98, 0x0);
2474 reg_write(0x90, 0x8000b001);
2475
developerbe40a9e2024-03-07 21:44:26 +08002476 /*IGMP p0~p3 -> p6 */
developerfd40db22021-04-29 10:08:25 +08002477 reg_write(0x94, 0x00ff0002);
2478 if (wan_num == 4)
2479 reg_write(0x98, 0x000a0f08);
2480 else
2481 reg_write(0x98, 0x000a1e08);
2482 reg_write(0x90, 0x80005003);
2483 reg_write(0x94, 0x8);
2484 reg_write(0x98, 0x0);
2485 reg_write(0x90, 0x80009002);
2486 reg_write(0x94, 0x1a004080);
2487 reg_write(0x98, 0x0);
2488 reg_write(0x90, 0x8000b002);
2489
developerbe40a9e2024-03-07 21:44:26 +08002490 /*IGMP query only p6 -> p0~p3 */
developerfd40db22021-04-29 10:08:25 +08002491 reg_write(0x94, 0x00ff0002);
2492 reg_write(0x98, 0x000a4008);
2493 reg_write(0x90, 0x80005004);
2494 reg_write(0x94, 0xff001100);
2495 reg_write(0x98, 0x000B4000);
2496 reg_write(0x90, 0x80005005);
2497 reg_write(0x94, 0x30);
2498 reg_write(0x98, 0x0);
2499 reg_write(0x90, 0x80009003);
2500 if (wan_num == 4)
2501 reg_write(0x94, 0x1a000f80);
2502 else
2503 reg_write(0x94, 0x1a001e80);
2504 reg_write(0x98, 0x0);
2505 reg_write(0x90, 0x8000b003);
2506
developerbe40a9e2024-03-07 21:44:26 +08002507 /*Force eth2 to receive all igmp packets */
developer2fdae312024-06-15 20:36:12 +08002508 ret = snprintf(cmd, sizeof(cmd),
developerbe40a9e2024-03-07 21:44:26 +08002509 "echo 2 > /sys/devices/virtual/net/%s/brif/%s/multicast_router",
2510 BR_DEVNAME, ETH_DEVNAME);
developer2fdae312024-06-15 20:36:12 +08002511
2512 if (ret < 0 || ret >= sizeof(cmd))
2513 goto error;
2514
developerfd40db22021-04-29 10:08:25 +08002515 ret = system(cmd);
2516 if (ret)
developer2fdae312024-06-15 20:36:12 +08002517 goto error;
2518
2519 return;
2520
2521error:
2522 printf("Failed to set /sys/devices/virtual/net/%s/brif/%s/multicast_router\n",
2523 BR_DEVNAME, ETH_DEVNAME);
developerfd40db22021-04-29 10:08:25 +08002524}
2525
2526void igmp_disable(int argc, char *argv[])
2527{
developerbe40a9e2024-03-07 21:44:26 +08002528 unsigned int reg_offset = 0, value = 0;
2529 int port_num = 0;
developerfd40db22021-04-29 10:08:25 +08002530
2531 if (argc < 4) {
2532 printf("insufficient arguments!\n");
2533 return;
2534 }
2535 port_num = strtoul(argv[3], NULL, 0);
2536 if (port_num < 0 || 6 < port_num) {
2537 printf("wrong port range, should be within 0~6\n");
2538 return;
2539 }
developerfd40db22021-04-29 10:08:25 +08002540 //set ISC: IGMP Snooping Control Register (offset: 0x0018)
2541 reg_offset = 0x2008;
2542 reg_offset |= (port_num << 8);
2543 value = 0x8000;
2544
2545 reg_write(reg_offset, value);
2546}
2547
2548void igmp_enable(int argc, char *argv[])
2549{
developerbe40a9e2024-03-07 21:44:26 +08002550 unsigned int reg_offset = 0, value = 0;
developerfd40db22021-04-29 10:08:25 +08002551 int port_num;
2552
2553 if (argc < 4) {
2554 printf("insufficient arguments!\n");
2555 return;
2556 }
2557 port_num = strtoul(argv[3], NULL, 0);
2558 if (port_num < 0 || 6 < port_num) {
2559 printf("wrong port range, should be within 0~6\n");
2560 return;
2561 }
developerfd40db22021-04-29 10:08:25 +08002562 //set ISC: IGMP Snooping Control Register (offset: 0x0018)
2563 reg_offset = 0x2008;
2564 reg_offset |= (port_num << 8);
2565 value = 0x9755;
2566 reg_write(reg_offset, value);
2567}
2568
developerbe40a9e2024-03-07 21:44:26 +08002569void igmp_off(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08002570{
developerbe40a9e2024-03-07 21:44:26 +08002571 unsigned int value = 0;
developerfd40db22021-04-29 10:08:25 +08002572 //set ISC: IGMP Snooping Control Register (offset: 0x0018)
2573 reg_read(REG_ISC_ADDR, &value);
developerbe40a9e2024-03-07 21:44:26 +08002574 value &= ~(1 << 18); //disable
developerfd40db22021-04-29 10:08:25 +08002575 reg_write(REG_ISC_ADDR, value);
2576
developerbe40a9e2024-03-07 21:44:26 +08002577 /*restore wan port multicast leaky vlan function: default disabled */
developerfd40db22021-04-29 10:08:25 +08002578 reg_read(0x2010, &value);
2579 reg_write(0x2010, value & (~(1 << 3)));
2580 reg_read(0x2410, &value);
2581 reg_write(0x2410, value & (~(1 << 3)));
2582
2583 printf("config igmpsnoop off.\n");
2584}
2585
developerbe40a9e2024-03-07 21:44:26 +08002586void switch_reset(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08002587{
developer8c3871b2022-07-01 14:07:53 +08002588 if (chip_name == 0x7988)
developerbe40a9e2024-03-07 21:44:26 +08002589 return;
developer8c3871b2022-07-01 14:07:53 +08002590
developerfd40db22021-04-29 10:08:25 +08002591 unsigned int value = 0;
2592 /*Software Register Reset and Software System Reset */
2593 reg_write(0x7000, 0x3);
2594 reg_read(0x7000, &value);
2595 printf("SYS_CTRL(0x7000) register value =0x%x \n", value);
2596 if (chip_name == 0x7531) {
2597 reg_write(0x7c0c, 0x11111111);
2598 reg_read(0x7c0c, &value);
2599 printf("GPIO Mode (0x7c0c) select value =0x%x \n", value);
2600 }
2601 printf("Switch Software Reset !!! \n");
2602}
2603
developerbe40a9e2024-03-07 21:44:26 +08002604void phy_set_fc(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08002605{
developerbe40a9e2024-03-07 21:44:26 +08002606 unsigned int port = 0, pause_capable = 0;
2607 unsigned int phy_value = 0;
developer3a780bf2024-06-15 20:34:27 +08002608 char *endptr;
developerfd40db22021-04-29 10:08:25 +08002609
developer3a780bf2024-06-15 20:34:27 +08002610 errno = 0;
2611 port = strtoul(argv[3], &endptr, 10);
2612 if (errno != 0 || *endptr != '\0' || port > MAX_PORT - 2) {
2613 printf("Error: wrong PHY port number, should be within 0~4\n");
2614 return;
2615 }
developerfd40db22021-04-29 10:08:25 +08002616
developer3a780bf2024-06-15 20:34:27 +08002617 errno = 0;
2618 pause_capable = strtoul(argv[4], &endptr, 10);
2619 if (errno != 0 || *endptr != '\0' || pause_capable > 1) {
2620 printf("Illegal parameter, full_duplex_pause_capable:0|1\n");
developerbe40a9e2024-03-07 21:44:26 +08002621 return;
developerfd40db22021-04-29 10:08:25 +08002622 }
developer3a780bf2024-06-15 20:34:27 +08002623
developerfd40db22021-04-29 10:08:25 +08002624 printf("port=%d, full_duplex_pause_capable:%d\n", port, pause_capable);
developerbe40a9e2024-03-07 21:44:26 +08002625
developerfd40db22021-04-29 10:08:25 +08002626 mii_mgr_read(port, 4, &phy_value);
2627 printf("read phy_value:0x%x\r\n", phy_value);
2628 phy_value &= (~(0x1 << 10));
2629 phy_value &= (~(0x1 << 11));
2630 if (pause_capable == 1) {
2631 phy_value |= (0x1 << 10);
2632 phy_value |= (0x1 << 11);
2633 }
2634 mii_mgr_write(port, 4, phy_value);
2635 printf("write phy_value:0x%x\r\n", phy_value);
developerbe40a9e2024-03-07 21:44:26 +08002636 return;
2637} /*end phy_set_fc */
developerfd40db22021-04-29 10:08:25 +08002638
developerbe40a9e2024-03-07 21:44:26 +08002639void phy_set_an(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08002640{
developerbe40a9e2024-03-07 21:44:26 +08002641 unsigned int port = 0, auto_negotiation_en = 0;
2642 unsigned int phy_value = 0;
developer3a780bf2024-06-15 20:34:27 +08002643 char *endptr;
developerfd40db22021-04-29 10:08:25 +08002644
developer3a780bf2024-06-15 20:34:27 +08002645 errno = 0;
2646 port = strtoul(argv[3], &endptr, 10);
2647 if (errno != 0 || *endptr != '\0' || port > MAX_PORT - 2) {
2648 printf("Error: wrong PHY port number, should be within 0~4\n");
2649 return;
2650 }
developerfd40db22021-04-29 10:08:25 +08002651
developer3a780bf2024-06-15 20:34:27 +08002652 errno = 0;
2653 auto_negotiation_en = strtoul(argv[4], &endptr, 10);
2654 if (errno != 0 || *endptr != '\0' || auto_negotiation_en > 1) {
2655 printf("Illegal parameter, auto_negotiation_en:0|1\n");
developerbe40a9e2024-03-07 21:44:26 +08002656 return;
developerfd40db22021-04-29 10:08:25 +08002657 }
developer3a780bf2024-06-15 20:34:27 +08002658
developerfd40db22021-04-29 10:08:25 +08002659 printf("port=%d, auto_negotiation_en:%d\n", port, auto_negotiation_en);
developerbe40a9e2024-03-07 21:44:26 +08002660
developerfd40db22021-04-29 10:08:25 +08002661 mii_mgr_read(port, 0, &phy_value);
2662 printf("read phy_value:0x%x\r\n", phy_value);
2663 phy_value &= (~(1 << 12));
2664 phy_value |= (auto_negotiation_en << 12);
2665 mii_mgr_write(port, 0, phy_value);
2666 printf("write phy_value:0x%x\r\n", phy_value);
developerbe40a9e2024-03-07 21:44:26 +08002667} /*end phy_set_an */
developerfd40db22021-04-29 10:08:25 +08002668
developerbe40a9e2024-03-07 21:44:26 +08002669void set_mac_pfc(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08002670{
developerbe40a9e2024-03-07 21:44:26 +08002671 unsigned int value = 0;
developer546b2792024-06-15 20:31:38 +08002672 unsigned int port, enable = 0;
2673 char *endptr;
developerfd40db22021-04-29 10:08:25 +08002674
developer546b2792024-06-15 20:31:38 +08002675 errno = 0;
2676 port = strtoul(argv[3], &endptr, 10);
2677 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
2678 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
2679 return;
2680 }
2681
2682 errno = 0;
2683 enable = strtoul(argv[4], &endptr, 10);
2684 if (errno != 0 || *endptr != '\0' || enable > 1) {
2685 printf("Error: Illegal paramete, enable|diable:0|1\n");
developerbe40a9e2024-03-07 21:44:26 +08002686 return;
developerfd40db22021-04-29 10:08:25 +08002687 }
developer546b2792024-06-15 20:31:38 +08002688 printf("enable: %d\n", enable);
2689
developer8c3871b2022-07-01 14:07:53 +08002690 if (chip_name == 0x7531 || chip_name == 0x7988) {
developerfd40db22021-04-29 10:08:25 +08002691 reg_read(REG_PFC_CTRL_ADDR, &value);
2692 value &= ~(1 << port);
2693 value |= (enable << port);
2694 printf("write reg: %x, value: %x\n", REG_PFC_CTRL_ADDR, value);
2695 reg_write(REG_PFC_CTRL_ADDR, value);
developerbe40a9e2024-03-07 21:44:26 +08002696 } else
developerfd40db22021-04-29 10:08:25 +08002697 printf("\nCommand not support by this chip.\n");
developerfd40db22021-04-29 10:08:25 +08002698}
2699
developerbe40a9e2024-03-07 21:44:26 +08002700void global_set_mac_fc(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08002701{
2702 unsigned char enable = 0;
developerbe40a9e2024-03-07 21:44:26 +08002703 unsigned int value = 0, reg = 0;
developerfd40db22021-04-29 10:08:25 +08002704
2705 if (chip_name == 0x7530) {
2706 enable = atoi(argv[3]);
2707 printf("enable: %d\n", enable);
2708
developerbe40a9e2024-03-07 21:44:26 +08002709 /*Check the input parameters is right or not. */
developerfd40db22021-04-29 10:08:25 +08002710 if (enable > 1) {
2711 printf(HELP_MACCTL_FC);
developerbe40a9e2024-03-07 21:44:26 +08002712 return;
developerfd40db22021-04-29 10:08:25 +08002713 }
2714 reg_write(0x7000, 0x3);
2715 reg = REG_GFCCR0_ADDR;
2716 reg_read(REG_GFCCR0_ADDR, &value);
2717 value &= (~REG_FC_EN_MASK);
2718 value |= (enable << REG_FC_EN_OFFT);
2719 printf("write reg: %x, value: %x\n", reg, value);
2720 reg_write(REG_GFCCR0_ADDR, value);
2721 } else
2722 printf("\r\nCommand not support by this chip.\n");
developerbe40a9e2024-03-07 21:44:26 +08002723} /*end mac_set_fc */
developerfd40db22021-04-29 10:08:25 +08002724
developerbe40a9e2024-03-07 21:44:26 +08002725void qos_sch_select(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08002726{
developerbe40a9e2024-03-07 21:44:26 +08002727 unsigned char port = 0, queue = 0;
developerfd40db22021-04-29 10:08:25 +08002728 unsigned char type = 0;
developerbe40a9e2024-03-07 21:44:26 +08002729 unsigned int value = 0, reg = 0;
developer546b2792024-06-15 20:31:38 +08002730 char *endptr;
developerfd40db22021-04-29 10:08:25 +08002731
2732 if (argc < 7)
developerbe40a9e2024-03-07 21:44:26 +08002733 return;
developerfd40db22021-04-29 10:08:25 +08002734
developer546b2792024-06-15 20:31:38 +08002735 errno = 0;
2736 port = strtoul(argv[3], &endptr, 10);
2737 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
2738 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
2739 return;
2740 }
developerfd40db22021-04-29 10:08:25 +08002741
developer546b2792024-06-15 20:31:38 +08002742 errno = 0;
2743 queue = strtoul(argv[4], &endptr, 10);
2744 if (errno != 0 || *endptr != '\0' || queue > 7) {
2745 printf("Error: wrong port queue member\n");
developerbe40a9e2024-03-07 21:44:26 +08002746 return;
developerfd40db22021-04-29 10:08:25 +08002747 }
2748
developer546b2792024-06-15 20:31:38 +08002749 errno = 0;
2750 type = strtoul(argv[6], &endptr, 10);
2751 if (errno != 0 || *endptr != '\0' || type > 2) {
developerfd40db22021-04-29 10:08:25 +08002752 printf(HELP_QOS_TYPE);
developerbe40a9e2024-03-07 21:44:26 +08002753 return;
developerfd40db22021-04-29 10:08:25 +08002754 }
2755
developerbe40a9e2024-03-07 21:44:26 +08002756 printf("\r\nswitch qos type: %d.\n", type);
developerfd40db22021-04-29 10:08:25 +08002757
2758 if (!strncmp(argv[5], "min", 4)) {
2759
2760 if (type == 0) {
developerbe40a9e2024-03-07 21:44:26 +08002761 /*min sharper-->round roubin, disable min sharper rate limit */
developerfd40db22021-04-29 10:08:25 +08002762 reg = GSW_MMSCR0_Q(queue) + 0x100 * port;
2763 reg_read(reg, &value);
2764 value = 0x0;
2765 reg_write(reg, value);
2766 } else if (type == 1) {
developerbe40a9e2024-03-07 21:44:26 +08002767 /*min sharper-->sp, disable min sharper rate limit */
developerfd40db22021-04-29 10:08:25 +08002768 reg = GSW_MMSCR0_Q(queue) + 0x100 * port;
2769 reg_read(reg, &value);
2770 value = 0x0;
2771 value |= (1 << 31);
2772 reg_write(reg, value);
2773 } else {
2774 printf("min sharper only support: rr or sp\n");
developerbe40a9e2024-03-07 21:44:26 +08002775 return;
developerfd40db22021-04-29 10:08:25 +08002776 }
2777 } else if (!strncmp(argv[5], "max", 4)) {
2778 if (type == 1) {
developerbe40a9e2024-03-07 21:44:26 +08002779 /*max sharper-->sp, disable max sharper rate limit */
developerfd40db22021-04-29 10:08:25 +08002780 reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
2781 reg_read(reg, &value);
2782 value = 0x0;
2783 value |= (1 << 31);
2784 reg_write(reg, value);
2785 } else if (type == 2) {
developerbe40a9e2024-03-07 21:44:26 +08002786 /*max sharper-->wfq, disable max sharper rate limit */
developerfd40db22021-04-29 10:08:25 +08002787 reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
2788 reg_read(reg, &value);
2789 value = 0x0;
2790 reg_write(reg, value);
2791 } else {
2792 printf("max sharper only support: wfq or sp\n");
developerbe40a9e2024-03-07 21:44:26 +08002793 return;
developerfd40db22021-04-29 10:08:25 +08002794 }
2795 } else {
developerbe40a9e2024-03-07 21:44:26 +08002796 printf("\r\nIllegal sharper:%s\n", argv[5]);
2797 return;
developerfd40db22021-04-29 10:08:25 +08002798 }
developerbe40a9e2024-03-07 21:44:26 +08002799 printf("reg:0x%x--value:0x%x\n", reg, value);
developerfd40db22021-04-29 10:08:25 +08002800}
2801
2802void get_upw(unsigned int *value, unsigned char base)
2803{
2804 *value &= (~((0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) |
2805 (0x7 << 16) | (0x7 << 20)));
developerbe40a9e2024-03-07 21:44:26 +08002806 switch (base) {
2807 case 0: /* port-based 0x2x40[18:16] */
2808 *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
2809 (0x2 << 12) | (0x7 << 16) | (0x2 << 20));
2810 break;
2811 case 1: /* tagged-based 0x2x40[10:8] */
2812 *value |= ((0x2 << 0) | (0x2 << 4) | (0x7 << 8) |
2813 (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
2814 break;
2815 case 2: /* DSCP-based 0x2x40[14:12] */
2816 *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
2817 (0x7 << 12) | (0x2 << 16) | (0x2 << 20));
2818 break;
2819 case 3: /* acl-based 0x2x40[2:0] */
2820 *value |= ((0x7 << 0) | (0x2 << 4) | (0x2 << 8) |
2821 (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
2822 break;
2823 case 4: /* arl-based 0x2x40[22:20] */
2824 *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
2825 (0x2 << 12) | (0x2 << 16) | (0x7 << 20));
2826 break;
2827 case 5: /* stag-based 0x2x40[6:4] */
2828 *value |= ((0x2 << 0) | (0x7 << 4) | (0x2 << 8) |
2829 (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
2830 break;
2831 default:
2832 break;
developerfd40db22021-04-29 10:08:25 +08002833 }
2834}
2835
2836void qos_set_base(int argc, char *argv[])
2837{
2838 unsigned char base = 0;
developerbe40a9e2024-03-07 21:44:26 +08002839 unsigned char port = 0;
2840 unsigned int value = 0;
developer546b2792024-06-15 20:31:38 +08002841 char *endptr;
developerfd40db22021-04-29 10:08:25 +08002842
2843 if (argc < 5)
2844 return;
2845
developer546b2792024-06-15 20:31:38 +08002846 errno = 0;
2847 port = strtoul(argv[3], &endptr, 10);
2848 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
2849 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
developerfd40db22021-04-29 10:08:25 +08002850 return;
2851 }
2852
developer546b2792024-06-15 20:31:38 +08002853 errno = 0;
2854 base = strtoul(argv[4], &endptr, 10);
2855 if (errno != 0 || *endptr != '\0' || base > 5) {
2856 printf(HELP_QOS_BASE);
developerfd40db22021-04-29 10:08:25 +08002857 return;
2858 }
2859
2860 printf("\r\nswitch qos base : %d. (port-based:0, tag-based:1,\
developerbe40a9e2024-03-07 21:44:26 +08002861 dscp-based:2, acl-based:3, arl-based:4, stag-based:5)\n", base);
developerfd40db22021-04-29 10:08:25 +08002862 if (chip_name == 0x7530) {
2863
2864 reg_read(0x44, &value);
2865 get_upw(&value, base);
2866 reg_write(0x44, value);
2867 printf("reg: 0x44, value: 0x%x\n", value);
2868
developer8c3871b2022-07-01 14:07:53 +08002869 } else if (chip_name == 0x7531 || chip_name == 0x7988) {
developerfd40db22021-04-29 10:08:25 +08002870
2871 reg_read(GSW_UPW(port), &value);
2872 get_upw(&value, base);
2873 reg_write(GSW_UPW(port), value);
developerbe40a9e2024-03-07 21:44:26 +08002874 printf("reg:0x%x, value: 0x%x\n", GSW_UPW(port), value);
developerfd40db22021-04-29 10:08:25 +08002875
2876 } else {
2877 printf("unknown switch device");
2878 return;
2879 }
2880}
2881
2882void qos_wfq_set_weight(int argc, char *argv[])
2883{
developerbe40a9e2024-03-07 21:44:26 +08002884 int port = 0, weight[8], i = 0;
2885 unsigned char queue = 0;
2886 unsigned int reg = 0, value = 0;
developerfd40db22021-04-29 10:08:25 +08002887
2888 port = atoi(argv[3]);
2889
2890 for (i = 0; i < 8; i++) {
2891 weight[i] = atoi(argv[i + 4]);
2892 }
2893
2894 /* MT7530 total 7 port */
2895 if (port < 0 || port > 6) {
2896 printf(HELP_QOS_PORT_WEIGHT);
2897 return;
2898 }
2899
2900 for (i = 0; i < 8; i++) {
2901 if (weight[i] < 1 || weight[i] > 16) {
2902 printf(HELP_QOS_PORT_WEIGHT);
2903 return;
2904 }
2905 }
2906 printf("port: %x, q0: %x, q1: %x, q2: %x, q3: %x, \
developerbe40a9e2024-03-07 21:44:26 +08002907 q4: %x, q5: %x, q6: %x, q7: %x\n", port, weight[0], weight[1], weight[2], weight[3], weight[4], weight[5], weight[6], weight[7]);
developerfd40db22021-04-29 10:08:25 +08002908
2909 for (queue = 0; queue < 8; queue++) {
2910 reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
2911 reg_read(reg, &value);
developerbe40a9e2024-03-07 21:44:26 +08002912 value &= (~(0xf << 24)); //bit24~27
developerfd40db22021-04-29 10:08:25 +08002913 value |= (((weight[queue] - 1) & 0xf) << 24);
2914 printf("reg: %x, value: %x\n", reg, value);
2915 reg_write(reg, value);
2916 }
2917}
2918
2919void qos_set_portpri(int argc, char *argv[])
2920{
developerbe40a9e2024-03-07 21:44:26 +08002921 unsigned char port = 0, prio = 0;
2922 unsigned int value = 0;
developer546b2792024-06-15 20:31:38 +08002923 char *endptr;
developerfd40db22021-04-29 10:08:25 +08002924
developer546b2792024-06-15 20:31:38 +08002925 errno = 0;
2926 port = strtoul(argv[3], &endptr, 10);
2927 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
2928 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
2929 return;
2930 }
developerfd40db22021-04-29 10:08:25 +08002931
developer546b2792024-06-15 20:31:38 +08002932 errno = 0;
2933 prio = strtoul(argv[4], &endptr, 10);
2934 if (errno != 0 || *endptr != '\0' || prio > 7) {
2935 printf("Error: wrong priority, should be within 0~7\n");
developerfd40db22021-04-29 10:08:25 +08002936 return;
2937 }
2938
2939 reg_read(GSW_PCR(port), &value);
2940 value &= (~(0x7 << 24));
2941 value |= (prio << 24);
2942 reg_write(GSW_PCR(port), value);
2943 printf("write reg: %x, value: %x\n", GSW_PCR(port), value);
2944}
2945
2946void qos_set_dscppri(int argc, char *argv[])
2947{
developerbe40a9e2024-03-07 21:44:26 +08002948 unsigned char prio = 0, dscp = 0, pim_n = 0, pim_offset = 0;
2949 unsigned int value = 0, reg = 0;
developer546b2792024-06-15 20:31:38 +08002950 char *endptr;
developerfd40db22021-04-29 10:08:25 +08002951
developer546b2792024-06-15 20:31:38 +08002952 errno = 0;
2953 dscp = strtoul(argv[3], &endptr, 10);
2954 if (errno != 0 || *endptr != '\0' || dscp > 63) {
2955 printf(HELP_QOS_DSCP_PRIO);
2956 return;
2957 }
developerfd40db22021-04-29 10:08:25 +08002958
developer546b2792024-06-15 20:31:38 +08002959 errno = 0;
2960 prio = strtoul(argv[4], &endptr, 10);
2961 if (errno != 0 || *endptr != '\0' || prio > 7) {
developerfd40db22021-04-29 10:08:25 +08002962 printf(HELP_QOS_DSCP_PRIO);
2963 return;
2964 }
2965
2966 pim_n = dscp / 10;
2967 pim_offset = (dscp - pim_n * 10) * 3;
2968 reg = 0x0058 + pim_n * 4;
2969 reg_read(reg, &value);
2970 value &= (~(0x7 << pim_offset));
2971 value |= ((prio & 0x7) << pim_offset);
2972 reg_write(reg, value);
2973 printf("write reg: %x, value: %x\n", reg, value);
2974}
2975
2976void qos_pri_mapping_queue(int argc, char *argv[])
2977{
developerbe40a9e2024-03-07 21:44:26 +08002978 unsigned char prio = 0, queue = 0, pem_n = 0, port = 0;
2979 unsigned int value = 0, reg = 0;
developer546b2792024-06-15 20:31:38 +08002980 char *endptr;
developerfd40db22021-04-29 10:08:25 +08002981
2982 if (argc < 6)
2983 return;
2984
developer546b2792024-06-15 20:31:38 +08002985 errno = 0;
2986 port = strtoul(argv[3], &endptr, 10);
2987 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
2988 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
2989 return;
2990 }
2991
2992 errno = 0;
2993 prio = strtoul(argv[4], &endptr, 10);
2994 if (errno != 0 || *endptr != '\0' || prio > 7) {
2995 printf(HELP_QOS_PRIO_QMAP);
2996 return;
2997 }
developerfd40db22021-04-29 10:08:25 +08002998
developer546b2792024-06-15 20:31:38 +08002999 errno = 0;
3000 queue = strtoul(argv[5], &endptr, 10);
3001 if (errno != 0 || *endptr != '\0' || queue > 7) {
developerfd40db22021-04-29 10:08:25 +08003002 printf(HELP_QOS_PRIO_QMAP);
3003 return;
3004 }
developerbe40a9e2024-03-07 21:44:26 +08003005
developerfd40db22021-04-29 10:08:25 +08003006 if (chip_name == 0x7530) {
3007 pem_n = prio / 2;
3008 reg = pem_n * 0x4 + 0x48;
3009 reg_read(reg, &value);
3010 if (prio % 2) {
3011 value &= (~(0x7 << 24));
3012 value |= ((queue & 0x7) << 24);
3013 } else {
3014 value &= (~(0x7 << 8));
3015 value |= ((queue & 0x7) << 8);
3016 }
3017 reg_write(reg, value);
3018 printf("write reg: %x, value: %x\n", reg, value);
developer8c3871b2022-07-01 14:07:53 +08003019 } else if (chip_name == 0x7531 || chip_name == 0x7988) {
developerfd40db22021-04-29 10:08:25 +08003020 pem_n = prio / 2;
3021 reg = GSW_PEM(pem_n) + 0x100 * port;
3022 reg_read(reg, &value);
developerbe40a9e2024-03-07 21:44:26 +08003023 if (prio % 2) { // 1 1
developerfd40db22021-04-29 10:08:25 +08003024 value &= (~(0x7 << 25));
3025 value |= ((queue & 0x7) << 25);
developerbe40a9e2024-03-07 21:44:26 +08003026 } else { // 0 0
developerfd40db22021-04-29 10:08:25 +08003027 value &= (~(0x7 << 9));
3028 value |= ((queue & 0x7) << 9);
3029 }
3030 reg_write(reg, value);
3031 printf("write reg: %x, value: %x\n", reg, value);
developerbe40a9e2024-03-07 21:44:26 +08003032 } else {
developerfd40db22021-04-29 10:08:25 +08003033 printf("unknown switch device");
3034 return;
3035 }
3036}
3037
3038static int macMT753xVlanSetVid(unsigned char index, unsigned char active,
developerbe40a9e2024-03-07 21:44:26 +08003039 unsigned short vid, unsigned char portMap,
3040 unsigned char tagPortMap, unsigned char ivl_en,
3041 unsigned char fid, unsigned short stag)
developerfd40db22021-04-29 10:08:25 +08003042{
3043 unsigned int value = 0;
3044 unsigned int value2 = 0;
developerbe40a9e2024-03-07 21:44:26 +08003045 unsigned int reg = 0;
3046 int i = 0;
developerfd40db22021-04-29 10:08:25 +08003047
3048 printf("index: %x, active: %x, vid: %x, portMap: %x, \
developerbe40a9e2024-03-07 21:44:26 +08003049 tagPortMap: %x, ivl_en: %x, fid: %x, stag: %x\n", index, active, vid, portMap, tagPortMap, ivl_en, fid, stag);
developerfd40db22021-04-29 10:08:25 +08003050
3051 value = (portMap << 16);
3052 value |= (stag << 4);
3053 value |= (ivl_en << 30);
3054 value |= (fid << 1);
3055 value |= (active ? 1 : 0);
3056
3057 // total 7 ports
3058 for (i = 0; i < 7; i++) {
3059 if (tagPortMap & (1 << i))
3060 value2 |= 0x2 << (i * 2);
3061 }
3062
3063 if (value2)
developerbe40a9e2024-03-07 21:44:26 +08003064 value |= (1 << 28); // eg_tag
developerfd40db22021-04-29 10:08:25 +08003065
developerbe40a9e2024-03-07 21:44:26 +08003066 reg = 0x98; // VAWD2
developerfd40db22021-04-29 10:08:25 +08003067 reg_write(reg, value2);
3068
developerbe40a9e2024-03-07 21:44:26 +08003069 reg = 0x94; // VAWD1
developerfd40db22021-04-29 10:08:25 +08003070 reg_write(reg, value);
3071
developerbe40a9e2024-03-07 21:44:26 +08003072 reg = 0x90; // VTCR
developerfd40db22021-04-29 10:08:25 +08003073 value = (0x80001000 + vid);
3074 reg_write(reg, value);
3075
developerbe40a9e2024-03-07 21:44:26 +08003076 reg = 0x90; // VTCR
developerfd40db22021-04-29 10:08:25 +08003077 while (1) {
3078 reg_read(reg, &value);
developerbe40a9e2024-03-07 21:44:26 +08003079 if ((value & 0x80000000) == 0) //table busy
developerfd40db22021-04-29 10:08:25 +08003080 break;
3081 }
3082
3083 /* switch clear */
3084 reg = 0x80;
3085 reg_write(reg, 0x8002);
3086 usleep(5000);
3087 reg_read(reg, &value);
3088
3089 printf("SetVid: index:%d active:%d vid:%d portMap:%x tagPortMap:%x\r\n",
3090 index, active, vid, portMap, tagPortMap);
3091 return 0;
3092
developerbe40a9e2024-03-07 21:44:26 +08003093} /*end macMT753xVlanSetVid */
developerfd40db22021-04-29 10:08:25 +08003094
3095static int macMT753xVlanSetPvid(unsigned char port, unsigned short pvid)
3096{
developerbe40a9e2024-03-07 21:44:26 +08003097 unsigned int value = 0;
3098 unsigned int reg = 0;
developerfd40db22021-04-29 10:08:25 +08003099
developerbe40a9e2024-03-07 21:44:26 +08003100 /*Parameters is error */
developerfd40db22021-04-29 10:08:25 +08003101 if (port > 6)
3102 return -1;
3103
3104 reg = 0x2014 + (port * 0x100);
3105 reg_read(reg, &value);
3106 value &= ~0xfff;
3107 value |= pvid;
3108 reg_write(reg, value);
3109
3110 /* switch clear */
3111 reg = 0x80;
3112 reg_write(reg, 0x8002);
3113 usleep(5000);
3114 reg_read(reg, &value);
3115
3116 printf("SetPVID: port:%d pvid:%d\r\n", port, pvid);
3117 return 0;
3118}
developerfd40db22021-04-29 10:08:25 +08003119
3120void doVlanSetPvid(int argc, char *argv[])
3121{
3122 unsigned char port = 0;
3123 unsigned short pvid = 0;
developer3a780bf2024-06-15 20:34:27 +08003124 char *endptr;
developerfd40db22021-04-29 10:08:25 +08003125
developer3a780bf2024-06-15 20:34:27 +08003126 errno = 0;
3127 port = strtoul(argv[3], &endptr, 10);
3128 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
3129 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
3130 return;
3131 }
3132
3133 errno = 0;
3134 pvid = strtoul(argv[4], &endptr, 10);
3135 if (errno != 0 || *endptr != '\0' || pvid > MAX_VID_VALUE) {
developerfd40db22021-04-29 10:08:25 +08003136 printf(HELP_VLAN_PVID);
3137 return;
3138 }
3139
3140 macMT753xVlanSetPvid(port, pvid);
3141
3142 printf("port:%d pvid:%d,vlancap: max_port:%d maxvid:%d\r\n",
3143 port, pvid, SWITCH_MAX_PORT, MAX_VID_VALUE);
developerbe40a9e2024-03-07 21:44:26 +08003144} /*end doVlanSetPvid */
developerfd40db22021-04-29 10:08:25 +08003145
3146void doVlanSetVid(int argc, char *argv[])
3147{
developer3a780bf2024-06-15 20:34:27 +08003148 unsigned char index = 0, active = 0;
3149 unsigned char portMap = 0, tagPortMap = 0;
3150 unsigned short vid = 0, stag = 0;
3151 unsigned char ivl_en = 0, fid = 0;
3152 char *endptr;
developerfd40db22021-04-29 10:08:25 +08003153
developer3a780bf2024-06-15 20:34:27 +08003154 errno = 0;
3155 index = strtoul(argv[3], &endptr, 10);
3156 if (errno != 0 || *endptr != '\0' || index >= MAX_VLAN_RULE) {
3157 printf(HELP_VLAN_VID);
3158 return;
3159 }
developerfd40db22021-04-29 10:08:25 +08003160
developer3a780bf2024-06-15 20:34:27 +08003161 errno = 0;
3162 active = strtoul(argv[4], &endptr, 10);
3163 if (errno != 0 || *endptr != '\0' || active > ACTIVED) {
3164 printf(HELP_VLAN_VID);
3165 return;
3166 }
developerfd40db22021-04-29 10:08:25 +08003167
developer3a780bf2024-06-15 20:34:27 +08003168 errno = 0;
3169 vid = strtoul(argv[5], &endptr, 10);
3170 if (errno != 0 || *endptr != '\0' || vid >= 4096) {
3171 printf(HELP_VLAN_VID);
3172 return;
3173 }
3174
3175 errno = 0;
3176 portMap = strtoul(argv[6], &endptr, 10);
3177 if (errno != 0 || *endptr != '\0') {
developerfd40db22021-04-29 10:08:25 +08003178 printf(HELP_VLAN_VID);
3179 return;
3180 }
3181
developer3a780bf2024-06-15 20:34:27 +08003182 errno = 0;
3183 tagPortMap = strtoul(argv[7], &endptr, 10);
3184 if (errno != 0 || *endptr != '\0') {
3185 printf(HELP_VLAN_VID);
3186 return;
3187 }
developerfd40db22021-04-29 10:08:25 +08003188
3189 printf("subcmd parameter argc = %d\r\n", argc);
3190 if (argc >= 9) {
developer3a780bf2024-06-15 20:34:27 +08003191 errno = 0;
3192 ivl_en = strtoul(argv[8], &endptr, 10);
3193 if (errno != 0 || *endptr != '\0') {
3194 printf(HELP_VLAN_VID);
3195 return;
3196 }
developerfd40db22021-04-29 10:08:25 +08003197 if (argc >= 10) {
developer3a780bf2024-06-15 20:34:27 +08003198 errno = 0;
3199 fid = strtoul(argv[9], &endptr, 16);
3200 if (errno != 0 || *endptr != '\0') {
3201 printf(HELP_VLAN_VID);
3202 return;
3203 }
3204 if (argc >= 11) {
3205 errno = 0;
3206 stag = strtoul(argv[10], &endptr, 10);
3207 if (errno != 0 || *endptr != '\0') {
3208 printf(HELP_VLAN_VID);
3209 return;
3210 }
3211 }
developerfd40db22021-04-29 10:08:25 +08003212 }
3213 }
3214 macMT753xVlanSetVid(index, active, vid, portMap, tagPortMap,
3215 ivl_en, fid, stag);
3216 printf("index:%d active:%d vid:%d\r\n", index, active, vid);
developerbe40a9e2024-03-07 21:44:26 +08003217} /*end doVlanSetVid */
developerfd40db22021-04-29 10:08:25 +08003218
3219void doVlanSetAccFrm(int argc, char *argv[])
3220{
3221 unsigned char port = 0;
3222 unsigned char type = 0;
developerbe40a9e2024-03-07 21:44:26 +08003223 unsigned int value = 0;
3224 unsigned int reg = 0;
developer3a780bf2024-06-15 20:34:27 +08003225 char *endptr;
developerfd40db22021-04-29 10:08:25 +08003226
developer3a780bf2024-06-15 20:34:27 +08003227 errno = 0;
3228 port = strtoul(argv[3], &endptr, 10);
3229 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
3230 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
3231 return;
3232 }
developerfd40db22021-04-29 10:08:25 +08003233
developer3a780bf2024-06-15 20:34:27 +08003234 errno = 0;
3235 type = strtoul(argv[4], &endptr, 10);
3236 if (errno != 0 || *endptr != '\0' || type > REG_PVC_ACC_FRM_RELMASK) {
developerfd40db22021-04-29 10:08:25 +08003237 printf(HELP_VLAN_ACC_FRM);
3238 return;
3239 }
3240
developer3a780bf2024-06-15 20:34:27 +08003241 printf("port: %d, type: %d\n", port, type);
3242
developerfd40db22021-04-29 10:08:25 +08003243 reg = REG_PVC_P0_ADDR + port * 0x100;
3244 reg_read(reg, &value);
3245 value &= (~REG_PVC_ACC_FRM_MASK);
3246 value |= ((unsigned int)type << REG_PVC_ACC_FRM_OFFT);
3247
3248 printf("write reg: %x, value: %x\n", reg, value);
3249 reg_write(reg, value);
developerbe40a9e2024-03-07 21:44:26 +08003250} /*end doVlanSetAccFrm */
developerfd40db22021-04-29 10:08:25 +08003251
3252void doVlanSetPortAttr(int argc, char *argv[])
3253{
3254 unsigned char port = 0;
3255 unsigned char attr = 0;
developerbe40a9e2024-03-07 21:44:26 +08003256 unsigned int value = 0;
3257 unsigned int reg = 0;
developer3a780bf2024-06-15 20:34:27 +08003258 char *endptr;
developerfd40db22021-04-29 10:08:25 +08003259
developer3a780bf2024-06-15 20:34:27 +08003260 errno = 0;
3261 port = strtoul(argv[3], &endptr, 10);
3262 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
3263 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
3264 return;
3265 }
developerfd40db22021-04-29 10:08:25 +08003266
developer3a780bf2024-06-15 20:34:27 +08003267 errno = 0;
3268 attr = strtoul(argv[4], &endptr, 10);
3269 if (errno != 0 || *endptr != '\0' || attr > 3) {
developerfd40db22021-04-29 10:08:25 +08003270 printf(HELP_VLAN_PORT_ATTR);
3271 return;
3272 }
3273
developer3a780bf2024-06-15 20:34:27 +08003274 printf("port: %x, attr: %x\n", port, attr);
3275
developerfd40db22021-04-29 10:08:25 +08003276 reg = 0x2010 + port * 0x100;
3277 reg_read(reg, &value);
3278 value &= (0xffffff3f);
3279 value |= (attr << 6);
3280
3281 printf("write reg: %x, value: %x\n", reg, value);
3282 reg_write(reg, value);
3283}
3284
3285void doVlanSetPortMode(int argc, char *argv[])
3286{
3287 unsigned char port = 0;
3288 unsigned char mode = 0;
developerbe40a9e2024-03-07 21:44:26 +08003289 unsigned int value = 0;
3290 unsigned int reg = 0;
developer3a780bf2024-06-15 20:34:27 +08003291 char *endptr;
developerbe40a9e2024-03-07 21:44:26 +08003292
developer3a780bf2024-06-15 20:34:27 +08003293 errno = 0;
3294 port = strtoul(argv[3], &endptr, 10);
3295 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
3296 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
3297 return;
3298 }
developerfd40db22021-04-29 10:08:25 +08003299
developer3a780bf2024-06-15 20:34:27 +08003300 errno = 0;
3301 mode = strtoul(argv[4], &endptr, 10);
3302 if (errno != 0 || *endptr != '\0' || mode > 3) {
developerfd40db22021-04-29 10:08:25 +08003303 printf(HELP_VLAN_PORT_MODE);
3304 return;
3305 }
3306
developer3a780bf2024-06-15 20:34:27 +08003307 printf("port: %x, mode: %x\n", port, mode);
3308
developerfd40db22021-04-29 10:08:25 +08003309 reg = 0x2004 + port * 0x100;
3310 reg_read(reg, &value);
3311 value &= (~((1 << 0) | (1 << 1)));
3312 value |= (mode & 0x3);
3313 printf("write reg: %x, value: %x\n", reg, value);
3314 reg_write(reg, value);
3315}
3316
3317void doVlanSetEgressTagPCR(int argc, char *argv[])
3318{
3319 unsigned char port = 0;
3320 unsigned char eg_tag = 0;
developerbe40a9e2024-03-07 21:44:26 +08003321 unsigned int value = 0;
3322 unsigned int reg = 0;
developer3a780bf2024-06-15 20:34:27 +08003323 char *endptr;
developerfd40db22021-04-29 10:08:25 +08003324
developer3a780bf2024-06-15 20:34:27 +08003325 errno = 0;
3326 port = strtoul(argv[3], &endptr, 10);
3327 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
3328 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
3329 return;
3330 }
developerfd40db22021-04-29 10:08:25 +08003331
developer3a780bf2024-06-15 20:34:27 +08003332 errno = 0;
3333 eg_tag = strtoul(argv[4], &endptr, 10);
3334 if (errno != 0 || *endptr != '\0' || (eg_tag > REG_PCR_EG_TAG_RELMASK)) {
developerfd40db22021-04-29 10:08:25 +08003335 printf(HELP_VLAN_EGRESS_TAG_PCR);
3336 return;
3337 }
3338
developer3a780bf2024-06-15 20:34:27 +08003339 printf("port: %d, eg_tag: %d\n", port, eg_tag);
3340
developerfd40db22021-04-29 10:08:25 +08003341 reg = REG_PCR_P0_ADDR + port * 0x100;
3342 reg_read(reg, &value);
3343 value &= (~REG_PCR_EG_TAG_MASK);
3344 value |= ((unsigned int)eg_tag << REG_PCR_EG_TAG_OFFT);
3345
3346 printf("write reg: %x, value: %x\n", reg, value);
3347 reg_write(reg, value);
3348
developerbe40a9e2024-03-07 21:44:26 +08003349} /*end doVlanSetEgressTagPCR */
developerfd40db22021-04-29 10:08:25 +08003350
3351void doVlanSetEgressTagPVC(int argc, char *argv[])
3352{
3353 unsigned char port = 0;
3354 unsigned char eg_tag = 0;
developerbe40a9e2024-03-07 21:44:26 +08003355 unsigned int value = 0;
3356 unsigned int reg = 0;
developer3a780bf2024-06-15 20:34:27 +08003357 char *endptr;
developerfd40db22021-04-29 10:08:25 +08003358
developer3a780bf2024-06-15 20:34:27 +08003359 errno = 0;
3360 port = strtoul(argv[3], &endptr, 10);
3361 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
3362 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
3363 return;
3364 }
developerfd40db22021-04-29 10:08:25 +08003365
developer3a780bf2024-06-15 20:34:27 +08003366 errno = 0;
3367 eg_tag = strtoul(argv[4], &endptr, 10);
3368 if (errno != 0 || *endptr != '\0' || (eg_tag > REG_PVC_EG_TAG_RELMASK)) {
developerfd40db22021-04-29 10:08:25 +08003369 printf(HELP_VLAN_EGRESS_TAG_PVC);
3370 return;
3371 }
3372
developer3a780bf2024-06-15 20:34:27 +08003373 printf("port: %d, eg_tag: %d\n", port, eg_tag);
3374
developerfd40db22021-04-29 10:08:25 +08003375 reg = REG_PVC_P0_ADDR + port * 0x100;
3376 reg_read(reg, &value);
3377 value &= (~REG_PVC_EG_TAG_MASK);
3378 value |= ((unsigned int)eg_tag << REG_PVC_EG_TAG_OFFT);
3379
3380 printf("write reg: %x, value: %x\n", reg, value);
3381 reg_write(reg, value);
developerbe40a9e2024-03-07 21:44:26 +08003382} /*end doVlanSetEgressTagPVC */
developerfd40db22021-04-29 10:08:25 +08003383
3384void doArlAging(int argc, char *argv[])
3385{
3386 unsigned char aging_en = 0;
developer2fdae312024-06-15 20:36:12 +08003387 unsigned int time = 0, aging_cnt = 0, aging_unit = 0;
3388 unsigned int value = 0, reg = 0;
3389 char *endptr;
developerfd40db22021-04-29 10:08:25 +08003390
developer2fdae312024-06-15 20:36:12 +08003391 errno = 0;
3392 aging_en = strtoul(argv[3], &endptr, 10);
3393 if (errno != 0 || *endptr != '\0' || aging_en > 1) {
3394 printf(HELP_ARL_AGING);
3395 return;
3396 }
developerfd40db22021-04-29 10:08:25 +08003397
developer2fdae312024-06-15 20:36:12 +08003398 errno = 0;
3399 time = strtoul(argv[4], &endptr, 10);
3400 if (errno != 0 || *endptr != '\0' || (time <= 0 || time > 65536)) {
developerfd40db22021-04-29 10:08:25 +08003401 printf(HELP_ARL_AGING);
3402 return;
3403 }
3404
developer2fdae312024-06-15 20:36:12 +08003405 printf("aging_en: %x, aging time: %x\n", aging_en, time);
3406
developerfd40db22021-04-29 10:08:25 +08003407 reg = 0xa0;
3408 reg_read(reg, &value);
3409 value &= (~(1 << 20));
3410 if (!aging_en) {
3411 value |= (1 << 20);
3412 }
3413
3414 aging_unit = (time / 0x100) + 1;
3415 aging_cnt = (time / aging_unit);
3416 aging_unit--;
3417 aging_cnt--;
3418
3419 value &= (0xfff00000);
3420 value |= ((aging_cnt << 12) | aging_unit);
3421
3422 printf("aging_unit: %x, aging_cnt: %x\n", aging_unit, aging_cnt);
3423 printf("write reg: %x, value: %x\n", reg, value);
3424
3425 reg_write(reg, value);
3426}
3427
3428void doMirrorEn(int argc, char *argv[])
3429{
developerbe40a9e2024-03-07 21:44:26 +08003430 unsigned char mirror_en = 0;
3431 unsigned char mirror_port = 0;
3432 unsigned int value = 0, reg = 0;
developer2fdae312024-06-15 20:36:12 +08003433 char *endptr;
developerfd40db22021-04-29 10:08:25 +08003434
developer2fdae312024-06-15 20:36:12 +08003435 errno = 0;
3436 mirror_en = strtoul(argv[3], &endptr, 10);
3437 if (errno != 0 || *endptr != '\0' || mirror_en > 1) {
3438 printf(HELP_MIRROR_EN);
3439 return;
3440 }
developerfd40db22021-04-29 10:08:25 +08003441
developer2fdae312024-06-15 20:36:12 +08003442 errno = 0;
3443 mirror_port = strtoul(argv[4], &endptr, 10);
3444 if (errno != 0 || *endptr != '\0' || mirror_port > REG_CFC_MIRROR_PORT_RELMASK) {
developerfd40db22021-04-29 10:08:25 +08003445 printf(HELP_MIRROR_EN);
3446 return;
3447 }
3448
developer2fdae312024-06-15 20:36:12 +08003449 printf("mirror_en: %d, mirror_port: %d\n", mirror_en, mirror_port);
3450
developerfd40db22021-04-29 10:08:25 +08003451 reg = REG_CFC_ADDR;
3452 reg_read(reg, &value);
3453 value &= (~REG_CFC_MIRROR_EN_MASK);
3454 value |= (mirror_en << REG_CFC_MIRROR_EN_OFFT);
3455 value &= (~REG_CFC_MIRROR_PORT_MASK);
3456 value |= (mirror_port << REG_CFC_MIRROR_PORT_OFFT);
3457
3458 printf("write reg: %x, value: %x\n", reg, value);
3459 reg_write(reg, value);
3460
developerbe40a9e2024-03-07 21:44:26 +08003461} /*end doMirrorEn */
developerfd40db22021-04-29 10:08:25 +08003462
3463void doMirrorPortBased(int argc, char *argv[])
3464{
developerbe40a9e2024-03-07 21:44:26 +08003465 unsigned char port = 0, port_tx_mir = 0, port_rx_mir = 0, vlan_mis =
3466 0, acl_mir = 0, igmp_mir = 0;
3467 unsigned int value = 0, reg = 0;
developer2fdae312024-06-15 20:36:12 +08003468 char *endptr;
developerfd40db22021-04-29 10:08:25 +08003469
developer2fdae312024-06-15 20:36:12 +08003470 errno = 0;
3471 port = strtoul(argv[3], &endptr, 10);
3472 if (errno != 0 || *endptr != '\0' || port > MAX_PORT)
3473 goto error;
3474
3475 errno = 0;
3476 port_tx_mir = strtoul(argv[4], &endptr, 10);
3477 if (errno != 0 || *endptr != '\0' || port_tx_mir > 1)
3478 goto error;
3479
3480 errno = 0;
3481 port_rx_mir = strtoul(argv[5], &endptr, 10);
3482 if (errno != 0 || *endptr != '\0' || port_rx_mir > 1)
3483 goto error;
3484
3485 errno = 0;
3486 acl_mir = strtoul(argv[6], &endptr, 10);
3487 if (errno != 0 || *endptr != '\0' || acl_mir > 1)
3488 goto error;
3489
3490 errno = 0;
3491 vlan_mis = strtoul(argv[7], &endptr, 10);
3492 if (errno != 0 || *endptr != '\0' || vlan_mis > 1)
3493 goto error;
3494
3495 errno = 0;
3496 igmp_mir = strtoul(argv[8], &endptr, 10);
3497 if (errno != 0 || *endptr != '\0' || igmp_mir > 1)
3498 goto error;
developerfd40db22021-04-29 10:08:25 +08003499
developerbe40a9e2024-03-07 21:44:26 +08003500 printf
3501 ("port:%d, port_tx_mir:%d, port_rx_mir:%d, acl_mir:%d, vlan_mis:%d, igmp_mir:%d\n",
3502 port, port_tx_mir, port_rx_mir, acl_mir, vlan_mis, igmp_mir);
developerfd40db22021-04-29 10:08:25 +08003503
developerfd40db22021-04-29 10:08:25 +08003504 reg = REG_PCR_P0_ADDR + port * 0x100;
3505 reg_read(reg, &value);
developerbe40a9e2024-03-07 21:44:26 +08003506 value &=
3507 ~(REG_PORT_TX_MIR_MASK | REG_PORT_RX_MIR_MASK | REG_PCR_ACL_MIR_MASK
3508 | REG_PCR_VLAN_MIS_MASK);
3509 value |=
3510 (port_tx_mir << REG_PORT_TX_MIR_OFFT) +
3511 (port_rx_mir << REG_PORT_RX_MIR_OFFT);
3512 value |=
3513 (acl_mir << REG_PCR_ACL_MIR_OFFT) +
3514 (vlan_mis << REG_PCR_VLAN_MIS_OFFT);
developerfd40db22021-04-29 10:08:25 +08003515
3516 printf("write reg: %x, value: %x\n", reg, value);
3517 reg_write(reg, value);
3518
3519 reg = REG_PIC_P0_ADDR + port * 0x100;
3520 reg_read(reg, &value);
3521 value &= ~(REG_PIC_IGMP_MIR_MASK);
3522 value |= (igmp_mir << REG_PIC_IGMP_MIR_OFFT);
3523
3524 printf("write reg: %x, value: %x\n", reg, value);
3525 reg_write(reg, value);
developer2fdae312024-06-15 20:36:12 +08003526 return;
developerfd40db22021-04-29 10:08:25 +08003527
developer2fdae312024-06-15 20:36:12 +08003528error:
3529 printf(HELP_MIRROR_PORTBASED);
3530 return;
developerbe40a9e2024-03-07 21:44:26 +08003531} /*end doMirrorPortBased */
developerfd40db22021-04-29 10:08:25 +08003532
3533void doStp(int argc, char *argv[])
3534{
3535 unsigned char port = 0;
3536 unsigned char fid = 0;
3537 unsigned char state = 0;
developerbe40a9e2024-03-07 21:44:26 +08003538 unsigned int value = 0;
3539 unsigned int reg = 0;
developer2fdae312024-06-15 20:36:12 +08003540 char *endptr;
developerfd40db22021-04-29 10:08:25 +08003541
developer2fdae312024-06-15 20:36:12 +08003542 errno = 0;
3543 port = strtoul(argv[2], &endptr, 10);
3544 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
3545 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
3546 return;
3547 }
developerfd40db22021-04-29 10:08:25 +08003548
developer2fdae312024-06-15 20:36:12 +08003549 errno = 0;
3550 fid = strtoul(argv[3], &endptr, 10);
3551 if (errno != 0 || *endptr != '\0' || fid > 7) {
3552 printf(HELP_STP);
3553 return;
3554 }
developerfd40db22021-04-29 10:08:25 +08003555
developer2fdae312024-06-15 20:36:12 +08003556 errno = 0;
3557 state = strtoul(argv[4], &endptr, 10);
3558 if (errno != 0 || *endptr != '\0' || state > 3) {
developerfd40db22021-04-29 10:08:25 +08003559 printf(HELP_STP);
3560 return;
3561 }
3562
developer2fdae312024-06-15 20:36:12 +08003563 printf("port: %d, fid: %d, state: %d\n", port, fid, state);
3564
developerfd40db22021-04-29 10:08:25 +08003565 reg = REG_SSC_P0_ADDR + port * 0x100;
3566 reg_read(reg, &value);
3567 value &= (~(3 << (fid << 2)));
3568 value |= ((unsigned int)state << (fid << 2));
3569
3570 printf("write reg: %x, value: %x\n", reg, value);
3571 reg_write(reg, value);
3572}
3573
developerbe40a9e2024-03-07 21:44:26 +08003574void _ingress_rate_set(int on_off, int port, int bw)
developerfd40db22021-04-29 10:08:25 +08003575{
developerbe40a9e2024-03-07 21:44:26 +08003576 unsigned int reg = 0, value = 0;
developerfd40db22021-04-29 10:08:25 +08003577
3578 reg = 0x1800 + (0x100 * port);
3579 value = 0;
developerbe40a9e2024-03-07 21:44:26 +08003580 /*token-bucket */
developerfd40db22021-04-29 10:08:25 +08003581 if (on_off == 1) {
3582 if (chip_name == 0x7530) {
3583 if (bw > 1000000) {
developerbe40a9e2024-03-07 21:44:26 +08003584 printf
3585 ("\n**Charge rate(%d) is larger than line rate(1000000kbps)**\n",
3586 bw);
3587 return;
developerfd40db22021-04-29 10:08:25 +08003588 }
developerbe40a9e2024-03-07 21:44:26 +08003589 value =
3590 ((bw / 32) << 16) + (1 << 15) + (7 << 8) +
3591 (1 << 7) + 0x0f;
developer8c3871b2022-07-01 14:07:53 +08003592 } else if (chip_name == 0x7531 || chip_name == 0x7988) {
3593 if ((chip_name == 0x7531) && (bw > 2500000)) {
developerbe40a9e2024-03-07 21:44:26 +08003594 printf
3595 ("\n**Charge rate(%d) is larger than line rate(2500000kbps)**\n",
3596 bw);
3597 return;
developerfd40db22021-04-29 10:08:25 +08003598 }
developer8c3871b2022-07-01 14:07:53 +08003599
3600 if ((chip_name == 0x7988) && (bw > 4000000)) {
developerbe40a9e2024-03-07 21:44:26 +08003601 printf
3602 ("\n**Charge rate(%d) is larger than line rate(4000000kbps)**\n",
3603 bw);
3604 return;
developerfd40db22021-04-29 10:08:25 +08003605 }
developer8c3871b2022-07-01 14:07:53 +08003606
developerbe40a9e2024-03-07 21:44:26 +08003607 if (bw / 32 >= 65536) //supoort 2.5G case
3608 value =
3609 ((bw / 32) << 16) + (1 << 15) + (1 << 14) +
3610 (1 << 12) + (7 << 8) + 0xf;
developer8c3871b2022-07-01 14:07:53 +08003611 else
developerbe40a9e2024-03-07 21:44:26 +08003612 value =
3613 ((bw / 32) << 16) + (1 << 15) + (1 << 14) +
3614 (7 << 8) + 0xf;
3615 } else
developerfd40db22021-04-29 10:08:25 +08003616 printf("unknow chip\n");
3617 }
developerfd40db22021-04-29 10:08:25 +08003618#if leaky_bucket
3619 reg_read(reg, &value);
3620 value &= 0xffff0000;
developerbe40a9e2024-03-07 21:44:26 +08003621 if (on_off == 1) {
developerfd40db22021-04-29 10:08:25 +08003622 value |= on_off << 15;
3623 //7530 same as 7531
3624 if (bw < 100) {
3625 value |= (0x0 << 8);
3626 value |= bw;
3627 } else if (bw < 1000) {
3628 value |= (0x1 << 8);
3629 value |= bw / 10;
3630 } else if (bw < 10000) {
3631 value |= (0x2 << 8);
3632 value |= bw / 100;
3633 } else if (bw < 100000) {
3634 value |= (0x3 << 8);
3635 value |= bw / 1000;
3636 } else {
3637 value |= (0x4 << 8);
3638 value |= bw / 10000;
3639 }
3640 }
3641#endif
3642 reg_write(reg, value);
3643 reg = 0x1FFC;
3644 reg_read(reg, &value);
3645 value = 0x110104;
3646 reg_write(reg, value);
developerbe40a9e2024-03-07 21:44:26 +08003647
3648 if (on_off)
3649 printf("switch port=%d, bw=%d\n", port, bw);
3650 else
3651 printf("switch port=%d ingress rate limit off\n", port);
developerfd40db22021-04-29 10:08:25 +08003652}
3653
developerbe40a9e2024-03-07 21:44:26 +08003654void ingress_rate_set(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08003655{
developerbe40a9e2024-03-07 21:44:26 +08003656 int on_off = 0, port = 0, bw = 0;
developer997ed6b2024-03-26 14:03:42 +08003657 char *endptr;
developerbe40a9e2024-03-07 21:44:26 +08003658
developer997ed6b2024-03-26 14:03:42 +08003659 /* clear errno before conversion to detect overflow */
3660 errno = 0;
3661 port = strtoul(argv[3], &endptr, 0);
3662
3663 if (errno == ERANGE) {
3664 printf("Conversion error, value out of range\n");
3665 return;
3666 }
3667 if (*endptr != '\0') {
3668 printf("Conversion error, no digits were found\n");
3669 return;
3670 }
3671
3672 if (port < 0 || port > 6) {
3673 printf("Wrong port range, should be within 0-6\n");
3674 return;
3675 }
3676
developerbe40a9e2024-03-07 21:44:26 +08003677 if (argv[2][1] == 'n') {
developer997ed6b2024-03-26 14:03:42 +08003678 errno = 0;
3679 bw = strtoul(argv[4], &endptr, 0);
3680 if (errno == ERANGE) {
3681 printf("Conversion error, value out of range\n");
3682 return;
3683 }
3684 if (*endptr != '\0') {
3685 printf("Conversion error, no digits were found\n");
3686 return;
3687 }
developerbe40a9e2024-03-07 21:44:26 +08003688 on_off = 1;
3689 } else if (argv[2][1] == 'f') {
3690 if (argc != 4)
3691 return;
3692 on_off = 0;
3693 }
3694
3695 _ingress_rate_set(on_off, port, bw);
3696}
3697
3698void _egress_rate_set(int on_off, int port, int bw)
3699{
3700 unsigned int value = 0, reg = 0;
developerfd40db22021-04-29 10:08:25 +08003701
3702 reg = 0x1040 + (0x100 * port);
3703 value = 0;
developerbe40a9e2024-03-07 21:44:26 +08003704 /*token-bucket */
developerfd40db22021-04-29 10:08:25 +08003705 if (on_off == 1) {
3706 if (chip_name == 0x7530) {
3707 if (bw < 0 || bw > 1000000) {
developerbe40a9e2024-03-07 21:44:26 +08003708 printf
3709 ("\n**Charge rate(%d) is larger than line rate(1000000kbps)**\n",
3710 bw);
3711 return;
developerfd40db22021-04-29 10:08:25 +08003712 }
developerbe40a9e2024-03-07 21:44:26 +08003713 value =
3714 ((bw / 32) << 16) + (1 << 15) + (7 << 8) +
3715 (1 << 7) + 0xf;
developer8c3871b2022-07-01 14:07:53 +08003716 } else if (chip_name == 0x7531 || chip_name == 0x7988) {
3717 if ((chip_name == 0x7531) && (bw < 0 || bw > 2500000)) {
developerbe40a9e2024-03-07 21:44:26 +08003718 printf
3719 ("\n**Charge rate(%d) is larger than line rate(2500000kbps)**\n",
3720 bw);
3721 return;
developerfd40db22021-04-29 10:08:25 +08003722 }
developer8c3871b2022-07-01 14:07:53 +08003723 if ((chip_name == 0x7988) && (bw < 0 || bw > 4000000)) {
developerbe40a9e2024-03-07 21:44:26 +08003724 printf
3725 ("\n**Charge rate(%d) is larger than line rate(4000000kbps)**\n",
3726 bw);
3727 return;
developer8c3871b2022-07-01 14:07:53 +08003728 }
3729
developerbe40a9e2024-03-07 21:44:26 +08003730 if (bw / 32 >= 65536) //support 2.5G cases
3731 value =
3732 ((bw / 32) << 16) + (1 << 15) + (1 << 14) +
3733 (1 << 12) + (7 << 8) + 0xf;
developer8c3871b2022-07-01 14:07:53 +08003734 else
developerbe40a9e2024-03-07 21:44:26 +08003735 value =
3736 ((bw / 32) << 16) + (1 << 15) + (1 << 14) +
3737 (7 << 8) + 0xf;
3738 } else
developerfd40db22021-04-29 10:08:25 +08003739 printf("unknow chip\n");
3740 }
3741 reg_write(reg, value);
3742 reg = 0x10E0;
3743 reg_read(reg, &value);
3744 value &= 0x18;
3745 reg_write(reg, value);
3746
developerbe40a9e2024-03-07 21:44:26 +08003747 if (on_off)
3748 printf("switch port=%d, bw=%d\n", port, bw);
3749 else
3750 printf("switch port=%d egress rate limit off\n", port);
3751}
3752
3753void egress_rate_set(int argc, char *argv[])
3754{
3755 unsigned int value = 0, reg = 0;
3756 int on_off = 0, port = 0, bw = 0;
developer997ed6b2024-03-26 14:03:42 +08003757 char *endptr;
developerbe40a9e2024-03-07 21:44:26 +08003758
developer997ed6b2024-03-26 14:03:42 +08003759 /* clear errno before conversion to detect overflow */
3760 errno = 0;
3761 port = strtoul(argv[3], &endptr, 0);
3762 if (errno == ERANGE) {
3763 printf("Conversion error, value out of range\n");
3764 return;
3765 }
3766 if (*endptr != '\0') {
3767 printf("Conversion error, no digits were found\n");
3768 return;
3769 }
3770 if (port < 0 || port > 6) {
3771 printf("Wrong port range, should be within 0-6\n");
3772 return;
3773 }
developerbe40a9e2024-03-07 21:44:26 +08003774 if (argv[2][1] == 'n') {
developer997ed6b2024-03-26 14:03:42 +08003775 errno = 0;
3776 bw = strtoul(argv[4], &endptr, 0);
3777 if (errno == ERANGE) {
3778 printf("Conversion error, value out of range\n");
3779 return;
3780 }
3781 if (*endptr != '\0') {
3782 printf("Conversion error, no digits were found\n");
3783 return;
3784 }
developerbe40a9e2024-03-07 21:44:26 +08003785 on_off = 1;
3786 } else if (argv[2][1] == 'f') {
3787 if (argc != 4)
3788 return;
3789 on_off = 0;
3790 }
3791
3792 _egress_rate_set(on_off, port, bw);
developerfd40db22021-04-29 10:08:25 +08003793}
3794
3795void rate_control(int argc, char *argv[])
3796{
3797 unsigned char dir = 0;
3798 unsigned char port = 0;
3799 unsigned int rate = 0;
developer3a780bf2024-06-15 20:34:27 +08003800 char *endptr;
developerfd40db22021-04-29 10:08:25 +08003801
developer3a780bf2024-06-15 20:34:27 +08003802 errno = 0;
3803 dir = strtoul(argv[2], &endptr, 10);
3804 if (errno != 0 || *endptr != '\0' || dir > 1) {
3805 printf("Error: wrong port member, should be 0:egress, 1:ingress\n");
3806 return;
3807 }
developerfd40db22021-04-29 10:08:25 +08003808
developer3a780bf2024-06-15 20:34:27 +08003809 errno = 0;
3810 port = strtoul(argv[3], &endptr, 10);
3811 if (errno != 0 || *endptr != '\0' || port > MAX_PORT) {
3812 printf("Error: wrong port member, should be within 0~%d\n", MAX_PORT);
3813 return;
3814 }
3815
3816 errno = 0;
3817 rate = strtoul(argv[4], &endptr, 10);
3818 if (errno != 0 || *endptr != '\0') {
3819 printf("Error: wrong traffic rate, unit is kbps\n");
developerfd40db22021-04-29 10:08:25 +08003820 return;
developer3a780bf2024-06-15 20:34:27 +08003821 }
developerfd40db22021-04-29 10:08:25 +08003822
developerbe40a9e2024-03-07 21:44:26 +08003823 if (dir == 1) //ingress
3824 _ingress_rate_set(1, port, rate);
3825 else if (dir == 0) //egress
3826 _egress_rate_set(1, port, rate);
developerfd40db22021-04-29 10:08:25 +08003827}
3828
developerbe40a9e2024-03-07 21:44:26 +08003829void collision_pool_enable(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08003830{
3831
developerbe40a9e2024-03-07 21:44:26 +08003832 unsigned char enable = 0;
3833 unsigned int value = 0, reg = 0;
developerfd40db22021-04-29 10:08:25 +08003834
3835 enable = atoi(argv[3]);
3836
developerfd40db22021-04-29 10:08:25 +08003837 printf("collision pool enable: %d \n", enable);
3838
developerbe40a9e2024-03-07 21:44:26 +08003839 /*Check the input parameters is right or not. */
developerfd40db22021-04-29 10:08:25 +08003840 if (enable > 1) {
3841 printf(HELP_COLLISION_POOL_EN);
developerbe40a9e2024-03-07 21:44:26 +08003842 return;
developerfd40db22021-04-29 10:08:25 +08003843 }
3844
developer8c3871b2022-07-01 14:07:53 +08003845 if (chip_name == 0x7531 || chip_name == 0x7988) {
developerfd40db22021-04-29 10:08:25 +08003846 reg = REG_CPGC_ADDR;
developerbe40a9e2024-03-07 21:44:26 +08003847 if (enable == 1) {
developerfd40db22021-04-29 10:08:25 +08003848 /* active reset */
3849 reg_read(reg, &value);
3850 value &= (~REG_CPCG_COL_RST_N_MASK);
3851 reg_write(reg, value);
3852
3853 /* enanble clock */
3854 reg_read(reg, &value);
3855 value &= (~REG_CPCG_COL_CLK_EN_MASK);
3856 value |= (1 << REG_CPCG_COL_CLK_EN_OFFT);
3857 reg_write(reg, value);
3858
3859 /* inactive reset */
3860 reg_read(reg, &value);
3861 value &= (~REG_CPCG_COL_RST_N_MASK);
3862 value |= (1 << REG_CPCG_COL_RST_N_OFFT);
3863 reg_write(reg, value);
3864
3865 /* enable collision pool */
3866 reg_read(reg, &value);
3867 value &= (~REG_CPCG_COL_EN_MASK);
3868 value |= (1 << REG_CPCG_COL_EN_OFFT);
3869 reg_write(reg, value);
3870
3871 reg_read(reg, &value);
3872 printf("write reg: %x, value: %x\n", reg, value);
developerbe40a9e2024-03-07 21:44:26 +08003873 } else {
developerfd40db22021-04-29 10:08:25 +08003874
3875 /* disable collision pool */
3876 reg_read(reg, &value);
3877 value &= (~REG_CPCG_COL_EN_MASK);
3878 reg_write(reg, value);
3879
3880 /* active reset */
3881 reg_read(reg, &value);
3882 value &= (~REG_CPCG_COL_RST_N_MASK);
3883 reg_write(reg, value);
3884
3885 /* inactive reset */
3886 reg_read(reg, &value);
3887 value &= (~REG_CPCG_COL_RST_N_MASK);
3888 value |= (1 << REG_CPCG_COL_RST_N_OFFT);
3889 reg_write(reg, value);
3890
3891 /* disable clock */
3892 reg_read(reg, &value);
3893 value &= (~REG_CPCG_COL_CLK_EN_MASK);
3894 reg_write(reg, value);
3895
3896 reg_read(reg, &value);
3897 printf("write reg: %x, value: %x\n", reg, value);
3898
3899 }
developerbe40a9e2024-03-07 21:44:26 +08003900 } else {
developerfd40db22021-04-29 10:08:25 +08003901 printf("\nCommand not support by this chip.\n");
developerbe40a9e2024-03-07 21:44:26 +08003902 }
developerfd40db22021-04-29 10:08:25 +08003903}
3904
developerbe40a9e2024-03-07 21:44:26 +08003905void collision_pool_mac_dump(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08003906{
developerbe40a9e2024-03-07 21:44:26 +08003907 unsigned int value = 0, reg = 0;
developerfd40db22021-04-29 10:08:25 +08003908
developer8c3871b2022-07-01 14:07:53 +08003909 if (chip_name == 0x7531 || chip_name == 0x7988) {
developerfd40db22021-04-29 10:08:25 +08003910 reg = REG_CPGC_ADDR;
3911 reg_read(reg, &value);
developerbe40a9e2024-03-07 21:44:26 +08003912 if (value & REG_CPCG_COL_EN_MASK)
developerfd40db22021-04-29 10:08:25 +08003913 table_dump_internal(COLLISION_TABLE);
3914 else
developerbe40a9e2024-03-07 21:44:26 +08003915 printf
3916 ("\ncollision pool is disabled, please enable it before use this command.\n");
3917 } else {
developerfd40db22021-04-29 10:08:25 +08003918 printf("\nCommand not support by this chip.\n");
3919 }
3920}
3921
developerbe40a9e2024-03-07 21:44:26 +08003922void collision_pool_dip_dump(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08003923{
developerbe40a9e2024-03-07 21:44:26 +08003924 unsigned int value = 0, reg = 0;
developerfd40db22021-04-29 10:08:25 +08003925
developer8c3871b2022-07-01 14:07:53 +08003926 if (chip_name == 0x7531 || chip_name == 0x7988) {
developerfd40db22021-04-29 10:08:25 +08003927 reg = REG_CPGC_ADDR;
3928 reg_read(reg, &value);
developerbe40a9e2024-03-07 21:44:26 +08003929 if (value & REG_CPCG_COL_EN_MASK)
developerfd40db22021-04-29 10:08:25 +08003930 dip_dump_internal(COLLISION_TABLE);
3931 else
developerbe40a9e2024-03-07 21:44:26 +08003932 printf
3933 ("\ncollision pool is disabled, please enable it before use this command.\n");
3934 } else {
developerfd40db22021-04-29 10:08:25 +08003935 printf("\nCommand not support by this chip.\n");
3936 }
developerfd40db22021-04-29 10:08:25 +08003937}
3938
developerbe40a9e2024-03-07 21:44:26 +08003939void collision_pool_sip_dump(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08003940{
developerbe40a9e2024-03-07 21:44:26 +08003941 unsigned int value = 0, reg = 0;
developerfd40db22021-04-29 10:08:25 +08003942
developerbe40a9e2024-03-07 21:44:26 +08003943 if (chip_name == 0x7531 || chip_name == 0x7988) {
developerfd40db22021-04-29 10:08:25 +08003944 reg = REG_CPGC_ADDR;
3945 reg_read(reg, &value);
developerbe40a9e2024-03-07 21:44:26 +08003946 if (value & REG_CPCG_COL_EN_MASK)
developerfd40db22021-04-29 10:08:25 +08003947 sip_dump_internal(COLLISION_TABLE);
3948 else
developerbe40a9e2024-03-07 21:44:26 +08003949 printf
3950 ("\ncollision pool is disabled, please enable it before use this command.\n");
3951 } else {
developerfd40db22021-04-29 10:08:25 +08003952 printf("\nCommand not support by this chip.\n");
3953 }
developerfd40db22021-04-29 10:08:25 +08003954}
3955
3956void pfc_get_rx_counter(int argc, char *argv[])
3957{
developerbe40a9e2024-03-07 21:44:26 +08003958 int port = 0;
3959 unsigned int value = 0, reg = 0;
3960 unsigned int user_pri = 0;
developerfd40db22021-04-29 10:08:25 +08003961
3962 port = strtoul(argv[3], NULL, 0);
3963 if (port < 0 || 6 < port) {
3964 printf("wrong port range, should be within 0~6\n");
3965 return;
3966 }
3967
developerbe40a9e2024-03-07 21:44:26 +08003968 if (chip_name == 0x7531 || chip_name == 0x7988) {
3969 reg = PFC_RX_COUNTER_L(port);
developerfd40db22021-04-29 10:08:25 +08003970 reg_read(reg, &value);
3971 user_pri = value & 0xff;
developerbe40a9e2024-03-07 21:44:26 +08003972 printf("\n port %d rx pfc (up=0)pause on counter is %d.\n",
3973 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08003974 user_pri = (value & 0xff00) >> 8;
developerbe40a9e2024-03-07 21:44:26 +08003975 printf("\n port %d rx pfc (up=1)pause on counter is %d.\n",
3976 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08003977 user_pri = (value & 0xff0000) >> 16;
developerbe40a9e2024-03-07 21:44:26 +08003978 printf("\n port %d rx pfc (up=2)pause on counter is %d.\n",
3979 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08003980 user_pri = (value & 0xff000000) >> 24;
developerbe40a9e2024-03-07 21:44:26 +08003981 printf("\n port %d rx pfc (up=3)pause on counter is %d.\n",
3982 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08003983
developerbe40a9e2024-03-07 21:44:26 +08003984 reg = PFC_RX_COUNTER_H(port);
developerfd40db22021-04-29 10:08:25 +08003985 reg_read(reg, &value);
3986 user_pri = value & 0xff;
developerbe40a9e2024-03-07 21:44:26 +08003987 printf("\n port %d rx pfc (up=4)pause on counter is %d.\n",
3988 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08003989 user_pri = (value & 0xff00) >> 8;
developerbe40a9e2024-03-07 21:44:26 +08003990 printf("\n port %d rx pfc (up=5)pause on counter is %d.\n",
3991 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08003992 user_pri = (value & 0xff0000) >> 16;
developerbe40a9e2024-03-07 21:44:26 +08003993 printf("\n port %d rx pfc (up=6)pause on counter is %d.\n",
3994 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08003995 user_pri = (value & 0xff000000) >> 24;
developerbe40a9e2024-03-07 21:44:26 +08003996 printf("\n port %d rx pfc (up=7)pause on counter is %d.\n",
3997 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08003998
3999 /* for rx counter could be updated successfully */
4000 reg_read(PMSR_P(port), &value);
4001 reg_read(PMSR_P(port), &value);
developerbe40a9e2024-03-07 21:44:26 +08004002 } else {
developerfd40db22021-04-29 10:08:25 +08004003 printf("\nCommand not support by this chip.\n");
4004 }
4005
4006}
4007
4008void pfc_get_tx_counter(int argc, char *argv[])
4009{
developerbe40a9e2024-03-07 21:44:26 +08004010 int port = 0;
4011 unsigned int value = 0, reg = 0;
4012 unsigned int user_pri = 0;
developerfd40db22021-04-29 10:08:25 +08004013
4014 port = strtoul(argv[3], NULL, 0);
4015 if (port < 0 || 6 < port) {
4016 printf("wrong port range, should be within 0~6\n");
4017 return;
4018 }
4019
developer8c3871b2022-07-01 14:07:53 +08004020 if (chip_name == 0x7531 || chip_name == 0x7988) {
developerbe40a9e2024-03-07 21:44:26 +08004021 reg = PFC_TX_COUNTER_L(port);
developerfd40db22021-04-29 10:08:25 +08004022 reg_read(reg, &value);
4023 user_pri = value & 0xff;
developerbe40a9e2024-03-07 21:44:26 +08004024 printf("\n port %d tx pfc (up=0)pause on counter is %d.\n",
4025 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08004026 user_pri = (value & 0xff00) >> 8;
developerbe40a9e2024-03-07 21:44:26 +08004027 printf("\n port %d tx pfc (up=1)pause on counter is %d.\n",
4028 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08004029 user_pri = (value & 0xff0000) >> 16;
developerbe40a9e2024-03-07 21:44:26 +08004030 printf("\n port %d tx pfc (up=2)pause on counter is %d.\n",
4031 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08004032 user_pri = (value & 0xff000000) >> 24;
developerbe40a9e2024-03-07 21:44:26 +08004033 printf("\n port %d tx pfc (up=3)pause on counter is %d.\n",
4034 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08004035
developerbe40a9e2024-03-07 21:44:26 +08004036 reg = PFC_TX_COUNTER_H(port);
developerfd40db22021-04-29 10:08:25 +08004037 reg_read(reg, &value);
4038 user_pri = value & 0xff;
developerbe40a9e2024-03-07 21:44:26 +08004039 printf("\n port %d tx pfc (up=4)pause on counter is %d.\n",
4040 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08004041 user_pri = (value & 0xff00) >> 8;
developerbe40a9e2024-03-07 21:44:26 +08004042 printf("\n port %d tx pfc (up=5)pause on counter is %d.\n",
4043 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08004044 user_pri = (value & 0xff0000) >> 16;
developerbe40a9e2024-03-07 21:44:26 +08004045 printf("\n port %d tx pfc (up=6)pause on counter is %d.\n",
4046 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08004047 user_pri = (value & 0xff000000) >> 24;
developerbe40a9e2024-03-07 21:44:26 +08004048 printf("\n port %d tx pfc (up=7)pause on counter is %d.\n",
4049 port, user_pri);
developerfd40db22021-04-29 10:08:25 +08004050
4051 /* for tx counter could be updated successfully */
4052 reg_read(PMSR_P(port), &value);
4053 reg_read(PMSR_P(port), &value);
developerbe40a9e2024-03-07 21:44:26 +08004054 } else {
4055 printf("\nCommand not support by this chip.\n");
developerfd40db22021-04-29 10:08:25 +08004056 }
4057}
4058
developerbe40a9e2024-03-07 21:44:26 +08004059void read_output_queue_counters(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08004060{
developerbe40a9e2024-03-07 21:44:26 +08004061 unsigned int port = 0;
4062 unsigned int value = 0, output_queue = 0;
4063 unsigned int base = 0x220;
developerfd40db22021-04-29 10:08:25 +08004064
4065 for (port = 0; port < 7; port++) {
developerbe40a9e2024-03-07 21:44:26 +08004066 reg_write(0x7038, base + (port * 4));
developerfd40db22021-04-29 10:08:25 +08004067 reg_read(0x7034, &value);
4068 output_queue = value & 0xff;
developerbe40a9e2024-03-07 21:44:26 +08004069 printf("\n port %d output queue 0 counter is %d.\n", port,
4070 output_queue);
developerfd40db22021-04-29 10:08:25 +08004071 output_queue = (value & 0xff00) >> 8;
developerbe40a9e2024-03-07 21:44:26 +08004072 printf("\n port %d output queue 1 counter is %d.\n", port,
4073 output_queue);
developerfd40db22021-04-29 10:08:25 +08004074
developerbe40a9e2024-03-07 21:44:26 +08004075 reg_write(0x7038, base + (port * 4) + 1);
developerfd40db22021-04-29 10:08:25 +08004076 reg_read(0x7034, &value);
4077 output_queue = value & 0xff;
developerbe40a9e2024-03-07 21:44:26 +08004078 printf("\n port %d output queue 2 counter is %d.\n", port,
4079 output_queue);
developerfd40db22021-04-29 10:08:25 +08004080 output_queue = (value & 0xff00) >> 8;
developerbe40a9e2024-03-07 21:44:26 +08004081 printf("\n port %d output queue 3 counter is %d.\n", port,
4082 output_queue);
developerfd40db22021-04-29 10:08:25 +08004083
developerbe40a9e2024-03-07 21:44:26 +08004084 reg_write(0x7038, base + (port * 4) + 2);
developerfd40db22021-04-29 10:08:25 +08004085 reg_read(0x7034, &value);
4086 output_queue = value & 0xff;
developerbe40a9e2024-03-07 21:44:26 +08004087 printf("\n port %d output queue 4 counter is %d.\n", port,
4088 output_queue);
developerfd40db22021-04-29 10:08:25 +08004089 output_queue = (value & 0xff00) >> 8;
developerbe40a9e2024-03-07 21:44:26 +08004090 printf("\n port %d output queue 5 counter is %d.\n", port,
4091 output_queue);
developerfd40db22021-04-29 10:08:25 +08004092
developerbe40a9e2024-03-07 21:44:26 +08004093 reg_write(0x7038, base + (port * 4) + 3);
developerfd40db22021-04-29 10:08:25 +08004094 reg_read(0x7034, &value);
4095 output_queue = value & 0xff;
developerbe40a9e2024-03-07 21:44:26 +08004096 printf("\n port %d output queue 6 counter is %d.\n", port,
4097 output_queue);
developerfd40db22021-04-29 10:08:25 +08004098 output_queue = (value & 0xff00) >> 8;
developerbe40a9e2024-03-07 21:44:26 +08004099 printf("\n port %d output queue 7 counter is %d.\n", port,
4100 output_queue);
developerfd40db22021-04-29 10:08:25 +08004101 }
4102}
4103
developerbe40a9e2024-03-07 21:44:26 +08004104void read_free_page_counters(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08004105{
developerbe40a9e2024-03-07 21:44:26 +08004106 unsigned int value = 0;
4107 unsigned int free_page = 0, free_page_last_read = 0;
4108 unsigned int fc_free_blk_lothd = 0, fc_free_blk_hithd = 0;
4109 unsigned int fc_port_blk_thd = 0, fc_port_blk_hi_thd = 0;
4110 unsigned int queue[8] = { 0 };
developerfd40db22021-04-29 10:08:25 +08004111
developer8c3871b2022-07-01 14:07:53 +08004112 if (chip_name == 0x7531 || chip_name == 0x7988) {
developerbe40a9e2024-03-07 21:44:26 +08004113 /* get system free page link counter */
developerfd40db22021-04-29 10:08:25 +08004114 reg_read(0x1fc0, &value);
4115 free_page = value & 0xFFF;
4116 free_page_last_read = (value & 0xFFF0000) >> 16;
4117
4118 /* get system flow control waterwark */
4119 reg_read(0x1fe0, &value);
4120 fc_free_blk_lothd = value & 0x3FF;
4121 fc_free_blk_hithd = (value & 0x3FF0000) >> 16;
4122
4123 /* get port flow control waterwark */
4124 reg_read(0x1fe4, &value);
4125 fc_port_blk_thd = value & 0x3FF;
4126 fc_port_blk_hi_thd = (value & 0x3FF0000) >> 16;
4127
4128 /* get queue flow control waterwark */
4129 reg_read(0x1fe8, &value);
developerbe40a9e2024-03-07 21:44:26 +08004130 queue[0] = value & 0x3F;
4131 queue[1] = (value & 0x3F00) >> 8;
4132 queue[2] = (value & 0x3F0000) >> 16;
4133 queue[3] = (value & 0x3F000000) >> 24;
developerfd40db22021-04-29 10:08:25 +08004134 reg_read(0x1fec, &value);
developerbe40a9e2024-03-07 21:44:26 +08004135 queue[4] = value & 0x3F;
4136 queue[5] = (value & 0x3F00) >> 8;
4137 queue[6] = (value & 0x3F0000) >> 16;
4138 queue[7] = (value & 0x3F000000) >> 24;
developerfd40db22021-04-29 10:08:25 +08004139 } else {
developerbe40a9e2024-03-07 21:44:26 +08004140 /* get system free page link counter */
developerfd40db22021-04-29 10:08:25 +08004141 reg_read(0x1fc0, &value);
4142 free_page = value & 0x3FF;
4143 free_page_last_read = (value & 0x3FF0000) >> 16;
4144
4145 /* get system flow control waterwark */
4146 reg_read(0x1fe0, &value);
4147 fc_free_blk_lothd = value & 0xFF;
4148 fc_free_blk_hithd = (value & 0xFF00) >> 8;
4149
4150 /* get port flow control waterwark */
4151 reg_read(0x1fe0, &value);
4152 fc_port_blk_thd = (value & 0xFF0000) >> 16;
4153 reg_read(0x1ff4, &value);
4154 fc_port_blk_hi_thd = (value & 0xFF00) >> 8;
4155
4156 /* get queue flow control waterwark */
4157 reg_read(0x1fe4, &value);
developerbe40a9e2024-03-07 21:44:26 +08004158 queue[0] = value & 0xF;
4159 queue[1] = (value & 0xF0) >> 4;
4160 queue[2] = (value & 0xF00) >> 8;
4161 queue[3] = (value & 0xF000) >> 12;
4162 queue[4] = (value & 0xF0000) >> 16;
4163 queue[5] = (value & 0xF00000) >> 20;
4164 queue[6] = (value & 0xF000000) >> 24;
4165 queue[7] = (value & 0xF0000000) >> 28;
developerfd40db22021-04-29 10:08:25 +08004166 }
4167
developerbe40a9e2024-03-07 21:44:26 +08004168 printf("<===Free Page=======Current=======Last Read access=====>\n");
4169 printf("\n");
4170 printf(" page counter %u %u\n ",
4171 free_page, free_page_last_read);
4172 printf("\n ");
4173 printf("=========================================================\n");
4174 printf("<===Type=======High threshold======Low threshold=========\n");
4175 printf("\n ");
4176 printf(" system: %u %u\n",
4177 fc_free_blk_hithd * 2, fc_free_blk_lothd * 2);
4178 printf(" port: %u %u\n",
4179 fc_port_blk_hi_thd * 2, fc_port_blk_thd * 2);
4180 printf(" queue 0: %u NA\n",
4181 queue[0]);
4182 printf(" queue 1: %u NA\n",
4183 queue[1]);
4184 printf(" queue 2: %u NA\n",
4185 queue[2]);
4186 printf(" queue 3: %u NA\n",
4187 queue[3]);
4188 printf(" queue 4: %u NA\n",
4189 queue[4]);
4190 printf(" queue 5: %u NA\n",
4191 queue[5]);
4192 printf(" queue 6: %u NA\n",
4193 queue[6]);
4194 printf(" queue 7: %u NA\n",
4195 queue[7]);
4196 printf("=========================================================\n");
developerfd40db22021-04-29 10:08:25 +08004197}
4198
4199void eee_enable(int argc, char *argv[])
4200{
developerbe40a9e2024-03-07 21:44:26 +08004201 unsigned long enable = 0;
4202 unsigned int value = 0;
4203 unsigned int eee_cap = 0;
developerfd40db22021-04-29 10:08:25 +08004204 unsigned int eee_en_bitmap = 0;
developerbe40a9e2024-03-07 21:44:26 +08004205 unsigned long port_map = 0;
developerfd40db22021-04-29 10:08:25 +08004206 long port_num = -1;
developerbe40a9e2024-03-07 21:44:26 +08004207 int p = 0;
developerfd40db22021-04-29 10:08:25 +08004208
4209 if (argc < 3)
4210 goto error;
4211
developerbe40a9e2024-03-07 21:44:26 +08004212 /* Check the input parameters is right or not. */
developerfd40db22021-04-29 10:08:25 +08004213 if (!strncmp(argv[2], "enable", 7))
4214 enable = 1;
4215 else if (!strncmp(argv[2], "disable", 8))
4216 enable = 0;
4217 else
4218 goto error;
4219
4220 if (argc > 3) {
4221 if (strlen(argv[3]) == 1) {
4222 port_num = strtol(argv[3], (char **)NULL, 10);
4223 if (port_num < 0 || port_num > MAX_PHY_PORT - 1) {
4224 printf("Illegal port index and port:0~4\n");
4225 goto error;
4226 }
4227 port_map = 1 << port_num;
4228 } else if (strlen(argv[3]) == 5) {
4229 port_map = 0;
4230 for (p = 0; p < MAX_PHY_PORT; p++) {
4231 if (argv[3][p] != '0' && argv[3][p] != '1') {
developerbe40a9e2024-03-07 21:44:26 +08004232 printf
4233 ("portmap format error, should be combination of 0 or 1\n");
developerfd40db22021-04-29 10:08:25 +08004234 goto error;
4235 }
4236 port_map |= ((argv[3][p] - '0') << p);
4237 }
4238 } else {
developerbe40a9e2024-03-07 21:44:26 +08004239 printf
4240 ("port_no or portmap format error, should be length of 1 or 5\n");
developerfd40db22021-04-29 10:08:25 +08004241 goto error;
4242 }
4243 } else {
4244 port_map = 0x1f;
4245 }
4246
developerbe40a9e2024-03-07 21:44:26 +08004247 eee_cap = (enable) ? 6 : 0;
developerfd40db22021-04-29 10:08:25 +08004248 for (p = 0; p < MAX_PHY_PORT; p++) {
4249 /* port_map describe p0p1p2p3p4 from left to rignt */
developerbe40a9e2024-03-07 21:44:26 +08004250 if (!!(port_map & (1 << p)))
developerfd40db22021-04-29 10:08:25 +08004251 mii_mgr_c45_write(p, 0x7, 0x3c, eee_cap);
4252
4253 mii_mgr_c45_read(p, 0x7, 0x3c, &value);
4254 /* mt7531: Always readback eee_cap = 0 when global EEE switch
4255 * is turned off.
4256 */
4257 if (value | eee_cap)
4258 eee_en_bitmap |= (1 << (MAX_PHY_PORT - 1 - p));
4259 }
4260
4261 /* Turn on/off global EEE switch */
developer8c3871b2022-07-01 14:07:53 +08004262 if (chip_name == 0x7531 || chip_name == 0x7988) {
developerfd40db22021-04-29 10:08:25 +08004263 mii_mgr_c45_read(0, 0x1f, 0x403, &value);
4264 if (eee_en_bitmap)
4265 value |= (1 << 6);
4266 else
4267 value &= ~(1 << 6);
4268 mii_mgr_c45_write(0, 0x1f, 0x403, value);
4269 } else {
4270 printf("\nCommand not support by this chip.\n");
4271 }
4272
developerbe40a9e2024-03-07 21:44:26 +08004273 printf("EEE(802.3az) %s", (enable) ? "enable" : "disable");
developerfd40db22021-04-29 10:08:25 +08004274 if (argc == 4) {
4275 if (port_num >= 0)
4276 printf(" port%ld", port_num);
4277 else
4278 printf(" port_map: %s", argv[3]);
4279 } else {
4280 printf(" all ports");
4281 }
4282 printf("\n");
4283
4284 return;
4285error:
4286 printf(HELP_EEE_EN);
4287 return;
4288}
4289
4290void eee_dump(int argc, char *argv[])
4291{
developerbe40a9e2024-03-07 21:44:26 +08004292 unsigned int cap = 0, lp_cap = 0;
developerfd40db22021-04-29 10:08:25 +08004293 long port = -1;
developerbe40a9e2024-03-07 21:44:26 +08004294 int p = 0;
developerfd40db22021-04-29 10:08:25 +08004295
4296 if (argc > 3) {
4297 if (strlen(argv[3]) > 1) {
4298 printf("port# format error, should be of length 1\n");
4299 return;
4300 }
4301
4302 port = strtol(argv[3], (char **)NULL, 0);
4303 if (port < 0 || port > MAX_PHY_PORT) {
4304 printf("port# format error, should be 0 to %d\n",
developerbe40a9e2024-03-07 21:44:26 +08004305 MAX_PHY_PORT);
developerfd40db22021-04-29 10:08:25 +08004306 return;
4307 }
4308 }
4309
4310 for (p = 0; p < MAX_PHY_PORT; p++) {
4311 if (port >= 0 && p != port)
4312 continue;
4313
4314 mii_mgr_c45_read(p, 0x7, 0x3c, &cap);
4315 mii_mgr_c45_read(p, 0x7, 0x3d, &lp_cap);
4316 printf("port%d EEE cap=0x%02x, link partner EEE cap=0x%02x",
4317 p, cap, lp_cap);
4318
4319 if (port >= 0 && p == port) {
4320 mii_mgr_c45_read(p, 0x3, 0x1, &cap);
4321 printf(", st=0x%03x", cap);
4322 }
4323 printf("\n");
4324 }
4325}
4326
4327void dump_each_port(unsigned int base)
4328{
4329 unsigned int pkt_cnt = 0;
4330 int i = 0;
4331
4332 for (i = 0; i < 7; i++) {
developer0dea3402022-10-14 13:41:11 +08004333 if (chip_name == 0x7988) {
4334 if ((base == 0x402C) && (i == 6))
4335 base = 0x408C;
4336 else if ((base == 0x408C) && (i == 6))
4337 base = 0x402C;
4338 else
4339 ;
4340 }
developerfd40db22021-04-29 10:08:25 +08004341 reg_read((base) + (i * 0x100), &pkt_cnt);
4342 printf("%8u ", pkt_cnt);
4343 }
4344 printf("\n");
4345}
4346
developerbe40a9e2024-03-07 21:44:26 +08004347void read_mib_counters(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08004348{
4349 printf("===================== %8s %8s %8s %8s %8s %8s %8s\n",
4350 "Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6");
4351 printf("Tx Drop Packet :");
4352 dump_each_port(0x4000);
4353 printf("Tx CRC Error :");
4354 dump_each_port(0x4004);
4355 printf("Tx Unicast Packet :");
4356 dump_each_port(0x4008);
4357 printf("Tx Multicast Packet :");
4358 dump_each_port(0x400C);
4359 printf("Tx Broadcast Packet :");
4360 dump_each_port(0x4010);
4361 printf("Tx Collision Event :");
4362 dump_each_port(0x4014);
4363 printf("Tx Pause Packet :");
4364 dump_each_port(0x402C);
4365 printf("Rx Drop Packet :");
4366 dump_each_port(0x4060);
4367 printf("Rx Filtering Packet :");
4368 dump_each_port(0x4064);
4369 printf("Rx Unicast Packet :");
4370 dump_each_port(0x4068);
4371 printf("Rx Multicast Packet :");
4372 dump_each_port(0x406C);
4373 printf("Rx Broadcast Packet :");
4374 dump_each_port(0x4070);
4375 printf("Rx Alignment Error :");
4376 dump_each_port(0x4074);
4377 printf("Rx CRC Error :");
4378 dump_each_port(0x4078);
4379 printf("Rx Undersize Error :");
4380 dump_each_port(0x407C);
4381 printf("Rx Fragment Error :");
4382 dump_each_port(0x4080);
4383 printf("Rx Oversize Error :");
4384 dump_each_port(0x4084);
4385 printf("Rx Jabber Error :");
4386 dump_each_port(0x4088);
4387 printf("Rx Pause Packet :");
4388 dump_each_port(0x408C);
4389}
4390
developerbe40a9e2024-03-07 21:44:26 +08004391void clear_mib_counters(int argc, char *argv[])
developerfd40db22021-04-29 10:08:25 +08004392{
4393 reg_write(0x4fe0, 0xf0);
developerbe40a9e2024-03-07 21:44:26 +08004394 read_mib_counters(argc, argv);
developerfd40db22021-04-29 10:08:25 +08004395 reg_write(0x4fe0, 0x800000f0);
4396}
4397
developerfd40db22021-04-29 10:08:25 +08004398void exit_free()
4399{
4400 free(attres);
4401 attres = NULL;
4402 switch_ioctl_fini();
4403 mt753x_netlink_free();
4404}