[Add support HAL of ethernet switch gsw mode]
[Description]
Add support HAL of ethernet switch gsw mode
1. add swtich tool BB files
2. use DISTRO_FEATURES "switch_gsw_mode" to change dts
3. modify hostapd-init.sh to add eth1 to brlan0 in gsw mode
[Release-log]
diff --git a/recipes-devtools/switch/files/COPYING b/recipes-devtools/switch/files/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/recipes-devtools/switch/files/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/recipes-devtools/switch/files/Makefile b/recipes-devtools/switch/files/Makefile
new file mode 100644
index 0000000..81ae127
--- /dev/null
+++ b/recipes-devtools/switch/files/Makefile
@@ -0,0 +1,14 @@
+EXEC = switch
+
+SRC=switch_fun.c switch_753x.c switch_ioctl.c switch_netlink.c
+
+all: $(EXEC)
+
+switch: $(SRC)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SRC) $(LDLIBS) $(LIBS)
+
+romfs:
+ $(ROMFSINST) /bin/switch
+
+clean:
+ -rm -f $(EXEC) *.elf *.gdb *.o
diff --git a/recipes-devtools/switch/files/switch_753x.c b/recipes-devtools/switch/files/switch_753x.c
new file mode 100644
index 0000000..54d1fe6
--- /dev/null
+++ b/recipes-devtools/switch/files/switch_753x.c
@@ -0,0 +1,650 @@
+/*
+ * switch_753x.c: set for 753x switch
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+
+#include "switch_netlink.h"
+#include "switch_ioctl.h"
+#include "switch_fun.h"
+
+struct mt753x_attr *attres;
+int chip_name;
+bool nl_init_flag;
+
+static void usage(char *cmd)
+{
+ printf("==================Usage===============================================================================================================================\n");
+
+ /* 1. basic operations */
+ printf("1) mt753x switch Basic operations=================================================================================================================>>>>\n");
+ printf(" 1.1) %s devs - list switch device id and model name \n", cmd);
+ printf(" 1.2) %s sysctl - show the ways to access kenerl driver: netlink or ioctl \n", cmd);
+ printf(" 1.3) %s reset - sw reset switch fsm and registers\n", cmd);
+ printf(" 1.4) %s reg r [offset] - read the reg with default switch \n", cmd);
+ printf(" 1.5) %s reg w [offset] [value] - write the reg with default switch \n", cmd);
+ printf(" 1.6) %s reg d [offset] - dump the reg with default switch\n", cmd);
+ printf(" 1.7) %s dev [devid] reg r [addr] - read the reg with the switch devid \n", cmd);
+ printf(" 1.8) %s dev [devid] reg w [addr] [value] - write the regs with the switch devid \n", cmd);
+ printf(" 1.9) %s dev [devid] reg d [addr] - dump the regs with the switch devid \n", cmd);
+ printf(" \n");
+
+ /* 2. phy operations */
+ printf("2) mt753x switch PHY operations===================================================================================================================>>>>\n");
+ printf(" 2.1) %s phy - dump all phy registers (clause 22)\n", cmd);
+ printf(" 2.2) %s phy [phy_addr] - dump phy register of specific port (clause 22)\n", cmd);
+ printf(" 2.3) %s phy cl22 r [port_num] [phy_reg] - read specific phy register of specific port by clause 22\n", cmd);
+ printf(" 2.4) %s phy cl22 w [port_num] [phy_reg] [value] - write specific phy register of specific port by clause 22\n", cmd);
+ printf(" 2.5) %s phy cl45 r [port_num] [dev_num] [phy_reg] - read specific phy register of specific port by clause 45\n", cmd);
+ printf(" 2.6) %s phy cl45 w [port_num] [dev_num] [phy_reg] [value] - write specific phy register of specific port by clause 45\n", cmd);
+ printf(" 2.7) %s phy fc [port_num] [enable 0|1] - set switch phy flow control, port is 0~4, enable is 1, disable is 0 \n", cmd);
+ printf(" 2.8) %s phy an [port_num] [enable 0|1] - set switch phy auto-negotiation, port is 0~4, enable is 1, disable is 0 \n", cmd);
+ printf(" 2.9) %s trreg r [port_num] [ch_addr] [node_addr] [data_addr] - read phy token-ring of specific port\n", cmd);
+ printf(" 2.10) %s trreg w [port_num] [ch_addr] [node_addr] [data_addr] - write phy token-ring of specific port\n", cmd);
+ printf(" [high_value] [low_value] \n");
+ printf(" 2.11) %s crossover [port_num] [mode auto|mdi|mdix] - switch auto or force mdi/mdix mode for crossover cable\n", cmd);
+ printf(" \n");
+
+ /* 3. mac operations */
+ printf("3) mt753x switch MAC operations====================================================================================================================>>>>\n");
+ printf(" 3.1) %s dump - dump switch mac table\n", cmd);
+ printf(" 3.2) %s clear - clear switch mac table\n", cmd);
+ printf(" 3.3) %s add [mac] [portmap] - add an entry (with portmap) to switch mac table\n", cmd);
+ printf(" 3.4) %s add [mac] [portmap] [vlan id] - add an entry (with portmap, vlan id) to switch mac table\n", cmd);
+ printf(" 3.5) %s add [mac] [portmap] [vlan id] [age] - add an entry (with portmap, vlan id, age out time) to switch mac table\n", cmd);
+ printf(" 3.6) %s del mac [mac] vid [vid] - delete an entry from switch mac table\n", cmd);
+ printf(" 3.7) %s del mac [mac] fid [fid] - delete an entry from switch mac table\n", cmd);
+ printf(" 3.8) %s search mac [mac] vid [vid] - search an entry with specific mac and vid\n", cmd);
+ printf(" 3.9) %s search mac [mac] fid [fid] - search an entry with specific mac and fid\n", cmd);
+ printf(" 3.10) %s filt [mac] - add a SA filtering entry (with portmap 1111111) to switch mac table\n", cmd);
+ printf(" 3.11) %s filt [mac] [portmap] - add a SA filtering entry (with portmap)to switch mac table\n", cmd);
+ printf(" 3.12) %s filt [mac] [portmap] [vlan id - add a SA filtering entry (with portmap, vlan id)to switch mac table\n", cmd);
+ printf(" 3.13) %s filt [mac] [portmap] [vlan id] [age] - add a SA filtering entry (with portmap, vlan id, age out time) to switch table\n", cmd);
+ printf(" 3.14) %s arl aging [active:0|1] [time:1~65536] - set switch arl aging timeout value \n", cmd);
+ printf(" 3.15) %s macctl fc [enable|disable] - set switch mac global flow control,enable is 1, disable is 0 \n", cmd);
+ printf(" \n");
+
+ /* 4. mib counter operations */
+ printf("4) mt753x switch mib counter operations============================================================================================================>>>>\n");
+ printf(" 4.1) %s esw_cnt get -get switch mib counters \n", cmd);
+ printf(" 4.2) %s esw_cnt clear -clear switch mib counters \n", cmd);
+ printf(" 4.3) %s output_queue_cnt get -get switch output queue counters \n", cmd);
+ printf(" 4.4) %s free_page get -get switch system free page counters \n", cmd);
+ printf(" \n");
+
+ /* 5. acl function operations */
+ printf("5) mt753x switch acl function operations============================================================================================================>>>>\n");
+ printf(" 5.1) %s acl enable [port] [port_enable:0|1] - set switch acl function enabled, port is 0~6,enable is 1, disable is 0 \n", cmd);
+ printf(" 5.2) %s acl etype add [ethtype] [portmap] - drop L2 ethertype packets \n", cmd);
+ printf(" 5.3) %s acl dmac add [mac] [portmap] - drop L2 dest-Mac packets \n", cmd);
+ printf(" 5.4) %s acl dip add [dip] [portmap] - drop dip packets \n", cmd);
+ printf(" 5.5) %s acl port add [sport] [portmap] - drop L4 UDP/TCP source port packets\n", cmd);
+ printf(" 5.6) %s acl L4 add [2byes] [portmap] - drop L4 packets with 2bytes payload\n", cmd);
+ printf(" 5.7) %s acl acltbl-add [tbl_idx:0~63/255] [vawd1] [vawd2] - set switch acl table new entry, max index-7530:63,7531:255 \n", cmd);
+ printf(" 5.8) %s acl masktbl-add [tbl_idx:0~31/127] [vawd1] [vawd2] - set switch acl mask table new entry, max index-7530:31,7531:127 \n", cmd);
+ printf(" 5.9) %s acl ruletbl-add [tbl_idx:0~31/127] [vawd1] [vawd2] - set switch acl rule table new entry, max index-7530:31,7531:127 \n", cmd);
+ printf(" 5.10) %s acl ratetbl-add [tbl_idx:0~31] [vawd1] [vawd2] - set switch acl rate table new entry \n", cmd);
+ printf(" 5.11) %s acl dip meter [dip] [portmap][meter:kbps] - rate limit dip packets \n", cmd);
+ printf(" 5.12) %s acl dip trtcm [dip] [portmap][CIR:kbps][CBS][PIR][PBS]- TrTCM dip packets \n", cmd);
+ printf(" 5.13) %s acl dip modup [dip] [portmap][usr_pri] - modify usr priority from ACL \n", cmd);
+ printf(" 5.14) %s acl dip pppoe [dip] [portmap] - pppoe header removal \n", cmd);
+ printf(" \n");
+
+ /* 6. dip table operations */
+ printf("6) mt753x switch dip table operations=================================================================================================================>>>>\n");
+ printf(" 6.1) %s dip dump - dump switch dip table\n", cmd);
+ printf(" 6.2) %s dip clear - clear switch dip table\n", cmd);
+ printf(" 6.3) %s dip add [dip] [portmap] - add a dip entry to switch table\n", cmd);
+ printf(" 6.4) %s dip del [dip] - del a dip entry to switch table\n", cmd);
+ printf(" \n");
+
+ /* 7. sip table operations */
+ printf("7) mt753x switch sip table operations=================================================================================================================>>>>\n");
+ printf(" 7.1) %s sip dump - dump switch sip table\n", cmd);
+ printf(" 7.2) %s sip clear - clear switch sip table\n", cmd);
+ printf(" 7.3) %s sip add [sip] [dip] [portmap] - add a sip entry to switch table\n", cmd);
+ printf(" 7.4) %s sip del [sip] [dip] - del a sip entry to switch table\n", cmd);
+ printf(" \n");
+
+ /* 8. vlan table operations */
+ printf("8) mt753x switch sip table operations====================================================================================================================>>>>\n");
+ printf(" 8.1) %s vlan dump - dump switch vlan table\n", cmd);
+ printf(" 8.2) %s vlan set [vlan idx] [vid] [portmap] - set vlan id and associated member at switch vlan table\n", cmd);
+ printf(" 8.3) %s vlan vid [vlan idx] [active:0|1] [vid] [portMap] - set switch vlan vid elements \n", cmd);
+ printf(" [egtagPortMap] [ivl_en] [fid] [stag] \n");
+ printf(" 8.4) %s vlan pvid [port] [pvid] - set switch vlan pvid \n", cmd);
+ printf(" 8.5) %s vlan acc-frm [port] [acceptable_frame_type:0~3] - set switch vlan acceptable_frame type : admit all frames: 0, \n", cmd);
+ printf(" admit only vlan-taged frames: 1,admit only untagged or priority-tagged frames: 2, reserved:3 \n");
+ printf(" 8.6) %s vlan port-attr [port] [attr:0~3] - set switch vlan port attribute: user port: 0, statck port: 1, \n", cmd);
+ printf(" translation port: 2, transparent port:3 \n");
+ printf(" 8.7) %s vlan port-mode [port] [mode:0~3] - set switch vlan port mode : port matrix mode: 0, fallback mode: 1, \n", cmd);
+ printf(" check mode: 2, security mode:3 \n");
+ printf(" 8.8) %s vlan eg-tag-pvc [port] [eg_tag:0~7] - set switch vlan eg tag pvc : disable: 0, consistent: 1, reserved: 2, \n", cmd);
+ printf(" reserved:3,untagged:4,swap:5,tagged:6, stack:7 \n");
+ printf(" 8.9) %s vlan eg-tag-pcr [port] [eg_tag:0~3] - set switch vlan eg tag pcr : untagged: 0, swap: 1, tagged: 2, stack:3 \n", cmd);
+ printf(" \n");
+
+ /* 9. rate limit operations */
+ printf("9) mt753x switch rate limit operations=================================================================================================================>>>>\n");
+ printf(" 9.1) %s ratectl [in_ex_gress:0|1] [port] [rate] - set switch port ingress(1) or egress(0) rate \n", cmd);
+ printf(" 9.2) %s ingress-rate on [port] [Kbps] - set ingress rate limit on port n (n= 0~ switch max port) \n", cmd);
+ printf(" 9.3) %s egress-rate on [port] [Kbps] - set egress rate limit on port n (n= 0~ switch max port) \n", cmd);
+ printf(" 9.4) %s ingress-rate off [port] - disable ingress rate limit on port n (n= 0~ switch max port) \n", cmd);
+ printf(" 9.5) %s egress-rate off [port] - disable egress rate limit on port n (n= 0~ switch max port)\n", cmd);
+ printf(" \n");
+
+ /* 10. igmp operations */
+ printf("10) mt753x igmp operations===============================================================================================================================>>>>\n");
+ printf(" 10.1) %s igmpsnoop on [leaky_en] [wan_num] - turn on IGMP snoop and router port learning\n", cmd);
+ printf(" leaky_en: 1 or 0. default 0; wan_num: 0 or 4. default 4\n");
+ printf(" 10.2) %s igmpsnoop off - turn off IGMP snoop and router port learning\n", cmd);
+ printf(" 10.3) %s igmpsnoop enable [port#] - enable IGMP HW leave/join/Squery/Gquery\n", cmd);
+ printf(" 10.4) %s igmpsnoop disable [port#] - disable IGMP HW leave/join/Squery/Gquery\n", cmd);
+ printf(" \n");
+
+ /* 11. QoS operations */
+ printf("11) mt753x QoS operations================================================================================================================================>>>>\n");
+ printf(" 11.1) %s qos sch [port:0~6] [queue:0~7] [shaper:min|max] [type:rr:0|sp:1|wfq:2] - set switch qos sch type\n", cmd);
+ printf(" 11.2) %s qos base [port:0~6] [base] - set switch qos base(UPW); port-based:0, tag-based:1, \n", cmd);
+ printf(" dscp-based:2, acl-based:3, arl-based:4, stag-based:5 \n");
+ printf(" 11.3) %s qos port-weight [port:0~6] [q0] [q1][q2][q3] - set switch qos port queue weight; \n", cmd);
+ printf(" [q4][q5][q6][q7] [qn]: the weight of queue n, range: 1~16 \n");
+ printf(" 11.4) %s qos port-prio [port:0~6] [prio:0~7] - set switch port qos user priority; port is 0~6, priority is 0~7 \n", cmd);
+ printf(" 11.5) %s qos dscp-prio [dscp:0~63] [prio:0~7] - set switch qos dscp user priority; dscp is 0~63, priority is 0~7 \n", cmd);
+ printf(" 11.6) %s qos prio-qmap [port:0~6] [prio:0~7] [queue:0~7] - set switch qos priority queue map; priority is 0~7,queue is 0~7 \n", cmd);
+ printf(" \n");
+
+ /*12. port mirror operations*/
+ printf(" 12) mt753x port mirror operations========================================================================================================================>>>>\n");
+ printf(" 12.1) %s mirror monitor [port] - enable port mirror and indicate monitor port number\n", cmd);
+ printf(" 12.2) %s mirror target [port] - set port mirror target\n", cmd);
+ printf(" [direction| 0:off, 1:rx, 2:tx, 3:all] \n");
+ printf(" 12.3) %s mirror enable [mirror_en:0|1] [mirror_port: 0-6] - set switch mirror function enable(1) or disabled(0) for port 0~6 \n", cmd);
+ printf(" 12.4) %s mirror port-based [port] [port_tx_mir:0|1] - set switch mirror port: target tx/rx/acl/vlan/igmp\n", cmd);
+ printf(" [port_rx_mir:0|1] [acl_mir:0|1] \n");
+ printf(" [vlan_mis:0|1] [igmp_mir:0|1] \n");
+ printf(" \n");
+
+ /*13. stp function*/
+ printf(" 13) mt753x stp operations===============================================================================================================================>>>>\n");
+ printf(" 13.1) %s stp [port] [fid] [state] - set switch spanning tree state, port is 0~6, fid is 0~7, \n", cmd);
+ printf(" state is 0~3(Disable/Discarding:0,Blocking/Listening/Discarding:1,) \n");
+ printf(" Learning:2,Forwarding:3 \n");
+ printf(" \n");
+
+ /*14. collision pool operations*/
+ printf("14) mt753x collision pool operations========================================================================================================================>>>>\n");
+ printf(" 14.1) %s collision-pool enable [enable 0|1] - enable or disable collision pool\n", cmd);
+ printf(" 14.2) %s collision-pool mac dump - dump collision pool mac table\n", cmd);
+ printf(" 14.3) %s collision-pool dip dump - dump collision pool dip table\n", cmd);
+ printf(" 14.4) %s collision-pool sip dump - dump collision pool sip table\n", cmd);
+ printf(" \n");
+
+ /*15. pfc(priority flow control) operations*/
+ printf("15) mt753x pfc(priority flow control) operations==============================================================================================================>>>>\n");
+ printf(" 15.1) %s pfc enable [port] [enable 0|1] - enable or disable port's pfc \n", cmd);
+ printf(" 15.2) %s pfc rx_counter [port] - get port n pfc 8 up rx counter \n", cmd);
+ printf(" 15.3) %s pfc tx_counter [port] - get port n pfc 8 up rx counter \n", cmd);
+ printf(" \n");
+
+ exit_free();
+ exit(0);
+}
+
+static void parse_reg_cmd(int argc, char *argv[], int len)
+{
+ int off, val = -1;
+ int i, j;
+
+ if (!strncmp(argv[len - 3], "reg", 4)) {
+ if (argv[len - 2][0] == 'r') {
+ off = strtoul(argv[len - 1], NULL, 16);
+ reg_read(off, &val);
+ printf(" Read reg=%x, value=%x\n", off, val);
+ } else if (argv[len - 2][0] == 'w') {
+ off = strtoul(argv[len - 1], NULL, 16);
+ if (argc != len + 1)
+ usage(argv[0]);
+ val = strtoul(argv[len], NULL, 16);
+ reg_write(off, val);
+ printf(" Write reg=%x, value=%x\n", off, val);
+ } else if (argv[len - 2][0] == 'd') {
+ off = strtoul(argv[len - 1], NULL, 16);
+ for (i = 0; i < 16; i++) {
+ printf("0x%08x: ", off + 0x10 * i);
+ for (j = 0; j < 4; j++) {
+ reg_read(off + i * 0x10 + j * 0x4, &val);
+ printf(" 0x%08x", val);
+ }
+ printf("\n");
+ }
+ } else
+ usage(argv[0]);
+ } else
+ usage(argv[0]);
+}
+
+static int get_chip_name()
+{
+ int temp;
+ /*judge 7530*/
+ reg_read((0x7ffc), &temp);
+ temp = temp >> 16;
+ if (temp == 0x7530)
+ return temp;
+ /*judge 7531*/
+ reg_read(0x781c, &temp);
+ temp = temp >> 16;
+ if (temp == 0x7531)
+ return temp;
+ return -1;
+}
+
+static int phy_operate(int argc, char *argv[])
+{
+ char op;
+ int ret = 0;
+ int port_num, dev_num, reg, value=-1;
+
+ if (strncmp(argv[2], "cl22", 4) && strncmp(argv[2], "cl45", 4))
+ usage(argv[0]);
+
+ op = argv[3][0];
+
+ switch(op) {
+ case 'r':
+ reg = strtoul(argv[argc-1], NULL, 0);
+ if (argc == 6) {
+ port_num = strtoul(argv[argc-2], NULL, 0);
+ ret = mii_mgr_read(port_num, reg, &value);
+ if (value == -1)
+ printf(" Phy read reg fail\n");
+ else
+ printf(" Phy read reg=0x%x, value=0x%x\n", reg, value);
+ } else if (argc == 7) {
+ dev_num = strtoul(argv[argc-2], NULL, 0);
+ port_num = strtoul(argv[argc-3], NULL, 0);
+ ret = mii_mgr_c45_read(port_num, dev_num, reg, &value);
+ if (value == -1)
+ printf(" Phy read reg fail\n");
+ else
+ printf(" Phy read reg=0x%x, value=0x%x\n", reg, value);
+ } else
+ ret = phy_dump(32);
+ break;
+ case 'w':
+ reg = strtoul(argv[argc-2], NULL, 0);
+ value = strtoul(argv[argc-1], NULL, 0);
+ if (argc == 7) {
+ port_num = strtoul(argv[argc-3], NULL, 0);
+ ret = mii_mgr_write(port_num, reg, value);
+ }
+ else if (argc == 8) {
+ dev_num = strtoul(argv[argc-3], NULL, 0);
+ port_num = strtoul(argv[argc-4], NULL, 0);
+ ret = mii_mgr_c45_write(port_num, dev_num, reg, value);
+ }
+ else
+ usage(argv[0]);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int i, j;
+ int err;
+
+ attres = (struct mt753x_attr *)malloc(sizeof(struct mt753x_attr));
+ attres->dev_id = -1;
+ attres->port_num = -1;
+ attres->phy_dev = -1;
+ nl_init_flag = true;
+
+ switch_ioctl_init();
+ err = mt753x_netlink_init();
+ if (err < 0)
+ nl_init_flag = false;
+
+ chip_name = get_chip_name();
+ if (chip_name < 0) {
+ printf("no chip unsupport or chip id is invalid!\n");
+ exit_free();
+ exit(0);
+ }
+
+ if (argc < 2)
+ usage(argv[0]);
+
+ if (!strcmp(argv[1], "dev")) {
+ attres->dev_id = strtoul(argv[2], NULL, 0);
+ argv += 2;
+ argc -= 2;
+ if (argc < 2)
+ usage(argv[0]);
+
+ }
+
+ if (argc == 2) {
+ if (!strcmp(argv[1], "devs")) {
+ attres->type = MT753X_ATTR_TYPE_MESG;
+ mt753x_list_swdev(attres, MT753X_CMD_REQUEST);
+ } else if (!strncmp(argv[1], "dump", 5)) {
+ table_dump();
+ } else if (!strncmp(argv[1], "clear", 6)) {
+ table_clear();
+ printf("done.\n");
+ } else if (!strncmp(argv[1], "reset", 5)) {
+ switch_reset(argc, argv);
+ } else if (!strncmp(argv[1], "phy", 4)) {
+ phy_dump(32); //dump all phy register
+ } else if (!strncmp(argv[1], "sysctl", 7)) {
+ if (nl_init_flag)
+ printf("netlink(%s)\n",MT753X_GENL_NAME);
+ else
+ printf("ioctl(%s)\n",ETH_DEVNAME);
+ } else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "arl", 4)) {
+ if (!strncmp(argv[2], "aging", 6))
+ doArlAging(argc, argv);
+ } else if (!strncmp(argv[1], "esw_cnt", 8)) {
+ if (!strncmp(argv[2], "get", 4))
+ read_mib_counters();
+ else if (!strncmp(argv[2], "clear", 6))
+ clear_mib_counters();
+ else
+ usage(argv[0]);
+ }else if (!strncmp(argv[1], "output_queue_cnt", 17)) {
+ if (!strncmp(argv[2], "get", 4))
+ read_output_queue_counters();
+ else
+ usage(argv[0]);
+ }else if (!strncmp(argv[1], "free_page", 10)) {
+ if (!strncmp(argv[2], "get", 4))
+ read_free_page_counters();
+ else
+ usage(argv[0]);
+ }
+ else if (!strncmp(argv[1], "ratectl", 8))
+ rate_control(argc, argv);
+ else if (!strncmp(argv[1], "add", 4))
+ table_add(argc, argv);
+ else if (!strncmp(argv[1], "filt", 5))
+ table_add(argc, argv);
+ else if (!strncmp(argv[1], "del", 4)) {
+ if (!strncmp(argv[4], "fid", 4))
+ table_del_fid(argc, argv);
+ else if (!strncmp(argv[4], "vid", 4))
+ table_del_vid(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "search", 7)) {
+ if (!strncmp(argv[4], "fid", 4))
+ table_search_mac_fid(argc, argv);
+ else if (!strncmp(argv[4], "vid", 4))
+ table_search_mac_vid(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "phy", 4)) {
+ if (argc == 3) {
+ int phy_addr = strtoul(argv[2], NULL, 0);
+ if (phy_addr < 0 || phy_addr > 31)
+ usage(argv[0]);
+ phy_dump(phy_addr);
+ } else if (argc == 5) {
+ if (!strncmp(argv[2], "fc", 2))
+ phy_set_fc(argc, argv);
+ else if (!strncmp(argv[2], "an", 2))
+ phy_set_an(argc, argv);
+ else
+ phy_dump(32);
+ } else
+ phy_operate(argc, argv);
+ } else if (!strncmp(argv[1], "trreg", 4)) {
+ if (rw_phy_token_ring(argc, argv) < 0)
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "macctl", 7)) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (!strncmp(argv[2], "fc", 3))
+ global_set_mac_fc(argc, argv);
+ else if (!strncmp(argv[2], "pfc", 4))
+ set_mac_pfc(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "qos", 4)) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (!strncmp(argv[2], "sch", 4))
+ qos_sch_select(argc, argv);
+ else if (!strncmp(argv[2], "base", 5))
+ qos_set_base(argc, argv);
+ else if (!strncmp(argv[2], "port-weight", 12))
+ qos_wfq_set_weight(argc, argv);
+ else if (!strncmp(argv[2], "port-prio", 10))
+ qos_set_portpri(argc, argv);
+ else if (!strncmp(argv[2], "dscp-prio", 10))
+ qos_set_dscppri(argc, argv);
+ else if (!strncmp(argv[2], "prio-qmap", 10))
+ qos_pri_mapping_queue(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "stp", 3)) {
+ if (argc < 3)
+ usage(argv[0]);
+ else
+ doStp(argc, argv);
+ } else if (!strncmp(argv[1], "sip", 5)) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (!strncmp(argv[2], "dump", 5))
+ sip_dump();
+ else if (!strncmp(argv[2], "add", 4))
+ sip_add(argc, argv);
+ else if (!strncmp(argv[2], "del", 4))
+ sip_del(argc, argv);
+ else if (!strncmp(argv[2], "clear", 6))
+ sip_clear();
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "dip", 4)) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (!strncmp(argv[2], "dump", 5))
+ dip_dump();
+ else if (!strncmp(argv[2], "add", 4))
+ dip_add(argc, argv);
+ else if (!strncmp(argv[2], "del", 4))
+ dip_del(argc, argv);
+ else if (!strncmp(argv[2], "clear", 6))
+ dip_clear();
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "mirror", 7)) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (!strncmp(argv[2], "monitor", 8))
+ set_mirror_to(argc, argv);
+ else if (!strncmp(argv[2], "target", 7))
+ set_mirror_from(argc, argv);
+ else if (!strncmp(argv[2], "enable", 7))
+ doMirrorEn(argc, argv);
+ else if (!strncmp(argv[2], "port-based", 11))
+ doMirrorPortBased(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "acl", 4)) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (!strncmp(argv[2], "dip", 4)) {
+ if (!strncmp(argv[3], "add", 4))
+ acl_dip_add(argc, argv);
+ else if (!strncmp(argv[3], "modup", 6))
+ acl_dip_modify(argc, argv);
+ else if (!strncmp(argv[3], "pppoe", 6))
+ acl_dip_pppoe(argc, argv);
+ else if (!strncmp(argv[3], "trtcm", 4))
+ acl_dip_trtcm(argc, argv);
+ else if (!strncmp(argv[3], "meter", 6))
+ acl_dip_meter(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[2], "dmac", 6)) {
+ if (!strncmp(argv[3], "add", 4))
+ acl_mac_add(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[2], "etype", 6)) {
+ if (!strncmp(argv[3], "add", 4))
+ acl_ethertype(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[2], "port", 5)) {
+ if (!strncmp(argv[3], "add", 4))
+ acl_sp_add(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[2], "L4", 5)) {
+ if (!strncmp(argv[3], "add", 4))
+ acl_l4_add(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[2], "enable", 7))
+ acl_port_enable(argc, argv);
+ else if (!strncmp(argv[2], "acltbl-add", 11))
+ acl_table_add(argc, argv);
+ else if (!strncmp(argv[2], "masktbl-add", 12))
+ acl_mask_table_add(argc, argv);
+ else if (!strncmp(argv[2], "ruletbl-add", 12))
+ acl_rule_table_add(argc, argv);
+ else if (!strncmp(argv[2], "ratetbl-add", 12))
+ acl_rate_table_add(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "vlan", 5)) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (!strncmp(argv[2], "dump", 5))
+ vlan_dump();
+ else if (!strncmp(argv[2], "set", 4))
+ vlan_set(argc, argv);
+ else if (!strncmp(argv[2], "clear", 6))
+ vlan_clear(argc, argv);
+ else if (!strncmp(argv[2], "vid", 4))
+ doVlanSetVid(argc, argv);
+ else if (!strncmp(argv[2], "pvid", 5))
+ doVlanSetPvid(argc, argv);
+ else if (!strncmp(argv[2], "acc-frm", 8))
+ doVlanSetAccFrm(argc, argv);
+ else if (!strncmp(argv[2], "port-attr", 10))
+ doVlanSetPortAttr(argc, argv);
+ else if (!strncmp(argv[2], "port-mode", 10))
+ doVlanSetPortMode(argc, argv);
+ else if (!strncmp(argv[2], "eg-tag-pcr", 11))
+ doVlanSetEgressTagPCR(argc, argv);
+ else if (!strncmp(argv[2], "eg-tag-pvc", 11))
+ doVlanSetEgressTagPVC(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "reg", 4)) {
+ parse_reg_cmd(argc, argv, 4);
+ } else if (!strncmp(argv[1], "ingress-rate", 6)) {
+ int port = 0, bw = 0;
+ if (argv[2][1] == 'n') {
+ port = strtoul(argv[3], NULL, 0);
+ bw = strtoul(argv[4], NULL, 0);
+ if (ingress_rate_set(1, port, bw) == 0)
+ printf("switch port=%d, bw=%d\n", port, bw);
+ }
+ else if (argv[2][1] == 'f') {
+ if (argc != 4)
+ usage(argv[0]);
+ port = strtoul(argv[3], NULL, 0);
+ if (ingress_rate_set(0, port, bw) == 0)
+ printf("switch port=%d ingress rate limit off\n", port);
+ } else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "egress-rate", 6)) {
+ int port = 0, bw = 0;
+ if (argv[2][1] == 'n') {
+ port = strtoul(argv[3], NULL, 0);
+ bw = strtoul(argv[4], NULL, 0);
+ if (egress_rate_set(1, port, bw) == 0)
+ printf("switch port=%d, bw=%d\n", port, bw);
+ } else if (argv[2][1] == 'f') {
+ if (argc != 4)
+ usage(argv[0]);
+ port = strtoul(argv[3], NULL, 0);
+ if (egress_rate_set(0, port, bw) == 0)
+ printf("switch port=%d egress rate limit off\n", port);
+ } else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "igmpsnoop", 10)) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (!strncmp(argv[2], "on", 3))
+ igmp_on(argc, argv);
+ else if (!strncmp(argv[2], "off", 4))
+ igmp_off();
+ else if (!strncmp(argv[2], "enable", 7))
+ igmp_enable(argc, argv);
+ else if (!strncmp(argv[2], "disable", 8))
+ igmp_disable(argc, argv);
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "collision-pool", 15)) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (!strncmp(argv[2], "enable", 7))
+ collision_pool_enable(argc, argv);
+ else if (!strncmp(argv[2], "mac", 4)){
+ if (!strncmp(argv[3], "dump", 5))
+ collision_pool_mac_dump();
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[2], "dip", 4)){
+ if (!strncmp(argv[3], "dump", 5))
+ collision_pool_dip_dump();
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[2], "sip", 4)){
+ if (!strncmp(argv[3], "dump", 5))
+ collision_pool_sip_dump();
+ else
+ usage(argv[0]);
+ }
+ else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "pfc", 15)) {
+ if (argc < 4 || argc > 5)
+ usage(argv[0]);
+ if (!strncmp(argv[2], "enable", 7))
+ set_mac_pfc(argc, argv);
+ else if (!strncmp(argv[2], "rx_counter", 11)){
+ pfc_get_rx_counter(argc, argv);
+ } else if (!strncmp(argv[2], "tx_counter", 11)){
+ pfc_get_tx_counter(argc, argv);
+ } else
+ usage(argv[0]);
+ } else if (!strncmp(argv[1], "crossover", 10)) {
+ if (argc < 4)
+ usage(argv[0]);
+ else
+ phy_crossover(argc, argv);
+ } else
+ usage(argv[0]);
+
+ exit_free();
+ return 0;
+}
diff --git a/recipes-devtools/switch/files/switch_extend.h b/recipes-devtools/switch/files/switch_extend.h
new file mode 100644
index 0000000..8522424
--- /dev/null
+++ b/recipes-devtools/switch/files/switch_extend.h
@@ -0,0 +1,341 @@
+#define atoi(x) strtoul(x, NULL,10)
+
+#define EXTEND_SETVID_PARAM 1
+#define SQA_VERIFY 1
+#define ETHCMD_DBG 1
+#define ACTIVED (1<<0)
+#define SWITCH_MAX_PORT 7
+
+#define GENERAL_TABLE 0
+#define COLLISION_TABLE 1
+
+#define GSW_BASE 0x0
+#define GSW_ARL_BASE (GSW_BASE + 0x0000)
+#define GSW_BMU_BASE (GSW_BASE + 0x1000)
+#define GSW_PORT_BASE (GSW_BASE + 0x2000)
+#define GSW_MAC_BASE (GSW_BASE + 0x3000)
+#define GSW_MIB_BASE (GSW_BASE + 0x4000)
+#define GSW_CFG_BASE (GSW_BASE + 0x7000)
+
+#define GSW_PCR(n) (GSW_PORT_BASE + (n)*0x100 + 0x04)
+#define GSW_MFC (GSW_ARL_BASE + 0x10)
+#define GSW_UPW(n) (GSW_PORT_BASE + (n)*0x100 + 0x40)
+//#define GSW_PEM(n) (GSW_ARL_BASE + (n)*0x4 + 0x48)
+#define GSW_PEM(n) (GSW_PORT_BASE + (n)*0x4 + 0x44)
+
+#define GSW_MMSCR0_Q(n) (GSW_BMU_BASE + (n)*0x8)
+#define GSW_MMSCR1_Q(n) (GSW_BMU_BASE + (n)*0x8 + 0x04)
+
+#define GSW_PMCR(n) (GSW_MAC_BASE + (n)*0x100)
+#define GSW_PMSR(n) (GSW_MAC_BASE + (n)*0x100 + 0x08)
+#define GSW_PINT_EN(n) (GSW_MAC_BASE + (n)*0x100 + 0x10)
+#define GSW_SMACCR0 (GSW_MAC_BASE + 0xe4)
+#define GSW_SMACCR1 (GSW_MAC_BASE + 0xe8)
+#define GSW_CKGCR (GSW_MAC_BASE + 0xf0)
+
+#define GSW_ESR(n) (GSW_MIB_BASE + (n)*0x100 + 0x00)
+#define GSW_INTS(n) (GSW_MIB_BASE + (n)*0x100 + 0x04)
+#define GSW_TGPC(n) (GSW_MIB_BASE + (n)*0x100 + 0x10)
+#define GSW_TBOC(n) (GSW_MIB_BASE + (n)*0x100 + 0x14)
+#define GSW_TGOC(n) (GSW_MIB_BASE + (n)*0x100 + 0x18)
+#define GSW_TEPC(n) (GSW_MIB_BASE + (n)*0x100 + 0x1C)
+#define GSW_RGPC(n) (GSW_MIB_BASE + (n)*0x100 + 0x20)
+#define GSW_RBOC(n) (GSW_MIB_BASE + (n)*0x100 + 0x24)
+#define GSW_RGOC(n) (GSW_MIB_BASE + (n)*0x100 + 0x28)
+#define GSW_REPC1(n) (GSW_MIB_BASE + (n)*0x100 + 0x2C)
+#define GSW_REPC2(n) (GSW_MIB_BASE + (n)*0x100 + 0x30)
+#define GSW_MIBCNTEN (GSW_MIB_BASE + 0x800)
+#define GSW_AECNT1 (GSW_MIB_BASE + 0x804)
+#define GSW_AECNT2 (GSW_MIB_BASE + 0x808)
+
+#define GSW_CFG_PPSC (GSW_CFG_BASE + 0x0)
+#define GSW_CFG_PIAC (GSW_CFG_BASE + 0x4)
+#define GSW_CFG_GPC (GSW_CFG_BASE + 0x14)
+
+#define MAX_VID_VALUE (4095)
+#define MAX_VLAN_RULE (16)
+
+
+#define REG_MFC_ADDR (0x0010)
+#define REG_ISC_ADDR (0x0018)
+
+#define REG_CFC_ADDR (0x0004)
+#define REG_CFC_MIRROR_PORT_OFFT (16)
+#define REG_CFC_MIRROR_PORT_LENG (3)
+#define REG_CFC_MIRROR_PORT_RELMASK (0x00000007)
+#define REG_CFC_MIRROR_PORT_MASK (REG_CFC_MIRROR_PORT_RELMASK << REG_CFC_MIRROR_PORT_OFFT)
+#define REG_CFC_MIRROR_EN_OFFT (19)
+#define REG_CFC_MIRROR_EN_LENG (1)
+#define REG_CFC_MIRROR_EN_RELMASK (0x00000001)
+#define REG_CFC_MIRROR_EN_MASK (REG_CFC_MIRROR_EN_RELMASK << REG_CFC_MIRROR_EN_OFFT)
+
+#define REG_ATA1_ADDR (0x0074)
+#define REG_ATA2_ADDR (0x0078)
+
+#define REG_ATWD_ADDR (0x007C)
+#define REG_ATWD_STATUS_OFFT (2)
+#define REG_ATWD_STATUS_LENG (2)
+#define REG_ATWD_STATUS_RELMASK (0x00000003)
+#define REG_ATWD_STATUS_MASK (REG_ATWD_STATUS_RELMASK << REG_ATWD_STATUS_OFFT)
+#define REG_ATWD_PORT_OFFT (4)
+#define REG_ATWD_PORT_LENG (8)
+#define REG_ATWD_PORT_RELMASK (0x000000FF)
+#define REG_ATWD_PORT_MASK (REG_ATWD_PORT_RELMASK << REG_ATWD_PORT_OFFT)
+#define REG_ATWD_LEAKY_EN_OFFT (12)
+#define REG_ATWD_LEAKY_EN_LENG (1)
+#define REG_ATWD_LEAKY_EN_RELMASK (0x00000001)
+#define REG_ATWD_LEAKY_EN_MASK (REG_ATWD_LEAKY_EN_RELMASK << REG_ATWD_LEAKY_EN_OFFT)
+#define REG_ATWD_EG_TAG_OFFT (13)
+#define REG_ATWD_EG_TAG_LENG (3)
+#define REG_ATWD_EG_TAG_RELMASK (0x00000007)
+#define REG_ATWD_EG_TAG_MASK (REG_ATWD_EG_TAG_RELMASK << REG_ATWD_EG_TAG_OFFT)
+#define REG_ATWD_USR_PRI_OFFT (16)
+#define REG_ATWD_USR_PRI_LENG (3)
+#define REG_ATWD_USR_PRI_RELMASK (0x00000007)
+#define REG_ATWD_USR_PRI_MASK (REG_ATWD_USR_PRI_RELMASK << REG_ATWD_USR_PRI_OFFT)
+#define REG_ATWD_SA_MIR_EN_OFFT (19)
+#define REG_ATWD_SA_MIR_EN_LENG (1)
+#define REG_ATWD_SA_MIR_EN_RELMASK (0x00000001)
+#define REG_ATWD_SA_MIR_EN_MASK (REG_ATWD_SA_MIR_EN_RELMASK << REG_ATWD_SA_MIR_EN_OFFT)
+#define REG_ATWD_SA_PORT_FW_OFFT (20)
+#define REG_ATWD_SA_PORT_FW_LENG (3)
+#define REG_ATWD_SA_PORT_FW_RELMASK (0x00000007)
+#define REG_ATWD_SA_PORT_FW_MASK (REG_ATWD_SA_PORT_FW_RELMASK << REG_ATWD_SA_PORT_FW_OFFT)
+
+#define REG_ATC_ADDR (0x0080)
+#define REG_ATC_AC_CMD_OFFT (0)
+#define REG_ATC_AC_CMD_LENG (3)
+#define REG_ATC_AC_CMD_RELMASK (0x00000007)
+#define REG_ATC_AC_CMD_MASK (REG_ATC_AC_CMD_RELMASK << REG_ATC_AC_CMD_OFFT)
+#define REG_ATC_AC_SAT_OFFT (4)
+#define REG_ATC_AC_SAT_LENG (2)
+#define REG_ATC_AC_SAT_RELMASK (0x00000003)
+#define REG_ATC_AC_SAT_MASK (REG_ATC_AC_SAT_RELMASK << REG_ATC_AC_SAT_OFFT)
+#define REG_ATC_AC_MAT_OFFT (8)
+#define REG_ATC_AC_MAT_LENG (4)
+#define REG_ATC_AC_MAT_RELMASK (0x0000000F)
+#define REG_ATC_AC_MAT_MASK (REG_ATC_AC_MAT_RELMASK << REG_ATC_AC_MAT_OFFT)
+#define REG_AT_SRCH_HIT_OFFT (13)
+#define REG_AT_SRCH_HIT_RELMASK (0x00000001)
+#define REG_AT_SRCH_HIT_MASK (REG_AT_SRCH_HIT_RELMASK << REG_AT_SRCH_HIT_OFFT)
+#define REG_AT_SRCH_END_OFFT (14)
+#define REG_AT_SRCH_END_RELMASK (0x00000001)
+#define REG_AT_SRCH_END_MASK (REG_AT_SRCH_END_RELMASK << REG_AT_SRCH_END_OFFT)
+#define REG_ATC_BUSY_OFFT (15)
+#define REG_ATC_BUSY_LENG (1)
+#define REG_ATC_BUSY_RELMASK (0x00000001)
+#define REG_ATC_BUSY_MASK (REG_ATC_BUSY_RELMASK << REG_ATC_BUSY_OFFT)
+#define REG_AT_ADDR_OFFT (16)
+#define REG_AT_ADDR_LENG (12)
+#define REG_AT_ADDR_RELMASK (0x00000FFF)
+#define REG_AT_ADDR_MASK (REG_AT_ADDR_RELMASK << REG_AT_ADDR_OFFT)
+
+#define REG_TSRA1_ADDR (0x0084)
+#define REG_TSRA2_ADDR (0x0088)
+#define REG_ATRD_ADDR (0x008C)
+
+#define REG_VTCR_ADDR (0x0090)
+#define REG_VTCR_VID_OFFT (0)
+#define REG_VTCR_VID_LENG (12)
+#define REG_VTCR_VID_RELMASK (0x00000FFF)
+#define REG_VTCR_VID_MASK (REG_VTCR_VID_RELMASK << REG_VTCR_VID_OFFT)
+#define REG_VTCR_FUNC_OFFT (12)
+#define REG_VTCR_FUNC_LENG (4)
+#define REG_VTCR_FUNC_RELMASK (0x0000000F)
+#define REG_VTCR_FUNC_MASK (REG_VTCR_FUNC_RELMASK << REG_VTCR_FUNC_OFFT)
+#define REG_VTCR_IDX_INVLD_OFFT (16)
+#define REG_VTCR_IDX_INVLD_RELMASK (0x00000001)
+#define REG_VTCR_IDX_INVLD_MASK (REG_VTCR_IDX_INVLD_RELMASK << REG_VTCR_IDX_INVLD_OFFT)
+#define REG_VTCR_BUSY_OFFT (31)
+#define REG_VTCR_BUSY_RELMASK (0x00000001)
+#define REG_VTCR_BUSY_MASK (REG_VTCR_BUSY_RELMASK << REG_VTCR_BUSY_OFFT)
+
+#define REG_VAWD1_ADDR (0x0094)
+#define REG_VAWD2_ADDR (0x0098)
+#define REG_VLAN_ID_BASE (0x0100)
+
+#define REG_CPGC_ADDR (0xB0)
+#define REG_CPCG_COL_EN_OFFT (0)
+#define REG_CPCG_COL_EN_RELMASK (0x00000001)
+#define REG_CPCG_COL_EN_MASK (REG_CPCG_COL_EN_RELMASK << REG_CPCG_COL_EN_OFFT)
+#define REG_CPCG_COL_CLK_EN_OFFT (1)
+#define REG_CPCG_COL_CLK_EN_RELMASK (0x00000001)
+#define REG_CPCG_COL_CLK_EN_MASK (REG_CPCG_COL_CLK_EN_RELMASK << REG_CPCG_COL_CLK_EN_OFFT)
+#define REG_CPCG_COL_RST_N_OFFT (2)
+#define REG_CPCG_COL_RST_N_RELMASK (0x00000001)
+#define REG_CPCG_COL_RST_N_MASK (REG_CPCG_COL_RST_N_RELMASK << REG_CPCG_COL_RST_N_OFFT)
+
+#define REG_GFCCR0_ADDR (0x1FE0)
+#define REG_FC_EN_OFFT (31)
+#define REG_FC_EN_RELMASK (0x00000001)
+#define REG_FC_EN_MASK (REG_FC_EN_RELMASK << REG_FC_EN_OFFT)
+
+#define REG_PFC_CTRL_ADDR (0x30b0)
+#define PFC_RX_COUNTER_L(n) (0x3030 + (n)*0x100)
+#define PFC_RX_COUNTER_H(n) (0x3034 + (n)*0x100)
+#define PFC_TX_COUNTER_L(n) (0x3040 + (n)*0x100)
+#define PFC_TX_COUNTER_H(n) (0x3044 + (n)*0x100)
+#define PMSR_P(n) (0x3008 + (n)*0x100)
+
+
+#define REG_SSC_P0_ADDR (0x2000)
+
+#define REG_PCR_P0_ADDR (0x2004)
+#define REG_PCR_VLAN_MIS_OFFT (2)
+#define REG_PCR_VLAN_MIS_LENG (1)
+#define REG_PCR_VLAN_MIS_RELMASK (0x00000001)
+#define REG_PCR_VLAN_MIS_MASK (REG_PCR_VLAN_MIS_RELMASK << REG_PCR_VLAN_MIS_OFFT)
+#define REG_PCR_ACL_MIR_OFFT (7)
+#define REG_PCR_ACL_MIR_LENG (1)
+#define REG_PCR_ACL_MIR_RELMASK (0x00000001)
+#define REG_PCR_ACL_MIR_MASK (REG_PCR_ACL_MIR_RELMASK << REG_PCR_ACL_MIR_OFFT)
+#define REG_PORT_RX_MIR_OFFT (8)
+#define REG_PORT_RX_MIR_LENG (1)
+#define REG_PORT_RX_MIR_RELMASK (0x00000001)
+#define REG_PORT_RX_MIR_MASK (REG_PORT_RX_MIR_RELMASK << REG_PORT_RX_MIR_OFFT)
+#define REG_PORT_TX_MIR_OFFT (9)
+#define REG_PORT_TX_MIR_LENG (1)
+#define REG_PORT_TX_MIR_RELMASK (0x00000001)
+#define REG_PORT_TX_MIR_MASK (REG_PORT_TX_MIR_RELMASK << REG_PORT_TX_MIR_OFFT)
+#define REG_PORT_ACL_EN_OFFT (10)
+#define REG_PORT_ACL_EN_LENG (1)
+#define REG_PORT_ACL_EN_RELMASK (0x00000001)
+#define REG_PORT_ACL_EN_MASK (REG_PORT_ACL_EN_RELMASK << REG_PORT_ACL_EN_OFFT)
+#define REG_PCR_EG_TAG_OFFT (28)
+#define REG_PCR_EG_TAG_LENG (2)
+#define REG_PCR_EG_TAG_RELMASK (0x00000003)
+#define REG_PCR_EG_TAG_MASK (REG_PCR_EG_TAG_RELMASK << REG_PCR_EG_TAG_OFFT)
+
+#define REG_PIC_P0_ADDR (0x2008)
+#define REG_PIC_IGMP_MIR_OFFT (19)
+#define REG_PIC_IGMP_MIR_LENG (1)
+#define REG_PIC_IGMP_MIR_RELMASK (0x00000001)
+#define REG_PIC_IGMP_MIR_MASK (REG_PIC_IGMP_MIR_RELMASK << REG_PIC_IGMP_MIR_OFFT)
+
+#define REG_PSC_P0_ADDR (0x200C)
+
+#define REG_PVC_P0_ADDR (0x2010)
+#define REG_PVC_ACC_FRM_OFFT (0)
+#define REG_PVC_ACC_FRM_LENG (2)
+#define REG_PVC_ACC_FRM_RELMASK (0x00000003)
+#define REG_PVC_ACC_FRM_MASK (REG_PVC_ACC_FRM_RELMASK << REG_PVC_ACC_FRM_OFFT)
+#define REG_PVC_EG_TAG_OFFT (8)
+#define REG_PVC_EG_TAG_LENG (3)
+#define REG_PVC_EG_TAG_RELMASK (0x00000007)
+#define REG_PVC_EG_TAG_MASK (REG_PVC_EG_TAG_RELMASK << REG_PVC_EG_TAG_OFFT)
+
+#define REG_PPBV1_P0_ADDR (0x2014)
+#define REG_PPBV2_P0_ADDR (0x2018)
+#define REG_BSR_P0_ADDR (0x201C)
+#define REG_STAG01_P0_ADDR (0x2020)
+#define REG_STAG23_P0_ADDR (0x2024)
+#define REG_STAG45_P0_ADDR (0x2028)
+#define REG_STAG67_P0_ADDR (0x202C)
+
+#define REG_CMACCR_ADDR (0x30E0)
+#define REG_MTCC_LMT_OFFT (9)
+#define REG_MTCC_LMT_LENG (4)
+#define REG_MTCC_LMT_RELMASK (0x0000000F)
+#define REG_MTCC_LMT_MASK (REG_MTCC_LMT_RELMASK << REG_MTCC_LMT_OFFT)
+
+#define ETHCMD_ENABLE "enable"
+#define ETHCMD_DISABLE "disable"
+
+#define HELP_VLAN_PVID "vlan pvid <port> <pvid>"
+
+#if defined(EXTEND_SETVID_PARAM) || defined(SQA_VERIFY)
+#define HELP_VLAN_VID "vlan vid <index> <active:0|1> <vid> <portMap> <egtagPortMap>\n" \
+ " <ivl_en> <fid> <stag>\n"
+#else
+#define HELP_VLAN_VID "vlan vid <index> <active:0|1> <vid> <portMap> <tagPortMap>\n"
+#endif //SQA_VERIFY
+
+//#if defined(SQA_VERIFY)
+
+#define MT7530_UPW_REG_UPDATE 1
+
+#define HELP_QOS_TYPE "qos type <rr:0|sp:1|wfq:2>\n"
+#ifdef MT7530_UPW_REG_UPDATE
+#define HELP_QOS_BASE "qos base <port-based:0|tag-based:1|dscp-based:2|acl-based:3|arl-based:4|stag-based:5>\n"
+#else
+#define HELP_QOS_BASE "qos base <port-based:0|tag-based:1|dscp-based:2|acl-based:3|arl-based:4>\n"
+#endif
+#define HELP_QOS_PRIO_QMAP "qos prio-qmap <prio:0~7> <queue:0~7>\n"
+#define HELP_QOS_PRIO_TAGMAP "qos prio-tagmap <prio:0~7> <tag:0~7>\n"
+#define HELP_QOS_PRIO_DSCPMAP "qos prio-dscpmap <prio:0~7> <dscp:0~63>\n"
+//#define HELP_QOS_VPRI_QMAP "qos vprio-qmap <prio:0~7> <queue:0~7>\n"
+#define HELP_QOS_PORT_PRIO "qos port-prio <port> <prio:0~7>\n"
+#define HELP_QOS_PORT_WEIGHT "qos port-weight <port:0~7> <q0> <q1> <q2> <q3> <q4> <q5> <q6> <q7>\n" \
+ " <qn>: the weight of queue n, range: 1~16\n"
+#define HELP_QOS_DSCP_PRIO "qos dscp-prio <dscp:0~63> <prio:0~7> : for ingress\n"
+
+#define HELP_ARL_L2LEN_CHK "arl l2len-chk <active:0|1>\n"
+
+#define HELP_ARL_AGING "arl aging <active:0|1> <time:1~65536>\n"
+
+#define HELP_ARL_MAC_TBL_ADD "arl mactbl-add <MacAddr> <DestPortMap>\n"\
+ " ** optional : <leaky_en:0|1> <eg_tag:0~7> <usr_pri:0~7> <sa_mir_en:0|1> <sa_port_fw:0~7>\n"
+
+#define HELP_ARL_DIP_TBL_ADD "arl diptbl-add <DIP> <DestPortMap> <leaky_en:0|1> <eg_tag:0~7> <usr_pri:0~7> <status:0~3>\n"
+
+#define HELP_ARL_SIP_TBL_ADD "arl siptbl-add <DIP> <SIP> <DestPortMap> <status:0~3>\n"
+
+#define HELP_ACL_SETPORTEN "acl enable <port> <port_enable:0|1>\n"
+#define HELP_ACL_ACL_TBL_ADD "arl acltbl-add <tbl_idx:0~63/255> <vawd1> <vawd2>\n"
+#define HELP_ACL_MASK_TBL_ADD "arl masktbl-add <tbl_idx:0~31/127> <vawd1> <vawd2>\n"
+#define HELP_ACL_RULE_TBL_ADD "arl ruletbl-add <tbl_idx:0~31/127> <vawd1> <vawd2>\n"
+#define HELP_ACL_RATE_TBL_ADD "arl ratetbl-add <tbl_idx:0~31> <vawd1> <vawd2>\n"
+#define HELP_ACL_TRTCM_TBL_ADD "arl trTCMtbl-add <tbl_idx:0~31> <vawd1> <vawd2>\n"
+
+
+#define HELP_VLAN_PORT_MODE "vlan port-mode <port> <mode:0~3>\n" \
+ "<mode>: 0: port matrix mode\n" \
+ " 1: fallback mode\n" \
+ " 2: check mode\n" \
+ " 3: security mode\n"\
+
+#define HELP_VLAN_PORT_ATTR "vlan port-attr <port> <attr:0~3>\n" \
+ "<attr>: 0: user port\n" \
+ " 1: statck port\n" \
+ " 2: translation port\n" \
+ " 3: transparent port\n"
+
+#define HELP_VLAN_EGRESS_TAG_PVC "vlan eg-tag-pvc <port> <eg_tag:0~7>\n" \
+ "<eg_tag>: 0: disable\n" \
+ " 1: consistent\n" \
+ " 2: reserved\n" \
+ " 3: reserved\n" \
+ " 4: untagged\n" \
+ " 5: swap\n" \
+ " 6: tagged\n" \
+ " 7: stack\n"
+
+#define HELP_VLAN_EGRESS_TAG_PCR "vlan eg-tag-pcr <port> <eg_tag:0~3>\n" \
+ "<eg_tag>: 0: untagged\n" \
+ " 1: swap\n" \
+ " 2: tagged\n" \
+ " 3: stack\n"
+
+#define HELP_VLAN_ACC_FRM "vlan acc-frm <port> <acceptable_frame_type:0~3>\n" \
+ "<type>: 0: admit all frames\n" \
+ " 1: admit only vlan-taged frames\n" \
+ " 2: admit only untagged or priority-tagged frames\n" \
+ " 3: reserved\n"
+
+
+#define HELP_SWITCH_RESET "switch software reset\n"
+#define HELP_MACCTL_FC "macctl fc <enable:0|1>\n"
+#define HELP_MIRROR_EN "mirror enable <mirror_en:0|1> <mirror_port: 0-6>\n"
+#define HELP_MIRROR_PORTBASED "mirror port-based <port> <port_tx_mir:0|1> <port_rx_mir:0|1> <acl_mir:0|1> <vlan_mis:0|1> <igmp_mir:0|1>\n"
+
+#define HELP_PHY_AN_EN "phyctl an <port> <auto_negotiation_en:0|1>\n"
+#define HELP_PHY_FC_EN "phyctl fc <port> <full_duplex_pause_capable:0|1>\n"
+
+#define HELP_STP "stp <port> <fid> <state>\n" \
+ "<state>: 0: Disable/Discarding\n" \
+ " 1: Blocking/Listening/Discarding\n" \
+ " 2: Learning\n" \
+ " 3: Forwarding\n"
+#define HELP_COLLISION_POOL_EN "collision-pool enable [enable 0|1] \n"
+
+//#endif //SQA_VERIFY
diff --git a/recipes-devtools/switch/files/switch_fun.c b/recipes-devtools/switch/files/switch_fun.c
new file mode 100644
index 0000000..b37b850
--- /dev/null
+++ b/recipes-devtools/switch/files/switch_fun.c
@@ -0,0 +1,3631 @@
+/*
+* switch_fun.c: switch function sets
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <stdbool.h>
+#include <time.h>
+
+#include "switch_extend.h"
+#include "switch_netlink.h"
+#include "switch_ioctl.h"
+#include "switch_fun.h"
+
+#define leaky_bucket 0
+
+static int getnext(char *src, int separator, char *dest)
+{
+ char *c;
+ int len;
+
+ if ((src == NULL) || (dest == NULL))
+ return -1;
+
+ c = strchr(src, separator);
+ if (c == NULL) {
+ strcpy(dest, src);
+ return -1;
+ }
+
+ len = c - src;
+ strncpy(dest, src, len);
+ dest[len] = '\0';
+ return len + 1;
+}
+
+static int str_to_ip(unsigned int *ip, char *str)
+{
+ int i;
+ int len;
+ char *ptr = str;
+ char buf[128];
+ unsigned char c[4];
+
+ for (i = 0; i < 3; ++i) {
+ if ((len = getnext(ptr, '.', buf)) == -1)
+ return 1;
+ c[i] = atoi(buf);
+ ptr += len;
+ }
+ c[3] = atoi(ptr);
+ *ip = (c[0] << 24) + (c[1] << 16) + (c[2] << 8) + c[3];
+ return 0;
+}
+
+/*convert IP address from number to string */
+static void ip_to_str(char *str, unsigned int ip)
+{
+ unsigned char *ptr = (char *)&ip;
+ unsigned char c[4];
+
+ c[0] = *(ptr);
+ c[1] = *(ptr + 1);
+ c[2] = *(ptr + 2);
+ c[3] = *(ptr + 3);
+ /*sprintf(str, "%d.%d.%d.%d", c[0], c[1], c[2], c[3]);*/
+ sprintf(str, "%d.%d.%d.%d", c[3], c[2], c[1], c[0]);
+}
+
+int reg_read(int offset, int *value)
+{
+ int ret = -1;
+
+ if (nl_init_flag == true) {
+ ret = reg_read_netlink(attres, offset, value);
+ } else {
+ if (attres->dev_id == -1)
+ ret = reg_read_ioctl(offset, value);
+ }
+ if (ret < 0) {
+ printf("Read fail\n");
+ exit_free();
+ exit(0);
+ }
+
+ return 0;
+}
+
+int reg_write(int offset, int value)
+{
+ int ret = -1;
+
+ if (nl_init_flag == true) {
+ ret = reg_write_netlink(attres, offset, value);
+ } else {
+ if (attres->dev_id == -1)
+ ret = reg_write_ioctl(offset, value);
+ }
+ if (ret < 0) {
+ printf("Write fail\n");
+ exit_free();
+ exit(0);
+ }
+ return 0;
+}
+
+int mii_mgr_read(unsigned int port_num, unsigned int reg, int *value)
+{
+ int ret = -1;
+
+ if (port_num > 31 || port_num < 0) {
+ printf("Invalid Port or PHY addr \n");
+ return -1;
+ }
+
+ if (nl_init_flag == true)
+ ret = phy_cl22_read_netlink(attres, port_num, reg, value);
+ else
+ ret = mii_mgr_cl22_read_ioctl(port_num, reg, value);
+
+ if (ret < 0) {
+ printf("Phy read fail\n");
+ exit_free();
+ exit(0);
+ }
+
+ return 0;
+}
+
+int mii_mgr_write(unsigned int port_num, unsigned int reg, unsigned int value)
+{
+ int ret = -1;
+
+ if (port_num > 31 || port_num < 0) {
+ printf("Invalid Port or PHY addr \n");
+ return -1;
+ }
+
+ if (nl_init_flag == true)
+ ret = phy_cl22_write_netlink(attres, port_num, reg, value);
+ else
+ ret = mii_mgr_cl22_write_ioctl(port_num, reg, value);
+
+ if (ret < 0) {
+ printf("Phy write fail\n");
+ exit_free();
+ exit(0);
+ }
+
+ return 0;
+}
+
+int mii_mgr_c45_read(unsigned int port_num, unsigned int dev, unsigned int reg, int *value)
+{
+ int ret = -1;
+
+ if (port_num > 31 || port_num < 0) {
+ printf("Invalid Port or PHY addr \n");
+ return -1;
+ }
+
+ if (nl_init_flag == true)
+ ret = phy_cl45_read_netlink(attres, port_num, dev, reg, value);
+ else
+ ret = mii_mgr_cl45_read_ioctl(port_num, dev, reg, value);
+
+ if (ret < 0) {
+ printf("Phy read fail\n");
+ exit_free();
+ exit(0);
+ }
+
+ return 0;
+}
+
+int mii_mgr_c45_write(unsigned int port_num, unsigned int dev, unsigned int reg, unsigned int value)
+{
+ int ret = -1;
+
+ if (port_num > 31 || port_num < 0) {
+ printf("Invalid Port or PHY addr \n");
+ return -1;
+ }
+
+ if (nl_init_flag == true)
+ ret = phy_cl45_write_netlink(attres, port_num, dev, reg, value);
+ else
+ ret = mii_mgr_cl45_write_ioctl(port_num, dev, reg, value);
+
+ if (ret < 0) {
+ printf("Phy write fail\n");
+ exit_free();
+ exit(0);
+ }
+ return 0;
+}
+
+
+int phy_dump(int phy_addr)
+{
+ int ret = -1;
+
+ if (nl_init_flag == true)
+ ret = phy_dump_netlink(attres, phy_addr);
+ else
+ ret = phy_dump_ioctl(phy_addr);
+
+ if (ret < 0) {
+ printf("Phy dump fail\n");
+ exit_free();
+ exit(0);
+ }
+
+ return 0;
+}
+
+void phy_crossover(int argc, char *argv[])
+{
+ int port_num = strtoul(argv[2], NULL, 10);
+ int value;
+ int ret = -1;
+
+ if ((port_num < 0) || (port_num > 4))
+ {
+ printf("invaild value, port_name:0~4\n");
+ return;
+ }
+
+ if (nl_init_flag == true)
+ ret = phy_cl45_read_netlink(attres, port_num, 0x1E, MT7530_T10_TEST_CONTROL, &value);
+ else
+ ret = mii_mgr_cl45_read_ioctl(port_num, 0x1E, MT7530_T10_TEST_CONTROL, &value);
+ if (ret < 0) {
+ printf("phy_cl45 read fail\n");
+ exit_free();
+ exit(0);
+ }
+
+ printf("mii_mgr_cl45:");
+ printf("Read: port#=%d, device=0x%x, reg=0x%x, value=0x%x\n", port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+
+ if (!strncmp(argv[3], "auto", 5))
+ {
+ value &= (~(0x3 << 3));
+ } else if (!strncmp(argv[3], "mdi", 4)) {
+ value &= (~(0x3 << 3));
+ value |= (0x2 << 3);
+ } else if (!strncmp(argv[3], "mdix", 5)) {
+ value |= (0x3 << 3);
+ } else {
+ printf("invaild parameter\n");
+ return;
+ }
+ printf("Write: port#=%d, device=0x%x, reg=0x%x. value=0x%x\n", port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+
+ if (nl_init_flag == true)
+ ret = phy_cl45_write_netlink(attres, port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+ else
+ ret = mii_mgr_cl45_write_ioctl(port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+
+ if (ret < 0) {
+ printf("phy_cl45 write fail\n");
+ exit_free();
+ exit(0);
+ }
+}
+
+int rw_phy_token_ring(int argc, char *argv[])
+{
+ int port_num, ch_addr, node_addr, data_addr,val_l=0;
+ int Tr_reg_control, val_h = 0;
+
+ if (argc < 4)
+ return -1;
+
+ if (argv[2][0] == 'r') {
+ if (argc != 7)
+ return -1;
+ mii_mgr_write(0, 0x1f, 0x52b5); // r31 = 0x52b5
+ port_num = strtoul(argv[3], NULL, 0);
+ if (port_num < 0 || port_num > MAX_PORT) {
+ printf("Illegal port index and port:0~6\n");
+ return -1;
+ }
+ ch_addr = strtoul(argv[4], NULL, 0);
+ node_addr = strtoul(argv[5], NULL, 0);
+ data_addr = strtoul(argv[6], NULL, 0);
+ printf("port = %x, ch_addr = %x, node_addr=%x, data_addr=%x\n", port_num, ch_addr, node_addr, data_addr);
+ Tr_reg_control = (1 << 15) | (1 << 13) | (ch_addr << 11) | (node_addr << 7) | (data_addr << 1);
+ mii_mgr_write(port_num, 16, Tr_reg_control); // r16 = Tr_reg_control
+ mii_mgr_read(port_num, 17, &val_l);
+ mii_mgr_read(port_num, 18, &val_h);
+ printf("switch trreg read Tr_reg_control=%x, value_H=%x, value_L=%x\n", Tr_reg_control, val_h, val_l);
+ } else if (argv[2][0] == 'w') {
+ if (argc != 9)
+ return -1;
+ mii_mgr_write(0, 0x1f, 0x52b5); // r31 = 0x52b5
+ port_num = strtoul(argv[3], NULL, 0);
+ if (port_num < 0 || port_num > MAX_PORT) {
+ printf("\n**Illegal port index and port:0~6\n");
+ return -1;
+ }
+ ch_addr = strtoul(argv[4], NULL, 0);
+ node_addr = strtoul(argv[5], NULL, 0);
+ data_addr = strtoul(argv[6], NULL, 0);
+ val_h = strtoul(argv[7], NULL, 0);
+ val_l = strtoul(argv[8], NULL, 0);
+ printf("port = %x, ch_addr = %x, node_addr=%x, data_addr=%x\n", port_num, ch_addr, node_addr, data_addr);
+ Tr_reg_control = (1 << 15) | (0 << 13) | (ch_addr << 11) | (node_addr << 7) | (data_addr << 1);
+ mii_mgr_write(port_num, 17, val_l);
+ mii_mgr_write(port_num, 18, val_h);
+ mii_mgr_write(port_num, 16, Tr_reg_control); // r16 = Tr_reg_control
+ printf("switch trreg Write Tr_reg_control=%x, value_H=%x, value_L=%x\n", Tr_reg_control, val_h, val_l);
+ } else
+ return -1;
+ return 0;
+}
+
+void write_acl_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+{
+ unsigned int value, reg;
+ unsigned int max_index;
+
+ if (chip_name == 0x7531)
+ max_index = 256;
+ else
+ max_index = 64;
+
+ printf("Pattern_acl_tbl_idx:%d\n", tbl_idx);
+
+ if (tbl_idx >= max_index) {
+ printf(HELP_ACL_ACL_TBL_ADD);
+ return;
+ }
+
+ reg = REG_VTCR_ADDR;
+ while (1)
+ { // wait until not busy
+ reg_read(reg, &value);
+ if ((value & REG_VTCR_BUSY_MASK) == 0) {
+ break;
+ }
+ }
+ reg_write(REG_VAWD1_ADDR, vawd1);
+ printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
+ reg_write(REG_VAWD2_ADDR, vawd2);
+ printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
+ reg = REG_VTCR_ADDR;
+ value = REG_VTCR_BUSY_MASK | (0x05 << REG_VTCR_FUNC_OFFT) | tbl_idx;
+ reg_write(reg, value);
+ printf("write reg: %x, value: %x\n", reg, value);
+
+ while (1)
+ { // wait until not busy
+ reg_read(reg, &value);
+ if ((value & REG_VTCR_BUSY_MASK) == 0)
+ break;
+ }
+}
+
+void acl_table_add(int argc, char *argv[])
+{
+ unsigned int vawd1, vawd2;
+ unsigned char tbl_idx;
+
+ tbl_idx = atoi(argv[3]);
+ vawd1 = strtoul(argv[4], (char **)NULL, 16);
+ vawd2 = strtoul(argv[5], (char **)NULL, 16);
+ write_acl_table(tbl_idx, vawd1, vawd2);
+}
+
+void write_acl_mask_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+{
+ unsigned int value, reg;
+ unsigned int max_index;
+
+ if (chip_name == 0x7531)
+ max_index = 128;
+ else
+ max_index = 32;
+
+ printf("Rule_mask_tbl_idx:%d\n", tbl_idx);
+
+ if (tbl_idx >= max_index) {
+ printf(HELP_ACL_MASK_TBL_ADD);
+ return;
+ }
+ reg = REG_VTCR_ADDR;
+ while (1)
+ { // wait until not busy
+ reg_read(reg, &value);
+ if ((value & REG_VTCR_BUSY_MASK) == 0)
+ break;
+ }
+ reg_write(REG_VAWD1_ADDR, vawd1);
+ printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
+ reg_write(REG_VAWD2_ADDR, vawd2);
+ printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
+ reg = REG_VTCR_ADDR;
+ value = REG_VTCR_BUSY_MASK | (0x09 << REG_VTCR_FUNC_OFFT) | tbl_idx;
+ reg_write(reg, value);
+ printf("write reg: %x, value: %x\n", reg, value);
+ while (1)
+ { // wait until not busy
+ reg_read(reg, &value);
+ if ((value & REG_VTCR_BUSY_MASK) == 0)
+ break;
+ }
+}
+
+void acl_mask_table_add(int argc, char *argv[])
+{
+ unsigned int vawd1, vawd2;
+ unsigned char tbl_idx;
+
+ tbl_idx = atoi(argv[3]);
+ vawd1 = strtoul(argv[4], (char **)NULL, 16);
+ vawd2 = strtoul(argv[5], (char **)NULL, 16);
+ write_acl_mask_table(tbl_idx, vawd1, vawd2);
+}
+
+void write_acl_rule_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+{
+ unsigned int value, reg;
+ unsigned int max_index;
+
+ if (chip_name == 0x7531)
+ max_index = 128;
+ else
+ max_index = 32;
+
+ printf("Rule_control_tbl_idx:%d\n", tbl_idx);
+
+ if (tbl_idx >= max_index) { /*Check the input parameters is right or not.*/
+ printf(HELP_ACL_RULE_TBL_ADD);
+ return;
+ }
+ reg = REG_VTCR_ADDR;
+
+ while (1)
+ { // wait until not busy
+ reg_read(reg, &value);
+ if ((value & REG_VTCR_BUSY_MASK) == 0) {
+ break;
+ }
+ }
+ reg_write(REG_VAWD1_ADDR, vawd1);
+ printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
+ reg_write(REG_VAWD2_ADDR, vawd2);
+ printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
+ reg = REG_VTCR_ADDR;
+ value = REG_VTCR_BUSY_MASK | (0x0B << REG_VTCR_FUNC_OFFT) | tbl_idx;
+ reg_write(reg, value);
+ printf("write reg: %x, value: %x\n", reg, value);
+
+ while (1)
+ { // wait until not busy
+ reg_read(reg, &value);
+ if ((value & REG_VTCR_BUSY_MASK) == 0) {
+ break;
+ }
+ }
+}
+
+void acl_rule_table_add(int argc, char *argv[])
+{
+ unsigned int vawd1, vawd2;
+ unsigned char tbl_idx;
+
+ tbl_idx = atoi(argv[3]);
+ vawd1 = strtoul(argv[4], (char **)NULL, 16);
+ vawd2 = strtoul(argv[5], (char **)NULL, 16);
+ write_acl_rule_table(tbl_idx, vawd1, vawd2);
+}
+
+void write_rate_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+{
+ unsigned int value, reg;
+ unsigned int max_index = 32;
+
+ printf("Rule_action_tbl_idx:%d\n", tbl_idx);
+
+ if (tbl_idx >= max_index) {
+ printf(HELP_ACL_RATE_TBL_ADD);
+ return;
+ }
+
+ reg = REG_VTCR_ADDR;
+ while (1) { // wait until not busy
+ reg_read(reg, &value);
+ if ((value & REG_VTCR_BUSY_MASK) == 0)
+ break;
+ }
+
+ reg_write(REG_VAWD1_ADDR, vawd1);
+ printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
+ reg_write(REG_VAWD2_ADDR, vawd2);
+ printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
+ reg = REG_VTCR_ADDR;
+ value = REG_VTCR_BUSY_MASK | (0x0D << REG_VTCR_FUNC_OFFT) | tbl_idx;
+ reg_write(reg, value);
+ printf("write reg: %x, value: %x\n", reg, value);
+
+ while (1) { // wait until not busy
+ reg_read(reg, &value);
+ if ((value & REG_VTCR_BUSY_MASK) == 0)
+ break;
+ }
+}
+
+void acl_rate_table_add(int argc, char *argv[])
+{
+ unsigned int vawd1, vawd2;
+ unsigned char tbl_idx;
+
+ tbl_idx = atoi(argv[3]);
+ vawd1 = strtoul(argv[4], (char **)NULL, 16);
+ vawd2 = strtoul(argv[5], (char **)NULL, 16);
+
+ write_rate_table(tbl_idx, vawd1, vawd2);
+}
+
+void write_trTCM_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+{
+ unsigned int value, reg;
+ unsigned int max_index = 32;
+
+ printf("trTCM_tbl_idx:%d\n", tbl_idx);
+
+ if (tbl_idx >= max_index) {
+ printf(HELP_ACL_TRTCM_TBL_ADD);
+ return;
+ }
+
+ reg = REG_VTCR_ADDR;
+ while (1) { // wait until not busy
+ reg_read(reg, &value);
+ if ((value & REG_VTCR_BUSY_MASK) == 0)
+ break;
+ }
+
+ reg_write(REG_VAWD1_ADDR, vawd1);
+ printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
+ reg_write(REG_VAWD2_ADDR, vawd2);
+ printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
+ reg = REG_VTCR_ADDR;
+ value = REG_VTCR_BUSY_MASK | (0x07 << REG_VTCR_FUNC_OFFT) | tbl_idx;
+ reg_write(reg, value);
+ printf("write reg: %x, value: %x\n", reg, value);
+
+ while (1) { // wait until not busy
+ reg_read(reg, &value);
+ if ((value & REG_VTCR_BUSY_MASK) == 0)
+ break;
+ }
+}
+
+int acl_parameters_pre_del(int len1, int len2, int argc, char *argv[], int *port)
+{
+ int i;
+ int ret = 0;
+ *port = 0;
+ if (argc < len1) {
+ printf("insufficient arguments!\n");
+ return -1;
+ }
+
+ if (len2 == 12)
+ {
+ if (!argv[4] || strlen(argv[4]) != len2) {
+ printf("The [%s] format error, should be of length %d\n",argv[4], len2);
+ return -1;
+ }
+ }
+
+ if (!argv[5] || strlen(argv[5]) != 8) {
+ printf("portsmap format error, should be of length 7\n");
+ return -1;
+ }
+
+ for (i = 0; i < 7; i++) {
+ if (argv[5][i] != '0' && argv[5][i] != '1') {
+ printf("portmap format error, should be of combination of 0 or 1\n");
+ return -1;
+ }
+ *port += (argv[5][i] - '0') * (1 << i);
+ }
+}
+
+void acl_compare_pattern(int ports, int comparion, int base, int word, unsigned char table_index)
+{
+ unsigned int value;
+
+ comparion |= 0xffff0000; //compare mask
+
+ value = ports << 8; //w_port_map
+ value |= 0x1 << 19; //enable
+ value |= base << 16; //mac header
+ value |= word << 1; //word offset
+
+ write_acl_table(table_index, comparion, value);
+}
+
+void acl_mac_add(int argc, char *argv[])
+{
+ unsigned int i, value, mac;
+ int ports;
+ char tmpstr[5];
+ int ret;
+
+ ret = acl_parameters_pre_del(6, 12, argc, argv, &ports);
+ if (ret < 0)
+ return;
+ //set pattern
+ strncpy(tmpstr, argv[4], 4);
+ tmpstr[4] = '\0';
+ value = strtoul(tmpstr, NULL, 16);
+ acl_compare_pattern(ports, value, 0x0, 0, 0);
+
+ strncpy(tmpstr, argv[4] + 4, 4);
+ tmpstr[4] = '\0';
+ value = strtoul(tmpstr, NULL, 16);
+ acl_compare_pattern(ports, value, 0x0, 1, 1);
+
+ strncpy(tmpstr, argv[4] + 8, 4);
+ tmpstr[4] = '\0';
+ value = strtoul(tmpstr, NULL, 16);
+ acl_compare_pattern(ports, value, 0x0, 2, 2);
+
+ //set mask
+ write_acl_mask_table(0,0x7,0);
+
+ //set action
+ value = 0x7; //drop
+ value |= 1 << 28; //acl intterupt enable
+ value |= 1 << 27; //acl hit count
+ value |= 2 << 24; //acl hit count group index (0~3)
+ write_acl_rule_table(0,value,0);
+}
+
+void acl_dip_meter(int argc, char *argv[])
+{
+ unsigned int i, value, ip_value, meter;
+ unsigned int idx, vid;
+ int stag = 0;
+ int ports;
+ char tmpstr[16];
+ int ret;
+
+ ret = acl_parameters_pre_del(7, -1, argc, argv, &ports);
+ if (ret < 0)
+ return;
+
+ str_to_ip(&ip_value, argv[4]);
+ //set pattern
+ value = (ip_value >> 16);
+ acl_compare_pattern(ports, value, 0x2, 0x8, 0);
+
+ //set pattern
+ value = (ip_value & 0xffff);
+ acl_compare_pattern(ports, value, 0x2, 0x9, 1);
+
+ //set mask
+ write_acl_mask_table(0,0x3,0);
+
+ //set action
+ meter = strtoul(argv[6], NULL, 0);
+ if (meter < 0 || ((chip_name == 0x7530) && (meter > 1000000)) ||
+ ((chip_name == 0x7531) && (meter > 2500000))) {
+ printf("\n**Illegal meter input, and 7530: 0~1000000Kpbs, 7531: 0~2500000Kpbs**\n");
+ return;
+ }
+ if (((chip_name == 0x7531) && (meter > 1000000))) {
+ reg_read(0xc,&value);
+ value |= 0x1 << 30;
+ reg_write(0xC,value);
+ printf("AGC: 0x%x\n",value);
+ value = meter / 1000; //uint is 1Mbps
+ } else {
+ reg_read(0xc,&value);
+ value &= ~(0x1 << 30);
+ reg_write(0xC,value);
+ printf("AGC: 0x%x\n",value);
+ value = meter >> 6; //uint is 64Kbps
+ }
+ value |= 0x1 << 15; //enable rate control
+ printf("Acl rate control:0x%x\n",value);
+ write_rate_table(0, value, 0);
+}
+
+void acl_dip_trtcm(int argc, char *argv[])
+{
+ unsigned int i, value, value2, ip_value;
+ unsigned int idx, vid;
+ unsigned int CIR, CBS, PIR, PBS;
+ int stag = 0;
+ int ports;
+ char tmpstr[16];
+ int ret;
+
+ ret = acl_parameters_pre_del(10, -1, argc, argv, &ports);
+ if (ret < 0)
+ return;
+
+ str_to_ip(&ip_value, argv[4]);
+ //set pattern
+ value = (ip_value >> 16);
+ acl_compare_pattern(ports, value, 0x2, 0x8, 0);
+
+ //set pattern
+ value = (ip_value & 0xffff);
+ acl_compare_pattern(ports, value, 0x2, 0x9, 1);
+
+ //set CBS PBS
+ CIR = strtoul(argv[6], NULL, 0);
+ CBS = strtoul(argv[7], NULL, 0);
+ PIR = strtoul(argv[8], NULL, 0);
+ PBS = strtoul(argv[9], NULL, 0);
+
+ if (CIR < 0 || CBS < 0 || PIR < 0 || PBS < 0 ||
+ CIR > 65535*64 || CBS > 65535 || PIR > 65535*64 || PBS > 65535) {
+ printf("\n**Illegal input parameters**\n");
+ return;
+ }
+
+ value = CBS << 16; //bit16~31
+ value |= PBS; //bit0~15
+ //value |= 1;//valid
+ CIR = CIR >> 6;
+ PIR = PIR >> 6;
+
+ value2 = CIR << 16; //bit16~31
+ value2 |= PIR; //bit0~15
+ write_trTCM_table(0,value,value2);
+
+ //set pattern
+ write_acl_mask_table(0,0x3,0);
+
+ //set action
+ value = 0x1 << (11 + 1); //TrTCM green meter#0 Low drop
+ value |= 0x2 << (8 + 1); //TrTCM yellow meter#0 Med drop
+ value |= 0x3 << (5 + 1); //TrTCM red meter#0 Hig drop
+ value |= 0x1 << 0; //TrTCM drop pcd select
+ write_acl_rule_table(0,0,value);
+}
+
+void acl_ethertype(int argc, char *argv[])
+{
+ unsigned int i, value, ethertype;
+ unsigned int idx, vid;
+ int stag = 0;
+ int ports;
+ char tmpstr[16];
+ int ret;
+
+ ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+ if (ret < 0)
+ return;
+ printf("ports:0x%x\n",ports);
+ ethertype = strtoul(argv[4], NULL, 16);
+ //set pattern
+ value = ethertype;
+ acl_compare_pattern(ports, value, 0x0, 0x6, 0);
+
+ //set pattern
+ write_acl_mask_table(0,0x1,0);
+
+ //set action(drop)
+ value = 0x7; //default. Nodrop
+ value |= 1 << 28; //acl intterupt enable
+ value |= 1 << 27; //acl hit count
+
+ write_acl_rule_table(0,value,0);
+}
+
+void acl_dip_modify(int argc, char *argv[])
+{
+ unsigned int i, value, ip_value;
+ unsigned int idx, vid;
+ int stag = 0;
+ int ports;
+ int priority;
+ char tmpstr[16];
+ int ret;
+
+ priority = strtoul(argv[6], NULL, 16);
+ if (priority < 0 || priority > 7) {
+ printf("\n**Illegal priority value!**\n");
+ return;
+ }
+
+ ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+ if (ret < 0)
+ return;
+
+ str_to_ip(&ip_value, argv[4]);
+ //set pattern
+ value = (ip_value >> 16);
+ acl_compare_pattern(ports, value, 0x2, 0x8, 0);
+
+ //set pattern
+ value = (ip_value & 0xffff);
+ acl_compare_pattern(ports, value, 0x2, 0x9, 1);
+
+ //set pattern
+ write_acl_mask_table(0,0x3,0);
+
+ //set action
+ value = 0x0; //default. Nodrop
+ value |= 1 << 28; //acl intterupt enable
+ value |= 1 << 27; //acl hit count
+ value |= priority << 4; //acl UP
+ write_acl_rule_table(0,value,0);
+}
+
+void acl_dip_pppoe(int argc, char *argv[])
+{
+ unsigned int i, value, ip_value;
+ unsigned int idx, vid;
+ int stag = 0;
+ int ports;
+ char tmpstr[16];
+ int ret;
+
+ ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+ if (ret < 0)
+ return;
+
+ str_to_ip(&ip_value, argv[4]);
+ //set pattern
+ value = (ip_value >> 16);
+ acl_compare_pattern(ports, value, 0x2, 0x8, 0);
+
+ //set pattern
+ value = (ip_value & 0xffff);
+ acl_compare_pattern(ports, value, 0x2, 0x9, 1);
+
+ //set pattern
+ write_acl_mask_table(0,0x3,0);
+
+ //set action
+ value = 0x0; //default. Nodrop
+ value |= 1 << 28; //acl intterupt enable
+ value |= 1 << 27; //acl hit count
+ value |= 1 << 20; //pppoe header remove
+ value |= 1 << 21; //SA MAC SWAP
+ value |= 1 << 22; //DA MAC SWAP
+ write_acl_rule_table(0,value,7);
+}
+
+void acl_dip_add(int argc, char *argv[])
+{
+ unsigned int i, value, ip_value;
+ unsigned int idx, vid;
+ int ports;
+ int stag = 0;
+ char tmpstr[16];
+ int ret;
+
+ ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+ if (ret < 0)
+ return;
+
+ str_to_ip(&ip_value, argv[4]);
+ //set pattern
+ value = (ip_value >> 16);
+ acl_compare_pattern(ports, value, 0x2, 0x8, 0);
+
+ //set pattern
+ value = (ip_value & 0xffff);
+ acl_compare_pattern(ports, value, 0x2, 0x9, 1);
+
+ //set pattern
+ write_acl_mask_table(0,0x3,0);
+
+ //set action
+ //value = 0x0; //default
+ value = 0x7; //drop
+ value |= 1 << 28; //acl intterupt enable
+ value |= 1 << 27; //acl hit count
+ value |= 2 << 24; //acl hit count group index (0~3)
+ write_acl_rule_table(0,value,0);
+}
+
+void acl_l4_add(int argc, char *argv[])
+{
+ unsigned int i, value;
+ unsigned int idx, vid;
+ int ports;
+ int stag = 0;
+ char tmpstr[16];
+ int ret;
+
+ ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+ if (ret < 0)
+ return;
+
+ //set pattern
+ value = strtoul(argv[4], NULL, 16);
+ acl_compare_pattern(ports, value, 0x5, 0x0, 0);
+
+ //set rue mask
+ write_acl_mask_table(0,0x1,0);
+ //set action
+ value = 0x7; //drop
+ //value |= 1;//valid
+ write_acl_rule_table(0,value,0);
+}
+
+void acl_sp_add(int argc, char *argv[])
+{
+ unsigned int i, value;
+ unsigned int idx, vid;
+ int ports;
+ int stag = 0;
+ char tmpstr[16];
+ int ret;
+
+ ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+ if (ret < 0)
+ return;
+ //set pattern
+ value = strtoul(argv[4], NULL, 0);
+ acl_compare_pattern(ports, value, 0x4, 0x0, 0);
+
+ //set rue mask
+ write_acl_mask_table(0,0x1,0);
+
+ //set action
+ value = 0x7; //drop
+ //value |= 1;//valid
+ write_acl_rule_table(0,value,0);
+}
+
+void acl_port_enable(int argc, char *argv[])
+{
+ unsigned int value, reg;
+ unsigned char acl_port, acl_en;
+
+ acl_port = atoi(argv[3]);
+ acl_en = atoi(argv[4]);
+
+ printf("acl_port:%d, acl_en:%d\n", acl_port, acl_en);
+
+ /*Check the input parameters is right or not.*/
+ if ((acl_port > SWITCH_MAX_PORT) || (acl_en > 1)) {
+ printf(HELP_ACL_SETPORTEN);
+ return;
+ }
+
+ reg = REG_PCR_P0_ADDR + (0x100 * acl_port); // 0x2004[10]
+ reg_read(reg, &value);
+ value &= (~REG_PORT_ACL_EN_MASK);
+ value |= (acl_en << REG_PORT_ACL_EN_OFFT);
+
+ printf("write reg: %x, value: %x\n", reg, value);
+ reg_write(reg, value);
+}
+
+static void dip_dump_internal(int type)
+{
+ int i, j, value, mac, mac2, value2;
+ int vid[16];
+ char tmpstr[16];
+ int table_size = 0;
+ int hit_value1 = 0;
+ int hit_value2 = 0;
+
+ for (i = 0; i < 8; i++) {
+ reg_read(REG_VLAN_ID_BASE + 4 * i, &value);
+ vid[2 * i] = value & 0xfff;
+ vid[2 * i + 1] = (value & 0xfff000) >> 12;
+ }
+
+ if(type == GENERAL_TABLE) {
+ table_size = 0x800;
+ reg_write(REG_ATC_ADDR, 0x8104); //dip search command
+ } else {
+ table_size = 0x40;
+ reg_write(REG_ATC_ADDR, 0x811c); //dip search command
+ }
+ printf("hash port(0:6) rsp_cnt flag timer dip-address ATRD\n");
+ for (i = 0; i < table_size; i++) {
+ while (1)
+ {
+ reg_read(REG_ATC_ADDR, &value);
+ if(type == GENERAL_TABLE) {
+ hit_value1 = value & (0x1 << 13);
+ hit_value2 = 1;
+ }else {
+ hit_value1 = value & (0x1 << 13);
+ hit_value2 = value & (0x1 << 28);
+ }
+
+ if (hit_value1 && hit_value2 ) { //search_rdy
+ reg_read(REG_ATRD_ADDR, &value2);
+ //printf("REG_ATRD_ADDR=0x%x\n\r",value2);
+
+ printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
+ j = (value2 >> 4) & 0xff; //r_port_map
+ printf("%c", (j & 0x01) ? '1' : '-');
+ printf("%c", (j & 0x02) ? '1' : '-');
+ printf("%c", (j & 0x04) ? '1' : '-');
+ printf("%c ", (j & 0x08) ? '1' : '-');
+ printf("%c", (j & 0x10) ? '1' : '-');
+ printf("%c", (j & 0x20) ? '1' : '-');
+ printf("%c", (j & 0x40) ? '1' : '-');
+
+ reg_read(REG_TSRA2_ADDR, &mac2);
+
+ printf(" 0x%4x", (mac2 & 0xffff)); //RESP_CNT
+ printf(" 0x%2x", ((mac2 >> 16) & 0xff)); //RESP_FLAG
+ printf(" %3d", ((mac2 >> 24) & 0xff)); //RESP_TIMER
+ //printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
+ reg_read(REG_TSRA1_ADDR, &mac);
+ ip_to_str(tmpstr, mac);
+ printf(" %s", tmpstr);
+ printf(" 0x%8x\n", value2); //ATRD
+ //printf("%04x", ((mac2 >> 16) & 0xffff));
+ //printf(" %c\n", (((value2 >> 20) & 0x03)== 0x03)? 'y':'-');
+ if (value & 0x4000) {
+ printf("end of table %d\n", i);
+ return;
+ }
+ break;
+ }
+ else if (value & 0x4000) { //at_table_end
+ printf("found the last entry %d (not ready)\n", i);
+ return;
+ }
+ usleep(5000);
+ }
+
+ if(type == GENERAL_TABLE)
+ reg_write(REG_ATC_ADDR, 0x8105); //search for next dip address
+ else
+ reg_write(REG_ATC_ADDR, 0x811d); //search for next dip address
+ usleep(5000);
+ }
+}
+
+void dip_dump(void)
+{
+ dip_dump_internal(GENERAL_TABLE);
+
+}
+
+void dip_add(int argc, char *argv[])
+{
+ unsigned int i, j, value;
+ char tmpstr[9];
+
+ str_to_ip(&value, argv[3]);
+
+ reg_write(REG_ATA1_ADDR, value);
+ printf("REG_ATA1_ADDR is 0x%x\n\r", value);
+
+ value = 0;
+#if 0
+ reg_write(REG_ATA2_ADDR, value);
+ printf("REG_ATA2_ADDR is 0x%x\n\r", value);
+#endif
+ if (!argv[4] || strlen(argv[4]) != 8) {
+ printf("portmap format error, should be of length 7\n");
+ return;
+ }
+ j = 0;
+ for (i = 0; i < 7; i++) {
+ if (argv[4][i] != '0' && argv[4][i] != '1') {
+ printf("portmap format error, should be of combination of 0 or 1\n");
+ return;
+ }
+ j += (argv[4][i] - '0') * (1 << i);
+ }
+ value = j << 4; //w_port_map
+ value |= (0x3 << 2); //static
+
+ reg_write(REG_ATWD_ADDR, value);
+
+ usleep(5000);
+ reg_read(REG_ATWD_ADDR, &value);
+ printf("REG_ATWD_ADDR is 0x%x\n\r", value);
+
+ value = 0x8011; //single w_dip_cmd
+ reg_write(REG_ATC_ADDR, value);
+
+ usleep(1000);
+
+ for (i = 0; i < 20; i++) {
+ reg_read(REG_ATC_ADDR, &value);
+ if ((value & 0x8000) == 0) { //mac address busy
+ printf("done.\n");
+ return;
+ }
+ usleep(1000);
+ }
+ if (i == 20)
+ printf("timeout.\n");
+}
+
+void dip_del(int argc, char *argv[])
+{
+ unsigned int i, j, value;
+ char tmpstr[9];
+
+ str_to_ip(&value, argv[3]);
+
+ reg_write(REG_ATA1_ADDR, value);
+
+ value = 0;
+ reg_write(REG_ATA2_ADDR, value);
+
+ value = 0; //STATUS=0, delete dip
+ reg_write(REG_ATWD_ADDR, value);
+
+ value = 0x8011; //w_dip_cmd
+ reg_write(REG_ATC_ADDR, value);
+
+ for (i = 0; i < 20; i++) {
+ reg_read(REG_ATC_ADDR, &value);
+ if ((value & 0x8000) == 0) { //mac address busy
+ if (argv[1] != NULL)
+ printf("done.\n");
+ return;
+ }
+ usleep(1000);
+ }
+ if (i == 20)
+ printf("timeout.\n");
+}
+
+void dip_clear(void)
+{
+
+ int value;
+ reg_write(REG_ATC_ADDR, 0x8102); //clear all dip
+ usleep(5000);
+ reg_read(REG_ATC_ADDR, &value);
+ printf("REG_ATC_ADDR is 0x%x\n\r", value);
+}
+
+static void sip_dump_internal(int type)
+{
+ int i, j, value, mac, mac2, value2;
+ int vid[16];
+ char tmpstr[16];
+
+ int table_size = 0;
+ int hit_value1 = 0;
+ int hit_value2 = 0;
+
+ for (i = 0; i < 8; i++) {
+ reg_read(REG_VLAN_ID_BASE + 4 * i, &value);
+ vid[2 * i] = value & 0xfff;
+ vid[2 * i + 1] = (value & 0xfff000) >> 12;
+ }
+
+ if (type == GENERAL_TABLE) {
+ table_size = 0x800;
+ reg_write(REG_ATC_ADDR, 0x8204); //sip search command
+ }else {
+ table_size = 0x40;
+ reg_write(REG_ATC_ADDR, 0x822c); //sip search command
+ }
+ printf("hash port(0:6) dip-address sip-address ATRD\n");
+ for (i = 0; i < table_size; i++) {
+ while (1)
+ {
+ reg_read(REG_ATC_ADDR, &value);
+ if(type == GENERAL_TABLE) {
+ hit_value1 = value & (0x1 << 13);
+ hit_value2 = 1;
+ } else {
+ hit_value1 = value & (0x1 << 13);
+ hit_value2 = value & (0x1 << 28);
+ }
+
+ if (hit_value1 && hit_value2) { //search_rdy
+ reg_read(REG_ATRD_ADDR, &value2);
+ //printf("REG_ATRD_ADDR=0x%x\n\r",value2);
+
+ printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
+ j = (value2 >> 4) & 0xff; //r_port_map
+ printf("%c", (j & 0x01) ? '1' : '-');
+ printf("%c", (j & 0x02) ? '1' : '-');
+ printf("%c", (j & 0x04) ? '1' : '-');
+ printf("%c", (j & 0x08) ? '1' : '-');
+ printf(" %c", (j & 0x10) ? '1' : '-');
+ printf("%c", (j & 0x20) ? '1' : '-');
+ printf("%c", (j & 0x40) ? '1' : '-');
+
+ reg_read(REG_TSRA2_ADDR, &mac2);
+
+ ip_to_str(tmpstr, mac2);
+ printf(" %s", tmpstr);
+
+ //printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
+ reg_read(REG_TSRA1_ADDR, &mac);
+ ip_to_str(tmpstr, mac);
+ printf(" %s", tmpstr);
+ printf(" 0x%x\n", value2);
+ //printf("%04x", ((mac2 >> 16) & 0xffff));
+ //printf(" %c\n", (((value2 >> 20) & 0x03)== 0x03)? 'y':'-');
+ if (value & 0x4000) {
+ printf("end of table %d\n", i);
+ return;
+ }
+ break;
+ } else if (value & 0x4000) { //at_table_end
+ printf("found the last entry %d (not ready)\n", i);
+ return;
+ }
+ usleep(5000);
+ }
+
+ if(type == GENERAL_TABLE)
+ reg_write(REG_ATC_ADDR, 0x8205); //search for next sip address
+ else
+ reg_write(REG_ATC_ADDR, 0x822d); //search for next sip address
+ usleep(5000);
+ }
+}
+
+void sip_dump(void)
+{
+
+ sip_dump_internal(GENERAL_TABLE);
+
+}
+
+
+void sip_add(int argc, char *argv[])
+{
+ unsigned int i, j, value;
+ char tmpstr[9];
+
+ str_to_ip(&value, argv[3]); //SIP
+
+ reg_write(REG_ATA2_ADDR, value);
+ printf("REG_ATA2_ADDR is 0x%x\n\r", value);
+
+ value = 0;
+
+ str_to_ip(&value, argv[4]); //DIP
+ reg_write(REG_ATA1_ADDR, value);
+ printf("REG_ATA1_ADDR is 0x%x\n\r", value);
+
+ if (!argv[5] || strlen(argv[5]) != 8) {
+ printf("portmap format error, should be of length 7\n");
+ return;
+ }
+ j = 0;
+ for (i = 0; i < 7; i++) {
+ if (argv[5][i] != '0' && argv[5][i] != '1') {
+ printf("portmap format error, should be of combination of 0 or 1\n");
+ return;
+ }
+ j += (argv[5][i] - '0') * (1 << i);
+ }
+ value = j << 4; //w_port_map
+ value |= (0x3 << 2); //static
+
+ reg_write(REG_ATWD_ADDR, value);
+
+ usleep(5000);
+ reg_read(REG_ATWD_ADDR, &value);
+ printf("REG_ATWD_ADDR is 0x%x\n\r", value);
+
+ value = 0x8021; //single w_sip_cmd
+ reg_write(REG_ATC_ADDR, value);
+
+ usleep(1000);
+
+ for (i = 0; i < 20; i++) {
+ reg_read(REG_ATC_ADDR, &value);
+ if ((value & 0x8000) == 0) { //mac address busy
+ printf("done.\n");
+ return;
+ }
+ usleep(1000);
+ }
+ if (i == 20)
+ printf("timeout.\n");
+}
+
+void sip_del(int argc, char *argv[])
+{
+ unsigned int i, j, value;
+ char tmpstr[9];
+
+ str_to_ip(&value, argv[3]);
+
+ reg_write(REG_ATA2_ADDR, value); //SIP
+
+ str_to_ip(&value, argv[4]);
+ reg_write(REG_ATA1_ADDR, value); //DIP
+
+ value = 0; //STATUS=0, delete sip
+ reg_write(REG_ATWD_ADDR, value);
+
+ value = 0x8021; //w_sip_cmd
+ reg_write(REG_ATC_ADDR, value);
+
+ for (i = 0; i < 20; i++) {
+ reg_read(REG_ATC_ADDR, &value);
+ if ((value & 0x8000) == 0) { //mac address busy
+ if (argv[1] != NULL)
+ printf("done.\n");
+ return;
+ }
+ usleep(1000);
+ }
+ if (i == 20)
+ printf("timeout.\n");
+}
+
+void sip_clear(void)
+{
+ int value;
+
+ reg_write(REG_ATC_ADDR, 0x8202); //clear all sip
+ usleep(5000);
+ reg_read(REG_ATC_ADDR, &value);
+ printf("REG_ATC_ADDR is 0x%x\n\r", value);
+}
+
+static void table_dump_internal(int type)
+{
+ int i, j, value, mac, mac2, value2;
+ int vid[16];
+ int table_size = 0;
+ int table_end = 0;
+ int hit_value1 = 0;
+ int hit_value2 = 0;
+
+ for (i = 0; i < 8; i++) {
+ reg_read(REG_VLAN_ID_BASE + 4 * i, &value);
+ vid[2 * i] = value & 0xfff;
+ vid[2 * i + 1] = (value & 0xfff000) >> 12;
+ }
+ if (type == GENERAL_TABLE){
+ table_size = 0x800;
+ table_end = 0x7FF;
+ reg_write(REG_ATC_ADDR, 0x8004);
+ } else {
+ table_size = 0x40;
+ table_end = 0x3F;
+ reg_write(REG_ATC_ADDR, 0x800C);
+ }
+ printf("hash port(0:6) fid vid age(s) mac-address filter my_mac\n");
+ for (i = 0; i < table_size; i++) {
+ while (1)
+ {
+ reg_read(REG_ATC_ADDR, &value);
+ //printf("ATC = 0x%x\n", value);
+ if(type == GENERAL_TABLE) {
+ hit_value1 = value & (0x1 << 13);
+ hit_value2 = 1;
+ } else {
+ hit_value1 = value & (0x1 << 13);
+ hit_value2 = value & (0x1 << 28);
+ }
+
+ if (hit_value1 && hit_value2 && (((value >> 15) & 0x1) == 0)) {
+ printf("%03x: ", (value >> 16) & 0xfff);
+ reg_read(REG_ATRD_ADDR, &value2);
+ j = (value2 >> 4) & 0xff; //r_port_map
+ if(j & 0x01)
+ printf("0");
+ else if (j & 0x02)
+ printf("1");
+ else if (j & 0x04)
+ printf("2");
+ else if (j & 0x08)
+ printf("3");
+ else if (j & 0x10)
+ printf("4");
+ else if (j & 0x20)
+ printf("5");
+ else if (j & 0x40)
+ printf("6");
+ else if (j & 0x80)
+ printf("7");
+ /*
+ printf("%c", (j & 0x01) ? '1' : '-');
+ printf("%c", (j & 0x02) ? '1' : '-');
+ printf("%c", (j & 0x04) ? '1' : '-');
+ printf("%c", (j & 0x08) ? '1' : '-');
+ printf("%c", (j & 0x10) ? '1' : '-');
+ printf("%c", (j & 0x20) ? '1' : '-');
+ printf("%c", (j & 0x40) ? '1' : '-');
+ printf("%c", (j & 0x80) ? '1' : '-');
+ */
+ printf(" ");
+ reg_read(REG_TSRA2_ADDR, &mac2);
+
+ printf(" %2d", (mac2 >> 12) & 0x7); //FID
+ printf(" %4d", (mac2 & 0xfff));
+ if (((value2 >> 24) & 0xff) == 0xFF)
+ printf(" --- "); //r_age_field:static
+ else
+ printf(" %5d ", (((value2 >> 24) & 0xff)+1)*2); //r_age_field
+ reg_read(REG_TSRA1_ADDR, &mac);
+ printf(" %08x", mac);
+ printf("%04x", ((mac2 >> 16) & 0xffff));
+ printf(" %c", (((value2 >> 20) & 0x03) == 0x03) ? 'y' : '-');
+ printf(" %c\n", (((value2 >> 23) & 0x01) == 0x01) ? 'y' : '-');
+ if ((value & 0x4000) && (((value >> 16) & 0xfff) == table_end)) {
+ printf("end of table %d\n", i);
+ return;
+ }
+ break;
+ }
+ else if ((value & 0x4000) && (((value >> 15) & 0x1) == 0) && (((value >> 16) & 0xfff) == table_end)) { //at_table_end
+ printf("found the last entry %d (not ready)\n", i);
+ return;
+ }
+ else
+ usleep(5);
+ }
+
+ if(type == GENERAL_TABLE)
+ reg_write(REG_ATC_ADDR, 0x8005);//search for next address
+ else
+ reg_write(REG_ATC_ADDR, 0x800d);//search for next address
+ usleep(5);
+ }
+}
+
+void table_dump(void)
+{
+ table_dump_internal(GENERAL_TABLE);
+
+}
+
+
+void table_add(int argc, char *argv[])
+{
+ unsigned int i, j, value, is_filter, is_mymac;
+ char tmpstr[9];
+
+ is_filter = (argv[1][0] == 'f') ? 1 : 0;
+ is_mymac = (argv[1][0] == 'm') ? 1 : 0;
+ if (!argv[2] || strlen(argv[2]) != 12) {
+ printf("MAC address format error, should be of length 12\n");
+ return;
+ }
+ strncpy(tmpstr, argv[2], 8);
+ tmpstr[8] = '\0';
+ value = strtoul(tmpstr, NULL, 16);
+ reg_write(REG_ATA1_ADDR, value);
+ printf("REG_ATA1_ADDR is 0x%x\n\r", value);
+
+ strncpy(tmpstr, argv[2] + 8, 4);
+ tmpstr[4] = '\0';
+
+ value = strtoul(tmpstr, NULL, 16);
+ value = (value << 16);
+ value |= (1 << 15); //IVL=1
+
+ if (argc > 4) {
+ j = strtoul(argv[4], NULL, 0);
+ if (4095 < j) {
+ printf("wrong vid range, should be within 0~4095\n");
+ return;
+ }
+ value |= j; //vid
+ }
+
+ reg_write(REG_ATA2_ADDR, value);
+ printf("REG_ATA2_ADDR is 0x%x\n\r", value);
+
+ if (!argv[3] || strlen(argv[3]) != 8) {
+ if (is_filter)
+ argv[3] = "11111111";
+ else {
+ printf("portmap format error, should be of length 8\n");
+ return;
+ }
+ }
+ j = 0;
+ for (i = 0; i < 7; i++) {
+ if (argv[3][i] != '0' && argv[3][i] != '1') {
+ printf("portmap format error, should be of combination of 0 or 1\n");
+ return;
+ }
+ j += (argv[3][i] - '0') * (1 << i);
+ }
+ value = j << 4; //w_port_map
+
+ if (argc > 5) {
+ j = strtoul(argv[5], NULL, 0);
+ if (j < 1 || 255 < j) {
+ printf("wrong age range, should be within 1~255\n");
+ return;
+ }
+ value |= (j << 24); //w_age_field
+ value |= (0x1 << 2); //dynamic
+ } else {
+ value |= (0xff << 24); //w_age_field
+ value |= (0x3 << 2); //static
+ }
+
+ if (argc > 6) {
+ j = strtoul(argv[6], NULL, 0);
+ if (7 < j) {
+ printf("wrong eg-tag range, should be within 0~7\n");
+ return;
+ }
+ value |= (j << 13); //EG_TAG
+ }
+
+ if (is_filter)
+ value |= (7 << 20); //sa_filter
+
+ if (is_mymac)
+ value |= (1 << 23);
+
+ reg_write(REG_ATWD_ADDR, value);
+
+ usleep(5000);
+ reg_read(REG_ATWD_ADDR, &value);
+ printf("REG_ATWD_ADDR is 0x%x\n\r", value);
+
+ value = 0x8001; //w_mac_cmd
+ reg_write(REG_ATC_ADDR, value);
+
+ usleep(1000);
+
+ for (i = 0; i < 20; i++) {
+ reg_read(REG_ATC_ADDR, &value);
+ if ((value & 0x8000) == 0) { //mac address busy
+ printf("done.\n");
+ return;
+ }
+ usleep(1000);
+ }
+ if (i == 20)
+ printf("timeout.\n");
+}
+
+void table_search_mac_vid(int argc, char *argv[])
+{
+ unsigned int i, j, value, mac, mac2, value2;
+ char tmpstr[9];
+
+ if (!argv[3] || strlen(argv[3]) != 12) {
+ printf("MAC address format error, should be of length 12\n");
+ return;
+ }
+ strncpy(tmpstr, argv[3], 8);
+ tmpstr[8] = '\0';
+ value = strtoul(tmpstr, NULL, 16);
+ reg_write(REG_ATA1_ADDR, value);
+ //printf("REG_ATA1_ADDR is 0x%x\n\r",value);
+
+ strncpy(tmpstr, argv[3] + 8, 4);
+ tmpstr[4] = '\0';
+
+ value = strtoul(tmpstr, NULL, 16);
+ value = (value << 16);
+ value |= (1 << 15); //IVL=1
+
+ j = strtoul(argv[5], NULL, 0);
+ if (4095 < j) {
+ printf("wrong vid range, should be within 0~4095\n");
+ return;
+ }
+ value |= j; //vid
+
+ reg_write(REG_ATA2_ADDR, value);
+ //printf("REG_ATA2_ADDR is 0x%x\n\r",value);
+
+ value = 0x8000; //w_mac_cmd
+ reg_write(REG_ATC_ADDR, value);
+
+ usleep(1000);
+
+ for (i = 0; i < 20; i++) {
+ reg_read(REG_ATC_ADDR, &value);
+ if ((value & 0x8000) == 0) { //mac address busy
+ break;
+ }
+ usleep(1000);
+ }
+ if (i == 20) {
+ printf("search timeout.\n");
+ return;
+ }
+
+ if (value & 0x1000) {
+ printf("search no entry.\n");
+ return;
+ }
+
+ printf("search done.\n");
+ printf("hash port(0:6) fid vid age mac-address filter my_mac\n");
+
+ printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
+ reg_read(REG_ATRD_ADDR, &value2);
+ j = (value2 >> 4) & 0xff; //r_port_map
+ printf("%c", (j & 0x01) ? '1' : '-');
+ printf("%c", (j & 0x02) ? '1' : '-');
+ printf("%c", (j & 0x04) ? '1' : '-');
+ printf("%c ", (j & 0x08) ? '1' : '-');
+ printf("%c", (j & 0x10) ? '1' : '-');
+ printf("%c", (j & 0x20) ? '1' : '-');
+ printf("%c", (j & 0x40) ? '1' : '-');
+ printf("%c", (j & 0x80) ? '1' : '-');
+
+ reg_read(REG_TSRA2_ADDR, &mac2);
+
+ printf(" %2d", (mac2 >> 12) & 0x7); //FID
+ printf(" %4d", (mac2 & 0xfff));
+ printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
+ reg_read(REG_TSRA1_ADDR, &mac);
+ printf(" %08x", mac);
+ printf("%04x", ((mac2 >> 16) & 0xffff));
+ printf(" %c", (((value2 >> 20) & 0x03) == 0x03) ? 'y' : '-');
+ printf(" %c\n", (((value2 >> 23) & 0x01) == 0x01) ? 'y' : '-');
+}
+
+void table_search_mac_fid(int argc, char *argv[])
+{
+ unsigned int i, j, value, mac, mac2, value2;
+ char tmpstr[9];
+
+ if (!argv[3] || strlen(argv[3]) != 12) {
+ printf("MAC address format error, should be of length 12\n");
+ return;
+ }
+ strncpy(tmpstr, argv[3], 8);
+ tmpstr[8] = '\0';
+ value = strtoul(tmpstr, NULL, 16);
+ reg_write(REG_ATA1_ADDR, value);
+ //printf("REG_ATA1_ADDR is 0x%x\n\r",value);
+
+ strncpy(tmpstr, argv[3] + 8, 4);
+ tmpstr[4] = '\0';
+
+ value = strtoul(tmpstr, NULL, 16);
+ value = (value << 16);
+ value &= ~(1 << 15); //IVL=0
+
+ j = strtoul(argv[5], NULL, 0);
+ if (7 < j) {
+ printf("wrong fid range, should be within 0~7\n");
+ return;
+ }
+ value |= (j << 12); //vid
+
+ reg_write(REG_ATA2_ADDR, value);
+ //printf("REG_ATA2_ADDR is 0x%x\n\r",value);
+
+ value = 0x8000; //w_mac_cmd
+ reg_write(REG_ATC_ADDR, value);
+
+ usleep(1000);
+
+ for (i = 0; i < 20; i++) {
+ reg_read(REG_ATC_ADDR, &value);
+ if ((value & 0x8000) == 0) { //mac address busy
+ break;
+ }
+ usleep(1000);
+ }
+ if (i == 20) {
+ printf("search timeout.\n");
+ return;
+ }
+
+ if (value & 0x1000) {
+ printf("search no entry.\n");
+ return;
+ }
+
+ printf("search done.\n");
+ printf("hash port(0:6) fid vid age mac-address filter my_mac\n");
+
+ printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
+ reg_read(REG_ATRD_ADDR, &value2);
+ j = (value2 >> 4) & 0xff; //r_port_map
+ printf("%c", (j & 0x01) ? '1' : '-');
+ printf("%c", (j & 0x02) ? '1' : '-');
+ printf("%c", (j & 0x04) ? '1' : '-');
+ printf("%c ", (j & 0x08) ? '1' : '-');
+ printf("%c", (j & 0x10) ? '1' : '-');
+ printf("%c", (j & 0x20) ? '1' : '-');
+ printf("%c", (j & 0x40) ? '1' : '-');
+ printf("%c", (j & 0x80) ? '1' : '-');
+
+ reg_read(REG_TSRA2_ADDR, &mac2);
+
+ printf(" %2d", (mac2 >> 12) & 0x7); //FID
+ printf(" %4d", (mac2 & 0xfff));
+ printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
+ reg_read(REG_TSRA1_ADDR, &mac);
+ printf(" %08x", mac);
+ printf("%04x", ((mac2 >> 16) & 0xffff));
+ printf(" %c", (((value2 >> 20) & 0x03) == 0x03) ? 'y' : '-');
+ printf(" %c\n", (((value2 >> 23) & 0x01) == 0x01) ? 'y' : '-');
+}
+
+void table_del_fid(int argc, char *argv[])
+{
+ int i, j, value;
+ char tmpstr[9];
+
+ if (!argv[3] || strlen(argv[3]) != 12) {
+ printf("MAC address format error, should be of length 12\n");
+ return;
+ }
+ strncpy(tmpstr, argv[3], 8);
+ tmpstr[8] = '\0';
+ value = strtoul(tmpstr, NULL, 16);
+ reg_write(REG_ATA1_ADDR, value);
+ strncpy(tmpstr, argv[3] + 8, 4);
+ tmpstr[4] = '\0';
+ value = strtoul(tmpstr, NULL, 16);
+ value = (value << 16);
+
+ if (argc > 5) {
+ j = strtoul(argv[5], NULL, 0);
+ if (j < 0 || 7 < j) {
+ printf("wrong fid range, should be within 0~7\n");
+ return;
+ }
+ value |= (j << 12); //fid
+ }
+
+ reg_write(REG_ATA2_ADDR, value);
+
+ value = 0; //STATUS=0, delete mac
+ reg_write(REG_ATWD_ADDR, value);
+
+ value = 0x8001; //w_mac_cmd
+ reg_write(REG_ATC_ADDR, value);
+
+ for (i = 0; i < 20; i++) {
+ reg_read(REG_ATC_ADDR, &value);
+ if ((value & 0x8000) == 0) { //mac address busy
+ if (argv[1] != NULL)
+ printf("done.\n");
+ return;
+ }
+ usleep(1000);
+ }
+ if (i == 20)
+ printf("timeout.\n");
+}
+
+void table_del_vid(int argc, char *argv[])
+{
+ int i, j, value;
+ char tmpstr[9];
+
+ if (!argv[3] || strlen(argv[3]) != 12) {
+ printf("MAC address format error, should be of length 12\n");
+ return;
+ }
+ strncpy(tmpstr, argv[3], 8);
+ tmpstr[8] = '\0';
+ value = strtoul(tmpstr, NULL, 16);
+ reg_write(REG_ATA1_ADDR, value);
+
+ strncpy(tmpstr, argv[3] + 8, 4);
+ tmpstr[4] = '\0';
+ value = strtoul(tmpstr, NULL, 16);
+ value = (value << 16);
+
+ j = strtoul(argv[5], NULL, 0);
+ if (j < 0 || 4095 < j) {
+ printf("wrong fid range, should be within 0~4095\n");
+ return;
+ }
+ value |= j; //vid
+ value |= 1 << 15;
+ reg_write(REG_ATA2_ADDR, value);
+
+ value = 0; //STATUS=0, delete mac
+ reg_write(REG_ATWD_ADDR, value);
+
+ value = 0x8001; //w_mac_cmd
+ reg_write(REG_ATC_ADDR, value);
+
+ for (i = 0; i < 20; i++) {
+ reg_read(REG_ATC_ADDR, &value);
+ if ((value & 0x8000) == 0) { //mac address busy
+ if (argv[1] != NULL)
+ printf("done.\n");
+ return;
+ }
+ usleep(1000);
+ }
+ if (i == 20)
+ printf("timeout.\n");
+}
+
+void table_clear(void)
+{
+ int i, value, mac;
+ reg_write(REG_ATC_ADDR, 0x8002);
+ usleep(5000);
+ reg_read(REG_ATC_ADDR, &value);
+
+ printf("REG_ATC_ADDR is 0x%x\n\r", value);
+}
+
+void set_mirror_to(int argc, char *argv[])
+{
+ unsigned int value;
+ int idx;
+
+ idx = strtoul(argv[3], NULL, 0);
+ if (idx < 0 || MAX_PORT < idx) {
+ printf("wrong port member, should be within 0~%d\n", MAX_PORT);
+ return;
+ }
+ if (chip_name == 0x7530) {
+
+ reg_read(REG_MFC_ADDR, &value);
+ value |= 0x1 << 3;
+ value &= 0xfffffff8;
+ value |= idx << 0;
+
+ reg_write(REG_MFC_ADDR, value);
+ } else {
+
+ reg_read(REG_CFC_ADDR, &value);
+ value &= (~REG_CFC_MIRROR_EN_MASK);
+ value |= (1 << REG_CFC_MIRROR_EN_OFFT);
+ value &= (~REG_CFC_MIRROR_PORT_MASK);
+ value |= (idx << REG_CFC_MIRROR_PORT_OFFT);
+ reg_write(REG_CFC_ADDR, value);
+ }
+}
+
+void set_mirror_from(int argc, char *argv[])
+{
+ unsigned int offset, value;
+ int idx, mirror;
+
+ idx = strtoul(argv[3], NULL, 0);
+ mirror = strtoul(argv[4], NULL, 0);
+
+ if (idx < 0 || MAX_PORT < idx) {
+ printf("wrong port member, should be within 0~%d\n", MAX_PORT);
+ return;
+ }
+
+ if (mirror < 0 || 3 < mirror) {
+ printf("wrong mirror setting, should be within 0~3\n");
+ return;
+ }
+
+ offset = (0x2004 | (idx << 8));
+ reg_read(offset, &value);
+
+ value &= 0xfffffcff;
+ value |= mirror << 8;
+
+ reg_write(offset, value);
+}
+
+void vlan_dump(void)
+{
+ int i, j, vid, value, value2;
+
+ printf(" vid fid portmap s-tag\n");
+ for (i = 1; i < 4095; i++) {
+ //reg_read(REG_VLAN_ID_BASE + 4*i, &vid);
+ //value = (0x80000000 + 2*i); //r_vid_cmd
+ value = (0x80000000 + i); //r_vid_cmd
+ reg_write(REG_VTCR_ADDR, value);
+
+ for (j = 0; j < 20; j++) {
+ reg_read(REG_VTCR_ADDR, &value);
+ if ((value & 0x80000000) == 0) { //mac address busy
+ break;
+ }
+ usleep(1000);
+ }
+ if (j == 20)
+ printf("timeout.\n");
+
+ reg_read(REG_VAWD1_ADDR, &value);
+ reg_read(REG_VAWD2_ADDR, &value2);
+ //printf("REG_VAWD1_ADDR value%d is 0x%x\n\r", i, value);
+ //printf("REG_VAWD2_ADDR value%d is 0x%x\n\r", i, value2);
+
+ if ((value & 0x01) != 0) {
+ printf(" %4d ", i);
+ printf(" %2d ", ((value & 0xe) >> 1));
+ printf(" %c", (value & 0x00010000) ? '1' : '-');
+ printf("%c", (value & 0x00020000) ? '1' : '-');
+ printf("%c", (value & 0x00040000) ? '1' : '-');
+ printf("%c", (value & 0x00080000) ? '1' : '-');
+ printf("%c", (value & 0x00100000) ? '1' : '-');
+ printf("%c", (value & 0x00200000) ? '1' : '-');
+ printf("%c", (value & 0x00400000) ? '1' : '-');
+ printf("%c", (value & 0x00800000) ? '1' : '-');
+ printf(" %4d\n", ((value & 0xfff0) >> 4));
+ } else {
+ /*print 16 vid for reference information*/
+ if (i <= 16) {
+ printf(" %4d ", i);
+ printf(" %2d ", ((value & 0xe) >> 1));
+ printf(" invalid\n");
+ }
+ }
+ }
+}
+
+
+static long timespec_diff_us(struct timespec start, struct timespec end)
+{
+ struct timespec temp;
+ unsigned long duration = 0;
+
+ if ((end.tv_nsec - start.tv_nsec) < 0) {
+ temp.tv_sec = end.tv_sec - start.tv_sec - 1;
+ temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
+ } else {
+ temp.tv_sec = end.tv_sec - start.tv_sec;
+ temp.tv_nsec = end.tv_nsec - start.tv_nsec;
+ }
+ /* calculate second part*/
+ duration += temp.tv_sec * 1000000;
+ /* calculate ns part*/
+ duration += temp.tv_nsec >> 10;
+
+ return duration;
+}
+
+
+void vlan_clear(int argc, char *argv[])
+{
+ unsigned int i, j, value, value2;
+ int idx, vid;
+ unsigned long duration_us = 0;
+ struct timespec start, end;
+
+ for (vid = 0; vid < 4096; vid++) {
+ clock_gettime(CLOCK_REALTIME, &start);
+ value = 0; //invalid
+ reg_write(REG_VAWD1_ADDR, value);
+
+ value = (0x80001000 + vid); //w_vid_cmd
+ reg_write(REG_VTCR_ADDR, value);
+ while (duration_us <= 1000) {
+ reg_read(REG_VTCR_ADDR, &value);
+ if ((value & 0x80000000) == 0) { //table busy
+ break;
+ }
+ clock_gettime(CLOCK_REALTIME, &end);
+ duration_us = timespec_diff_us(start, end);
+ }
+ if (duration_us > 1000)
+ printf("config vlan timeout: %ld.\n", duration_us);
+ }
+}
+
+void vlan_set(int argc, char *argv[])
+{
+ unsigned int i, j, value, value2;
+ int idx, vid;
+ int stag = 0;
+ unsigned char eg_con = 0;
+ unsigned char eg_tag = 0;
+
+ if (argc < 5) {
+ printf("insufficient arguments!\n");
+ return;
+ }
+ vid = strtoul(argv[4], NULL, 0);
+ if (vid < 0 || 0xfff < vid) {
+ printf("wrong vlan id range, should be within 0~4095\n");
+ return;
+ }
+ if (strlen(argv[5]) != 8) {
+ printf("portmap format error, should be of length 7\n");
+ return;
+ }
+ j = 0;
+ for (i = 0; i < 8; i++) {
+ if (argv[5][i] != '0' && argv[5][i] != '1') {
+ printf("portmap format error, should be of combination of 0 or 1\n");
+ return;
+ }
+ j += (argv[5][i] - '0') * (1 << i);
+ }
+ //set vlan identifier
+ /*
+ reg_read(REG_VLAN_ID_BASE + 4*(idx/2), &value);
+ if (idx % 2 == 0) {
+ value &= 0xfff000;
+ value |= vid;
+ }
+ else {
+ value &= 0xfff;
+ value |= (vid << 12);
+ }
+ reg_write(REG_VLAN_ID_BASE + 4*(idx/2), value);
+ */
+
+ /*port stag*/
+ if (argc > 6) {
+ stag = strtoul(argv[6], NULL, 16);
+ printf("STAG index is 0x%x\n", stag);
+ }
+
+ //set vlan member
+ value = (j << 16);
+ //value |= (idx << 1);//fid
+ value |= (1 << 30); //IVL=1
+ value |= ((stag & 0xfff) << 4); //stag
+ value |= 1; //valid
+
+ if (argc > 7) {
+ value |= (eg_con << 29); //eg_con
+ value |= (1 << 28); //eg tag control enable
+ }
+
+ if (argc > 8) {
+ value |= (1 << 28); //eg tag control enable
+ value2 = eg_tag; //port 0
+ value2 |= eg_tag << 2; //port 1
+ value2 |= eg_tag << 4; //port 2
+ reg_write(REG_VAWD2_ADDR, value2);
+ }
+ reg_write(REG_VAWD1_ADDR, value);
+
+ //value = (0x80001000 + idx); //w_vid_cmd
+ value = (0x80001000 + vid); //w_vid_cmd
+ reg_write(REG_VTCR_ADDR, value);
+
+ for (j = 0; j < 300; j++) {
+ usleep(1000);
+ reg_read(REG_VTCR_ADDR, &value);
+ if ((value & 0x80000000) == 0) //table busy
+ break;
+ }
+
+ if (j == 300)
+ printf("config vlan timeout.\n");
+}
+
+void igmp_on(int argc, char *argv[])
+{
+ unsigned int leaky_en = 0;
+ unsigned int wan_num = 4;
+ unsigned int port, offset, value;
+ char cmd[80];
+
+ if (argc > 3)
+ leaky_en = strtoul(argv[3], NULL, 10);
+ if (argc > 4)
+ wan_num = strtoul(argv[4], NULL, 10);
+
+ if (leaky_en == 1) {
+ if (wan_num == 4) {
+ /* reg_write(0x2410, 0x810000c8); */
+ reg_read(0x2410, &value);
+ reg_write(0x2410, value | (1 << 3));
+ /* reg_write(0x2010, 0x810000c0); */
+ reg_read(0x2010, &value);
+ reg_write(0x2010, value & (~(1 << 3)));
+ reg_write(REG_ISC_ADDR, 0x10027d10);
+ } else {
+ /* reg_write(0x2010, 0x810000c8); */
+ reg_read(0x2010, &value);
+ reg_write(0x2010, value | (1 << 3));
+ /* reg_write(0x2410, 0x810000c0); */
+ reg_read(0x2410, &value);
+ reg_write(0x2410, value & (~(1 << 3)));
+ reg_write(REG_ISC_ADDR, 0x01027d01);
+ }
+ }
+ else
+ reg_write(REG_ISC_ADDR, 0x10027d60);
+
+ reg_write(0x1c, 0x08100810);
+ reg_write(0x2008, 0xb3ff);
+ reg_write(0x2108, 0xb3ff);
+ reg_write(0x2208, 0xb3ff);
+ reg_write(0x2308, 0xb3ff);
+ reg_write(0x2408, 0xb3ff);
+ reg_write(0x2608, 0xb3ff);
+ /* Enable Port ACL
+ * reg_write(0x2P04, 0xff0403);
+ */
+ for (port = 0; port <= 6; port++) {
+ offset = 0x2004 + port * 0x100;
+ reg_read(offset, &value);
+ reg_write(offset, value | (1 << 10));
+ }
+
+ /*IGMP query only p4 -> p5*/
+ reg_write(0x94, 0x00ff0002);
+ if (wan_num == 4)
+ reg_write(0x98, 0x000a1008);
+ else
+ reg_write(0x98, 0x000a0108);
+ reg_write(0x90, 0x80005000);
+ reg_write(0x94, 0xff001100);
+ if (wan_num == 4)
+ reg_write(0x98, 0x000B1000);
+ else
+ reg_write(0x98, 0x000B0100);
+ reg_write(0x90, 0x80005001);
+ reg_write(0x94, 0x3);
+ reg_write(0x98, 0x0);
+ reg_write(0x90, 0x80009000);
+ reg_write(0x94, 0x1a002080);
+ reg_write(0x98, 0x0);
+ reg_write(0x90, 0x8000b000);
+
+ /*IGMP p5 -> p4*/
+ reg_write(0x94, 0x00ff0002);
+ reg_write(0x98, 0x000a2008);
+ reg_write(0x90, 0x80005002);
+ reg_write(0x94, 0x4);
+ reg_write(0x98, 0x0);
+ reg_write(0x90, 0x80009001);
+ if (wan_num == 4)
+ reg_write(0x94, 0x1a001080);
+ else
+ reg_write(0x94, 0x1a000180);
+ reg_write(0x98, 0x0);
+ reg_write(0x90, 0x8000b001);
+
+ /*IGMP p0~p3 -> p6*/
+ reg_write(0x94, 0x00ff0002);
+ if (wan_num == 4)
+ reg_write(0x98, 0x000a0f08);
+ else
+ reg_write(0x98, 0x000a1e08);
+ reg_write(0x90, 0x80005003);
+ reg_write(0x94, 0x8);
+ reg_write(0x98, 0x0);
+ reg_write(0x90, 0x80009002);
+ reg_write(0x94, 0x1a004080);
+ reg_write(0x98, 0x0);
+ reg_write(0x90, 0x8000b002);
+
+ /*IGMP query only p6 -> p0~p3*/
+ reg_write(0x94, 0x00ff0002);
+ reg_write(0x98, 0x000a4008);
+ reg_write(0x90, 0x80005004);
+ reg_write(0x94, 0xff001100);
+ reg_write(0x98, 0x000B4000);
+ reg_write(0x90, 0x80005005);
+ reg_write(0x94, 0x30);
+ reg_write(0x98, 0x0);
+ reg_write(0x90, 0x80009003);
+ if (wan_num == 4)
+ reg_write(0x94, 0x1a000f80);
+ else
+ reg_write(0x94, 0x1a001e80);
+ reg_write(0x98, 0x0);
+ reg_write(0x90, 0x8000b003);
+
+ /*Force eth2 to receive all igmp packets*/
+ sprintf(cmd,"echo 2 > /sys/devices/virtual/net/%s/brif/%s/multicast_router",BR_DEVNAME,ETH_DEVNAME);
+ system(cmd);
+}
+
+void igmp_disable(int argc, char *argv[])
+{
+ unsigned int reg_offset, value;
+ int port_num;
+
+ if (argc < 4) {
+ printf("insufficient arguments!\n");
+ return;
+ }
+ port_num = strtoul(argv[3], NULL, 0);
+ if (port_num < 0 || 6 < port_num) {
+ printf("wrong port range, should be within 0~6\n");
+ return;
+ }
+
+ //set ISC: IGMP Snooping Control Register (offset: 0x0018)
+ reg_offset = 0x2008;
+ reg_offset |= (port_num << 8);
+ value = 0x8000;
+
+ reg_write(reg_offset, value);
+}
+
+void igmp_enable(int argc, char *argv[])
+{
+ unsigned int reg_offset, value;
+ int port_num;
+
+ if (argc < 4) {
+ printf("insufficient arguments!\n");
+ return;
+ }
+ port_num = strtoul(argv[3], NULL, 0);
+ if (port_num < 0 || 6 < port_num) {
+ printf("wrong port range, should be within 0~6\n");
+ return;
+ }
+
+ //set ISC: IGMP Snooping Control Register (offset: 0x0018)
+ reg_offset = 0x2008;
+ reg_offset |= (port_num << 8);
+ value = 0x9755;
+ reg_write(reg_offset, value);
+}
+
+void igmp_off()
+{
+ unsigned int value;
+ //set ISC: IGMP Snooping Control Register (offset: 0x0018)
+ reg_read(REG_ISC_ADDR, &value);
+ value &= ~(1 << 18); //disable
+ reg_write(REG_ISC_ADDR, value);
+
+ /*restore wan port multicast leaky vlan function: default disabled*/
+ reg_read(0x2010, &value);
+ reg_write(0x2010, value & (~(1 << 3)));
+ reg_read(0x2410, &value);
+ reg_write(0x2410, value & (~(1 << 3)));
+
+ printf("config igmpsnoop off.\n");
+}
+
+void switch_reset(int argc, char *argv[])
+{
+ unsigned int value = 0;
+ /*Software Register Reset and Software System Reset */
+ reg_write(0x7000, 0x3);
+ reg_read(0x7000, &value);
+ printf("SYS_CTRL(0x7000) register value =0x%x \n", value);
+ if (chip_name == 0x7531) {
+ reg_write(0x7c0c, 0x11111111);
+ reg_read(0x7c0c, &value);
+ printf("GPIO Mode (0x7c0c) select value =0x%x \n", value);
+ }
+ printf("Switch Software Reset !!! \n");
+}
+
+int phy_set_fc(int argc, char *argv[])
+{
+ unsigned int port, pause_capable;
+ unsigned int phy_value;
+
+ port = atoi(argv[3]);
+ pause_capable = atoi(argv[4]);
+
+ /*Check the input parameters is right or not.*/
+ if (port < 0 || port > MAX_PORT-2 || pause_capable < 0
+ || pause_capable > 1) {
+ printf("Illegal parameter (port:0~4, full_duplex_pause_capable:0|1)\n");
+ return -1;
+ }
+ printf("port=%d, full_duplex_pause_capable:%d\n", port, pause_capable);
+ mii_mgr_read(port, 4, &phy_value);
+ printf("read phy_value:0x%x\r\n", phy_value);
+ phy_value &= (~(0x1 << 10));
+ phy_value &= (~(0x1 << 11));
+ if (pause_capable == 1) {
+ phy_value |= (0x1 << 10);
+ phy_value |= (0x1 << 11);
+ }
+ mii_mgr_write(port, 4, phy_value);
+ printf("write phy_value:0x%x\r\n", phy_value);
+ return 0;
+} /*end phy_set_fc*/
+
+int phy_set_an(int argc, char *argv[])
+{
+ unsigned int port, auto_negotiation_en;
+ unsigned int phy_value;
+
+ port = atoi(argv[3]);
+ auto_negotiation_en = atoi(argv[4]);
+
+ /*Check the input parameters is right or not.*/
+ if (port < 0 || port > MAX_PORT-2 || auto_negotiation_en < 0
+ || auto_negotiation_en > 1) {
+ printf("Illegal parameter (port:0~4, auto_negotiation_en:0|1)\n");
+ return -1;
+ }
+ printf("port=%d, auto_negotiation_en:%d\n", port, auto_negotiation_en);
+ mii_mgr_read(port, 0, &phy_value);
+ printf("read phy_value:0x%x\r\n", phy_value);
+ phy_value &= (~(1 << 12));
+ phy_value |= (auto_negotiation_en << 12);
+ mii_mgr_write(port, 0, phy_value);
+ printf("write phy_value:0x%x\r\n", phy_value);
+ return 0;
+} /*end phy_set_an*/
+
+int set_mac_pfc(int argc, char *argv[])
+{
+ unsigned int value;
+ unsigned char port, enable = 0;
+
+ port = atoi(argv[3]);
+ enable = atoi(argv[4]);
+ printf("enable: %d\n", enable);
+ if (port < 0 || port > 6 || enable < 0 || enable > 1) {
+ printf("Illegal parameter (port:0~6, enable|diable:0|1) \n");
+ return -1;
+ }
+ if (chip_name == 0x7531) {
+ reg_read(REG_PFC_CTRL_ADDR, &value);
+ value &= ~(1 << port);
+ value |= (enable << port);
+ printf("write reg: %x, value: %x\n", REG_PFC_CTRL_ADDR, value);
+ reg_write(REG_PFC_CTRL_ADDR, value);
+ }
+ else
+ printf("\nCommand not support by this chip.\n");
+ return 0;
+}
+
+int global_set_mac_fc(int argc, char *argv[])
+{
+ unsigned char enable = 0;
+ unsigned int value, reg;
+
+ if (chip_name == 0x7530) {
+ enable = atoi(argv[3]);
+ printf("enable: %d\n", enable);
+
+ /*Check the input parameters is right or not.*/
+ if (enable > 1) {
+ printf(HELP_MACCTL_FC);
+ return -1;
+ }
+ reg_write(0x7000, 0x3);
+ reg = REG_GFCCR0_ADDR;
+ reg_read(REG_GFCCR0_ADDR, &value);
+ value &= (~REG_FC_EN_MASK);
+ value |= (enable << REG_FC_EN_OFFT);
+ printf("write reg: %x, value: %x\n", reg, value);
+ reg_write(REG_GFCCR0_ADDR, value);
+ } else
+ printf("\r\nCommand not support by this chip.\n");
+ return 0;
+} /*end mac_set_fc*/
+
+int qos_sch_select(int argc, char *argv[])
+{
+ unsigned char type = 0, port, queue;
+ unsigned int value, reg;
+
+ if (argc < 7)
+ return -1;
+
+ port = atoi(argv[3]);
+ queue = atoi(argv[4]);
+ type = atoi(argv[6]);
+
+ if (port < 0 || port > 6 || queue < 0 || queue > 7) {
+ printf("\n Illegal input parameters\n");
+ return -1;
+ }
+ if ((type != 0 && type != 1 && type != 2)) {
+ printf(HELP_QOS_TYPE);
+ return -1;
+ }
+
+ printf("\r\nswitch qos type: %d.\n",type);
+
+ if (!strncmp(argv[5], "min", 4)) {
+
+ if (type == 0) {
+ /*min sharper-->round roubin, disable min sharper rate limit*/
+ reg = GSW_MMSCR0_Q(queue) + 0x100 * port;
+ reg_read(reg, &value);
+ value &= (0x0);
+ reg_write(reg, value);
+ } else if (type == 1) {
+ /*min sharper-->sp, disable min sharper rate limit*/
+ reg = GSW_MMSCR0_Q(queue) + 0x100 * port;
+ reg_read(reg, &value);
+ value &= (0x0);
+ value |= (1 << 31);
+ reg_write(reg, value);
+ } else {
+ printf("min sharper only support: rr or sp\n");
+ return -1;
+ }
+ } else if (!strncmp(argv[5], "max", 4)) {
+ if (type == 1) {
+ /*max sharper-->sp, disable max sharper rate limit*/
+ reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
+ reg_read(reg, &value);
+ value &= (0x0);
+ value |= (1 << 31);
+ reg_write(reg, value);
+ } else if (type == 2) {
+ /*max sharper-->wfq, disable max sharper rate limit*/
+ reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
+ reg_read(reg, &value);
+ value &= (0x0);
+ reg_write(reg, value);
+ } else {
+ printf("max sharper only support: wfq or sp\n");
+ return -1;
+ }
+ } else {
+ printf("\r\nIllegal sharper:%s\n",argv[5]);
+ return -1;
+ }
+ printf("reg:0x%x--value:0x%x\n",reg,value);
+
+ return 0;
+}
+
+void get_upw(int *value, unsigned char base)
+{
+ *value &= (~((0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) |
+ (0x7 << 16) | (0x7 << 20)));
+ switch (base)
+ {
+ case 0: /* port-based 0x2x40[18:16] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x7 << 16) | (0x2 << 20));
+ break;
+ case 1: /* tagged-based 0x2x40[10:8] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x7 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ case 2: /* DSCP-based 0x2x40[14:12] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x7 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ case 3: /* acl-based 0x2x40[2:0] */
+ *value |= ((0x7 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ case 4: /* arl-based 0x2x40[22:20] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x7 << 20));
+ break;
+ case 5: /* stag-based 0x2x40[6:4] */
+ *value |= ((0x2 << 0) | (0x7 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ default:
+ break;
+ }
+}
+
+void qos_set_base(int argc, char *argv[])
+{
+ unsigned char base = 0, port;
+ unsigned int value;
+
+ if (argc < 5)
+ return;
+
+ port = atoi(argv[3]);
+ base = atoi(argv[4]);
+
+ if ((base < 0 || base > 6)) {
+ printf(HELP_QOS_BASE);
+ return;
+ }
+
+ if ((port < 0 || port > 6)) {
+ printf("Illegal port index:%d\n",port);
+ return;
+ }
+
+ printf("\r\nswitch qos base : %d. (port-based:0, tag-based:1,\
+ dscp-based:2, acl-based:3, arl-based:4, stag-based:5)\n",
+ base);
+ if (chip_name == 0x7530) {
+
+ reg_read(0x44, &value);
+ get_upw(&value, base);
+ reg_write(0x44, value);
+ printf("reg: 0x44, value: 0x%x\n", value);
+
+ } else if (chip_name == 0x7531) {
+
+ reg_read(GSW_UPW(port), &value);
+ get_upw(&value, base);
+ reg_write(GSW_UPW(port), value);
+ printf("reg:0x%x, value: 0x%x\n",GSW_UPW(port),value);
+
+ } else {
+ printf("unknown switch device");
+ return;
+ }
+}
+
+void qos_wfq_set_weight(int argc, char *argv[])
+{
+ unsigned char port, queue, weight[8], i;
+ unsigned int reg, value;
+
+ port = atoi(argv[3]);
+
+ for (i = 0; i < 8; i++) {
+ weight[i] = atoi(argv[i + 4]);
+ }
+
+ /* MT7530 total 7 port */
+ if (port < 0 || port > 6) {
+ printf(HELP_QOS_PORT_WEIGHT);
+ return;
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (weight[i] < 1 || weight[i] > 16) {
+ printf(HELP_QOS_PORT_WEIGHT);
+ return;
+ }
+ }
+ printf("port: %x, q0: %x, q1: %x, q2: %x, q3: %x, \
+ 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]);
+
+ for (queue = 0; queue < 8; queue++) {
+ reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
+ reg_read(reg, &value);
+ value &= (~(0xf << 24)); //bit24~27
+ value |= (((weight[queue] - 1) & 0xf) << 24);
+ printf("reg: %x, value: %x\n", reg, value);
+ reg_write(reg, value);
+ }
+}
+
+void qos_set_portpri(int argc, char *argv[])
+{
+ unsigned char port, prio;
+ unsigned int value;
+
+ port = atoi(argv[3]);
+ prio = atoi(argv[4]);
+
+ if ((port < 0 || port >= 7) || (prio < 0 || prio > 7)) {
+ printf(HELP_QOS_PORT_PRIO);
+ return;
+ }
+
+ reg_read(GSW_PCR(port), &value);
+ value &= (~(0x7 << 24));
+ value |= (prio << 24);
+ reg_write(GSW_PCR(port), value);
+ printf("write reg: %x, value: %x\n", GSW_PCR(port), value);
+}
+
+void qos_set_dscppri(int argc, char *argv[])
+{
+ unsigned char prio, dscp, pim_n, pim_offset;
+ unsigned int reg, value;
+
+ dscp = atoi(argv[3]);
+ prio = atoi(argv[4]);
+
+ if ((dscp < 0 || dscp > 63) || (prio < 0 || prio > 7)) {
+ printf(HELP_QOS_DSCP_PRIO);
+ return;
+ }
+
+ pim_n = dscp / 10;
+ pim_offset = (dscp - pim_n * 10) * 3;
+ reg = 0x0058 + pim_n * 4;
+ reg_read(reg, &value);
+ value &= (~(0x7 << pim_offset));
+ value |= ((prio & 0x7) << pim_offset);
+ reg_write(reg, value);
+ printf("write reg: %x, value: %x\n", reg, value);
+}
+
+void qos_pri_mapping_queue(int argc, char *argv[])
+{
+ unsigned char prio, queue, pem_n, port;
+ unsigned int reg, value;
+
+ if (argc < 6)
+ return;
+
+ port = atoi(argv[3]);
+ prio = atoi(argv[4]);
+ queue = atoi(argv[5]);
+
+ if ((prio < 0 || prio > 7) || (queue < 0 || queue > 7)) {
+ printf(HELP_QOS_PRIO_QMAP);
+ return;
+ }
+ if (chip_name == 0x7530) {
+ pem_n = prio / 2;
+ reg = pem_n * 0x4 + 0x48;
+ reg_read(reg, &value);
+ if (prio % 2) {
+ value &= (~(0x7 << 24));
+ value |= ((queue & 0x7) << 24);
+ } else {
+ value &= (~(0x7 << 8));
+ value |= ((queue & 0x7) << 8);
+ }
+ reg_write(reg, value);
+ printf("write reg: %x, value: %x\n", reg, value);
+ } else if (chip_name == 0x7531) {
+ pem_n = prio / 2;
+ reg = GSW_PEM(pem_n) + 0x100 * port;
+ reg_read(reg, &value);
+ if (prio % 2) { // 1 1
+ value &= (~(0x7 << 25));
+ value |= ((queue & 0x7) << 25);
+ } else { // 0 0
+ value &= (~(0x7 << 9));
+ value |= ((queue & 0x7) << 9);
+ }
+ reg_write(reg, value);
+ printf("write reg: %x, value: %x\n", reg, value);
+ }
+ else {
+ printf("unknown switch device");
+ return;
+ }
+}
+
+static int macMT753xVlanSetVid(unsigned char index, unsigned char active,
+ unsigned short vid, unsigned char portMap, unsigned char tagPortMap,
+ unsigned char ivl_en, unsigned char fid, unsigned short stag)
+{
+ unsigned int value = 0;
+ unsigned int value2 = 0;
+ int reg = 0;
+ int i;
+
+ printf("index: %x, active: %x, vid: %x, portMap: %x, \
+ tagPortMap: %x, ivl_en: %x, fid: %x, stag: %x\n",
+ index, active, vid, portMap, tagPortMap, ivl_en, fid, stag);
+
+ value = (portMap << 16);
+ value |= (stag << 4);
+ value |= (ivl_en << 30);
+ value |= (fid << 1);
+ value |= (active ? 1 : 0);
+
+ // total 7 ports
+ for (i = 0; i < 7; i++) {
+ if (tagPortMap & (1 << i))
+ value2 |= 0x2 << (i * 2);
+ }
+
+ if (value2)
+ value |= (1 << 28); // eg_tag
+
+ reg = 0x98; // VAWD2
+ reg_write(reg, value2);
+
+ reg = 0x94; // VAWD1
+ reg_write(reg, value);
+
+ reg = 0x90; // VTCR
+ value = (0x80001000 + vid);
+ reg_write(reg, value);
+
+ reg = 0x90; // VTCR
+ while (1) {
+ reg_read(reg, &value);
+ if ((value & 0x80000000) == 0) //table busy
+ break;
+ }
+
+ /* switch clear */
+ reg = 0x80;
+ reg_write(reg, 0x8002);
+ usleep(5000);
+ reg_read(reg, &value);
+
+ printf("SetVid: index:%d active:%d vid:%d portMap:%x tagPortMap:%x\r\n",
+ index, active, vid, portMap, tagPortMap);
+ return 0;
+
+} /*end macMT753xVlanSetVid*/
+
+static int macMT753xVlanGetVtbl(unsigned short index)
+{
+ unsigned short vid = 0;
+ unsigned int reg, value, vawd1, vawd2;
+
+ reg = 0x90; // VTCR
+ value = (0x80000000 + index);
+
+ reg_write(reg, value);
+
+ reg = 0x90; // VTCR
+ while (1) {
+ reg_read(reg, &value);
+ if ((value & 0x80000000) == 0) //table busy
+ break;
+ }
+
+ reg = 0x94; // VAWD1
+ reg_read(reg, &vawd1);
+
+ reg = 0x98; // VAWD2
+ reg_read(reg, &vawd2);
+
+ if (vawd1 & 0x1) {
+ fprintf(stderr, "%d.%s vid:%d fid:%d portMap:0x%x \
+ tagMap:0x%x stag:0x%x ivl_en:0x%x\r\n",
+ index, (vawd1 & 0x1) ? "on" : "off", index, ((vawd1 & 0xe) >> 1),
+ (vawd1 & 0xff0000) >> 16, vawd2, (vawd1 & 0xfff0) >> 0x4, (vawd1 >> 30) & 0x1);
+ }
+ return 0;
+} /*end macMT753xVlanGetVtbl*/
+
+static int macMT753xVlanSetPvid(unsigned char port, unsigned short pvid)
+{
+ unsigned int value;
+ unsigned int reg;
+
+ /*Parameters is error*/
+ if (port > 6)
+ return -1;
+
+ reg = 0x2014 + (port * 0x100);
+ reg_read(reg, &value);
+ value &= ~0xfff;
+ value |= pvid;
+ reg_write(reg, value);
+
+ /* switch clear */
+ reg = 0x80;
+ reg_write(reg, 0x8002);
+ usleep(5000);
+ reg_read(reg, &value);
+
+ printf("SetPVID: port:%d pvid:%d\r\n", port, pvid);
+ return 0;
+}
+
+static int macMT753xVlanGetPvid(unsigned char port)
+{
+ unsigned int value;
+ unsigned int reg;
+
+ /*Parameters is error*/
+ if (port > 6)
+ return -1;
+ reg = 0x2014 + (port * 0x100);
+ reg_read(reg, &value);
+ return (value & 0xfff);
+}
+
+static int macMT753xVlanDisp(void)
+{
+ unsigned int i = 0;
+ unsigned int reg, value;
+
+ reg = 0x2604;
+ reg_read(reg, &value);
+ value &= 0x30000000;
+
+ fprintf(stderr, "VLAN function is %s\n", value ? ETHCMD_ENABLE : ETHCMD_DISABLE);
+ fprintf(stderr, "PVID e0:%02d e1:%02d e2:%02d e3:%02d e4:%02d e5:%02d e6:%02d\n",
+ macMT753xVlanGetPvid(0), macMT753xVlanGetPvid(1), macMT753xVlanGetPvid(2),
+ macMT753xVlanGetPvid(3), macMT753xVlanGetPvid(4), macMT753xVlanGetPvid(5), macMT753xVlanGetPvid(6));
+
+ for (i = 0; i < MAX_VID_VALUE; i++)
+ macMT753xVlanGetVtbl(i);
+
+} /*end macMT753xVlanDisp*/
+
+void doVlanSetPvid(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned short pvid = 0;
+
+ port = atoi(argv[3]);
+ pvid = atoi(argv[4]);
+ /*Check the input parameters is right or not.*/
+ if ((port >= SWITCH_MAX_PORT) || (pvid > MAX_VID_VALUE)) {
+ printf(HELP_VLAN_PVID);
+ return;
+ }
+
+ macMT753xVlanSetPvid(port, pvid);
+
+ printf("port:%d pvid:%d,vlancap: max_port:%d maxvid:%d\r\n",
+ port, pvid, SWITCH_MAX_PORT, MAX_VID_VALUE);
+} /*end doVlanSetPvid*/
+
+void doVlanSetVid(int argc, char *argv[])
+{
+ unsigned char index = 0;
+ unsigned char active = 0;
+ unsigned char portMap = 0;
+ unsigned char tagPortMap = 0;
+ unsigned short vid = 0;
+
+ unsigned char ivl_en = 0;
+ unsigned char fid = 0;
+ unsigned short stag = 0;
+
+ index = atoi(argv[3]);
+ active = atoi(argv[4]);
+ vid = atoi(argv[5]);
+
+ /*Check the input parameters is right or not.*/
+ if ((index >= MAX_VLAN_RULE) || (vid >= 4096) || (active > ACTIVED)) {
+ printf(HELP_VLAN_VID);
+ return;
+ }
+
+ /*CPU Port is always the membership*/
+ portMap = atoi(argv[6]);
+ tagPortMap = atoi(argv[7]);
+
+ printf("subcmd parameter argc = %d\r\n", argc);
+ if (argc >= 9) {
+ ivl_en = atoi(argv[8]);
+ if (argc >= 10) {
+ fid = atoi(argv[9]);
+ if (argc >= 11)
+ stag = atoi(argv[10]);
+ }
+ }
+ macMT753xVlanSetVid(index, active, vid, portMap, tagPortMap,
+ ivl_en, fid, stag);
+ printf("index:%d active:%d vid:%d\r\n", index, active, vid);
+} /*end doVlanSetVid*/
+
+void doVlanSetAccFrm(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char type = 0;
+ unsigned int value;
+ unsigned int reg;
+
+ port = atoi(argv[3]);
+ type = atoi(argv[4]);
+
+ printf("port: %d, type: %d\n", port, type);
+
+ /*Check the input parameters is right or not.*/
+ if ((port > SWITCH_MAX_PORT) || (type > REG_PVC_ACC_FRM_RELMASK)) {
+ printf(HELP_VLAN_ACC_FRM);
+ return;
+ }
+
+ reg = REG_PVC_P0_ADDR + port * 0x100;
+ reg_read(reg, &value);
+ value &= (~REG_PVC_ACC_FRM_MASK);
+ value |= ((unsigned int)type << REG_PVC_ACC_FRM_OFFT);
+
+ printf("write reg: %x, value: %x\n", reg, value);
+ reg_write(reg, value);
+} /*end doVlanSetAccFrm*/
+
+void doVlanSetPortAttr(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char attr = 0;
+ unsigned int value;
+ unsigned int reg;
+
+ port = atoi(argv[3]);
+ attr = atoi(argv[4]);
+
+ printf("port: %x, attr: %x\n", port, attr);
+
+ /*Check the input parameters is right or not.*/
+ if ((port < 0 || port > SWITCH_MAX_PORT) || (attr < 0 || attr > 3)) {
+ printf(HELP_VLAN_PORT_ATTR);
+ return;
+ }
+
+ reg = 0x2010 + port * 0x100;
+ reg_read(reg, &value);
+ value &= (0xffffff3f);
+ value |= (attr << 6);
+
+ printf("write reg: %x, value: %x\n", reg, value);
+ reg_write(reg, value);
+}
+
+void doVlanSetPortMode(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char mode = 0;
+ unsigned int value;
+ unsigned int reg;
+ port = atoi(argv[3]);
+ mode = atoi(argv[4]);
+ printf("port: %x, mode: %x\n", port, mode);
+
+ /*Check the input parameters is right or not.*/
+ if ((port < 0 || port > SWITCH_MAX_PORT) || (mode < 0 || mode > 3)) {
+ printf(HELP_VLAN_PORT_MODE);
+ return;
+ }
+
+ reg = 0x2004 + port * 0x100;
+ reg_read(reg, &value);
+ value &= (~((1 << 0) | (1 << 1)));
+ value |= (mode & 0x3);
+ printf("write reg: %x, value: %x\n", reg, value);
+ reg_write(reg, value);
+}
+
+void doVlanSetEgressTagPCR(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char eg_tag = 0;
+ unsigned int value;
+ unsigned int reg;
+
+ port = atoi(argv[3]);
+ eg_tag = atoi(argv[4]);
+
+ printf("port: %d, eg_tag: %d\n", port, eg_tag);
+
+ /*Check the input parameters is right or not.*/
+ if ((port > SWITCH_MAX_PORT) || (eg_tag > REG_PCR_EG_TAG_RELMASK)) {
+ printf(HELP_VLAN_EGRESS_TAG_PCR);
+ return;
+ }
+
+ reg = REG_PCR_P0_ADDR + port * 0x100;
+ reg_read(reg, &value);
+ value &= (~REG_PCR_EG_TAG_MASK);
+ value |= ((unsigned int)eg_tag << REG_PCR_EG_TAG_OFFT);
+
+ printf("write reg: %x, value: %x\n", reg, value);
+ reg_write(reg, value);
+
+} /*end doVlanSetEgressTagPCR*/
+
+void doVlanSetEgressTagPVC(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char eg_tag = 0;
+ unsigned int value;
+ unsigned int reg;
+
+ port = atoi(argv[3]);
+ eg_tag = atoi(argv[4]);
+
+ printf("port: %d, eg_tag: %d\n", port, eg_tag);
+
+ /*Check the input parameters is right or not.*/
+ if ((port > SWITCH_MAX_PORT) || (eg_tag > REG_PVC_EG_TAG_RELMASK)) {
+ printf(HELP_VLAN_EGRESS_TAG_PVC);
+ return;
+ }
+
+ reg = REG_PVC_P0_ADDR + port * 0x100;
+ reg_read(reg, &value);
+ value &= (~REG_PVC_EG_TAG_MASK);
+ value |= ((unsigned int)eg_tag << REG_PVC_EG_TAG_OFFT);
+
+ printf("write reg: %x, value: %x\n", reg, value);
+ reg_write(reg, value);
+} /*end doVlanSetEgressTagPVC*/
+
+void doArlAging(int argc, char *argv[])
+{
+ unsigned char aging_en = 0;
+ unsigned int time = 0, aging_cnt = 0, aging_unit = 0, value, reg;
+ ;
+
+ aging_en = atoi(argv[3]);
+ time = atoi(argv[4]);
+ printf("aging_en: %x, aging time: %x\n", aging_en, time);
+
+ /*Check the input parameters is right or not.*/
+ if ((aging_en != 0 && aging_en != 1) || (time <= 0 || time > 65536)) {
+ printf(HELP_ARL_AGING);
+ return;
+ }
+
+ reg = 0xa0;
+ reg_read(reg, &value);
+ value &= (~(1 << 20));
+ if (!aging_en) {
+ value |= (1 << 20);
+ }
+
+ aging_unit = (time / 0x100) + 1;
+ aging_cnt = (time / aging_unit);
+ aging_unit--;
+ aging_cnt--;
+
+ value &= (0xfff00000);
+ value |= ((aging_cnt << 12) | aging_unit);
+
+ printf("aging_unit: %x, aging_cnt: %x\n", aging_unit, aging_cnt);
+ printf("write reg: %x, value: %x\n", reg, value);
+
+ reg_write(reg, value);
+}
+
+void doMirrorEn(int argc, char *argv[])
+{
+ unsigned char mirror_en;
+ unsigned char mirror_port;
+ unsigned int value, reg;
+
+ mirror_en = atoi(argv[3]);
+ mirror_port = atoi(argv[4]);
+
+ printf("mirror_en: %d, mirror_port: %d\n", mirror_en, mirror_port);
+
+ /*Check the input parameters is right or not.*/
+ if ((mirror_en > 1) || (mirror_port > REG_CFC_MIRROR_PORT_RELMASK)) {
+ printf(HELP_MIRROR_EN);
+ return;
+ }
+
+ reg = REG_CFC_ADDR;
+ reg_read(reg, &value);
+ value &= (~REG_CFC_MIRROR_EN_MASK);
+ value |= (mirror_en << REG_CFC_MIRROR_EN_OFFT);
+ value &= (~REG_CFC_MIRROR_PORT_MASK);
+ value |= (mirror_port << REG_CFC_MIRROR_PORT_OFFT);
+
+ printf("write reg: %x, value: %x\n", reg, value);
+ reg_write(reg, value);
+
+} /*end doMirrorEn*/
+
+void doMirrorPortBased(int argc, char *argv[])
+{
+ unsigned char port, port_tx_mir, port_rx_mir, vlan_mis, acl_mir, igmp_mir;
+ unsigned int value, reg;
+
+ port = atoi(argv[3]);
+ port_tx_mir = atoi(argv[4]);
+ port_rx_mir = atoi(argv[5]);
+ acl_mir = atoi(argv[6]);
+ vlan_mis = atoi(argv[7]);
+ igmp_mir = atoi(argv[8]);
+
+ printf("port:%d, port_tx_mir:%d, port_rx_mir:%d, acl_mir:%d, vlan_mis:%d, igmp_mir:%d\n", port, port_tx_mir, port_rx_mir, acl_mir, vlan_mis, igmp_mir);
+
+ /*Check the input parameters is right or not.*/
+ //if((port >= vlanCap->max_port_no) || (port_tx_mir > 1) || (port_rx_mir > 1) || (acl_mir > 1) || (vlan_mis > 1)){
+ if ((port >= 7) || (port_tx_mir > 1) || (port_rx_mir > 1) || (acl_mir > 1) || (vlan_mis > 1)) { // also allow CPU port (port6)
+ printf(HELP_MIRROR_PORTBASED);
+ return;
+ }
+
+ reg = REG_PCR_P0_ADDR + port * 0x100;
+ reg_read(reg, &value);
+ value &= ~(REG_PORT_TX_MIR_MASK | REG_PORT_RX_MIR_MASK | REG_PCR_ACL_MIR_MASK | REG_PCR_VLAN_MIS_MASK);
+ value |= (port_tx_mir << REG_PORT_TX_MIR_OFFT) + (port_rx_mir << REG_PORT_RX_MIR_OFFT);
+ value |= (acl_mir << REG_PCR_ACL_MIR_OFFT) + (vlan_mis << REG_PCR_VLAN_MIS_OFFT);
+
+ printf("write reg: %x, value: %x\n", reg, value);
+ reg_write(reg, value);
+
+ reg = REG_PIC_P0_ADDR + port * 0x100;
+ reg_read(reg, &value);
+ value &= ~(REG_PIC_IGMP_MIR_MASK);
+ value |= (igmp_mir << REG_PIC_IGMP_MIR_OFFT);
+
+ printf("write reg: %x, value: %x\n", reg, value);
+ reg_write(reg, value);
+
+} /*end doMirrorPortBased*/
+
+void doStp(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char fid = 0;
+ unsigned char state = 0;
+ unsigned int value;
+ unsigned int reg;
+
+ port = atoi(argv[2]);
+ fid = atoi(argv[3]);
+ state = atoi(argv[4]);
+
+ printf("port: %d, fid: %d, state: %d\n", port, fid, state);
+
+ /*Check the input parameters is right or not.*/
+ if ((port > MAX_PORT + 1) || (fid > 7) || (state > 3)) {
+ printf(HELP_STP);
+ return;
+ }
+
+ reg = REG_SSC_P0_ADDR + port * 0x100;
+ reg_read(reg, &value);
+ value &= (~(3 << (fid << 2)));
+ value |= ((unsigned int)state << (fid << 2));
+
+ printf("write reg: %x, value: %x\n", reg, value);
+ reg_write(reg, value);
+}
+
+int ingress_rate_set(int on_off, int port, int bw)
+{
+ unsigned int reg, value;
+
+ reg = 0x1800 + (0x100 * port);
+ value = 0;
+ /*token-bucket*/
+ if (on_off == 1) {
+ if (chip_name == 0x7530) {
+ if (bw < 0 || bw > 1000000) {
+ printf("\n**Charge rate(%d) is larger than line rate(1000000kbps)**\n",bw);
+ return -1;
+ }
+ value = ((bw / 32) << 16) + (1 << 15) + (7 << 8) + (1 << 7) + 0x0f;
+ } else if (chip_name == 0x7531) {
+ if (bw < 0 || bw > 2500000) {
+ printf("\n**Charge rate(%d) is larger than line rate(2500000kbps)**\n",bw);
+ return -1;
+ }
+ if (bw/32 >= 65536) //supoort 2.5G case
+ value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (1 << 12) + (7 << 8) + 0xf;
+ else
+ value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (7 << 8) + 0xf;
+ }
+ else
+ printf("unknow chip\n");
+ }
+
+#if leaky_bucket
+ reg_read(reg, &value);
+ value &= 0xffff0000;
+ if (on_off == 1)
+ {
+ value |= on_off << 15;
+ //7530 same as 7531
+ if (bw < 100) {
+ value |= (0x0 << 8);
+ value |= bw;
+ } else if (bw < 1000) {
+ value |= (0x1 << 8);
+ value |= bw / 10;
+ } else if (bw < 10000) {
+ value |= (0x2 << 8);
+ value |= bw / 100;
+ } else if (bw < 100000) {
+ value |= (0x3 << 8);
+ value |= bw / 1000;
+ } else {
+ value |= (0x4 << 8);
+ value |= bw / 10000;
+ }
+ }
+#endif
+ reg_write(reg, value);
+ reg = 0x1FFC;
+ reg_read(reg, &value);
+ value = 0x110104;
+ reg_write(reg, value);
+ return 0;
+}
+
+int egress_rate_set(int on_off, int port, int bw)
+{
+ unsigned int reg, value;
+
+ reg = 0x1040 + (0x100 * port);
+ value = 0;
+ /*token-bucket*/
+ if (on_off == 1) {
+ if (chip_name == 0x7530) {
+ if (bw < 0 || bw > 1000000) {
+ printf("\n**Charge rate(%d) is larger than line rate(1000000kbps)**\n",bw);
+ return -1;
+ }
+ value = ((bw / 32) << 16) + (1 << 15) + (7 << 8) + (1 << 7) + 0xf;
+ } else if (chip_name == 0x7531) {
+ if (bw < 0 || bw > 2500000) {
+ printf("\n**Charge rate(%d) is larger than line rate(2500000kbps)**\n",bw);
+ return -1;
+ }
+ if (bw/32 >= 65536) //support 2.5G cases
+ value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (1 << 12) + (7 << 8) + 0xf;
+ else
+ value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (7 << 8) + 0xf;
+ }
+ else
+ printf("unknow chip\n");
+ }
+ reg_write(reg, value);
+ reg = 0x10E0;
+ reg_read(reg, &value);
+ value &= 0x18;
+ reg_write(reg, value);
+
+ return 0;
+}
+
+void rate_control(int argc, char *argv[])
+{
+ unsigned char dir = 0;
+ unsigned char port = 0;
+ unsigned int rate = 0;
+
+ dir = atoi(argv[2]);
+ port = atoi(argv[3]);
+ rate = atoi(argv[4]);
+
+ if (rate < 0)
+ return;
+
+ if (dir == 1) //ingress
+ ingress_rate_set(1, port, rate);
+ else if (dir == 0) //egress
+ egress_rate_set(1, port, rate);
+ else
+ return;
+}
+
+int collision_pool_enable(int argc, char *argv[])
+{
+
+ unsigned char enable;
+ unsigned int value, reg;
+
+ enable = atoi(argv[3]);
+
+
+ printf("collision pool enable: %d \n", enable);
+
+ /*Check the input parameters is right or not.*/
+ if ((enable > 1) || (enable < 0)) {
+ printf(HELP_COLLISION_POOL_EN);
+ return -1;
+ }
+
+ if (chip_name == 0x7531) {
+ reg = REG_CPGC_ADDR;
+ if(enable == 1) {
+ /* active reset */
+ reg_read(reg, &value);
+ value &= (~REG_CPCG_COL_RST_N_MASK);
+ reg_write(reg, value);
+
+ /* enanble clock */
+ reg_read(reg, &value);
+ value &= (~REG_CPCG_COL_CLK_EN_MASK);
+ value |= (1 << REG_CPCG_COL_CLK_EN_OFFT);
+ reg_write(reg, value);
+
+ /* inactive reset */
+ reg_read(reg, &value);
+ value &= (~REG_CPCG_COL_RST_N_MASK);
+ value |= (1 << REG_CPCG_COL_RST_N_OFFT);
+ reg_write(reg, value);
+
+ /* enable collision pool */
+ reg_read(reg, &value);
+ value &= (~REG_CPCG_COL_EN_MASK);
+ value |= (1 << REG_CPCG_COL_EN_OFFT);
+ reg_write(reg, value);
+
+ reg_read(reg, &value);
+ printf("write reg: %x, value: %x\n", reg, value);
+ }else {
+
+ /* disable collision pool */
+ reg_read(reg, &value);
+ value &= (~REG_CPCG_COL_EN_MASK);
+ reg_write(reg, value);
+
+ /* active reset */
+ reg_read(reg, &value);
+ value &= (~REG_CPCG_COL_RST_N_MASK);
+ reg_write(reg, value);
+
+ /* inactive reset */
+ reg_read(reg, &value);
+ value &= (~REG_CPCG_COL_RST_N_MASK);
+ value |= (1 << REG_CPCG_COL_RST_N_OFFT);
+ reg_write(reg, value);
+
+ /* disable clock */
+ reg_read(reg, &value);
+ value &= (~REG_CPCG_COL_CLK_EN_MASK);
+ reg_write(reg, value);
+
+ reg_read(reg, &value);
+ printf("write reg: %x, value: %x\n", reg, value);
+
+ }
+ }else{
+ printf("\nCommand not support by this chip.\n");
+}
+
+ return 0;
+}
+
+void collision_pool_mac_dump()
+{
+ unsigned int value, reg;
+
+ if (chip_name == 0x7531) {
+ reg = REG_CPGC_ADDR;
+ reg_read(reg, &value);
+ if(value & REG_CPCG_COL_EN_MASK)
+ table_dump_internal(COLLISION_TABLE);
+ else
+ printf("\ncollision pool is disabled, please enable it before use this command.\n");
+ }else {
+ printf("\nCommand not support by this chip.\n");
+ }
+}
+
+void collision_pool_dip_dump()
+{
+ unsigned int value, reg;
+
+ if (chip_name == 0x7531) {
+ reg = REG_CPGC_ADDR;
+ reg_read(reg, &value);
+ if(value & REG_CPCG_COL_EN_MASK)
+ dip_dump_internal(COLLISION_TABLE);
+ else
+ printf("\ncollision pool is disabled, please enable it before use this command.\n");
+ }else {
+ printf("\nCommand not support by this chip.\n");
+ }
+
+
+}
+
+void collision_pool_sip_dump()
+{
+ unsigned int value, reg;
+
+ if (chip_name == 0x7531) {
+ reg = REG_CPGC_ADDR;
+ reg_read(reg, &value);
+ if(value & REG_CPCG_COL_EN_MASK)
+ sip_dump_internal(COLLISION_TABLE);
+ else
+ printf("\ncollision pool is disabled, please enable it before use this command.\n");
+ }else {
+ printf("\nCommand not support by this chip.\n");
+ }
+
+
+}
+
+void pfc_get_rx_counter(int argc, char *argv[])
+{
+ int port;
+ unsigned int value, reg;
+ unsigned int user_pri;
+
+ port = strtoul(argv[3], NULL, 0);
+ if (port < 0 || 6 < port) {
+ printf("wrong port range, should be within 0~6\n");
+ return;
+ }
+
+ if (chip_name == 0x7531) {
+ reg= PFC_RX_COUNTER_L(port);
+ reg_read(reg, &value);
+ user_pri = value & 0xff;
+ printf("\n port %d rx pfc (up=0)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff00) >> 8;
+ printf("\n port %d rx pfc (up=1)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff0000) >> 16;
+ printf("\n port %d rx pfc (up=2)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff000000) >> 24;
+ printf("\n port %d rx pfc (up=3)pause on counter is %d.\n", port,user_pri);
+
+ reg= PFC_RX_COUNTER_H(port);
+ reg_read(reg, &value);
+ user_pri = value & 0xff;
+ printf("\n port %d rx pfc (up=4)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff00) >> 8;
+ printf("\n port %d rx pfc (up=5)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff0000) >> 16;
+ printf("\n port %d rx pfc (up=6)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff000000) >> 24;
+ printf("\n port %d rx pfc (up=7)pause on counter is %d.\n", port,user_pri);
+
+ /* for rx counter could be updated successfully */
+ reg_read(PMSR_P(port), &value);
+ reg_read(PMSR_P(port), &value);
+ }else {
+ printf("\nCommand not support by this chip.\n");
+ }
+
+}
+
+void pfc_get_tx_counter(int argc, char *argv[])
+{
+ int port;
+ unsigned int value, reg;
+ unsigned int user_pri;
+
+ port = strtoul(argv[3], NULL, 0);
+ if (port < 0 || 6 < port) {
+ printf("wrong port range, should be within 0~6\n");
+ return;
+ }
+
+ if (chip_name == 0x7531) {
+ reg= PFC_TX_COUNTER_L(port);
+ reg_read(reg, &value);
+ user_pri = value & 0xff;
+ printf("\n port %d tx pfc (up=0)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff00) >> 8;
+ printf("\n port %d tx pfc (up=1)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff0000) >> 16;
+ printf("\n port %d tx pfc (up=2)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff000000) >> 24;
+ printf("\n port %d tx pfc (up=3)pause on counter is %d.\n", port,user_pri);
+
+ reg= PFC_TX_COUNTER_H(port);
+ reg_read(reg, &value);
+ user_pri = value & 0xff;
+ printf("\n port %d tx pfc (up=4)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff00) >> 8;
+ printf("\n port %d tx pfc (up=5)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff0000) >> 16;
+ printf("\n port %d tx pfc (up=6)pause on counter is %d.\n", port,user_pri);
+ user_pri = (value & 0xff000000) >> 24;
+ printf("\n port %d tx pfc (up=7)pause on counter is %d.\n", port,user_pri);
+
+ /* for tx counter could be updated successfully */
+ reg_read(PMSR_P(port), &value);
+ reg_read(PMSR_P(port), &value);
+ }else {
+ printf("\nCommand not support by this chip.\n");
+ }
+}
+
+void read_output_queue_counters()
+{
+
+unsigned int port=0;
+unsigned int value, output_queue;
+unsigned int base=0x220;
+
+for (port = 0; port < 7; port++) {
+ reg_write(0x7038, base + (port *4));
+ reg_read(0x7034, &value);
+ output_queue = value & 0xff;
+ printf("\n port %d output queue 0 counter is %d.\n", port,output_queue);
+ output_queue = (value & 0xff00) >> 8;
+ printf("\n port %d output queue 1 counter is %d.\n", port,output_queue);
+
+ reg_write(0x7038, base + (port *4) + 1);
+ reg_read(0x7034, &value);
+ output_queue = value & 0xff;
+ printf("\n port %d output queue 2 counter is %d.\n", port,output_queue);
+ output_queue = (value & 0xff00) >> 8;
+ printf("\n port %d output queue 3 counter is %d.\n", port,output_queue);
+
+ reg_write(0x7038, base + (port *4) + 2);
+ reg_read(0x7034, &value);
+ output_queue = value & 0xff;
+ printf("\n port %d output queue 4 counter is %d.\n", port,output_queue);
+ output_queue = (value & 0xff00) >> 8;
+ printf("\n port %d output queue 5 counter is %d.\n", port,output_queue);
+
+ reg_write(0x7038, base + (port *4) + 3);
+ reg_read(0x7034, &value);
+ output_queue = value & 0xff;
+ printf("\n port %d output queue 6 counter is %d.\n", port,output_queue);
+ output_queue = (value & 0xff00) >> 8;
+ printf("\n port %d output queue 7 counter is %d.\n", port,output_queue);
+ }
+}
+
+void read_free_page_counters()
+{
+unsigned int value;
+unsigned int free_page,free_page_last_read;
+unsigned int fc_free_blk_lothd,fc_free_blk_hithd;
+unsigned int fc_port_blk_thd,fc_port_blk_hi_thd;
+unsigned int queue[8]={0};
+
+if (chip_name == 0x7531) {
+ /* get system free page link counter*/
+ reg_read(0x1fc0, &value);
+ free_page = value & 0xFFF;
+ free_page_last_read = (value & 0xFFF0000) >> 16;
+
+ /* get system flow control waterwark */
+ reg_read(0x1fe0, &value);
+ fc_free_blk_lothd = value & 0x3FF;
+ fc_free_blk_hithd = (value & 0x3FF0000) >> 16;
+
+ /* get port flow control waterwark */
+ reg_read(0x1fe4, &value);
+ fc_port_blk_thd = value & 0x3FF;
+ fc_port_blk_hi_thd = (value & 0x3FF0000) >> 16;
+
+ /* get queue flow control waterwark */
+ reg_read(0x1fe8, &value);
+ queue[0]= value & 0x3F;
+ queue[1]= (value & 0x3F00) >> 8;
+ queue[2]= (value & 0x3F0000) >> 16;
+ queue[3]= (value & 0x3F000000) >> 24;
+ reg_read(0x1fec, &value);
+ queue[4]= value & 0x3F;
+ queue[5]= (value & 0x3F00) >> 8;
+ queue[6]= (value & 0x3F0000) >> 16;
+ queue[7]= (value & 0x3F000000) >> 24;
+ }else{
+ /* get system free page link counter*/
+ reg_read(0x1fc0, &value);
+ free_page = value & 0x3FF;
+ free_page_last_read = (value & 0x3FF0000) >> 16;
+
+ /* get system flow control waterwark */
+ reg_read(0x1fe0, &value);
+ fc_free_blk_lothd = value & 0xFF;
+ fc_free_blk_hithd = (value & 0xFF00) >> 8;
+
+ /* get port flow control waterwark */
+ reg_read(0x1fe0, &value);
+ fc_port_blk_thd = (value & 0xFF0000) >> 16;
+ reg_read(0x1ff4, &value);
+ fc_port_blk_hi_thd = (value & 0xFF00) >> 8;
+
+ /* get queue flow control waterwark */
+ reg_read(0x1fe4, &value);
+ queue[0]= value & 0xF;
+ queue[1]= (value & 0xF0) >> 4;
+ queue[2]= (value & 0xF00) >> 8;
+ queue[3]= (value & 0xF000) >>12;
+ queue[4]= (value & 0xF0000) >>16;
+ queue[5]= (value & 0xF00000) >> 20;
+ queue[6]= (value & 0xF000000) >> 24;
+ queue[7]= (value & 0xF0000000) >> 28;
+ }
+
+ printf("<===Free Page=======Current=======Last Read access=====> \n ");
+ printf(" \n ");
+ printf(" page counter %u %u \n ",free_page,free_page_last_read);
+ printf(" \n ");
+ printf("========================================================= \n ");
+ printf("<===Type=======High threshold======Low threshold=========\n ");
+ printf(" \n ");
+ printf(" system: %u %u \n", fc_free_blk_hithd*2, fc_free_blk_lothd*2);
+ printf(" port: %u %u \n", fc_port_blk_hi_thd*2, fc_port_blk_thd*2);
+ printf(" queue 0: %u NA \n", queue[0]);
+ printf(" queue 1: %u NA \n", queue[1]);
+ printf(" queue 2: %u NA \n", queue[2]);
+ printf(" queue 3: %u NA \n", queue[3]);
+ printf(" queue 4: %u NA \n", queue[4]);
+ printf(" queue 5: %u NA \n", queue[5]);
+ printf(" queue 6: %u NA \n", queue[6]);
+ printf(" queue 7: %u NA \n", queue[7]);
+ printf("=========================================================\n ");
+}
+
+void dump_each_port(int base)
+{
+ unsigned int pkt_cnt = 0;
+ int i = 0;
+
+ for (i = 0; i < 7; i++) {
+ reg_read((base) + (i * 0x100), &pkt_cnt);
+ printf("%8u ", pkt_cnt);
+ }
+ printf("\n");
+}
+
+void read_mib_counters()
+{
+ printf("===================== %8s %8s %8s %8s %8s %8s %8s\n",
+ "Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6");
+ printf("Tx Drop Packet :");
+ dump_each_port(0x4000);
+ printf("Tx CRC Error :");
+ dump_each_port(0x4004);
+ printf("Tx Unicast Packet :");
+ dump_each_port(0x4008);
+ printf("Tx Multicast Packet :");
+ dump_each_port(0x400C);
+ printf("Tx Broadcast Packet :");
+ dump_each_port(0x4010);
+ printf("Tx Collision Event :");
+ dump_each_port(0x4014);
+ printf("Tx Pause Packet :");
+ dump_each_port(0x402C);
+ printf("Rx Drop Packet :");
+ dump_each_port(0x4060);
+ printf("Rx Filtering Packet :");
+ dump_each_port(0x4064);
+ printf("Rx Unicast Packet :");
+ dump_each_port(0x4068);
+ printf("Rx Multicast Packet :");
+ dump_each_port(0x406C);
+ printf("Rx Broadcast Packet :");
+ dump_each_port(0x4070);
+ printf("Rx Alignment Error :");
+ dump_each_port(0x4074);
+ printf("Rx CRC Error :");
+ dump_each_port(0x4078);
+ printf("Rx Undersize Error :");
+ dump_each_port(0x407C);
+ printf("Rx Fragment Error :");
+ dump_each_port(0x4080);
+ printf("Rx Oversize Error :");
+ dump_each_port(0x4084);
+ printf("Rx Jabber Error :");
+ dump_each_port(0x4088);
+ printf("Rx Pause Packet :");
+ dump_each_port(0x408C);
+}
+
+void clear_mib_counters()
+{
+ reg_write(0x4fe0, 0xf0);
+ read_mib_counters();
+ reg_write(0x4fe0, 0x800000f0);
+}
+
+
+void exit_free()
+{
+ free(attres);
+ attres = NULL;
+ switch_ioctl_fini();
+ mt753x_netlink_free();
+}
diff --git a/recipes-devtools/switch/files/switch_fun.h b/recipes-devtools/switch/files/switch_fun.h
new file mode 100644
index 0000000..57a2345
--- /dev/null
+++ b/recipes-devtools/switch/files/switch_fun.h
@@ -0,0 +1,139 @@
+/*
+* switch_fun.h: switch function sets
+*/
+#ifndef SWITCH_FUN_H
+#define SWITCH_FUN_H
+
+#include <stdbool.h>
+
+#define MT7530_T10_TEST_CONTROL 0x145
+
+#define MAX_PORT 6
+#define CONFIG_MTK_7531_DVT 1
+
+extern int chip_name;
+extern struct mt753x_attr *attres;
+extern bool nl_init_flag;
+
+/*basic operation*/
+int reg_read(int offset, int *value);
+int reg_write(int offset, int value);
+int mii_mgr_read(unsigned int port_num, unsigned int reg, int *value);
+int mii_mgr_write(unsigned int port_num, unsigned int reg, unsigned int value);
+int mii_mgr_c45_read(unsigned int port_num, unsigned int dev, unsigned int reg, int *value);
+int mii_mgr_c45_write(unsigned int port_num, unsigned int dev, unsigned int reg, unsigned int value);
+
+/*phy setting*/
+int phy_dump(int phy_addr);
+void phy_crossover(int argc, char *argv[]);
+int rw_phy_token_ring(int argc, char *argv[]);
+/*arl setting*/
+void doArlAging(int argc, char *argv[]);
+
+/*acl setting*/
+void acl_mac_add(int argc, char *argv[]);
+void acl_dip_meter(int argc, char *argv[]);
+void acl_dip_trtcm(int argc, char *argv[]);
+void acl_ethertype(int argc, char *argv[]);
+void acl_ethertype(int argc, char *argv[]);
+void acl_dip_modify(int argc, char *argv[]);
+void acl_dip_pppoe(int argc, char *argv[]);
+void acl_dip_add(int argc, char *argv[]);
+void acl_l4_add(int argc, char *argv[]);
+void acl_sp_add(int argc, char *argv[]);
+
+void acl_port_enable(int argc, char *argv[]);
+void acl_table_add(int argc, char *argv[]);
+void acl_mask_table_add(int argc, char *argv[]);
+void acl_rule_table_add(int argc, char *argv[]);
+void acl_rate_table_add(int argc, char *argv[]);
+
+/*dip table*/
+void dip_dump(void);
+void dip_add(int argc, char *argv[]);
+void dip_del(int argc, char *argv[]);
+void dip_clear(void);
+
+/*sip table*/
+void sip_dump(void);
+void sip_add(int argc, char *argv[]);
+void sip_del(int argc, char *argv[]);
+void sip_clear(void);
+
+/*stp*/
+void doStp(int argc, char *argv[]);
+
+/*mac table*/
+void table_dump(void);
+void table_add(int argc, char *argv[]);
+void table_search_mac_vid(int argc, char *argv[]);
+void table_search_mac_fid(int argc, char *argv[]);
+void table_del_fid(int argc, char *argv[]);
+void table_del_vid(int argc, char *argv[]);
+void table_clear(void);
+
+/*vlan table*/
+void vlan_dump(void);
+void vlan_clear(int argc, char *argv[]);
+void vlan_set(int argc, char *argv[]);
+
+void doVlanSetPvid(int argc, char *argv[]);
+void doVlanSetVid(int argc, char *argv[]);
+void doVlanSetAccFrm(int argc, char *argv[]);
+void doVlanSetPortAttr(int argc, char *argv[]);
+void doVlanSetPortMode(int argc, char *argv[]);
+void doVlanSetEgressTagPCR(int argc, char *argv[]);
+void doVlanSetEgressTagPVC(int argc, char *argv[]);
+
+/*igmp function*/
+void igmp_on(int argc, char *argv[]);
+void igmp_off();
+void igmp_disable(int argc, char *argv[]);
+void igmp_enable(int argc, char *argv[]);
+
+/*mirror function*/
+void set_mirror_to(int argc, char *argv[]);
+void set_mirror_from(int argc, char *argv[]);
+void doMirrorPortBased(int argc, char *argv[]);
+void doMirrorEn(int argc, char *argv[]);
+
+/*rate control*/
+void rate_control(int argc, char *argv[]);
+int ingress_rate_set(int on_off, int port, int bw);
+int egress_rate_set(int on_off, int port, int bw);
+
+/*QoS*/
+int qos_sch_select(int argc, char *argv[]);
+void qos_set_base(int argc, char *argv[]);
+void qos_wfq_set_weight(int argc, char *argv[]);
+void qos_set_portpri(int argc, char *argv[]);
+void qos_set_dscppri(int argc, char *argv[]);
+void qos_pri_mapping_queue(int argc, char *argv[]);
+
+/*flow control*/
+int global_set_mac_fc(int argc, char *argv[]);
+int phy_set_fc(int argc, char *argv[]);
+int phy_set_an(int argc, char *argv[]);
+
+/* collision pool functions */
+int collision_pool_enable(int argc, char *argv[]);
+void collision_pool_mac_dump();
+void collision_pool_dip_dump();
+void collision_pool_sip_dump();
+
+/*pfc functions*/
+int set_mac_pfc(int argc, char *argv[]);
+void pfc_get_rx_counter(int argc, char *argv[]);
+void pfc_get_tx_counter(int argc, char *argv[]);
+
+/*switch reset*/
+void switch_reset(int argc, char *argv[]);
+
+void read_mib_counters();
+void clear_mib_counters();
+void read_output_queue_counters();
+void read_free_page_counters();
+
+void phy_crossover(int argc, char *argv[]);
+void exit_free();
+#endif
\ No newline at end of file
diff --git a/recipes-devtools/switch/files/switch_ioctl.c b/recipes-devtools/switch/files/switch_ioctl.c
new file mode 100644
index 0000000..ca3f15b
--- /dev/null
+++ b/recipes-devtools/switch/files/switch_ioctl.c
@@ -0,0 +1,331 @@
+/*
+ * switch_ioctl.c: switch(ioctl) set API
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+
+#include "switch_fun.h"
+#include "switch_ioctl.h"
+
+static int esw_fd;
+
+void switch_ioctl_init(void)
+{
+ esw_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (esw_fd < 0) {
+ perror("socket");
+ exit(0);
+ }
+}
+
+void switch_ioctl_fini(void)
+{
+ close(esw_fd);
+}
+
+int reg_read_ioctl(int offset, int *value)
+{
+ struct ifreq ifr;
+ struct esw_reg reg;
+
+ struct ra_mii_ioctl_data mii;
+ strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+ ifr.ifr_data = &mii;
+
+ mii.phy_id = 0x1f;
+ mii.reg_num = offset;
+
+ if (-1 == ioctl(esw_fd, RAETH_MII_READ, &ifr)) {
+ perror("ioctl");
+ close(esw_fd);
+ exit(0);
+ }
+ *value = mii.val_out;
+ return 0;
+}
+
+int reg_read_tr(int offset, int *value)
+{
+ struct ifreq ifr;
+ struct esw_reg reg;
+ struct ra_mii_ioctl_data mii;
+
+ strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+ ifr.ifr_data = &mii;
+
+ mii.phy_id = 0;
+ mii.reg_num = offset;
+
+ if (-1 == ioctl(esw_fd, RAETH_MII_READ, &ifr)) {
+ perror("ioctl");
+ close(esw_fd);
+ exit(0);
+ }
+ *value = mii.val_out;
+ return 0;
+}
+
+int reg_write_ioctl(int offset, int value)
+{
+ struct ifreq ifr;
+ struct esw_reg reg;
+ struct ra_mii_ioctl_data mii;
+
+ strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+ ifr.ifr_data = &mii;
+
+ mii.phy_id = 0x1f;
+ mii.reg_num = offset;
+ mii.val_in = value;
+
+ if (-1 == ioctl(esw_fd, RAETH_MII_WRITE, &ifr)) {
+ perror("ioctl");
+ close(esw_fd);
+ exit(0);
+ }
+ return 0;
+}
+
+int reg_write_tr(int offset, int value)
+{
+ struct ifreq ifr;
+ struct esw_reg reg;
+ struct ra_mii_ioctl_data mii;
+
+ strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+ ifr.ifr_data = &mii;
+
+ mii.phy_id = 0;
+ mii.reg_num = offset;
+ mii.val_in = value;
+
+ if (-1 == ioctl(esw_fd, RAETH_MII_WRITE, &ifr)) {
+ perror("ioctl");
+ close(esw_fd);
+ exit(0);
+ }
+ return 0;
+}
+
+int phy_dump_ioctl(int phy_addr)
+{
+ struct ifreq ifr;
+ struct esw_reg reg;
+
+ reg.val = phy_addr;
+ strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+ ifr.ifr_data = ®
+ if (-1 == ioctl(esw_fd, RAETH_ESW_PHY_DUMP, &ifr)) {
+ perror("ioctl");
+ close(esw_fd);
+ exit(0);
+ }
+ return 0;
+}
+
+int mii_mgr_cl22_read_ioctl(unsigned int port_num, unsigned int reg, int *value)
+{
+ int reg_value;
+ int loop_cnt;
+ int op_busy;
+
+ loop_cnt = 0;
+
+ /*Change to indirect access mode*/
+ /*if you need to use direct access mode, please change back manually by reset bit5*/
+ reg_read(0x7804, ®_value);
+ if (((reg_value >> 5) & 0x1) == 0) {
+ reg_value |= 1 << 5;
+ reg_write(0x7804, reg_value);
+ printf("Change to indirect access mode:0x%x\n",reg_value);
+ }
+ reg_value = 0x80090000 | (port_num << 20) | (reg << 25);
+ reg_write(0x701c, reg_value);
+ while (1)
+ {
+ reg_read(0x701c, ®_value);
+ op_busy = reg_value & (1 << 31);
+ if (!op_busy) {
+ reg_value = reg_value & 0xFFFF;
+ break;
+ } else if (loop_cnt < 10)
+ loop_cnt++;
+ else {
+ printf("MDIO read opeartion timeout\n");
+ reg_value = 0;
+ break;
+ }
+ }
+ printf(" PHY Indirect Access Control(0x701c) register read value =0x%x \n", reg_value);
+ *value = reg_value;
+ return 0;
+}
+
+int mii_mgr_cl22_write_ioctl(unsigned int port_num, unsigned int reg, unsigned int value)
+{
+ int reg_value;
+ int loop_cnt;
+ int op_busy;
+
+ loop_cnt = 0;
+ /*Change to indirect access mode*/
+ /*if you need to use direct access mode, please change back manually by reset bit5*/
+ reg_read(0x7804, ®_value);
+ if (((reg_value >> 5) & 0x1) == 0) {
+ reg_value |= 1 << 5;
+ reg_write(0x7804, reg_value);
+ printf("Change to indirect access mode:0x%x\n",reg_value);
+ }
+
+ reg_value = 0x80050000 | (port_num << 20) | (reg << 25) | value;
+ reg_write(0x701c, reg_value);
+ while (1)
+ {
+ reg_read(0x701c, ®_value);
+ op_busy = reg_value & (1 << 31);
+ if (!op_busy)
+ break;
+ else if (loop_cnt < 10)
+ loop_cnt++;
+ else {
+ printf("MDIO write opeartion timeout\n");
+ break;
+ }
+ }
+
+ printf(" PHY Indirect Access Control(0x701c) register write value =0x%x \n", reg_value);
+ return 0;
+}
+
+int mii_mgr_cl45_read_ioctl(int port_num, int dev, int reg, int *value)
+{
+ int sk, method, ret, i;
+ struct ifreq ifr;
+ struct ra_mii_ioctl_data mii;
+
+ sk = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sk < 0)
+ printf("Open socket failed\n");
+
+ strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+ ifr.ifr_data = &mii;
+
+ method = RAETH_MII_WRITE;
+ mii.phy_id = port_num;
+ mii.reg_num = 13;
+ mii.val_in = dev;
+ ret = ioctl(sk, method, &ifr);
+
+ method = RAETH_MII_WRITE;
+ mii.phy_id = port_num;
+ mii.reg_num = 14;
+ mii.val_in = reg;
+ ret = ioctl(sk, method, &ifr);
+
+ method = RAETH_MII_WRITE;
+ mii.phy_id = port_num;
+ mii.reg_num = 13;
+ mii.val_in = (0x6000 | dev);
+ ret = ioctl(sk, method, &ifr);
+
+ usleep(1000);
+
+ method = RAETH_MII_READ;
+ mii.phy_id = port_num;
+ mii.reg_num = 14;
+ ret = ioctl(sk, method, &ifr);
+
+ close(sk);
+ *value = mii.val_out;
+ return 0;
+}
+
+int mii_mgr_cl45_write_ioctl(int port_num, int dev, int reg, int value)
+{
+ int sk, method, ret, i;
+ struct ifreq ifr;
+ struct ra_mii_ioctl_data mii;
+
+ sk = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sk < 0)
+ printf("Open socket failed\n");
+
+ strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+ ifr.ifr_data = &mii;
+
+ method = RAETH_MII_WRITE;
+ mii.phy_id = port_num;
+ mii.reg_num = 13;
+ mii.val_in = dev;
+ ret = ioctl(sk, method, &ifr);
+
+ method = RAETH_MII_WRITE;
+ mii.phy_id = port_num;
+ mii.reg_num = 14;
+ mii.val_in = reg;
+ ret = ioctl(sk, method, &ifr);
+
+ method = RAETH_MII_WRITE;
+ mii.phy_id = port_num;
+ mii.reg_num = 13;
+ mii.val_in = (0x6000 | dev);
+ ret = ioctl(sk, method, &ifr);
+
+ usleep(1000);
+
+ method = RAETH_MII_WRITE;
+ mii.phy_id = port_num;
+ mii.reg_num = 14;
+ mii.val_in = value;
+ ret = ioctl(sk, method, &ifr);
+
+ close(sk);
+
+ return ret;
+}
+
+int dump_gphy(void)
+{
+ int port_num = 5;
+ int cl45_start_reg = 0x9B;
+ int cl45_end_reg = 0xA2;
+ int cl22_reg[6] = {0x00, 0x01, 0x04, 0x05, 0x09, 0x0A};
+ int i, j, ret;
+ int *value;
+
+ int sk, method;
+ struct ifreq ifr;
+ struct ra_mii_ioctl_data mii;
+
+ sk = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sk < 0)
+ printf("Open socket failed\n");
+
+ strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+ ifr.ifr_data = &mii;
+ /* dump CL45 reg first*/
+ for (i = 0; i < 5; i++) {
+ printf("== Port %d ==\n", i);
+ for (j = cl45_start_reg; j < (cl45_end_reg + 1); j++) {
+ mii_mgr_cl45_read_ioctl(i, 0x1E, j, value);
+ printf("dev1Eh_reg%xh = 0x%x\n", j, *value);
+ }
+ }
+ printf("== Global ==\n");
+ for (i = 0; i < 6; i++) {
+ method = RAETH_MII_READ;
+ mii.phy_id = 0;
+ mii.reg_num = cl22_reg[i];
+ ret = ioctl(sk, method, &ifr);
+ printf("Reg%xh = 0x%x\n", cl22_reg[i], mii.val_out);
+ }
+
+ close(sk);
+ return 0;
+}
diff --git a/recipes-devtools/switch/files/switch_ioctl.h b/recipes-devtools/switch/files/switch_ioctl.h
new file mode 100644
index 0000000..c12e8d8
--- /dev/null
+++ b/recipes-devtools/switch/files/switch_ioctl.h
@@ -0,0 +1,65 @@
+/*
+ * switch_ioctl.h: switch(ioctl) set API
+ */
+
+#ifndef SWITCH_IOCTL_H
+#define SWITCH_IOCTL_H
+
+#define ETH_DEVNAME "eth1"
+#define BR_DEVNAME "brlan0"
+
+#define RAETH_MII_READ 0x89F3
+#define RAETH_MII_WRITE 0x89F4
+#define RAETH_ESW_PHY_DUMP 0x89F7
+
+struct esw_reg {
+ unsigned int off;
+ unsigned int val;
+};
+
+struct ra_mii_ioctl_data {
+ __u32 phy_id;
+ __u32 reg_num;
+ __u32 val_in;
+ __u32 val_out;
+ __u32 port_num;
+ __u32 dev_addr;
+ __u32 reg_addr;
+};
+
+struct ra_switch_ioctl_data {
+ unsigned int cmd;
+ unsigned int on_off;
+ unsigned int port;
+ unsigned int bw;
+ unsigned int vid;
+ unsigned int fid;
+ unsigned int port_map;
+ unsigned int rx_port_map;
+ unsigned int tx_port_map;
+ unsigned int igmp_query_interval;
+ unsigned int reg_addr;
+ unsigned int reg_val;
+ unsigned int mode;
+ unsigned int qos_queue_num;
+ unsigned int qos_type;
+ unsigned int qos_pri;
+ unsigned int qos_dscp;
+ unsigned int qos_table_idx;
+ unsigned int qos_weight;
+ unsigned char mac[6];
+};
+
+extern int chip_name;
+
+void switch_ioctl_init(void);
+void switch_ioctl_fini(void);
+int reg_read_ioctl(int offset, int *value);
+int reg_write_ioctl(int offset, int value);
+int phy_dump_ioctl(int phy_addr);
+int mii_mgr_cl22_read_ioctl(unsigned int port_num, unsigned int reg, int *value);
+int mii_mgr_cl22_write_ioctl(unsigned int port_num, unsigned int reg,
+ unsigned int value);
+int mii_mgr_cl45_read_ioctl(int port_num, int dev, int reg, int *value);
+int mii_mgr_cl45_write_ioctl(int port_num, int dev, int reg, int value);
+#endif
diff --git a/recipes-devtools/switch/files/switch_netlink.c b/recipes-devtools/switch/files/switch_netlink.c
new file mode 100644
index 0000000..c89ddb6
--- /dev/null
+++ b/recipes-devtools/switch/files/switch_netlink.c
@@ -0,0 +1,436 @@
+/*
+ * switch_netlink.c: switch(netlink) set API
+ *
+ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+
+#include "switch_netlink.h"
+
+static struct nl_sock *user_sock;
+static struct nl_cache *cache;
+static struct genl_family *family;
+static struct nlattr *attrs[MT753X_ATTR_TYPE_MAX + 1];
+
+static int wait_handler(struct nl_msg *msg, void *arg)
+{
+ int *finished = arg;
+
+ *finished = 1;
+ return NL_STOP;
+}
+
+static int list_swdevs(struct nl_msg *msg, void *arg)
+{
+ struct mt753x_attr *val = arg;
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+
+ if (nla_parse(attrs, MT753X_ATTR_TYPE_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL) < 0)
+ goto done;
+
+ if (gnlh->cmd == MT753X_CMD_REPLY) {
+ if (attrs[MT753X_ATTR_TYPE_MESG]) {
+ val->dev_info =
+ nla_get_string(attrs[MT753X_ATTR_TYPE_MESG]);
+ printf("register switch dev:\n%s", val->dev_info);
+ }
+ else {
+ fprintf(stderr, "ERROR:No switch dev now\n");
+ goto done;
+ }
+ } else
+ goto done;
+ return 0;
+done:
+ return NL_SKIP;
+}
+
+static int construct_attrs(struct nl_msg *msg, void *arg)
+{
+ struct mt753x_attr *val = arg;
+ int type = val->type;
+
+ if (val->dev_id > -1)
+ NLA_PUT_U32(msg, MT753X_ATTR_TYPE_DEV_ID, val->dev_id);
+
+ if (val->op == 'r') {
+ if (val->phy_dev != -1)
+ NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY_DEV, val->phy_dev);
+ if (val->port_num >= 0)
+ NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY, val->port_num);
+ NLA_PUT_U32(msg, type, val->reg);
+ } else if (val->op == 'w') {
+ if (val->phy_dev != -1)
+ NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY_DEV, val->phy_dev);
+ if (val->port_num >= 0)
+ NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY, val->port_num);
+ NLA_PUT_U32(msg, type, val->reg);
+ NLA_PUT_U32(msg, MT753X_ATTR_TYPE_VAL, val->value);
+ } else {
+ printf("construct_attrs_message\n");
+ NLA_PUT_STRING(msg, type, "hello");
+ }
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static int spilt_attrs(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct mt753x_attr *val = arg;
+ char *str;
+ int data;
+
+ if (nla_parse(attrs, MT753X_ATTR_TYPE_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL) < 0)
+ goto done;
+
+ if ((gnlh->cmd == MT753X_CMD_WRITE) || (gnlh->cmd == MT753X_CMD_READ)) {
+ if (attrs[MT753X_ATTR_TYPE_MESG]) {
+ str = nla_get_string(attrs[MT753X_ATTR_TYPE_MESG]);
+ printf(" %s\n", str);
+ if (!strncmp(str, "No", 2))
+ goto done;
+ }
+ if (attrs[MT753X_ATTR_TYPE_REG]) {
+ val->reg =
+ nla_get_u32(attrs[MT753X_ATTR_TYPE_REG]);
+ }
+ if (attrs[MT753X_ATTR_TYPE_VAL]) {
+ val->value =
+ nla_get_u32(attrs[MT753X_ATTR_TYPE_VAL]);
+ }
+ }
+ else
+ goto done;
+
+ return 0;
+done:
+ return NL_SKIP;
+}
+
+static int mt753x_request_callback(int cmd, int (*spilt)(struct nl_msg *, void *),
+ int (*construct)(struct nl_msg *, void *),
+ void *arg)
+{
+ struct nl_msg *msg;
+ struct nl_cb *callback = NULL;
+ int finished;
+ int flags = 0;
+ int err;
+
+ /*Allocate an netllink message buffer*/
+ msg = nlmsg_alloc();
+ if (!msg) {
+ fprintf(stderr, "Failed to allocate netlink message\n");
+ exit(1);
+ }
+ if (!construct) {
+ if (cmd == MT753X_CMD_REQUEST)
+ flags |= NLM_F_REQUEST;
+ else
+ flags |= NLM_F_DUMP;
+ }
+ genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, genl_family_get_id(family),
+ 0, flags, cmd, 0);
+
+ /*Fill attaribute of netlink message by construct function*/
+ if (construct) {
+ if (construct(msg, arg) < 0) {
+ fprintf(stderr, "attributes error\n");
+ goto nal_put_failure;
+ }
+ }
+
+ /*Allocate an new callback handler*/
+ callback = nl_cb_alloc(NL_CB_CUSTOM);
+ if (!callback) {
+ fprintf(stderr, "Failed to allocate callback handler\n");
+ exit(1);
+ }
+
+ /*Send netlink message*/
+ err = nl_send_auto_complete(user_sock, msg);
+ if (err < 0) {
+ fprintf(stderr, "nl_send_auto_complete failied:%d\n", err);
+ goto out;
+ }
+ finished = 0;
+ if (spilt)
+ nl_cb_set(callback, NL_CB_VALID, NL_CB_CUSTOM, spilt, arg);
+
+ if (construct)
+ nl_cb_set(callback, NL_CB_ACK, NL_CB_CUSTOM, wait_handler,
+ &finished);
+ else
+ nl_cb_set(callback, NL_CB_FINISH, NL_CB_CUSTOM, wait_handler,
+ &finished);
+
+ /*receive message from kernel request*/
+ err = nl_recvmsgs(user_sock, callback);
+ if (err < 0)
+ goto out;
+
+ /*wait until an ACK is received for the latest not yet acknowledge*/
+ if (!finished)
+ err = nl_wait_for_ack(user_sock);
+out:
+ if (callback)
+ nl_cb_put(callback);
+
+nal_put_failure:
+ nlmsg_free(msg);
+ return err;
+}
+
+void mt753x_netlink_free(void)
+{
+ if (family)
+ nl_object_put((struct nl_object *)family);
+ if (cache)
+ nl_cache_free(cache);
+ if (user_sock)
+ nl_socket_free(user_sock);
+ user_sock = NULL;
+ cache = NULL;
+ family = NULL;
+}
+
+int mt753x_netlink_init(void)
+{
+ int ret;
+
+ user_sock = NULL;
+ cache = NULL;
+ family = NULL;
+
+ /*Allocate an new netlink socket*/
+ user_sock = nl_socket_alloc();
+ if (!user_sock) {
+ fprintf(stderr, "Failed to create user socket\n");
+ goto err;
+ }
+ /*Connetct the genl controller*/
+ if (genl_connect(user_sock)) {
+ fprintf(stderr, "Failed to connetct to generic netlink\n");
+ goto err;
+ }
+ /*Allocate an new nl_cache*/
+ ret = genl_ctrl_alloc_cache(user_sock, &cache);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to allocate netlink cache\n");
+ goto err;
+ }
+
+ /*Look up generic netlik family by "mt753x" in the provided cache*/
+ family = genl_ctrl_search_by_name(cache, MT753X_GENL_NAME);
+ if (!family) {
+ //fprintf(stderr,"switch(mt753x) API not be prepared\n");
+ goto err;
+ }
+ return 0;
+err:
+ mt753x_netlink_free();
+ return -EINVAL;
+}
+
+void mt753x_list_swdev(struct mt753x_attr *arg, int cmd)
+{
+ int err;
+
+ err = mt753x_request_callback(cmd, list_swdevs, NULL, arg);
+ if (err < 0)
+ fprintf(stderr, "mt753x list dev error\n");
+}
+
+static int mt753x_request(struct mt753x_attr *arg, int cmd)
+{
+ int err;
+
+ err = mt753x_request_callback(cmd, spilt_attrs, construct_attrs, arg);
+ if (err < 0) {
+ fprintf(stderr, "mt753x deal request error\n");
+ return err;
+ }
+ return 0;
+}
+
+static int phy_operate_netlink(char op, struct mt753x_attr *arg, int port_num,
+ int phy_dev, int offset, int *value)
+{
+ int ret;
+ struct mt753x_attr *attr = arg;
+
+ attr->port_num = port_num;
+ attr->phy_dev = phy_dev;
+ attr->reg = offset;
+ attr->value = -1;
+ attr->type = MT753X_ATTR_TYPE_REG;
+
+ switch (op)
+ {
+ case 'r':
+ attr->op = 'r';
+ ret = mt753x_request(attr, MT753X_CMD_READ);
+ *value = attr->value;
+ break;
+ case 'w':
+ attr->op = 'w';
+ attr->value = *value;
+ ret = mt753x_request(attr, MT753X_CMD_WRITE);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+int reg_read_netlink(struct mt753x_attr *arg, int offset, int *value)
+{
+ int ret;
+
+ ret = phy_operate_netlink('r', arg, -1, -1, offset, value);
+ return ret;
+}
+
+int reg_write_netlink(struct mt753x_attr *arg, int offset, int value)
+{
+ int ret;
+
+ ret = phy_operate_netlink('w', arg, -1, -1, offset, &value);
+ return ret;
+}
+
+int phy_cl22_read_netlink(struct mt753x_attr *arg, int port_num, int phy_addr, int *value)
+{
+ int ret;
+
+ ret = phy_operate_netlink('r', arg, port_num, -1, phy_addr, value);
+ return ret;
+}
+
+int phy_cl22_write_netlink(struct mt753x_attr *arg, int port_num, int phy_addr, int value)
+{
+ int ret;
+
+ ret = phy_operate_netlink('w', arg, port_num, -1, phy_addr, &value);
+ return ret;
+}
+
+int phy_cl45_read_netlink(struct mt753x_attr *arg, int port_num, int phy_dev,
+ int phy_addr, int *value)
+{
+ int ret;
+
+ ret = phy_operate_netlink('r', arg, port_num, phy_dev, phy_addr, value);
+ return ret;
+}
+
+int phy_cl45_write_netlink(struct mt753x_attr *arg, int port_num, int phy_dev,
+ int phy_addr, int value)
+{
+ int ret;
+
+ ret = phy_operate_netlink('w', arg, port_num, phy_dev, phy_addr, &value);
+ return ret;
+}
+
+void dump_extend_phy_reg(struct mt753x_attr *arg, int port_no, int from,
+ int to, int is_local, int page_no)
+{
+ int ret;
+ int i = 0;
+ int temp = 0;
+ int r31 = 0;
+
+ if (is_local == 0) {
+ printf("\n\nGlobal Register Page %d\n",page_no);
+ printf("===============");
+ r31 |= 0 << 15; //global
+ r31 |= ((page_no&0x7) << 12); //page no
+ phy_cl22_write_netlink(arg, port_no, 31, r31); //select global page x
+ for (i = 16; i < 32; i++) {
+ if(i%8 == 0)
+ printf("\n");
+ phy_cl22_read_netlink(arg, port_no, i, &temp);
+ printf("%02d: %04X ", i, temp);
+ }
+ } else {
+ printf("\n\nLocal Register Port %d Page %d\n",port_no, page_no);
+ printf("===============");
+ r31 |= 1 << 15; //local
+ r31 |= ((page_no&0x7) << 12); //page no
+ phy_cl22_write_netlink(arg, port_no, 31, r31); //select global page x
+ for (i = 16; i < 32; i++) {
+ if (i%8 == 0) {
+ printf("\n");
+ }
+ phy_cl22_read_netlink(arg, port_no, i, &temp);
+ printf("%02d: %04X ",i, temp);
+ }
+ }
+ printf("\n");
+}
+
+int phy_dump_netlink(struct mt753x_attr *arg, int phy_addr)
+{
+ int i;
+ int ret;
+ unsigned int offset, value;
+
+ if (phy_addr == 32) {
+ /*dump all phy register*/
+ for (i = 0; i < 5; i++) {
+ printf("\n[Port %d]=============", i);
+ for (offset = 0; offset < 16; offset++) {
+ if (offset % 8 == 0)
+ printf("\n");
+ ret = phy_cl22_read_netlink(arg, i, offset, &value);
+ printf("%02d: %04X ", offset, value);
+ }
+ }
+ } else {
+ printf("\n[Port %d]=============", phy_addr);
+ for (offset = 0; offset < 16; offset++) {
+ if (offset % 8 == 0)
+ printf("\n");
+ ret = phy_cl22_read_netlink(arg, phy_addr, offset, &value);
+ printf("%02d: %04X ", offset, value);
+ }
+ }
+ printf("\n");
+ for (offset = 0; offset < 5; offset++) { //global register page 0~4
+ if (phy_addr == 32) //dump all phy register
+ dump_extend_phy_reg(arg, 0, 16, 31, 0, offset);
+ else
+ dump_extend_phy_reg(arg, phy_addr, 16, 31, 0, offset);
+ }
+
+ if (phy_addr == 32) { //dump all phy register
+ for (offset = 0; offset < 5; offset++) { //local register port 0-port4
+ dump_extend_phy_reg(arg, offset, 16, 31, 1, 0); //dump local page 0
+ dump_extend_phy_reg(arg, offset, 16, 31, 1, 1); //dump local page 1
+ dump_extend_phy_reg(arg, offset, 16, 31, 1, 2); //dump local page 2
+ dump_extend_phy_reg(arg, offset, 16, 31, 1, 3); //dump local page 3
+ }
+ } else {
+ dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 0); //dump local page 0
+ dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 1); //dump local page 1
+ dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 2); //dump local page 2
+ dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 3); //dump local page 3
+ }
+ return ret;
+}
diff --git a/recipes-devtools/switch/files/switch_netlink.h b/recipes-devtools/switch/files/switch_netlink.h
new file mode 100644
index 0000000..de7d36b
--- /dev/null
+++ b/recipes-devtools/switch/files/switch_netlink.h
@@ -0,0 +1,63 @@
+/*
+ * switch_netlink.h: switch(netlink) set API
+ *
+ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
+ */
+#ifndef MT753X_NETLINK_H
+#define MT753X_NETLINK_H
+
+#define MT753X_GENL_NAME "mt753x"
+#define MT753X_GENL_VERSION 0X1
+
+/*add your cmd to here*/
+enum {
+ MT753X_CMD_UNSPEC = 0, /*Reserved*/
+ MT753X_CMD_REQUEST, /*user->kernelrequest/get-response*/
+ MT753X_CMD_REPLY, /*kernel->user event*/
+ MT753X_CMD_READ,
+ MT753X_CMD_WRITE,
+ __MT753X_CMD_MAX,
+};
+#define MT753X_CMD_MAX (__MT753X_CMD_MAX - 1)
+
+/*define attar types */
+enum
+{
+ MT753X_ATTR_TYPE_UNSPEC = 0,
+ MT753X_ATTR_TYPE_MESG, /*MT753X message*/
+ MT753X_ATTR_TYPE_PHY,
+ MT753X_ATTR_TYPE_PHY_DEV,
+ MT753X_ATTR_TYPE_REG,
+ MT753X_ATTR_TYPE_VAL,
+ MT753X_ATTR_TYPE_DEV_NAME,
+ MT753X_ATTR_TYPE_DEV_ID,
+ __MT753X_ATTR_TYPE_MAX,
+};
+#define MT753X_ATTR_TYPE_MAX (__MT753X_ATTR_TYPE_MAX - 1)
+
+struct mt753x_attr {
+ int port_num;
+ int phy_dev;
+ int reg;
+ int value;
+ int type;
+ char op;
+ char *dev_info;
+ int dev_name;
+ int dev_id;
+};
+
+int mt753x_netlink_init(void);
+void mt753x_netlink_free(void);
+void mt753x_list_swdev(struct mt753x_attr *arg, int cmd);
+int reg_read_netlink(struct mt753x_attr *arg, int offset, int *value);
+int reg_write_netlink(struct mt753x_attr *arg, int offset, int value);
+int phy_cl22_read_netlink(struct mt753x_attr *arg, int port_num, int phy_addr, int *value);
+int phy_cl22_write_netlink(struct mt753x_attr *arg, int port_num, int phy_addr, int value);
+int phy_cl45_read_netlink(struct mt753x_attr *arg, int port_num, int phy_dev,
+ int phy_addr, int *value);
+int phy_cl45_write_netlink(struct mt753x_attr *arg, int port_num, int phy_dev,
+ int phy_addr, int value);
+int phy_dump_netlink(struct mt753x_attr *arg, int phy_addr);
+
+#endif
diff --git a/recipes-devtools/switch/switch_1.0.bb b/recipes-devtools/switch/switch_1.0.bb
new file mode 100644
index 0000000..5c95e6e
--- /dev/null
+++ b/recipes-devtools/switch/switch_1.0.bb
@@ -0,0 +1,37 @@
+SUMMARY = "Command to config switch"
+SECTION = "applications"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe"
+
+S = "${WORKDIR}"
+
+DEPENDS = "libnl"
+
+SRC_URI = " \
+ file://COPYING \
+ file://Makefile \
+ file://switch_753x.c \
+ file://switch_extend.h \
+ file://switch_fun.c \
+ file://switch_fun.h \
+ file://switch_ioctl.c \
+ file://switch_ioctl.h \
+ file://switch_netlink.c \
+ file://switch_netlink.h \
+ "
+
+CFLAGS_prepend = " \
+ -D_GNU_SOURCE \
+ -I${STAGING_INCDIR}/libnl3 \
+ -I${S} \
+ "
+
+do_compile() {
+ oe_runmake -C ${S} "LIBS=-L${STAGING_LIBDIR} -lnl-3 -lnl-genl-3 -lm"
+}
+
+do_install() {
+ install -d ${D}/usr/sbin
+ install -d ${D}/lib/network
+ install -m 0755 ${WORKDIR}/switch ${D}/usr/sbin
+}