76 Commits
Author SHA1 Message Date
logicog f8e437f3a4 Makefile: Lower limit of --xram-size to protect ChaCha20 space
ChaCha20 uses 256 bytes starting from 0xbf00 for its calculations.
Make sure the linker checks that this space is not overwritten.
2026-10-17 06:30:16 +02:00
logicog 82dfb8f789 ChaCha20 implementation for encryption
Add an implementation in 8051 assembler for the generation of a
ChaCha20 keystream and an encryption function using the keystream
in C.

A test function using the example from RFC7539 is provided in
chacha20_test.

Keys, nonce, and block counter and the pointers to the input plaintext,
its length and the output pointer are provided via a struct chacha20,
which also holds the working state of the ChaCha20 algorithm
2026-10-17 06:30:14 +02:00
bloq 8224b06f9e Merge pull request #540 from DrDoof/fix/igmp-link-local
igmp: leave groups in 224.0.0.0/24 to flooding
2026-10-14 02:01:59 -05:00
bloq 69151362a0 Merge pull request #566 from DrDoof/fix/igmp-off-lookup
igmp: flood all IP multicast again after igmp off
2026-10-14 02:01:55 -05:00
bloq 24e83d5b74 Merge pull request #299 from DrDoof/feat/lacp
lacp: implement IEEE 802.3ad (LACP)
2026-10-14 01:35:24 -05:00
logicog 3d81df0cad Merge pull request #564 from hlyi/machine_refactoring
machine: one board definition per file, replacing the #if/#elif chain
2026-10-14 05:51:25 +02:00
d00f 2481810906 lacp: tidy up after review
Move port_bit() to rtl837x_common.h as PORT_BIT(), a uint16_t shift,
and MAC_ADDR_LEN from rtl837x_lldp.h next to it, and use MAC_ADDR_LEN
for every address in the LACP code instead of a literal 6. Define
lacp_mux_update() before its first caller and drop the forward
declaration, declare variables at the top of their blocks, put the
operator at the end of a continued line, drop the field value comments
of the LACPDU struct, and leave lacp_port_lag to lacp_init() instead of
initialising it in the test environment.
2026-10-14 00:55:11 +02:00
d00f 03311debe6 Merge pull request #586 from mintsoft/lldp-blocking
LLDP: prevent the switch from passing LLDPDUs when lldp is enabled
2026-10-13 12:51:18 +02:00
Rob Emery e4adec9c11 Renaming for consistency and spaces -> tabs 2026-10-13 08:27:53 +01:00
d00f d525229b42 doc: lacp: shorten, point to stp.md for the trap
The trap is described with STP, so the LACP page only says that it is
used. The LACP sections leave link_aggregation.md, which now points to
lacp.md, and the timing section gives the values in seconds and the
802.3ad requirements without the test history.
2026-10-12 22:05:56 +02:00
d00f 73b23808cf lacp: keep comments to the frame layout
The comments repeated the documentation, described tests or explained
the code to its author. What stays describes the LACPDU structures. The
timer constants are decimal, in units of the LACP timer.
2026-10-12 22:05:56 +02:00
d00f 4a14f50932 test: build the LACP test on the real headers, drop the port_hash test
The LACP test now compiles with the shared harness flags and
sdcc_shim.h against the firmware headers, so the copies under
test/lacp/shim are gone. test_port_tables already covers the trunk hash
seed that test/port_hash checked against its own register copies.
lacp_in() declares its locals at the top, which the stricter host build
needs.
2026-10-12 22:02:56 +02:00
d00f 1bfe632174 doc: lacp: lag <n> d and a static list leave LACP, new lacp_lag_set() prototype 2026-10-12 21:59:08 +02:00
Rob Emery 265a80bb25 Trapping the 01:80:c2:00:00:0e prevents the switch from passing
between ports
2026-10-12 20:32:29 +01:00
d00f 64efd3fb9f lacp: drop the unused long timeout and an unrelated pvid hunk 2026-10-12 21:21:07 +02:00
d00f 2e6425f5e6 lacp: keep lacp_in() and lacp_lag_set() out of the data segment
The port and group of lacp_in(), the member mask passed to
lacp_lag_set() and the compiler temporaries both functions spilled took
six bytes of DSEG, and with them six bytes of stack. The locals and the
mask live in xdata now, the partner fields go through the scratch word,
and lacp_lag_set() records the new group of a port before it releases
the old one. One byte is left: the group number passed in.
2026-10-12 21:21:07 +02:00
bloq 1856aeba28 Merge pull request #579 from nuclearbananaslug/patch-1
mirror: parse the monitor port argument
2026-10-12 12:01:27 -05:00
d00f 4e4a2ea4db lacp: review follow-ups
lacp_in() always leaves uip_len at 0, so the tcpip_output() after it
never ran. The LAG page names the active members by front-panel port
instead of a logical mask. The partner key is not part of selection;
say so under Known limits.
2026-10-12 16:27:22 +02:00
d00f 4ccbf51976 lacp: ignore a LACPDU that carries our own system id
Two ports of one group cabled to each other heard themselves and the
group aggregated with itself. Sandbox T24.
2026-10-12 16:27:22 +02:00
d00f 0df48fbb1c httpd: leave the L2 listing as it is on main
Listing by next-address also returned the reserved-multicast entries STP
writes, shown as port 1 with a delete button, while l2_delete() still
looks up by next-unicast and so removed the unicast entry after that
index instead. The change was there to show the LACP steering entries;
delivery by trap writes none, so it goes.
2026-10-12 16:27:21 +02:00
d00f 25040070e5 lacp: "lag <n> d" and a static member list take the group out of LACP
Both paths wrote the trunk registers directly and left the protocol
running on the group, so "lag show" said disabled while the partner kept
both links in one aggregate, and re-sending the LACP line did not repair
it because the same-ports shortcut returns early. Each path now releases
the group from LACP first; for a group that never ran LACP that is a
no-op.
2026-10-12 16:27:20 +02:00
d00f edf6351d85 lacp: arm the partner timeout from our own LACP_Timeout
The receive machine armed current_while from the partner's TIMEOUT bit,
so against a partner on the slow rate a port whose LACPDUs stopped with
the link still up stayed in the trunk for the long timeout, two minutes.
802.3ad 43.4.12 starts the timer from the actor's own LACP_Timeout, and
we always advertise the short one: the partner sends every second and is
let go after the short timeout.

Sandbox T23 plays a slow-rate partner that goes quiet and fails on the
code before this.
2026-10-12 16:27:19 +02:00
DrDoof c3b4cc893b lacp: implement IEEE 802.3ad link aggregation
Dynamic link aggregation on top of the static LAGG, for RTL8372/8373:
receive, selection and mux state machines (coupled mux, one aggregator
per group), with "lacp show" to look inside. Each of the four trunk
groups runs its own aggregator on the candidate ports assigned with
"lag <n> lacp <ports>"; the engine starts with the first such group and
stops with the last.

LACPDUs reach the CPU through the reserved-multicast trap, so delivery
needs no L2 entry and nothing written per VLAN or per PVID. The trap
acts on the address before the VLAN lookup and before the ingress
filters, so a LACPDU also arrives on a port that admits tagged frames
only and on a port STP holds in blocking, neither of which a forwarded
one reaches. A trapped frame carries no VLAN tag,
so lacp_in() takes the offset of the PDU body from TRAP_RX_BODY(). The
action is set with trap_rma_set(), which leaves the flags sharing that
register alone, and "lacp off" puts the slow-protocols drop default
back. doc/lacp.md and doc/link_aggregation.md record what was measured,
including why the trap looked like a dead end at first.

The web UI gets a Static/LACP mode per group on the LAG page with live
status, and the startup-config validator knows the per-group syntax. A
host-side sandbox for the state machines runs in the test harness
together with the LAG hash check. It drives both forms of an incoming
LACPDU, so the body offset of a trapped one is covered as well.

The L2 table page iterated with the "next unicast" read method, so
static multicast entries such as an IGMP group were invisible. It now
iterates with "next address", skips L3 entries (their layout carries IP
addresses where a MAC is expected), and reports the lowest member of a
multicast entry's port mask, so such an entry shows up as a static
entry on that port.

A port taken out of LACP forgets its partner, so "lacp show" after
"lacp off" no longer reports one. Applying the same candidate set to a
group again, as the LAG page does on every Apply, leaves the trunk
alone instead of tearing it down for a second or two. lacp_in() checks
the frame length and ethertype before reading a LACPDU, so a runt or a
foreign frame on the slow-protocols address cannot leave stale buffer
bytes as a partner. The sandbox covers these three in T20-T22. On the
LAG page, LACP mode with no ports checked sends "lag N lacp off", and
the startup-config validator wants at least one port after "lacp".
2026-10-12 15:09:57 +02:00
d00f b83b67d234 Merge pull request #514 from DrDoof/feat/trap
trap: deliver reserved multicast to the CPU by trap, STP first
2026-10-12 15:07:11 +02:00
Antony efd61be64e mirror: parse the monitor port argument 2026-10-12 13:04:49 +00:00
logicog da7909f422 Merge pull request #563 from dobodu/main
Add port isolation and related messages in French
2026-10-12 06:32:45 +02:00
DrDoof 14b2ce1c49 trap: deliver reserved multicast to the CPU by trap, STP first
A reserved-multicast trap goes to the port named in EXT_CPU_CTRL, which
names no port out of reset, so trapped frames were dropped at ingress.
trap_init() points it at the CPU port once at startup, and
trap_rma_set() changes only the action field of an RMA register.

A trapped frame arrives without the VLAN tag a forwarded one gets, so
TRAP_RX_BODY() gives the offset of the payload for both forms.

STP now traps its address while it runs instead of steering it with a
static L2 entry per VLAN, so turning it on no longer walks the VLAN
table and a pvid change no longer needs stp off and on. With STP off
the flooding entries are restored as before.

A trapped BPDU passes the tagged-only ingress filter that drops a
forwarded one, so the stp_setup() warning about such ports goes.
2026-10-12 01:16:28 +02:00
d00f 84d9408151 Merge pull request #447 from DrDoof/feat/ntp
ntp: keep the time from an NTP server
2026-10-11 23:20:06 +02:00
dobodu 05c0571154 Add warning for unsupported firmware images
Add french translation for fw_other
2026-10-11 21:46:50 +02:00
dobodu 8790f0dca4 Merge branch 'logicog:main' into main 2026-10-11 21:38:57 +02:00
René van Dorst 98af999304 Merge pull request #547 from brunoz78/fw-machine-check
web: warn when a firmware image was built for another machine
2026-10-11 14:16:30 +00:00
René van Dorst 0a996fa6d0 Merge pull request #548 from brunoz78/tab-hostname
web: name the browser tab after the switch hostname
2026-10-11 13:50:09 +00:00
René van Dorst 441e575661 Merge pull request #569 from DrDoof/fix/flash-security-dummy
flash: set the dummy cycles required by the security register read
2026-10-11 11:20:32 +00:00
d00f a27118a428 flash: add the dummy cycles required by the security register read
Opcode 0x48 outputs 8 dummy clocks between the address and the first data
byte. flash_configure_sio() sets DUMMYCYCLES to 0 and flash_read_security()
never raises it, so the controller captures the dummy slot as the first of
its four data bytes while the address still advances by four. The printed
output therefore shows 0xff in place of every fourth byte and skips one
content byte per transfer. flash_read_uid() already sets DUMMYCYCLES for
opcode 0x4b, which needs the same allowance.
2026-10-11 03:19:00 +02:00
d00f 01709431dc Merge pull request #446 from DrDoof/feat/dns
dns: resolve host names
2026-10-10 23:52:45 +02:00
d00f de0d413c0c dns: show the last lookup with the servers
The answer to a lookup arrives after the command has returned, so the
console of the web interface never shows it. Plain "dns" now prints the
name and the address, or whether it is still pending or failed.
2026-10-10 17:54:55 +02:00
hlyi b3ac10cae7 Update HG0402XG_V1_1.c
Change 0xFF to GPIO_NA
2026-10-10 06:31:16 -07:00
René van Dorst 4e00f5a592 Merge pull request #398 from mintsoft/lldpd
LLDP implementation
2026-10-10 09:17:00 +00:00
Rob Emery eff3f42ae1 Rewriting sim implementation to be data driven
The value for enabled should be an int, not a string
2026-10-10 09:51:50 +01:00
Rob Emery dda873a633 Moving lldp cmd parsing to be above the is_sfp check to take precedence
Needed to increase buffer size for this to send app.js

The logical port status is what is returned in the array, for
non-sequential systems we need to map through physToLog rather
than just subtracting 1

physToLog is 1 based! not 0; also fixing up typecasts

Reimplementing using an array of objects to represent ports.
The previous approach of a bitmask of logical ports, was just too
simple on devices such as the SWGT024_V2_0_MANAGED which has
gaps in the port assignments.
2026-10-10 09:51:33 +01:00
Rob Emery 9b2bd7f1b8 The tick rate has been changed now so we'll have to approximate
timing with ticks

Fixing up the log_to_phys_port assignment

2000 is about every 10 seconds, so scaling up to once every 30ish

Removing the attempt to block lldp frames,
This does not work however the hard work has been done for us in
the #514 so we can borrow that work later on
2026-10-10 09:50:38 +01:00
Rob Emery 2dfe531fe0 Fixing missing parts to make the tests pass
boot_to_html outputs 1 and 0 not true and false, making the sim match
the real implementation.
lldp.json has a hanging , in the array; so overwriting it
2026-10-10 09:50:27 +01:00
Rob Emery 72c2625121 Icon from https://github.com/logicog/RTLPlayground/pull/429#issuecomment-5687458129 2026-10-10 09:50:27 +01:00
Rob Emery 58fd1a3ccc Adding lldp.json to the simulator
Moving the global on/off onto the LLDP page

Building a table of LLDP status from the S ports. Later on, if
we wish to implement an lldp receiver we can display the remote
details here

Adding support to the cmd parser for the lldp commands
2026-10-10 09:50:01 +01:00
Rob Emery 4f1a2f04d8 Allowing commands like port 1 lldp block and port 2 lldp permit
so we are able to enable/disable lldp transmission on a specific
port.
2026-10-10 09:50:01 +01:00
Rob Emery cedc795b82 Adding UI options to enable/disable LLDP 2026-10-10 09:50:01 +01:00
Rob Emery ccf541a06b Refactor and golfing from https://github.com/logicog/RTLPlayground/pull/398#issuecomment-5654087271
I've tweaked it a little to keep the port_position in as I think
that is clearer than a random "12" in the loop later on
2026-10-10 09:50:01 +01:00
Rob Emery d5124df89e avoid SRAM 2026-10-10 09:50:01 +01:00
Rob Emery 3eacc9c8a5 LLPD_MAC_ADDR_LEN -> MAC_ADDR_LEN and memcopy instead of manually setting bytes 2026-10-10 09:50:01 +01:00
Rob Emery 735672ccf1 Moving to Bank3 2026-10-10 09:49:52 +01:00
Rob Emery 1ebee4d6e9 Implementing basic LLDP server, should send port_id message
to each port once every 30 seconds.
* Additionally fixes the on-ward passing of LLDP frames through
the switch

The ports on the case are marked 1-8 so this should reflect that
rather than being 0-based

We can send the hostname as well, this can be dynamically allocated

Let's send the model as the system description as well
2026-10-10 09:49:24 +01:00
DrDoof 24c0a95734 igmp: stop looking up IPv4 multicast in the L2 table on igmp off
igmp_setup(), which `igmp off` also calls, enabled the lookup of IPv4
multicast in the L2 table. Groups learned while IGMP was on therefore
kept going only to the ports that had reported them, and with reports
no longer trapped nothing updated those entries until a reboot.

The lookup is now enabled in igmp_enable() and disabled in igmp_setup(),
so with IGMP off all IP multicast is flooded again.
2026-10-10 02:43:04 +02:00
DrDoof f88f655f5a igmp: leave groups in 224.0.0.0/24 to flooding
The switch keeps flooding 224.0.0.0/24 with IGMP on, but a report for a
group in that block still made an entry for it, and the entry limited
the group to the ports that reported it. A host announcing mDNS on
224.0.0.251 thereby cut mDNS off from every other port. Such reports
are now ignored, as RFC 4541 asks.
2026-10-09 18:02:41 +02:00
HL Yi a6b0918885 refactoring machine.c, two files per device 2026-10-08 18:43:05 -05:00
dobodu 1d6fe690a4 Add port isolation and related messages in French 2026-10-08 22:49:58 +02:00
René van Dorst e67c928eb7 Merge pull request #465 from andreas5232/add-device-ONT-S207CW-62TS-SE
add support for ONT-S207CW-62TS-SE and identical Binardat-2G06-04210GSM
2026-10-08 06:45:31 +00:00
Andreas Erhard 46f8ea8712 re-added struct comments again 2026-10-08 00:32:02 +02:00
Andreas Erhard b0eab52a2e applied feedback from review 2026-10-07 01:18:08 +02:00
Andreas Erhard 8ce062c349 resized images 2026-10-07 01:13:20 +02:00
Andreas Erhard f768220a73 updated docs and removed duplicate picturs 2026-10-05 23:51:02 +02:00
René van Dorst eab2e26510 Merge pull request #553 from DrDoof/cleanup/leds-dump-debug
leds: move the LED register dump to BANK3 and behind a command
2026-10-05 17:43:11 +00:00
DrDoof b0ed56d423 leds: move the LED register dump to BANK3 and behind a command
leds_dump() printed the pin mux, the LED enables and every LED set on each
boot, from BANK2. It now lives in its own file in BANK3, where there is
room, and runs only on the new "leds" command, next to gpio and sds, so it
stays at hand for bringing up a new board without costing BANK2 or boot
output.
2026-10-05 08:22:19 +02:00
Andreas Erhard fa632cdc6e updated docs and corrected led mapping 2026-10-05 00:43:25 +02:00
Andreas Erhard 177fb76e1b Merge branch 'main' into add-device-ONT-S207CW-62TS-SE 2026-10-04 23:45:20 +02:00
Brunoz78andClaude Opus 5.5 4f009539b0 web: name the browser tab after the switch hostname
With several switches open, every tab was called "Switch". The
dashboard tab now shows the hostname, and the login page shows the
hostname seen at the last login on that address (kept in localStorage,
which is per switch), or the address itself before the first login.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 18:33:23 +02:00
Brunoz78andClaude Opus 5.5 bb90e0c9ba web: warn when a firmware image was built for another machine
The firmware page accepted any valid image, also one built for a
different board whose SFP, LED and button pins differ. Every image
carries its machine name as a NUL-terminated string, the same one the
switch reports as hw_ver; when the selected image lacks it, the page
now warns below the check result and in the confirmation dialog. The
upload stays possible on purpose.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:41:47 +02:00
Andreas Erhard 24069439b0 reversed rj45 port order and optimized led config 2026-10-04 01:11:10 +02:00
Andreas Erhard 4117f549cc Merge branch 'main' into add-device-ONT-S207CW-62TS-SE 2026-10-03 19:27:49 +02:00
DrDoof 3cd6d60e0b ntp: keep the time from an NTP server
The switch has no battery backed clock, only a seconds counter that starts
at zero on every boot. An SNTP client keeps UTC as the time of the last
answer plus the seconds counted since: "ntp server <name|ip>", "ntp interval
<minutes>", "ntp timezone <+hh:mm>", "ntp dst off|eu|us", "ntp on|off",
"ntp" and "time". A server given by name goes through the DNS resolver, an
answer from an unsynchronised server is ignored, and a failed attempt is
repeated after 30 seconds.

The local time adds the time zone offset and, while the European or United
States rule says so, one hour. The date is split with a shift and subtract
division and a walk over the years, so no 32-bit division from the library
ends up in the common area.

The System page gets the NTP settings and shows the local time.
2026-09-29 22:40:59 +02:00
DrDoof 67b8c718fb dns: resolve host names
A small resolver for IPv4 address records, so that clients such as NTP can
be given a host name: "dns server <ip> [<ip>]", "dns lookup <name>" and
"dns". Without a configured server it uses the one DHCP handed out. A query
goes to the servers in turn every two seconds and gives up after six tries;
answers with compressed names and CNAME records ahead of the address are
understood. A name that already is a dotted address is taken without a
query.

The resolver sits in BANK3, the command line in BANK2 next to the helpers it
uses. The System page shows and sets the servers.
2026-09-29 22:40:43 +02:00
Andreas Erhard 9733ff61a0 another almost working state. port order is wrong and leds are not correct, but ports are all working 2026-09-21 01:16:16 +02:00
Andreas Erhard 36459fdd76 Merge branch 'main' into add-device-ONT-S207CW-62TS-SE 2026-09-20 22:18:41 +02:00
Andreas Erhard a4e3b4368b extracted ONT-S207CW-62TS-SE into separate device 2026-09-18 22:16:06 +02:00
Andreas Erhard c514eb8bf3 Merge branch 'logicog:main' into add-device-ONT-S207CW-62TS-SE 2026-09-17 23:33:30 +02:00
Andreas Erhard 575274786a incorporated feedback from PR 2026-09-17 12:08:37 +02:00
Andreas Erhard eb83b8be09 added support for ONT-S207CW-62TS-SE and identical Binardat-2G06-04210GSM 2026-09-17 00:18:46 +02:00
144 changed files with 5016 additions and 1708 deletions

No files matched your search

+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
apt install make gcc sdcc xxd python-is-python3 libjson-c-dev zlib1g-dev -y
- name: Run the host-side unit tests
run: make -C test
- name: Check if machine.c can be compiled for all machines
- name: Check that every machine definition can be compiled
run: make machine_check
- name: Make project (4x2/RTL8372)
run: make CI=1 MACHINE="KP_9000_6XHML_X2"
+46 -11
View File
@@ -7,17 +7,20 @@ HTML_LOCATION = 262144
ifeq ($(origin CC),default)
CC = sdcc
endif
CC_FLAGS = -mmcs51 -I. -Ihttpd -Iuip
CC_FLAGS = -mmcs51 -I. -Imachine -Ihttpd -Iuip
ASM ?= sdas8051
AFLAGS= -plosgff
SUBDIRS := tools
SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS))
ifeq ($(MACHINE),)
MACHINE:= $(shell grep "^\s*#define MACHINE_" machine.h | sed "s/^\s*#define MACHINE_//")
else
# $MACHINE selects machine/$(MACHINE).c as the board definition and is passed
# on as -DMACHINE_$(MACHINE), which the rest of the firmware tests with
# #if defined(MACHINE_...), and as -DMACHINE_NAME, which machine.h uses to
# include machine/$(MACHINE).h. Both take the same value, so they cannot drift.
ifneq ($(MACHINE),)
CC_FLAGS += -DMACHINE_$(MACHINE)
CC_FLAGS += -DMACHINE_NAME=$(MACHINE)
endif
# Health instrumentation and the "health" console command: HEALTH=1 gmake ...
ifneq ($(HEALTH),)
@@ -28,6 +31,9 @@ ifeq ($(CI),1)
CC_FLAGS += --Werror
endif
# The board definition being built: one file per MACHINE_* symbol in machine.h.
MACHINE_SRC = machine/$(MACHINE).c
BUILDDIR = output/$(MACHINE)
VERSION_HEADER := version.h
@@ -51,17 +57,31 @@ BUILD_DATE := $(shell date -u -d @$(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S" 2>/d
|| date -u -r $(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S")
endif
all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
# $(MACHINE_SRC) is listed here so an unknown $MACHINE fails before anything else
# is built, including the tools/ subdirectory.
all: create_build_dir $(VERSION_HEADER) $(MACHINE_SRC) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
create_build_dir:
mkdir -p "$(BUILDDIR)"
mkdir -p "$(BUILDDIR)/uip"
mkdir -p "$(BUILDDIR)/httpd"
mkdir -p "$(BUILDDIR)/machine"
mkdir -p "$(BUILDDIR)/crypto"
# Keep machine.c in first position to fail immediately on invalid $MACHINE value
# Every machine is a pair machine/<MACHINE>.c + machine/<MACHINE>.h. Selecting
# them by name means no #if/#elif chain, so an unknown or empty $MACHINE is
# caught here instead of by a #error further down the build.
$(MACHINE_SRC):
@echo "ERROR: MACHINE='$(MACHINE)' has no definition (expected $(MACHINE_SRC))." >&2
@echo " Every machine is one file pair under machine/, named after the" >&2
@echo " MACHINE_* symbol it defines; see machine/*.c for the full list." >&2
@echo " Example: make MACHINE=KP_9000_6XHML_X2" >&2
@false
# Keep the per-machine definition in first position to fail immediately on an
# invalid $MACHINE value
SRCS = \
machine.c \
$(MACHINE_SRC) \
machine_init.c \
cmd_editor.c \
cmd_parser.c \
@@ -70,6 +90,10 @@ SRCS = \
rtlplayground.c \
boot.c \
sfp.c \
dns.c \
dns_cli.c \
ntp.c \
ntp_cli.c \
syslog.c \
udp_apps.c \
crypto/chacha20.c
@@ -81,11 +105,15 @@ SRCS += \
rtl837x_igmp.c \
rtl837x_init.c \
rtl837x_leds.c \
rtl837x_leds_dump.c \
rtl837x_phy.c \
rtl837x_pins.c\
rtl837x_port.c \
rtl837x_stp.c \
rtl837x_storm.c
rtl837x_lldp.c \
rtl837x_storm.c \
rtl837x_lacp.c \
rtl837x_trap.c
SRCS += \
httpd/httpd.c \
httpd/page_impl.c
@@ -174,15 +202,22 @@ $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.i
.PHONY: clean distclean all $(SUBDIRS) $(SUBDIRSCLEAN) create_build_dir
# Every machine/ definition is compiled, so a machine added to machine/ is
# covered without registering it anywhere. The machine-specific defines are
# filtered out of $(CC_FLAGS) and supplied per iteration instead, so this also
# works as "make machine_check MACHINE=...".
MACHINE_DEFS := $(sort $(patsubst machine/%.c,%,$(wildcard machine/*.c)))
MACHINE_LESS_CC_FLAGS = $(filter-out -DMACHINE_%,$(CC_FLAGS))
.PHONY:
machine_check:
@mkdir -p $(BUILDDIR)/tmp
@set -eo pipefail; \
for MACHINE in `grep -E '^[[:space:]]*(//[[:space:]]*)?#define MACHINE_' machine.h | sed -E 's%^[[:space:]]*(//[[:space:]]*)?#define MACHINE_%%' | awk '{print $$1}' | sort -u`; \
for MACHINE in $(MACHINE_DEFS); \
do \
echo "Checking $${MACHINE}"; \
$(CC) $(CC_FLAGS) -DMACHINE_$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine.c; \
$(CC) $(CC_FLAGS) -DMACHINE_$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine_init.c; \
$(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_$${MACHINE} -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine/$${MACHINE}.c; \
$(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_$${MACHINE} -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine_init.c; \
done
@rm -rf $(BUILDDIR)/tmp
+1
View File
@@ -359,6 +359,7 @@ The following documents give further documentation on specific features of the R
- [IGMP (IP-MC streaming)](doc/igmp.md)
- [SFP+ ports](doc/sfp.md)
- [Trunking aka. port aggregation](doc/trunking.md)
- [LACP (802.3ad link aggregation)](doc/lacp.md)
- [VLAN](doc/vlan.md)
- [Storm control](doc/storm_control.md)
- [Modifications and Flash replacement](doc/mods.md)
+62 -12
View File
@@ -14,16 +14,22 @@
#include "rtl837x_regs.h"
#include "rtl837x_sfr.h"
#include "rtl837x_stp.h"
#include "rtl837x_lacp.h"
#include "rtl837x_igmp.h"
#include "rtl837x_bandwidth.h"
#include "rtl837x_lldp.h"
#include "rtl837x_storm.h"
#include "rtl837x_trap.h"
#include "sfp.h"
#include "dhcp.h"
#include "syslog.h"
#include "dns.h"
#include "ntp.h"
#include "uip/uip.h"
#include "version.h"
#include "machine.h"
#include "rtl837x_leds.h"
#include "phy.h"
#pragma codeseg BANK2
@@ -32,6 +38,7 @@
extern __code const struct machine machine;
extern __xdata bool stp_enabled;
extern __code const uint8_t log_to_phys_port[9];
extern __xdata bool lldp_enabled;
extern volatile __xdata uint32_t ticks;
extern volatile __xdata uint8_t sfr_data[4];
@@ -528,11 +535,21 @@ void parse_lag(void)
goto err;
if (cmd_compare(2, "d")) {
lacp_lag_set(group, 0);
port_lag_members_set(group, 0);
return;
}
uint8_t w = 2;
__xdata uint8_t lacp_mode = 0;
if (cmd_words_len > 2 && cmd_compare(2, "lacp")) {
lacp_mode = 1;
w = 3;
if (cmd_words_len > 3 && cmd_compare(3, "off")) {
lacp_lag_set(group, 0);
return;
}
}
while (w < cmd_words_len) {
// Parse port.
if (cmd_parse_port_separator(cmd_words_b[w++]) == 0)
@@ -540,10 +557,15 @@ void parse_lag(void)
members |= ((uint16_t)1) << atoi_results_u8;
}
port_lag_members_set(group, members);
if (lacp_mode) {
lacp_lag_set(group, members);
} else {
lacp_lag_set(group, 0);
port_lag_members_set(group, members);
}
return;
err:
cmd_error("lag (show | <1-4> (d | <port>...))\n");
cmd_error("lag (show | <1-4> (d | [lacp] <port>...))\n");
}
@@ -841,9 +863,14 @@ void parse_mirror(void)
if (cmd_words_len < 2)
goto err;
// The first argument is the mirroring (monitor) port
uint8_t ret = cmd_parse_port(cmd_words_b[1]);
if (ret == 0)
goto err;
mirroring_port = atoi_results_u8;
uint8_t w = 2;
uint8_t port;
uint8_t ret;
while (w < cmd_words_len) {
uint8_t idx = cmd_words_b[w++];
ret = cmd_parse_port(idx);
@@ -853,10 +880,6 @@ void parse_mirror(void)
idx += ret;
port = atoi_results_u8;
// Use the first port argument as mirroring_port
if (w == 2)
mirroring_port = port;
ret = cmd_buffer[idx];
uint16_t pmask = ((uint16_t)1) << port;
if (ret != 't')
@@ -879,6 +902,7 @@ void parse_port(void)
cmd_error("\nUsage:" \
"\nport <port> [show|on|off]" \
"\nport <port> [10m|100m|1g|2g5|duplex] [half|full]" \
"\nport <port> lldp [block|permit]" \
"\nport <port> name [custom port name]\n");
return;
}
@@ -911,6 +935,14 @@ void parse_port(void)
print_string("\nName set to: \"");
print_string_x(port_names[phy_settings.port]);
print_string("\"\n");
} else if (cmd_compare(2, "lldp")) {
if (cmd_compare(3, "block")){
lldp_logical_port_status &= ~((uint16_t)1 << phy_settings.port);
} else if (cmd_compare(3, "permit")) {
lldp_logical_port_status |= (uint16_t)1 << phy_settings.port;
} else {
print_string ("Unknown port <port> lldp [block|permit] command\n");
}
} else if (machine.is_sfp[phy_settings.port]) {
print_string(" is SFP no PHY information available.\n");
} else if (cmd_compare(2, "10m")) {
@@ -1854,6 +1886,10 @@ void cmd_parser(void) __banked
parse_mtu();
} else if (cmd_compare(0, "syslog")) {
parse_syslog();
} else if (cmd_compare(0, "dns")) {
dns_parse();
} else if (cmd_compare(0, "ntp") || cmd_compare(0, "time")) {
ntp_parse();
} else if (cmd_compare(0, "ip")) {
if (cmd_compare(1, "dhcp")) {
dhcp_start();
@@ -1954,6 +1990,13 @@ void cmd_parser(void) __banked
} else if (cmd_compare(0, "health")) {
health_show();
#endif
} else if (cmd_compare(0, "lacp")) {
if (cmd_compare(1, "show"))
lacp_show();
else if (cmd_compare(1, "off"))
lacp_off();
else
cmd_error("lacp (show | off); a group starts LACP with: lag <1-4> lacp <port>...\n");
} else if (cmd_compare(0, "pvid")) {
if (cmd_words_len == 3 && cmd_parse_port_separator(cmd_words_b[1]) != 0
&& atoi_short(cmd_words_b[2]) && atoi_results_short && atoi_results_short <= 4094)
@@ -1976,6 +2019,8 @@ void cmd_parser(void) __banked
write_char('\n');
} else if (cmd_compare(0, "gpio")) {
print_gpio_status();
} else if (cmd_compare(0, "leds")) {
leds_dump();
} else if (cmd_compare(0, "regget")) {
parse_regget();
} else if (cmd_compare(0, "regset")) {
@@ -2002,11 +2047,6 @@ void cmd_parser(void) __banked
parse_storm();
} else if (cmd_compare(0, "version")) {
print_sw_version();
} else if (cmd_compare(0, "time")) {
print_string(" Tick counter: "); print_long(ticks); print_string(" Sec Counter: ");
reg_read_m(RTL837X_REG_SEC_COUNTER);
print_sfr_data();
write_char('\n');
} else if (cmd_compare(0, "history")) {
__xdata uint16_t p = (cmd_history_ptr + 1) & CMD_HISTORY_MASK;
__xdata uint8_t found_begin = 0;
@@ -2024,6 +2064,16 @@ void cmd_parser(void) __banked
parse_ingress();
} else if (cmd_compare(0, "session")) {
parse_session();
} else if (cmd_compare(0, "lldp")) {
if (cmd_compare(1, "on")) {
print_string("LLDP enabled\n");
lldp_enabled = 1;
trap_rma_set(RTL837X_RMA0E_CONF, RTL837X_RMA_ACT_TRAP);
} else {
print_string("LLDP disabled\n");
lldp_enabled = 0;
trap_rma_set(RTL837X_RMA0E_CONF, RTL837X_RMA_ACT_FORWARD);
}
}
else {
cmd_error("Unknown command\n");
+1
View File
@@ -20,6 +20,7 @@ extern __xdata uint8_t err_status;
#define HEALTH_PH_STP 4
#define HEALTH_PH_CMD 5
#define HEALTH_PHASES 6
#define HEALTH_LLDP 7
extern __xdata uint16_t health_rx_frames;
#define health_rx_frame() health_rx_frames++
+7 -2
View File
@@ -9,9 +9,13 @@ void chacha_count(void);
__xdata struct chacha20_t __at(0xbf00) chacha20;
#ifdef CHACHA20_TEST
__xdata uint8_t plaintext[256];
__xdata uint8_t cyphertext[256];
#endif
#ifdef DEBUG
void chacha20_print_block(void)
{
for (uint8_t i=0; i < 64; i++) {
@@ -20,7 +24,7 @@ void chacha20_print_block(void)
write_char(' ');
}
}
#endif
void chacha20_encrypt(void)
{
@@ -47,7 +51,7 @@ void chacha20_encrypt(void)
};
}
#ifdef CHACHA20_TEST
// Test the example of RFC 7539 Section 2.4.2
void chacha20_test(void)
{
@@ -96,3 +100,4 @@ void chacha20_test(void)
print_byte(cyphertext[i]); write_char(' ');
}
}
#endif
+238
View File
@@ -0,0 +1,238 @@
/*
* DNS resolver for the RTL837x platform
* This code is in the Public Domain
*/
#include <stdint.h>
#include "rtl837x_common.h"
#include "cmd_parser.h"
#include "uip/uip.h"
#include "dhcp.h"
#include "dns.h"
#pragma codeseg BANK3
#pragma constseg BANK3
#define DNS_PORT 53
#define DNS_TRIES 6
#define DNS_TIMEOUT (2 * SYS_TICK_HZ)
extern __xdata struct dhcp_state dhcp_state;
extern volatile __xdata uint32_t ticks;
__xdata struct dns_state dns_state;
__xdata uip_ipaddr_t dns_ip;
uint8_t * __xdata dns_cand[3];
static uint8_t dns_used(__xdata uint8_t *a) __reentrant
{
return a[0] | a[1] | a[2] | a[3];
}
static uint8_t dns_name_is_ip(void) __reentrant
{
__xdata char *s = dns_state.name;
uint8_t i, n;
uint16_t v;
for (i = 0; i < 4; i++) {
v = 0;
n = 0;
while (*s >= '0' && *s <= '9') {
v = v * 10 + (*s++ - '0');
if (++n > 3 || v > 255)
return 0;
}
if (!n)
return 0;
dns_state.addr[i] = v;
if (i < 3 && *s++ != '.')
return 0;
}
return !*s;
}
static void dns_next(void) __reentrant
{
uint8_t k = 0;
if (dns_state.conn) {
uip_udp_remove(dns_state.conn);
dns_state.conn = 0;
}
if (dns_used(dns_state.server[0]))
dns_cand[k++] = dns_state.server[0];
if (dns_used(dns_state.server[1]))
dns_cand[k++] = dns_state.server[1];
if (dns_used(dhcp_state.dns))
dns_cand[k++] = dhcp_state.dns;
if (!k || dns_state.tries >= DNS_TRIES) {
dns_state.status = DNS_FAILED;
if (dns_state.verbose)
print_string(k ? "DNS: no answer\n" : "DNS: no server\n");
return;
}
k = dns_state.tries % k;
uip_ipaddr(dns_ip, dns_cand[k][0], dns_cand[k][1], dns_cand[k][2], dns_cand[k][3]);
dns_state.conn = uip_udp_new(&dns_ip, HTONS(DNS_PORT));
if (!dns_state.conn) {
dns_state.status = DNS_FAILED;
print_string("DNS: no free UDP connection\n");
return;
}
dns_state.send = 1;
}
static void dns_query(void) __reentrant
{
__xdata uint8_t *p = (__xdata uint8_t *)uip_appdata;
__xdata char *n = dns_state.name;
__xdata uint8_t *label;
uint16_t len = 12;
dns_state.id++;
p[0] = dns_state.id >> 8;
p[1] = dns_state.id;
p[2] = 0x01;
p[3] = 0x00;
p[4] = 0;
p[5] = 1;
p[6] = p[7] = p[8] = p[9] = p[10] = p[11] = 0;
while (*n) {
label = p + len++;
*label = 0;
while (*n && *n != '.') {
p[len++] = *n++;
(*label)++;
}
if (*n)
n++;
}
p[len++] = 0;
p[len++] = 0;
p[len++] = 1;
p[len++] = 0;
p[len++] = 1;
uip_udp_send(len);
}
static uint16_t dns_skip_name(__xdata uint8_t *p, uint16_t i, uint16_t len) __reentrant
{
while (i < len) {
if (!p[i])
return i + 1;
if ((p[i] & 0xc0) == 0xc0)
return i + 2;
i += p[i] + 1;
}
return len;
}
static void dns_answer(void) __reentrant
{
__xdata uint8_t *p = (__xdata uint8_t *)uip_appdata;
uint16_t len = uip_datalen();
uint16_t i, an;
if (dns_state.status != DNS_PENDING || len < 12 || !(p[2] & 0x80)
|| p[0] != (uint8_t)(dns_state.id >> 8) || p[1] != (uint8_t)dns_state.id)
return;
an = ((uint16_t)p[6] << 8) | p[7];
i = dns_skip_name(p, 12, len) + 4;
while (!(p[3] & 0x0f) && an-- && i + 10 <= len) {
i = dns_skip_name(p, i, len);
if (i + 10 > len)
break;
if (!p[i] && p[i + 1] == 1 && !p[i + 8] && p[i + 9] == 4 && i + 14 <= len) {
memcpy(dns_state.addr, p + i + 10, 4);
dns_state.status = DNS_DONE;
uip_udp_remove(dns_state.conn);
dns_state.conn = 0;
if (dns_state.verbose) {
print_string("DNS: ");
print_string_x(dns_state.name);
print_string(" is ");
print_ip(dns_state.addr);
write_char('\n');
}
return;
}
i += 10 + (((uint16_t)p[i + 8] << 8) | p[i + 9]);
}
dns_state.tries = DNS_TRIES;
dns_next();
}
void dns_init(void) __banked
{
memset(dns_state.server, 0, sizeof(dns_state.server));
dns_state.name[0] = 0;
dns_state.status = DNS_IDLE;
dns_state.conn = 0;
}
void dns_lookup(void) __banked
{
if (dns_name_is_ip()) {
dns_state.status = DNS_DONE;
return;
}
dns_state.tries = 0;
dns_state.status = DNS_PENDING;
dns_next();
}
void dns_show(void) __banked
{
print_string("DNS servers ");
print_ip(dns_state.server[0]);
write_char(' ');
print_ip(dns_state.server[1]);
print_string(", from DHCP ");
print_ip(dhcp_state.dns);
write_char('\n');
if (!dns_state.name[0])
return;
print_string("Last lookup ");
print_string_x(dns_state.name);
print_string(": ");
if (dns_state.status == DNS_DONE)
print_ip(dns_state.addr);
else if (dns_state.status == DNS_PENDING)
print_string("pending");
else
print_string("failed");
write_char('\n');
}
void dns_callback(uint16_t lport) __banked __reentrant
{
if (!dns_state.conn || lport != dns_state.conn->lport)
return;
if (uip_newdata()) {
dns_answer();
return;
}
if (dns_state.status != DNS_PENDING)
return;
if (dns_state.send) {
dns_state.send = 0;
dns_state.sent = ticks;
dns_query();
return;
}
if (ticks - dns_state.sent >= DNS_TIMEOUT) {
dns_state.tries++;
dns_next();
}
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef _DNS_H_
#define _DNS_H_
#include <stdint.h>
#define DNS_NAME_LEN 48
#define DNS_IDLE 0
#define DNS_PENDING 1
#define DNS_DONE 2
#define DNS_FAILED 3
struct uip_udp_conn;
struct dns_state {
uint8_t server[2][4]; /* configured servers, 0.0.0.0 = unused */
char name[DNS_NAME_LEN]; /* name of the current or last lookup */
uint8_t addr[4]; /* address found by the last lookup */
uint8_t status; /* DNS_* */
uint8_t verbose; /* print the result of the lookup */
uint8_t tries; /* queries sent for the current lookup */
uint8_t send; /* a query is due on the connection */
uint16_t id;
uint32_t sent; /* ticks when the last query went out */
struct uip_udp_conn *conn;
};
extern __xdata struct dns_state dns_state;
void dns_init(void) __banked;
void dns_lookup(void) __banked;
void dns_show(void) __banked;
void dns_callback(uint16_t lport) __banked __reentrant;
void dns_parse(void) __banked __reentrant;
#endif
+63
View File
@@ -0,0 +1,63 @@
/*
* Command line interface of the DNS resolver for the RTL837x platform
* This code is in the Public Domain
*/
#include <stdint.h>
#include "rtl837x_common.h"
#include "cmd_parser.h"
#include "dns.h"
#pragma codeseg BANK2
#pragma constseg BANK2
extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
extern __xdata uint8_t cmd_words_len;
extern __xdata uint8_t cmd_words_b[15];
extern __xdata uint8_t ip[4];
uint8_t cmd_compare(uint8_t start, __code const uint8_t * cmd);
uint8_t parse_ip(uint8_t idx);
void dns_parse(void) __banked __reentrant
{
__xdata uint8_t *s;
uint8_t n;
if (cmd_words_len < 2) {
dns_show();
return;
}
if (cmd_compare(1, "server") && cmd_words_len >= 3 && parse_ip(cmd_words_b[2])) {
memcpy(dns_state.server[0], ip, 4);
memset(dns_state.server[1], 0, 4);
if (cmd_words_len >= 4) {
if (!parse_ip(cmd_words_b[3]))
goto err;
memcpy(dns_state.server[1], ip, 4);
}
return;
}
if (cmd_compare(1, "lookup") && cmd_words_len >= 3) {
if (dns_state.status == DNS_PENDING) {
print_string("DNS: a lookup is already running\n");
return;
}
s = &cmd_buffer[cmd_words_b[2]];
for (n = 0; s[n] && s[n] != ' '; n++) {
if (n == DNS_NAME_LEN - 1)
goto err;
dns_state.name[n] = s[n];
}
dns_state.name[n] = 0;
dns_state.verbose = 1;
dns_lookup();
if (dns_state.status == DNS_DONE) {
print_ip(dns_state.addr);
write_char('\n');
}
return;
}
err:
print_string("Error: dns [server <ip> [<ip>]|lookup <name>]\n");
}
+122
View File
@@ -0,0 +1,122 @@
# ONT-S207CW-62TS-SE / Binardat 2G06-04210GSM / Binardat 2G06-04210GS
## Overview
ONT-S207CW-62TS-SE, Binardat 2G06-04210GSM (managed), and Binardat 2G06-04210GS (unmanaged) are **switches with identical hardware**:
- **CPU:** RTL8372N (confirmed via serial: "Detecting CPU: RTL8372N")
- **Flash:** GD25Q128E (16MB)
- **Ports:** 4x 2.5G RJ45 + 2x 10G SFP+
- **Console:** 115200 baud (RTLPlayground firmware) / 9600 baud (stock firmware)
**Note:** These devices are **RTL8372N-based** with **LAN ports mounted upside-down on the PCB**, requiring a custom configuration. The `MACHINE_ONT_S207CW_62TS_SE` definition uses a **custom configuration** with:
- Corrected port mapping (physical ports 1-4 = RJ45, 5-6 = SFP)
- Optimized LED sets for different port wiring (RJ45 Ports 1-2 have reversed LED wiring)
- Custom LED mux configuration
## Device Photos
### Binardat 2G06-04210GSM
**Front View:**
<img src="photos/ONT-S207CW-Binardat-2G06-04210GSM/binardat-2g06-04210gsm-front.jpg" width="400" />
**Back View:**
<img src="photos/ONT-S207CW-Binardat-2G06-04210GSM/binardat-2g06-04210gsm-back.jpg" width="400" />
**PCB View:**
<img src="photos/ONT-S207CW-Binardat-2G06-04210GSM/binardat-2g06-04210gsm-pcb.jpg" width="400" />
*Photos courtesy of [andreas5232](https://github.com/andreas5232) from [emesix/ONT-S207CW-62TS-SE#1](https://github.com/emesix/ONT-S207CW-62TS-SE/issues/1)*
## Hardware Specification
| Feature | Value |
|---|---|
| **CPU** | RTL8372N |
| **Flash** | GD25Q128E (16MB) |
| **RAM** | Integrated in RTL8372N |
| **RJ45 Ports** | 4x 2.5GBase-T (Ports 1-4) |
| **SFP+ Ports** | 2x 10G (Ports 5-6) |
| **Console** | UART (115200 baud for RTLPlayground, 9600 baud for stock) |
| **Stock Web UI IP** | 192.168.2.1 |
| **Loader Mode IP** | 192.168.10.247 |
## Port Layout
```
┌─────────────────────────────────────────────┐
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │RJ45 │ │RJ45 │ │RJ45 │ │RJ45 │ │SFP+ │ │SFP+ │ │
│ │ 1 │ │ 2 │ │ 3 │ │ 4 │ │ 5 │ │ 6 │ │
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
│ │
│ [System LEDs] │
└─────────────────────────────────────────────┘
```
## LED Behavior
### RJ45 Ports (Physical 1-4)
| LED Color | Speed |
|---|---|
| **Green** | 2.5G |
| **Orange** | 1G / 100M / 10M |
| **Off** | No link |
### SFP+ Ports (Physical 5-6)
| LED Color | Speed |
|---|---|
| **Green** | 10G |
| **Orange** | 2.5G / 1G |
| **Off** | No link / No SFP module |
## Port to Logical Mapping
Custom mapping for ONT-S207CW-62TS-SE:
| Physical Port | Logical Port | Type | LED Set |
|---|---|---|---|
| 1 | 7 | RJ45 | 2 |
| 2 | 6 | RJ45 | 2 |
| 3 | 5 | RJ45 | 0 |
| 4 | 4 | RJ45 | 0 |
| 5 | 3 | SFP+ (SDS0) | 3 |
| 6 | 8 | SFP+ (SDS1) | 3 |
**Note:** Ports 1-2 (RJ45) have reversed LED wiring and use LED-Set 2. SFP Ports 5-6 use LED-Set 3 to account for wiring differences.
## Flashing Instructions
See the [README.md](../../README.md) for general flashing instructions.
## Stock Firmware Information
| Property | Value |
|---|---|
| **Default IP** | 192.168.2.1 (ONT) / 192.168.10.247 (Loader Mode) |
| **Default Login** | admin/admin (may vary by OEM) |
| **Console Baud** | 9600 (stock) / 115200 (RTLPlayground) |
| **CPU String** | "RTL8372N" |
| **Loader Mode IP** | 192.168.10.247 |
## Configuration Details
- **CPU:** RTL8372N
- **SFP:** SDS0 on logical port 3 (GPIO37), SDS1 on logical port 8 (GPIO38)
- **Port Mapping:** Physical 1-4 → Logical 7-4, Physical 5-6 → Logical 3,8
- **LED Wiring:** RJ45 Ports 1-2 and SFP Port 6 have reversed LED pins (orange/green swapped)
- **LED Sets:** Set 0 for RJ45 Ports 3-4, Set 1 unused, Set 2 for RJ45 Ports 1-2, Set 3 for SFP Ports 5-6
## Notes
- ONT-S207CW-62TS-SE, Binardat 2G06-04210GSM (managed), and Binardat 2G06-04210GS (unmanaged) are **RTL8372N-based** with **LAN ports mounted upside-down on the PCB**
- Web UI shows correct physical port order (1-2-3-4 for RJ45, 5-6 for SFP)
- Loader Mode always remains accessible at `192.168.10.247` for recovery
- Serial console: 9600 baud (stock) → 115200 baud (RTLPlayground)
## References
- [GitHub Issue: emesix/ONT-S207CW-62TS-SE#1](https://github.com/emesix/ONT-S207CW-62TS-SE/issues/1) - Original photos and discussion
- [PR: logicog/RTLPlayground#465](https://github.com/logicog/RTLPlayground/pull/465) - Feedback and improvements
Binary file not shown.

After

Width:  |  Height:  |  Size: 546 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 639 KiB

+23
View File
@@ -0,0 +1,23 @@
# DNS
The switch can resolve host names to IPv4 addresses, for the NTP client and
for anything else that is given a name instead of an address.
```
dns server <ip> [<ip>] # one or two servers, 0.0.0.0 removes them
dns lookup <name> # resolve a name and print the address
dns # show the servers and the last lookup
```
The answer to a lookup arrives after the command has returned, so it is
printed on the serial console and in the syslog. In the console of the web
interface, run `dns` afterwards to see it.
Without a configured server the resolver uses the one handed out by DHCP.
Only address records are looked up; a query goes to the servers in turn,
every two seconds, and gives up after six tries. A name that already is a
dotted address is taken as it is, without a query.
The DNS servers are set in the Network card of the System page as well.
Settings made there or on the console are kept only once the configuration is
saved.
+5 -1
View File
@@ -73,7 +73,8 @@ uint8_t igmp_packet_handler(void) __banked;
void igmp_show(void) __banked;
```c
`igmp_setup()` is called at boot-time and configures flooding of all IP-MC packets by
default, as otherwise no IP-MC would be possible in the network.
default, as otherwise no IP-MC would be possible in the network. `igmp off` calls it as
well; groups learned while IGMP was on stay in the table, but are no longer looked up.
`igmp_enable()`starts IGMP which cause IGMP packets to be handled by the CPU and forwarding
of IP-MC packets to be limited to only subscribed ports.
@@ -85,6 +86,9 @@ for frames to 01:00:5e:xx:xx:xx and returns 0 when the frame is not a trapped IG
so that it is passed on to the IP stack. IGMPv1/v2 reports (0x12, 0x16) join the group given
in the IGMP header, IGMPv2 leaves (0x17) leave it, IGMPv3 reports use the first group record
(type 4 joins, type 3 leaves). Trapped IGMP frames arrive without a VLAN tag.
Reports for groups in 224.0.0.0/24 are ignored: the switch floods that block
even with IGMP on, and an entry for a group such as 224.0.0.251 (mDNS) would
otherwise limit it to the ports that reported it, as RFC 4541 warns against.
`igmp_show()` prints out the IGMP configuration on the CLI.
+8 -7
View File
@@ -73,13 +73,14 @@ without being flooded to the other ports. No bridge relays these frames:
their addresses are in the set that 802.1D-2004 clause 7.12.6 forbids a
bridge to forward, and what travels the network is the information, with
every bridge regenerating BPDUs of its own on its designated ports. The reserved-multicast *trap* action
cannot do that on this hardware, because its destination is an external CPU
attached to a physical port, which these boards do not populate. The protocol
modules therefore leave the reserved-multicast action at *forward* and constrain
the egress with a static L2 multicast entry instead: the lookup hits the entry's
own port mask rather than the VLAN flood mask. Verified on a SWTGW218AS both
ways, with the CPU bit cleared, where delivery stops, and with the CPU bit alone,
where nothing egresses.
does that: it delivers to the port named in `EXT_CPU_CTRL` (0x6724), which
`trap_init()` sets to 9, the CPU port, at startup; with the reset value 0xf it
names no port and the trapped frame is dropped. STP traps its address while it
runs (see stp.md). Where the action is left at *forward*, the egress can be
constrained with a static L2 multicast entry instead: the lookup hits the
entry's own port mask rather than the VLAN flood mask. Verified on a SWTGW218AS
both ways, with the CPU bit cleared, where delivery stops, and with the CPU bit
alone, where nothing egresses.
`port_l2mc_set()` writes one such entry. The SMI layout is the L2 multicast
variant of the table entry:
+155
View File
@@ -0,0 +1,155 @@
# LACP (Link Aggregation Control Protocol, IEEE 802.3ad)
A static link aggregation group works only if both ends are configured for the
same links, and nothing checks that they are. LACP lets the two ends agree on
which links reach the same partner, aggregates only those, and takes a link out
of the group when the partner stops answering.
The switch runs LACP in software on the 8051. LACP frames belong to the Slow
Protocols, with destination `01:80:C2:00:00:02` and ethertype `0x8809`; the
subtype of LACP frames is 1. The implementation has the Receive, Selection and
Mux machines of 802.3ad clause 43 and does not aggregate links whose partners
differ. Up to `LACP_NUM_LAGS` (4) groups can run LACP; the others stay static.
## Getting the frames to the CPU
While LACP runs, the reserved multicast action for `01:80:C2:00:00:02` is
*trap*, the same mechanism STP uses for its BPDUs, see [stp.md](stp.md). A
trapped LACPDU has no VLAN tag after the RTL tag, and `TRAP_RX_BODY()` gives the
offset of the LACPDU in the received frame. When the last group leaves LACP,
the action goes back to *drop*.
## What has to match across the members
802.3ad requires that every link in an aggregate be full duplex and run at the
same speed. Beyond the standard, anything that changes how a frame is treated
has to be identical across members, because the hash picks the member per frame
and a difference would make the behaviour depend on that choice:
* must match: speed and duplex, VLAN membership and pvid, ingress filtering,
port isolation
* may differ: EEE, LED configuration, counters, cable diagnostics
None of this is enforced yet — `port_lag_members_set()` writes a member mask and
a hash setting and validates nothing. See #377 for the discussion of whether a
mismatch should be rejected or applied to the whole group.
## Protocol timing
The timer values are in units of the LACP timer, which steps every four ticks
of the system clock, 50 times per second:
| Constant | Value | Time |
|----------------------|-------|------|
| `LACP_FAST_PERIODIC` | 50 | 1 s |
| `LACP_SLOW_PERIODIC` | 1500 | 30 s |
| `LACP_SHORT_TIMEOUT` | 200 | 4 s |
802.3ad specifies a fast periodic time of 1 s with a short timeout of 3 s, and a
slow periodic time of 30 s with a long timeout of 90 s. The switch transmits at
the rate the partner asks for with its TIMEOUT bit. Its own timeout is always
the short one, one second above the standard, so a partner that stops sending
while its link stays up leaves the trunk after 4 s.
The Partner block of a transmitted LACPDU repeats the partner's actor
information as it was last received: system priority, system, key, port
priority, port and state. A Linux partner sets our SYNC only when this block
matches what it sent.
## LACP API
```
void lacp_init(void) __banked;
void lacp_off(void) __banked;
void lacp_lag_set(uint8_t lag, __xdata uint16_t ports) __banked;
void lacp_in(void) __banked;
void lacp_timers(void) __banked;
void lacp_show(void) __banked;
```
`lacp_init()` has to run before the startup configuration replays, because xdata
is not zeroed and the port-to-LAG map uses `0xff` as "no LAG"; a stray zero would
make a port look like it belongs to LAG 0.
## LACP configuration on the serial console
A group is put under LACP by adding `lacp` to the `lag` command:
```
lag 1 lacp 7 8 # ports 7 and 8 become LACP candidates of group 1
lag 1 lacp off # group 1 leaves LACP, its trunk is cleared (so does "lag 1 lacp")
lag 1 d # group 1 disabled, whether it ran LACP or not
lag 1 7 8 # plain static aggregation, no protocol
```
A group put under LACP gives up the static trunk it had: the hardware trunk is
cleared and rebuilt from the ports that converge. The other way round, `lag 1 d`
and a static member list take the group out of LACP before they touch the
trunk. A port named in another LACP group moves to the new one. The protocol
starts with the first group put under LACP and stops when the last one is taken
out; there is no separate switch for it. Two commands act on the whole engine:
```
lacp off # every group leaves LACP, protocol stopped
lacp show
```
`lacp show` prints the engine state, then one line per group with its candidate
ports, the elected aggregator and the trunk members actually programmed into the
hardware, then one line per port with the actor and partner state bytes and the
receive-machine state.
## LACP configuration via the Web Interface
Each group on the LAG page has a Static/LACP mode next to its member ports;
for an LACP group it shows the elected aggregator and the active members. Below
the groups a table has one row per LACP port with its group, actor and partner
state, receive state, LACPDU count and partner system. The page reads
`/lacp.json` every three seconds while it is open. The member checkboxes of a
static group come from the hardware registers in `/lag.json`.
## A test with a Linux 802.3ad bond
Two ports of the switch to two interfaces of one host:
```
ip link add bond0 type bond mode 802.3ad
ip link set enp1s0 down && ip link set enp1s0 master bond0
ip link set enp2s0 down && ip link set enp2s0 master bond0
ip link set bond0 up
```
On the switch, with those two ports as the group:
```
lag 1 lacp 7 8
```
`lacp show` should then give both ports an actor state of `0x3f` (ACTIVITY,
TIMEOUT, AGGREGATION, SYNC, COLLECTING and DISTRIBUTING), a partner state with
SYNC set, and the partner's system MAC. `lag show` lists the trunk members as
programmed in the hardware and should show both ports.
On the host, `/proc/net/bonding/bond0` should show the same `Aggregator ID` for
both slaves; different IDs mean that each link is in a group of its own. Both
churn states should read `none`.
Further checks:
* `tcpdump -i enp1s0 ether proto 0x8809` on each slave shows the LACPDUs of the
switch and of that slave, never those of the other slave.
* The host log has no `illegal loopback`.
* The three reserved bytes after the actor state in a LACPDU from the switch
are zero.
When one slave goes down, the group narrows to the remaining member, and the
slave rejoins after it comes back.
## Known limits
* No Churn Detection machines and no Marker protocol.
* Coupled Mux: collecting and distributing are enabled together.
* One aggregator per group.
* Selection compares the partner's system only, not its key: two aggregates
that one partner system offers on the same group land in one trunk here.
* Member compatibility is not validated; see #377.
+4
View File
@@ -227,3 +227,7 @@ iperf Done.
```
As you can see, the total throughput was 4.71 GBit/sec which is close to the
maximum possible with a single 5GBit link.
## LACP
Dynamic aggregation with LACP is described in [lacp.md](lacp.md).
+33
View File
@@ -0,0 +1,33 @@
# Time
The switch has no battery backed clock. It counts seconds from power on, and
it can take the date and time from an NTP server once the network is up. The
time is lost at every restart and set again at the first synchronisation.
```
ntp server <name|ip> # default pool.ntp.org
ntp interval <1-1440> # minutes between two synchronisations, default 60
ntp timezone <+hh:mm> # offset from UTC, -12:00 to +14:00
ntp dst off|eu|us # daylight saving rule
ntp on
ntp off
ntp # settings and time
time # local date and time
```
The client speaks SNTP version 4 and synchronises at once when turned on,
then after every interval. A server given by name is resolved through the DNS
resolver before every synchronisation. An answer from an unsynchronised
server is ignored, and a failed attempt is repeated after 30 seconds.
The local time is UTC plus the time zone offset, plus one hour while daylight
saving time applies:
* `eu`: from 01:00 UTC on the last Sunday of March to 01:00 UTC on the last
Sunday of October;
* `us`: from 02:00 local time on the second Sunday of March to 02:00 local
time on the first Sunday of November.
The same settings, with the current local time and the last synchronisation,
are in the Time card of the System page. Settings made there or on the
console are kept only once the configuration is saved.
+25 -19
View File
@@ -35,28 +35,34 @@ BPDUs are addressed to `01:80:C2:00:00:00`, a reserved link-local group. The
ASIC's Reserved-Multicast action for that address decides what happens to the
frame.
Forwarding to the CPU port works normally: the 8051 sits behind an ordinary
port of the internal switch and is an ordinary member of a forwarding mask.
The *trap* action does not deliver to it. Its destination is an external CPU
attached to a physical port (`cpuTag_externalCpuPort_set`, `EXT_CPU_CTRL` in
the vendor SDK), which these boards do not populate. The ACL trap and
redirect actions do not deliver to the 8051 either.
While STP runs, the action is *trap*. A trap delivers to the port named in
`EXT_CPU_CTRL` (0x6724), whose reset value 0xf names no port, and with that
value the trapped frame is dropped at ingress. `trap_init()` sets it to 9, the
port the 8051 sits behind, once at startup. The trap needs no per-VLAN L2
entries, so it does not depend on which VLANs exist or on the PVIDs, and turning
STP on no longer walks the whole VLAN table. BPDUs reach the CPU on a port that
STP holds in blocking with either action: measured on a SWTGW218AS by sending
BPDUs into a blocked port with forward and with trap, both ports stopped being
edge and waited out the forward delay. The chip exempts this address from the
ingress state check; the slow-protocols address used by LACP is not exempt.
Delivery therefore uses the *forward* action, constrained to the CPU port
by a static L2 multicast entry (`port_l2mc_set()`), one per VLAN in use:
A trapped frame reaches the CPU in the format it came in with: unlike a
forwarded one it has no VLAN tag inserted after the RTL tag, and the RTL tag
carries the trap reason. `stp_in()` reads the BPDU from the offset
`TRAP_RX_BODY()` returns, which works for both.
* while STP runs, the entry's member mask is the CPU port only — BPDUs reach
the CPU and are not flooded to other ports, as a participating bridge
requires;
* with STP off, the same entries are retargeted to all ports, restoring the
transparency an unmanaged switch is expected to have, so a surrounding
spanning tree can span *through* this device.
With STP off, the action goes back to *forward* and a static L2 multicast
entry per VLAN in use (`port_l2mc_set()`) targets all ports, restoring the
transparency an unmanaged switch is expected to have, so a surrounding
spanning tree can span *through* this device.
A BPDU delivered this way is an ordinary frame to the port's ingress logic
and passes through its acceptable-frame-type filter. BPDUs are untagged, so a
port set to admit tagged frames only (`ingress <port>t`) never delivers one
to the CPU. `stp_setup()` prints a warning for every STP-enabled port in that
state.
The port's acceptable-frame-type filter treats the two actions differently.
BPDUs are untagged, so a port set to admit tagged frames only
(`ingress <port>t`) drops a forwarded BPDU before it reaches the CPU, while a
trapped one passes. Both were measured on a SWTGW218AS with `ingress 3t`:
LACPDUs, delivered by forward, stopped arriving on port 3, and BPDUs sent into
the same port, delivered by trap, kept arriving. A port that admits tagged
frames only therefore takes part in STP.
## Link aggregation
+2
View File
@@ -29,6 +29,8 @@ The following devices have been tested and are fully working:
| Mokerlink| 2G040210GSM | Yes | [2M-PCB43-V1.1](devices/2M-PCB43-V1.1.md) | | 4 + 2 |
| Mokerlink| ZX-SWTGW218AS | Yes | [SWTG118AS-V2.0-16029](devices/SWTGW218AS.md) | 2M | 8 + 1 |
| MokerLink| POE-2G080110GS | No | [2M-PCB51-ML-V1.1](devices/2M-PCB51-ML-V1_1.md) | 4M | 8 + 1 |
| Binardat | 2G06-04210GSM | No | [PCB-SWTG024AS-A-2.0.1](devices/ONT-S207CW-62TS-SE.md) | 0.5M | 4 + 2 |
| ONT | ONT-S207CW-62TS-SE | No | [PCB-SWTG024AS-A-2.0.1](devices/ONT-S207CW-62TS-SE.md) | 0.5M | 4 + 2 |
| Netcore | GS9 | No | [PB-2132](devices/PB-2132.md) | 4M | 8 + 1 |
| Ruiying | RY-4GT-2SX | No | [FG-4GT-2SX_V2.0](devices/FG-4GT-2SX_V2.0.md) | 4M | 4 + 2 |
| Ruiying | RY-8GT-1SX | No | [FG-8GT-1SX](devices/FG-8GT-1SX.md) | 1M | 8 + 1 |
+182 -19
View File
@@ -3,7 +3,7 @@ var LANG={
en:{
nav_dash:"Dashboard",nav_ports:"Ports",nav_stp:"Spanning tree",nav_stats:"Statistics",
nav_vlan:"VLANs",nav_l2:"MAC table",nav_mirror:"Mirroring",nav_isolate:"Isolation",nav_lag:"LAG",nav_eee:"EEE",
nav_bw:"Bandwidth",nav_system:"System",nav_fw:"Firmware",
nav_bw:"Bandwidth",nav_system:"System",nav_fw:"Firmware",nav_lldp:"LLDP",
hdr_dirty:"unsaved changes",hdr_dirty_t:"Running config differs from startup config",
hdr_save:"Save to flash",hdr_save_t:"Persist running configuration to flash",
th_auto:"System",th_auto_sel:"System (Selenized)",sy_display:"Display",sy_theme:"Theme",sy_display_note:"Stored in this browser only.",th_light:"Light",th_dark:"Dark",
@@ -40,6 +40,7 @@ stp_en_q:"Enable spanning tree?",
stp_en_d:"Ports start blocked and take up to twice the forward delay to reach forwarding; edge ports recover immediately.",
stp_dis_q:"Disable spanning tree?",stp_dis_d:"All ports go straight to forwarding; loop protection is lost.",
stp_cost_err:"Path cost must be 0-200000000",
lldp_enabled: "LLDP Enabled",lldp_title:"Service Status",lldp_portname:"Name",lldp_enable:"Send Frames",
st_title:"Port statistics",st_h:"totals since boot",st_txg:"TX good",st_txb:"TX bad",st_rxg:"RX good",
st_rxb:"RX bad",st_details:"Details",st_counters:"MIB counters",st_nonzero:"non-zero only",
st_autoref:"auto-refresh",st_counter:"Counter",st_value:"Value",st_fail:"failed to load counters",
@@ -66,6 +67,9 @@ iso_title:"Port isolation",iso_from:"From port",iso_to:"To port",iso_all:"Allow
iso_intro:"A frame entering a port may only leave through the ports ticked in its row. Isolation is decided before forwarding, so a port that is not ticked is unreachable directly, whatever the address table says.",
iso_legend:"The cell of the port itself is always allowed. A port number in red marks a port that is not fully open.",
lag_hash:"Hash:",lag_note:"A LAG needs at least one member to be saved in the startup config; applying an empty group clears it.",
lacp_heading:"LACP (802.3ad)",lag_mode:"Mode",lag_static:"Static",lacp_neg:"negotiating",lacp_agg:"aggregator",
lacp_members:"active members",lacp_hint:"LACP: select candidate ports and press Apply to start negotiation",
lacp_actor:"Actor",lacp_partner:"Partner",lacp_rxstate:"RX state",lacp_rx:"LACPDUs received",lacp_psys:"Partner system",
lag_clear_q:"Clear LAG {n}?",lag_clear_d:"All member ports return to normal operation.",
e_title:"Energy Efficient Ethernet",e_adv:"Advertised",e_lp:"Link partner",e_active:"Active",e_enable:"Enable",
e_note:"Advertised and link-partner flags per speed: 100M, 1G, 2.5G. SFP ports do not support EEE.",
@@ -89,7 +93,14 @@ sy_ip_err:"Invalid IP / netmask / gateway",sy_host_err:"Hostname: 1-23 printable
sy_net_q:"Apply network settings?",sy_net_d:"The management IP changes to {ip}: this page will need to be reopened there.",
sy_ip_changed:"IP changed, reconnect at http://{ip}/",sy_dhcp_q:"Switch to DHCP?",
sy_dhcp_d:"The switch requests an address via DHCP. You must find its new IP to reconnect.",
sy_sysip_err:"Invalid syslog server IP",sy_sysport_err:"Syslog port must be 1-65535",
sy_sysip_err:"Invalid syslog server IP",sy_dns1:"DNS server",sy_dns2:"Second DNS",sy_dns_err:"Invalid DNS server IP",sy_dns_dhcp:"from DHCP: {ip}",
sy_time:"Time",sy_ntp:"NTP",sy_ntpsrv:"NTP server",sy_ntpsrv_p:"host name or IPv4 address",sy_ntpint:"Poll interval [min]",
sy_tz:"Time zone",sy_dst:"Daylight saving",sy_dst_eu:"Europe",
sy_dst_us:"United States",sy_now:"Local time",
sy_sync:"Last synchronisation",sy_ntpaddr:"Server address",sy_nosync:"not synchronised",sy_waiting:"waiting for the server",
sy_ago:"{n} min ago",sy_ntp_err:"Enter the host name or IPv4 address of the NTP server",sy_ntpint_err:"Poll interval must be 1-1440",
sy_time_note:"The switch has no battery backed clock: the time is lost at every restart and set again from the NTP server once the network is up. Save to flash to keep the settings.",
sy_sysport_err:"Syslog port must be 1-65535",
sy_pw_len:"Password: 1-20 characters",sy_pw_space:"Password cannot contain spaces",sy_pw_match:"Passwords do not match",
sy_pw_q:"Change admin password?",sy_pw_d:"Takes effect immediately for new logins. Save to flash to persist.",
sy_reboot_q:"Reboot the switch?",sy_reboot_d:"There are UNSAVED changes and they will be lost. Save to flash first if you want to keep them.",
@@ -108,6 +119,7 @@ fw_intro:"Upload an RTLPlayground image (512 KiB .bin). The image is staged to f
fw_upload:"Upload",fw_checking:"{f}: {n} bytes. Checking...",fw_size_err:"size is {n}, expected 524288 (512 KiB)",
fw_magic_err:"missing bank header / LJMP magic: not a firmware image",fw_crc_err:"CRC16 check failed: corrupt image",
fw_valid:"valid RTLPlayground image (size, magic and CRC16 OK)",fw_q:"Upload firmware?",
fw_other:"This image was not built for this switch ({m}): its SFP, LED and button pins may differ. Upload it only if you are sure.",
fw_d:"On a good checksum the switch resets itself and applies the image during boot (the startup config is preserved). Do not power it off until it comes back.",
fw_finishing:"finishing flash write... {s} s",fw_uploading:"uploading... {p}% / {s} s",
fw_verified:"checksum verified, the switch is rebooting...",
@@ -519,6 +531,9 @@ l2_learned:"appris",l2_loading:"chargement...",l2_failed:"chargement non réussi
l2_del_t:"Supprimer l'entrée",l2_flush_q:"Effacer toutes les entrées MAC apprises?",
m_title:"Duplication de ports",m_active:"actif",m_monitor:"Port de supervision",m_mirror:"Mirroir",m_both:"RX&TX",
m_note:"RX&TX = duplique RX et TX du port vers le port de supervision.",m_none:"Selectionnez au moins un port à dupliquer",
iso_title:"Isolation des ports",iso_from:"Du port",iso_to:"Au port",iso_all:"Tout autoriser",
iso_intro:"Une trame réseau accédant à un port ne peut repartir que par le port selectionné dans cette ligne. L'isolement est prioritaire sur la retransmission, un port non non coché n'est pas accessible directement, quoi que dit la table d'adresses.",
iso_legend:"La cellule du port lui-même est toujours autorisée. Une port de couleur rouge indique que celui-ci n'est que partiellement ouvert.",
lag_hash:"Hachage:",lag_note:"Un groupe d'agrégation de Lien (LAG) nécessite au moins un membre pour être sauvegardé dans la configuration de démarrage; Utiliser un groupe vide fait office de remise à zero.",
lag_clear_q:"Effacer l'agrégation {n}?",lag_clear_d:"Tous les ports membres vont redevenir normaux.",
e_title:"Gestion énergétique des ports",e_adv:"Capacités",e_lp:"Capacité du partenaire",e_active:"Actif",e_enable:"Basse consommation",
@@ -559,6 +574,7 @@ fw_intro:"Charge une image RTLPlayground (512 KiB .bin). L'image est envoée en
fw_upload:"Charger",fw_checking:"{f}: {n} bytes. Vérification...",fw_size_err:"la taille est {n} alors que nous attendons 524288 (512 KiB)",
fw_magic_err:"Entête de banque de donnée manquant / contrôle LJMP: ce n'est pas une image de firmware",fw_crc_err:"Somme de contrôle erronée: image corrompue",
fw_valid:"Image RTLPlayground valide (taille, LJMP et somme de contrôle OK)",fw_q:"Chargement du firmware?",
fw_other:"Cette image n'a pas été prévue pour ce commutateur({m}): La puce, les LED et les boouton peuvent être différents. Poursuivez seulement si vous êtes sûrs de vous.",
fw_d:"Si la somme de contrôle est correcte, le commutateur va redémarrer tout seul et charger la nouvelle image lors du démarrage (la configuration est préservée). Ne pas éteindre l'appareil avant que les voyants ne s'éteignent.",
fw_finishing:"Fin d'écriture en mémoire flash... {s} s",fw_uploading:"Chargement... {p}% / {s} s",
fw_verified:"Somme de contrôle vérifiée, le commutateur redémarre...",
@@ -675,6 +691,7 @@ fw_intro:"Ein RTLPlayground-Image hochladen (.bin, 512 KiB). Das Image wird im F
fw_upload:"Hochladen",fw_checking:"{f}: {n} Bytes. Wird geprüft...",fw_size_err:"Grösse ist {n}, erwartet 524288 (512 KiB)",
fw_magic_err:"Bank-Header / LJMP-Kennung fehlt: kein Firmware-Image",fw_crc_err:"CRC16-Prüfung fehlgeschlagen: Image beschädigt",
fw_valid:"gültiges RTLPlayground-Image (Grösse, Kennung und CRC16 in Ordnung)",fw_q:"Firmware hochladen?",
fw_other:"Dieses Image wurde nicht für diesen Switch ({m}) gebaut: SFP-, LED- und Tasten-Pins können abweichen. Nur hochladen, wenn du sicher bist.",
fw_d:"Ist die Prüfsumme korrekt, startet der Switch neu und übernimmt das Image beim Hochfahren (die Startkonfiguration bleibt erhalten). Nicht vom Strom trennen, bis er wieder erreichbar ist.",
fw_finishing:"Flash wird fertig beschrieben... {s} s",fw_uploading:"wird hochgeladen... {p}% / {s} s",
fw_verified:"Prüfsumme bestätigt, der Switch startet neu...",
@@ -781,6 +798,9 @@ var CONF_CMDS=[
/^gw\s+(\d{1,3}\.){3}\d{1,3}$/,/^netmask\s+(\d{1,3}\.){3}\d{1,3}$/,
/^syslog\s+(on|off)$/,/^syslog\s+ip\s+(\d{1,3}\.){3}\d{1,3}$/,/^syslog\s+port\s+\d{1,5}$/,
/^session\s+\d{1,5}$/,
/^dns\s+server\s+(\d{1,3}\.){3}\d{1,3}(\s+(\d{1,3}\.){3}\d{1,3})?$/,
/^ntp\s+(on|off)$/,/^ntp\s+server\s+[A-Za-z0-9.-]{1,47}$/,/^ntp\s+interval\s+\d{1,4}$/,
/^ntp\s+timezone\s+[+-]?\d{1,2}(:\d{2})?$/,/^ntp\s+dst\s+(off|eu|us)$/,
/^passwd\s+\S+$/,/^hostname\s+\S{1,23}$/,
/^vlan\s+\d{1,4}\s+d$/,/^vlan\s+\d{1,4}\s+mgmt$/,
/^vlan\s+\d{1,4}(\s+[a-zA-Z]\w*)?(\s+\d{1,2}t?)+$/,
@@ -788,9 +808,10 @@ var CONF_CMDS=[
/^ingress(\s+\d{1,2}[tua])+$/,/^ingress\s+[tua]$/,
/^port\s+\d{1,2}\s+(10m|100m|1g|2g5|5g|10g|auto|on|off)(\s+(half|full))?$/,
/^port\s+\d{1,2}\s+name\s+\S+$/,
/^port\s+\d{1,2}\s+lldp\s+(permit|block)+$/,
/^eee\s+(on|off)(\s+\d{1,2})?(\s+(100m|1g|2g5))?$/,
/^mirror(\s+\d{1,2})(\s+\d{1,2}[tr]?)+$/,/^mirror\s+off$/,
/^lag\s+[1-4](\s+\d{1,2})+$/,/^lag\s+[1-4]\s+d$/,/^laghash\s+[1-4](\s+\w+)+$/,
/^lag\s+[1-4](\s+\d{1,2})+$/,/^lag\s+[1-4]\s+d$/,/^lag\s+[1-4]\s+lacp(\s+\d{1,2})+$/,/^lag\s+[1-4]\s+lacp\s+off$/,/^laghash\s+[1-4](\s+\w+)+$/,
/^isolate\s+\d{1,2}(\s+(off|\d{1,2}))+$/,
/^stp\s+(on|off)$/,/^stp\s+(prio|hello|maxage|fwd|txhold)\s+\d{1,2}$/,
/^stp\s+version\s+(rstp|stp)$/,
@@ -798,7 +819,7 @@ var CONF_CMDS=[
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+cost\s+\d{1,9}$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+prio\s+\d{1,3}$/,
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+guard\s+(none|bpdu|root)$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+filter\s+(on|off)$/,
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+p2p\s+(auto|on|off)$/,
/^igmp\s+(on|off)$/,/^mtu\s+\d{1,2}\s+\d+$/,
/^igmp\s+(on|off)$/,/^mtu\s+\d{1,2}\s+\d+$/,/^lldp\s+(on|off)$/,
/^bw\s+(in|out)\s+\d{1,2}\s+\S+$/,
/^storm\s+\d{1,2}\s+(bcast|mcast|ucast|umcast)\s+(off|\d{1,8}\s+(pps|kbps))$/,
];
@@ -860,6 +881,7 @@ var TABS=[
{id:"mirror",icon:"M12 3v18M7 8l-4 4 4 4M17 8l4 4-4 4"},
{id:"isolate",icon:"M4 4h6v6H4zM14 14h6v6h-6zM14 4h6v6h-6zM4 14h6v6H4z"},
{id:"lag", icon:"M7 8a4 4 0 100 8h3M17 8a4 4 0 110 8h-3M9 12h6"},
{id:"lldp", icon:"M11 12a1 1 0 002 0 1 1 0 00-2 0M8.5 8.5a5 5 0 000 7M15.5 8.5a5 5 0 010 7M5.6 5.6a9 9 0 000 12.8M18.4 5.6a9 9 0 010 12.8"},
{id:"eee", icon:"M13 2L4 14h6l-1 8 9-12h-6z"},
{id:"bw", icon:"M4 18a8 8 0 0116 0M12 18l4-6"},
{id:"system",icon:"M12 8a4 4 0 100 8 4 4 0 000-8zM4 12h2M18 12h2M12 4v2M12 18v2M6 6l1.5 1.5M16.5 16.5L18 18M18 6l-1.5 1.5M7.5 16.5L6 18"},
@@ -1048,7 +1070,11 @@ function renderInfo(){
if(v==null||v==="")return;
tb.appendChild(h("tr",null,[h("td",{class:"mut",text:t(r[0])}),h("td",{class:"mono",text:String(v)})]));
});
if(S.info.hostname)$("brandname").textContent=$("brandname").title=S.info.hostname;
if(S.info.hostname){
$("brandname").textContent=$("brandname").title=document.title=S.info.hostname;
// Remembered per switch (each has its own origin) for the login page tab
try{localStorage.setItem("rtl_host",S.info.hostname);}catch(e){}
}
if(S.info.sw_ver)$("fver").textContent="RTLPlayground "+S.info.sw_ver;
}
function pollInfo(){
@@ -1791,6 +1817,15 @@ function buildLag(){
for(var g=1;g<=4;g++)(function(g){
var card=h("div",{class:"card"});
card.appendChild(h("h2",{text:"LAG "+g}));
var mr=h("div",{style:"display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:10px",class:"small"});
mr.appendChild(h("span",{class:"mut",text:t("lag_mode")}));
var ms=h("select",{class:"in",id:"lgm"+g});
ms.appendChild(h("option",{value:"static",text:t("lag_static")}));
ms.appendChild(h("option",{value:"lacp",text:"LACP"}));
ms.addEventListener("change",function(){$("lgs"+g).textContent=ms.value==="lacp"?t("lacp_hint"):""});
mr.appendChild(ms);
card.appendChild(mr);
card.appendChild(h("p",{class:"small mono",id:"lgs"+g,style:"margin-bottom:10px"}));
var pr=h("div",{style:"display:flex;gap:10px;flex-wrap:wrap;margin-bottom:10px"});
for(var p=1;p<=S.n;p++)pr.appendChild(h("label",null,[
h("input",{type:"checkbox",id:"lg"+g+"p"+p}),document.createTextNode(" "+p+" "),
@@ -1803,14 +1838,34 @@ function buildLag(){
});
card.appendChild(hr);
card.appendChild(h("button",{class:"ctl pri",text:t("c_apply"),onclick:function(){lagApply(g)}}));
card.addEventListener("change",function(){card.dataset.dirty="1"});
w.appendChild(card);
})(g);
}
var lacpCfg=[0,0,0,0,0];
function maskPorts(m){var r=[];for(var p=1;p<=S.n;p++)if((m>>S.physToLog[p-1])&1)r.push(p);return r.length?r.join(" "):"-"}
function lagLoad(){
return getJSON("/lag.json").then(function(s){
return getJSON("/lacp.json").then(function(c){
var tb=$("lacptbl").tBodies[0];
tb.innerHTML="";
c.lags.forEach(function(lg,i){
var g=i+1;
lacpCfg[g]=parseInt(lg.cfg,16);
if($("lgm"+g).closest(".card").dataset.dirty)return;
$("lgm"+g).value=lacpCfg[g]?"lacp":"static";
$("lgs"+g).textContent=lacpCfg[g]?"LACP: "+t("lacp_agg")+" "+(lg.aggValid?lg.agg:"("+t("lacp_neg")+")")+", "+t("lacp_members")+" "+maskPorts(parseInt(lg.members,16)):"";
});
if(c.on)c.ports.forEach(function(p){
if(p.lag===255)return;
var tr=tb.insertRow();
[p.p,p.lag+1,p.a,p.pt,p.rs,parseInt(p.rx,16),p.psys].forEach(function(v){tr.insertCell().textContent=v});
});
return getJSON("/lag.json");
}).then(function(s){
s.forEach(function(l){
var g=l.lagNum+1;
var members=parseInt(l.members,2);
if($("lgm"+g).closest(".card").dataset.dirty)return;
var members=lacpCfg[g]||parseInt(l.members,2);
for(var p=1;p<=S.n;p++)
$("lg"+g+"p"+p).checked=!!((members>>S.physToLog[p-1])&1);
var hash=parseInt(l.hash,16);
@@ -1819,21 +1874,51 @@ function lagLoad(){
});
}
function lagApply(g){
var cmd="lag "+g,n=0;
var lacp=$("lgm"+g).value==="lacp",cmd="lag "+g+(lacp?" lacp":""),n=0,pre=[];
delete $("lgm"+g).closest(".card").dataset.dirty;
for(var p=1;p<=S.n;p++)if($("lg"+g+"p"+p).checked){cmd+=" "+p;n++;}
if(!n){
if(!lacp&&lacpCfg[g])pre.push("lag "+g+" lacp off");
if(lacp&&!n)cmd="lag "+g+" lacp off";
if(!n&&!lacp){
confirmModal(t("lag_clear_q",{n:g}),t("lag_clear_d"),function(){
postCmd("lag "+g+" d").then(lagLoad).catch(function(){});
postCmds(pre.concat(["lag "+g+" d"])).then(lagLoad).catch(function(){});
});
return;
}
var hcmd="laghash "+g,nh=0;
HASHF.forEach(function(f){if($("lg"+g+"h"+f).checked){hcmd+=" "+f;nh++;}});
var cmds=[cmd];
var cmds=pre.concat([cmd]);
if(nh)cmds.push(hcmd);
postCmds(cmds).then(lagLoad).catch(function(){});
}
tabHooks.lag={enter:function(){needPorts(function(){buildLag();lagLoad().catch(function(){})})}};
var lagPoller=new Poller(function(){return lagLoad().catch(function(){})},3000);
tabHooks.lag={enter:function(){needPorts(function(){buildLag();lagPoller.start()})},leave:function(){lagPoller.stop()}};
function lldpLoad(){
return getJSON("/lldp.json").then(function(s){
$("lldp_en").checked=s.on;
var tb=$("lldp_table").tBodies[0];tb.innerHTML="";
byPort(s.portStatus).forEach(function(p){
var tr=tb.insertRow();
tr.insertCell().textContent=p.portNum;
tr.insertCell().textContent=p.name;
var sw=h("label",{class:"switch"},[
h("input",{type:"checkbox",onchange:function(){
postCmd("port "+p.portNum+" lldp "+(this.checked?"permit":"block"))
.then(function(){setTimeout(lldpLoad,300)}).catch(function(){});
}}),h("i")]);
sw.firstChild.checked=p.permitted;
tr.insertCell().appendChild(sw);
});
});
}
$("lldp_en").addEventListener("change",function(){
var el=this;
postCmd("lldp "+(el.checked?"on":"off")).catch(function(){el.checked=!el.checked});
});
tabHooks.lldp={enter:lldpLoad};
function eeeFlags(bits){
var b=parseInt(bits,2);
@@ -1993,6 +2078,16 @@ function sysLoad(){
if(S.info.session_timeout)$("sy-sesstmo").value=S.info.session_timeout;
}).catch(function(){});
cfgReload();
dnsLoad();
}
function dnsLoad(){
return api("/cmd",{method:"POST",body:"dns"}).then(function(r){
var m=r.body.match(/DNS servers ([\d.]+) ([\d.]+), from DHCP ([\d.]+)/);
if(!m)return;
function v(x){return x==="0.0.0.0"?"":x}
$("sy-dns1").value=v(m[1]);$("sy-dns2").value=v(m[2]);
$("sy-dnsdhcp").textContent=m[3]==="0.0.0.0"?"":t("sy_dns_dhcp",{ip:m[3]});
}).catch(function(){});
}
function cfgParseKnown(txt){
var igmp=false,syslog=false;
@@ -2009,13 +2104,15 @@ function cfgParseKnown(txt){
$("sy-apply").addEventListener("click",function(){
var ip=$("sy-ip").value.trim(),mask=$("sy-mask").value.trim(),gw=$("sy-gw").value.trim();
if(!okIp(ip)||!okIp(mask)||!okIp(gw)){toast(t("sy_ip_err"),"err");return;}
var d1=$("sy-dns1").value.trim(),d2=$("sy-dns2").value.trim();
if((d1&&!okIp(d1))||(d2&&!okIp(d2))){toast(t("sy_dns_err"),"err");return;}
var cmds=[];
var hn=$("sy-host").value.trim();
if(hn&&hn!==S.info.hostname){
if(!/^[\x21-\x7e]{1,23}$/.test(hn)||/["\\]/.test(hn)){toast(t("sy_host_err"),"err");return;}
cmds.push("hostname "+hn);
}
cmds.push("ip "+ip+"\nnetmask "+mask+"\ngw "+gw);
cmds.push("ip "+ip+"\nnetmask "+mask+"\ngw "+gw+"\ndns server "+(d1||"0.0.0.0")+(d2?" "+d2:""));
var changingIp=ip!==S.info.ip_address;
confirmModal(t("sy_net_q"),changingIp?t("sy_net_d",{ip:ip}):"",function(){
postCmds(cmds).then(function(){
@@ -2107,11 +2204,58 @@ $("cfgreload").addEventListener("click",cfgReload);
$("cfgwrite").addEventListener("click",function(){
writeConfig($("cfgedit").value,t("cw_title"));
});
tabHooks.system={enter:sysLoad};
var ntpBase=null,ntpTimer=null;
function tzText(m){var a=Math.abs(m);return(m<0?"-":"+")+String(Math.floor(a/60)).padStart(2,"0")+":"+String(a%60).padStart(2,"0")}
function ntpTick(){
if(!ntpBase)return;
var d=new Date(ntpBase.ms+(Date.now()-ntpBase.at));
function p(n){return String(n).padStart(2,"0")}
$("sy-sync").textContent=t("sy_ago",{n:ntpBase.sync+Math.floor((Date.now()-ntpBase.at)/60000)});
$("sy-now").textContent=d.getUTCFullYear()+"-"+p(d.getUTCMonth()+1)+"-"+p(d.getUTCDate())+" "
+p(d.getUTCHours())+":"+p(d.getUTCMinutes())+":"+p(d.getUTCSeconds())+" UTC"+ntpBase.tz;
}
function ntpLoad(){
return api("/cmd",{method:"POST",body:"ntp"}).then(function(r){
var m=r.body.match(/NTP (on|off), server (\S*), address ([\d.]+), interval (\d+) min, timezone ([+-]\d\d:\d\d), dst (\w+)/);
if(!m)return;
var x=r.body.match(/Time (\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d) UTC([+-]\d\d:\d\d)( DST)?, synchronised (\d+) min ago/);
$("sy-ntpaddr").textContent=m[3]==="0.0.0.0"?"-":m[3];
if(x){
ntpBase={at:Date.now(),ms:Date.UTC(+x[1],+x[2]-1,+x[3],+x[4],+x[5],+x[6]),tz:x[7]+(x[8]?" DST":""),sync:+x[9]};
ntpTick();
}else{
ntpBase=null;
$("sy-now").textContent=t("sy_nosync");
$("sy-sync").textContent=m[1]==="on"?t("sy_waiting"):"-";
}
if($("sy-ntpcard").dataset.dirty)return;
$("sy-ntp").checked=m[1]==="on";$("sy-ntpsrv").value=m[2];$("sy-ntpint").value=m[4];
$("sy-tz").value=m[5];$("sy-dst").value=m[6];
}).catch(function(){});
}
[-720,-660,-600,-570,-540,-480,-420,-360,-300,-240,-210,-180,-120,-60,0,60,120,180,210,240,270,300,330,345,
360,390,420,480,525,540,570,600,630,660,720,765,780,840].forEach(function(z){
$("sy-tz").appendChild(h("option",{value:tzText(z),text:"UTC"+tzText(z)}));
});
["change","input"].forEach(function(ev){$("sy-ntpcard").addEventListener(ev,function(){this.dataset.dirty="1"})});
$("sy-ntpapply").addEventListener("click",function(){
var srv=$("sy-ntpsrv").value.trim(),iv=$("sy-ntpint").value.trim();
if(!/^[A-Za-z0-9.-]{1,47}$/.test(srv)){toast(t("sy_ntp_err"),"err");return;}
if(!(+iv>=1&&+iv<=1440)){toast(t("sy_ntpint_err"),"err");return;}
delete $("sy-ntpcard").dataset.dirty;
postCmds(["ntp server "+srv,"ntp interval "+iv,"ntp timezone "+$("sy-tz").value,"ntp dst "+$("sy-dst").value,
"ntp "+($("sy-ntp").checked?"on":"off")]).then(ntpLoad).catch(function(){});
});
$("sy-ntprefresh").addEventListener("click",ntpLoad);
tabHooks.system={
enter:function(){sysLoad();ntpLoad();clearInterval(ntpTimer);ntpTimer=setInterval(ntpTick,1000)},
leave:function(){clearInterval(ntpTimer)},
};
var CONF_OVERWRITE=[
/^ip\b/,/^gw\b/,/^netmask\b/,/^hostname\b/,
/^syslog\s+ip\b/,/^syslog\s+port\b/,/^passwd\b/,/^session\b/,
/^syslog\s+ip\b/,/^syslog\s+port\b/,/^dns\s+server\b/,/^passwd\b/,/^session\b/,
/^ntp\s+server\b/,/^ntp\s+interval\b/,/^ntp\s+timezone\b/,/^ntp\s+dst\b/,
/^vlan\s+\d{1,4}\s+mgmt$/,/^vlan\s+\d{1,4}(?!\s+mgmt\b)/,
/^pvid\s+\d{1,2}\b/,
/^port\s+\d{1,2}(?!\s+name\b)/,/^port\s+\d{1,2}\s+name\b/,
@@ -2121,7 +2265,7 @@ var CONF_OVERWRITE=[
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+(edge|cost|prio|guard|filter|p2p)\b/,
/^igmp\b/,/^mtu\s+\d{1,2}\b/,/^storm\s+\d{1,2}\s+(bcast|mcast|ucast|umcast)\b/,
];
var CONF_TOGGLE=[/^(syslog)\s+(on|off)$/,/^(stp)\s+(on|off)$/,/^(stp\s+(port\s+\d{1,2}|lag\s+[1-4]))\s+(on|off)$/];
var CONF_TOGGLE=[/^(syslog)\s+(on|off)$/,/^(ntp)\s+(on|off)$/,/^(stp)\s+(on|off)$/,/^(stp\s+(port\s+\d{1,2}|lag\s+[1-4]))\s+(on|off)$/];
function mergeConf(base,texts){
var conf=base.slice();
function drop(rx){conf=conf.filter(function(c){return!rx.test(c)})}
@@ -2137,6 +2281,7 @@ function mergeConf(base,texts){
else drop(/^eee /);
conf.push(line);return;
}
if((m=line.match(/^lag (\d) lacp off$/))){drop(new RegExp("^lag "+m[1]+" lacp( |$)"));return;}
if(line==="mirror off"){drop(/^mirror /);return;}
if(!isConfCmd(line))return;
if((m=line.match(/^ingress (.+)$/))){
@@ -2231,10 +2376,26 @@ $("saveBtn").addEventListener("click",function(){
});
});
var fwBuf=null;
var fwBuf=null,fwOther=false;
// Every image carries its machine name as a NUL-terminated string, the same
// one the running switch reports as hw_ver: an image without it was built
// for another board (SFP, LED and button pins differ between machines).
function fwForThisSwitch(u){
var name=S.info.hw_ver;
if(!name)return true;
var n=[];
for(var i=0;i<name.length;i++)n.push(name.charCodeAt(i)&0xff);
n.push(0);
outer:for(var p=0;p<=u.length-n.length;p++){
for(var k=0;k<n.length;k++)if(u[p+k]!==n[k])continue outer;
return true;
}
return false;
}
$("fwfile").addEventListener("change",function(){
var f=this.files[0];
fwBuf=null;
fwOther=false;
$("fwup").disabled=true;
$("fwinfo").textContent="";
if(!f)return;
@@ -2257,13 +2418,15 @@ $("fwfile").addEventListener("change",function(){
return;
}
fwBuf=f;
info.innerHTML='<span style="color:var(--ok)">\u2713 '+esc(t("fw_valid"))+"</span>";
fwOther=!fwForThisSwitch(u);
info.innerHTML='<span style="color:var(--ok)">\u2713 '+esc(t("fw_valid"))+"</span>"+
(fwOther?'<br><span style="color:var(--warn)">\u26a0 '+esc(t("fw_other",{m:S.info.hw_ver}))+"</span>":"");
$("fwup").disabled=false;
});
});
$("fwup").addEventListener("click",function(){
if(!fwBuf)return;
confirmModal(t("fw_q"),t("fw_d"),function(){
confirmModal(t("fw_q"),(fwOther?t("fw_other",{m:S.info.hw_ver})+" ":"")+t("fw_d"),function(){
var form=new FormData();
form.append("uploadedfile",fwBuf,fwBuf.name);
var xhr=new XMLHttpRequest();
+35
View File
@@ -331,6 +331,17 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
</div>
</section>
<section class="tab" id="tab-lldp">
<div class="card"><h2 data-i18n="lldp_title">LLDP</h2>
<label class="row"><span class="lb" data-i18n="lldp_enabled">Enabled</span>
<span class="switch"><input type="checkbox" id="lldp_en"><i></i></span>
</label>
<div class="scrollx"><table class="t" id="lldp_table">
<thead><tr><th data-i18n="c_port">Port Number</th><th data-i18n="lldp_portname">Name</th><th data-i18n="lldp_enable">Send Frames</th></tr></thead>
<tbody></tbody></table></div>
</div>
</section>
<section class="tab" id="tab-isolate">
<div class="card"><h2 data-i18n="iso_title">Port isolation</h2>
<p class="small mut" style="margin-bottom:10px" data-i18n="iso_intro">A frame entering a port may only leave through the ports ticked in its row.</p>
@@ -345,6 +356,11 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
<section class="tab" id="tab-lag">
<div id="lagwrap" class="grid2"></div>
<div class="card" style="margin-top:14px"><h2 data-i18n="lacp_heading">LACP (802.3ad)</h2>
<div class="scrollx"><table class="t" id="lacptbl">
<thead><tr><th data-i18n="c_port">Port</th><th>LAG</th><th data-i18n="lacp_actor">Actor</th><th data-i18n="lacp_partner">Partner</th><th data-i18n="lacp_rxstate">RX state</th><th data-i18n="lacp_rx">LACPDUs received</th><th data-i18n="lacp_psys">Partner system</th></tr></thead>
<tbody></tbody></table></div>
</div>
<p class="small mut" style="margin-top:10px" data-i18n="lag_note">A LAG needs at least one member to be saved in the startup config; applying an empty group clears it.</p>
</section>
@@ -378,6 +394,9 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
<label class="row"><span class="lb" data-i18n="i_ip">IP address</span><input class="in" id="sy-ip" size="15"></label>
<label class="row"><span class="lb" data-i18n="i_mask">Netmask</span><input class="in" id="sy-mask" size="15"></label>
<label class="row"><span class="lb" data-i18n="i_gw">Gateway</span><input class="in" id="sy-gw" size="15"></label>
<label class="row"><span class="lb" data-i18n="sy_dns1">DNS server</span><input class="in" id="sy-dns1" size="15"></label>
<label class="row"><span class="lb" data-i18n="sy_dns2">Second DNS</span><input class="in" id="sy-dns2" size="15"></label>
<p class="small mut" id="sy-dnsdhcp"></p>
<div style="display:flex;gap:10px;margin-top:12px">
<button class="ctl pri" id="sy-apply" data-i18n="c_apply">Apply</button>
<button class="ctl" id="sy-dhcp" data-i18n="sy_dhcp" data-i18n-t="sy_dhcp_t">Use DHCP</button>
@@ -397,6 +416,22 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
<input class="in" id="sy-sesstmo" style="width:80px" type="number" min="1" max="65535"></label>
<p class="small mut" data-i18n="sy_services_note">Service state reflects the startup config; runtime state is not readable.</p>
</div>
<div class="card" id="sy-ntpcard"><h2 data-i18n="sy_time">Time</h2>
<label class="row" style="justify-content:space-between"><span data-i18n="sy_ntp">NTP</span>
<span class="switch"><input type="checkbox" id="sy-ntp"><i></i></span></label>
<label class="row"><span class="lb" data-i18n="sy_ntpsrv">NTP server</span><input class="in" id="sy-ntpsrv" maxlength="47" data-i18n-p="sy_ntpsrv_p"></label>
<label class="row"><span class="lb" data-i18n="sy_ntpint">Poll interval [min]</span><input class="in sm" id="sy-ntpint" type="number" min="1" max="1440"></label>
<label class="row"><span class="lb" data-i18n="sy_tz">Time zone</span><select class="in" id="sy-tz"></select></label>
<label class="row"><span class="lb" data-i18n="sy_dst">Daylight saving</span><select class="in" id="sy-dst"><option value="off" data-i18n="c_offc">Off</option><option value="eu" data-i18n="sy_dst_eu">Europe</option><option value="us" data-i18n="sy_dst_us">United States</option></select></label>
<div style="display:flex;gap:10px;margin-top:8px">
<button class="ctl pri" id="sy-ntpapply" data-i18n="c_apply">Apply</button>
<button class="ctl" id="sy-ntprefresh" data-i18n="c_refresh">Refresh</button>
</div>
<label class="row" style="margin-top:10px"><span class="lb" data-i18n="sy_now">Local time</span><span class="mono" id="sy-now">-</span></label>
<label class="row"><span class="lb" data-i18n="sy_sync">Last synchronisation</span><span id="sy-sync">-</span></label>
<label class="row"><span class="lb" data-i18n="sy_ntpaddr">Server address</span><span class="mono" id="sy-ntpaddr">-</span></label>
<p class="small mut" style="margin-top:8px" data-i18n="sy_time_note">The switch has no battery backed clock.</p>
</div>
<div class="card"><h2 data-i18n="sy_password">Admin password</h2>
<label class="row"><span class="lb" data-i18n="sy_newpw">New password</span><input class="in" id="sy-pw1" type="password" maxlength="20"></label>
<label class="row"><span class="lb" data-i18n="sy_repeat">Repeat</span><input class="in" id="sy-pw2" type="password" maxlength="20"></label>
+6 -2
View File
@@ -92,8 +92,12 @@ button:hover{filter:brightness(1.1)}
try{l=localStorage.getItem("rtl_lang");}catch(e){}
if(!L[l])l=(navigator.language||"en").slice(0,2);
var s=L[l]||L.en;
document.title=s[0];
document.getElementById("hn").textContent=s[0];
// Name the tab after the switch: the hostname seen at the last login here,
// otherwise the address, so several open switches can be told apart
var host=null;
try{host=localStorage.getItem("rtl_host");}catch(e){}
document.title=(host||location.hostname)+" – "+s[0];
document.getElementById("hn").textContent=host||s[0];
document.getElementById("sub").textContent=s[1];
document.getElementById("lp").textContent=s[2];
document.getElementById("lb").textContent=s[3];
+4
View File
@@ -1034,6 +1034,10 @@ void httpd_appcall(void)
send_lag();
} else if (is_word(q, "/stp.json")) {
send_stp();
} else if (is_word(q, "/lldp.json")) {
send_lldp();
} else if (is_word(q, "/lacp.json")) {
send_lacp();
} else if (is_word(q, "/vlanlist")) {
send_vlanlist();
} else if (is_word(q, "/config")) {
+80 -1
View File
@@ -14,6 +14,7 @@
#include "version.h"
#include "machine.h"
#include "rtl837x_stp.h"
#include "rtl837x_lacp.h"
#include "page_impl.h"
#include "syslog.h"
@@ -49,6 +50,9 @@ extern __xdata char sfp_module_model[2][17];
extern __xdata char sfp_module_serial[2][17];
extern __xdata uint8_t sfp_options[2];
extern __xdata uint16_t lldp_logical_port_status;
extern __xdata bool lldp_enabled;
__code const uint8_t * __code const HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n";
__code const uint8_t * __code const HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/plain\r\n\r\n";
@@ -619,7 +623,6 @@ static void bridge_to_html(void)
byte_to_html(pi_mac[i]);
}
void send_stp(void)
{
uint8_t i, j, st, dsg;
@@ -734,8 +737,84 @@ void send_stp(void)
slen += strtox(outbuf + slen, "]}");
}
void send_lacp(void)
{
dbg_string("send_lacp called\n");
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
slen += strtox(outbuf + slen, "{\"on\":");
bool_to_html(lacpEnabled);
slen += strtox(outbuf + slen, ",\"lags\":[");
for (uint8_t l = 0; l < LACP_NUM_LAGS; l++) {
slen += strtox(outbuf + slen, "{\"cfg\":\"");
byte_to_html(lacp_lag_ports[l] >> 8);
byte_to_html(lacp_lag_ports[l]);
slen += strtox(outbuf + slen, "\",\"aggValid\":");
bool_to_html(lacp_agg_valid[l]);
slen += strtox(outbuf + slen, ",\"agg\":\"");
for (uint8_t j = 0; j < MAC_ADDR_LEN; j++)
byte_to_html(lacp_agg_sys[l][j]);
slen += strtox(outbuf + slen, "\",\"members\":\"");
byte_to_html(lacp_members_last[l] >> 8);
byte_to_html(lacp_members_last[l]);
slen += strtox(outbuf + slen, "\"},");
}
slen -= 1; // remove comma
slen += strtox(outbuf + slen, "],\"ports\":[");
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
slen += strtox(outbuf + slen, "{\"p\":");
itoa_html(machine.log_to_phys_port[i]);
slen += strtox(outbuf + slen, ",\"lag\":");
itoa_html(lacp_port_lag[i]);
slen += strtox(outbuf + slen, ",\"a\":\"");
byte_to_html(lacp_actor_state[i]);
slen += strtox(outbuf + slen, "\",\"pt\":\"");
byte_to_html(lacp_partner_state[i]);
slen += strtox(outbuf + slen, "\",\"rs\":");
itoa_html(lacp_rx_state[i]);
slen += strtox(outbuf + slen, ",\"rx\":\"");
byte_to_html(lacp_rx_count[i] >> 8);
byte_to_html(lacp_rx_count[i]);
slen += strtox(outbuf + slen, "\",\"psys\":\"");
for (uint8_t j = 0; j < MAC_ADDR_LEN; j++)
byte_to_html(lacp_partner_sys[i][j]);
slen += strtox(outbuf + slen, "\"},");
}
slen -= 1; // remove comma
slen += strtox(outbuf + slen, "]}");
}
void send_lldp(void)
{
dbg_string("send_lldp called\n");
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
slen += strtox(outbuf + slen, "{\"on\":");
bool_to_html(lldp_enabled);
slen += strtox(outbuf + slen, ",\"portStatus\":[");
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
slen += strtox(outbuf + slen, "{\"portNum\":");
itoa_html(machine.log_to_phys_port[i]);
slen += strtox(outbuf + slen, ",\"logPort\":");
itoa_html(i);
slen += strtox(outbuf + slen, ",\"name\":\"");
for (uint8_t j = 0; j < PORT_NAME_SIZE && port_names[i][j]; j++) {
json_char_to_html(port_names[i][j]);
}
slen += strtox(outbuf + slen, "\",\"permitted\":");
bool_to_html(1 & (lldp_logical_port_status >> i));
slen += strtox(outbuf + slen, "}");
if (i < machine.max_port)
char_to_html(',');
else
char_to_html(']');
}
char_to_html('}');
}
void send_eee(void)
{
+2
View File
@@ -23,6 +23,8 @@ void send_config(void);
void send_cmd_log(void);
void send_lag(void);
void send_stp(void);
void send_lldp(void);
void send_lacp(void);
void send_vlanlist(void);
/* Convert only the lower nibble to ascii HEX char.
-1407
View File
File diff suppressed because it is too large. Load diff
+11 -46
View File
@@ -3,54 +3,19 @@
#include <stdint.h>
/*
* Select your machine type below
*/
// Legacy KP-9000 4+2 targets. Prefer the PCB-revision-specific targets below.
// #define MACHINE_KP_9000_6XHML_X2
// #define MACHINE_KP_9000_6XH_X2
#define MACHINE_STR_HELPER(x) #x
#define MACHINE_STR(x) MACHINE_STR_HELPER(x)
// KP-9000 4+2 targets by PCB silkscreen revision.
// #define MACHINE_KP_9000_6XH_X2_V1_1
// #define MACHINE_KP_9000_6XHML_X2_V1_1
// #define MACHINE_KP_9000_6XH_X2_V1_2
// #define MACHINE_KP_9000_6XHML_X2_V1_2
// #define MACHINE_KP_9000_6XH_X2_V2_1
// #define MACHINE_KP_9000_6XHML_X2_V2_1
// #define MACHINE_KP_9000_6XH_X
// #define MACHINE_KP_9000_9XH_X_EU
// #define MACHINE_KP_9000_9XHML_X_V2_2
// #define MACHINE_KP_9000_9XHML_X_V3_1
// #define MACHINE_KP_9000_9XHML_X_V3_2
// #define MACHINE_SWGT024_V2_0_MANAGED
// #define MACHINE_SWGT024_V2_0_UNMANAGED
// #define MACHINE_TRENDNET_TEG_S562
// #define MACHINE_HG0402XG_V1_1
// #define MACHINE_SWTG018AS_A_V_2_0
// #define MACHINE_SWTGW218AS
// #define MACHINE_PCB_SWTG018AS_V2_1_0
// #define MACHINE_PCB_K0402WS_V3
// #define MACHINE_PCB_K0402WS_V2
// #define MACHINE_K0501W_V2_0
// #define MACHINE_LIANGUO_ZX_SWTGW215AS
// #define MACHINE_ZX310S_4T2XH
// #define MACHINE_ZX310S_4T2XT
// #define MACHINE_STEAMEMO_IG204_V1
// #define MACHINE_DEFAULT_8C_1SFP
// #define MACHINE_HI_K0801WS
// #define MACHINE_FNS1200P
// #define MACHINE_PCB_SWTG024AS_A_2_0_1
// #define MACHINE_SWTG024AS_A_2_0_1_5C_1SFP
// #define MACHINE_SWTG024AS_V2_0
// #define MACHINE_FG_4GT_2SX_V2_0
// #define MACHINE_FG_8GT_1SX
// #define MACHINE_LIANGUO_HYWS_SGT0108S
// #define MACHINE_POE_2G080110GS
// #define MACHINE_PB_2132
// #define MACHINE_HASIVO_S600W_4GT_2XGT_SE
// #define MACHINE_HASIVO_S1100WP_8GT_1SX_SE
// #define MACHINE_F7008_2_5
#define MACHINE_DEF_DIR machine
#ifndef MACHINE_NAME
#define MACHINE_NAME default_machine
#endif
#define MACHINE_INC(dir,file) MACHINE_STR(dir/file)
#include MACHINE_INC(MACHINE_DEF_DIR,MACHINE_NAME.h)
#define LED_27 1
// SYSTEM LED
+25
View File
@@ -0,0 +1,25 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0},
.led_sets = { { LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5,
LEDS_2G5 | LEDS_LINK,
LEDS_1G | LEDS_LINK,
LEDS_2G5 | LEDS_LINK | LEDS_ACT },
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_DEFAULT_8C_1SFP_H_
#define _MACHINE_DEFAULT_8C_1SFP_H_
#define MACHINE_MODEL "8+1 SFP Port Switch"
#endif
+41
View File
@@ -0,0 +1,41 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = {
{ /* SET0 */
LEDS_2G5 | LEDS_LINK, /* LEDID0 - green: 2.5G link */
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, /* LEDID1 - yellow: traffic */
0,
0,
},
{ /* SET1 - SFP+ */
LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_LINK,
LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_LINK | LEDS_ACT,
0,
0,
},
},
.led_mux_custom = 1,
.led_mux = {
0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0c, 0x02,
0x0d, 0x10, 0x11, 0x02, 0x14, 0x02, 0x02, 0x15,
0x02, 0x02, 0x18, 0x02, 0x02, 0x19, 0x02, 0x02,
0x1c, 0x1d, 0x02, 0x02,
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_F7008_2_5_H_
#define _MACHINE_F7008_2_5_H_
#define MACHINE_MODEL "F7008-2.5 8+1 SFP Port Switch"
#endif
+66
View File
@@ -0,0 +1,66 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
// Left SFP port
.sfp_port[0].pin_detect = GPIO38,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
// Right SFP port
.sfp_port[1].pin_detect = GPIO37,
.sfp_port[1].pin_los = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
/* Ports 1-4 RJ45 use set 0, port 5-6 SFP uses set 1
* Ports 1-4: Green: 2.5GBit, Amber: 10/100/1000MBit
* Ports 5-6: Green: 100MBit-10GBit
*/
.led_sets = {
{
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
LEDS_2G5 | LEDS_LINK | LEDS_ACT
},
{
LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
LEDS_10G | LEDS_LINK,
0,
LEDS_COL | LEDS_DUPLEX
},
{
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
LEDS_2G5 | LEDS_1G | LEDS_LINK,
LEDS_5G | LEDS_2G5 | LEDS_LINK | LEDS_ACT,
LEDS_10G | LEDS_LINK | LEDS_ACT
},
{
LEDS_TX,
LEDS_RX,
LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5 |
LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_ACT,
LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5 |
LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK
},
},
.led_mux_custom = 1,
.led_mux = {
0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x3f, 0x15, 0x16,
0x18, 0x0e, 0x19, 0x11, 0x12, 0x1a, 0x15, 0x16, 0x1c, 0x19,
0x1a, 0x1d, 0x1d, 0x1e, 0x1e, 0x20, 0x21, 0x22
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_FG_4GT_2SX_V2_0_H_
#define _MACHINE_FG_4GT_2SX_V2_0_H_
#define MACHINE_MODEL "FG-4GT-2SX_V2.0"
#endif
+45
View File
@@ -0,0 +1,45 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO38,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = {
/*
Ports 1-8: Left Amber 10/100/1000MBit (Vendor no 10M, but we add it)
Right Green 2.5GBit
SFP-port: Any speed
*/
{
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
},
{
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
0,
},
},
.led_mux_custom = 1,
.led_mux = {
0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0c, 0x09, 0x0d, 0x10,
0x11, 0x0e, 0x14, 0x11, 0x12, 0x15, 0x15, 0x16, 0x18, 0x19,
0x1a, 0x19, 0x1d, 0x1e, 0x1c, 0x1d, 0x20, 0x21,
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_FG_8GT_1SX_H_
#define _MACHINE_FG_8GT_1SX_H_
#define MACHINE_MODEL "FG-8GT-1SX"
#endif
+55
View File
@@ -0,0 +1,55 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
/* Left SFP (logical 8, SDS1): GPIO30=ModAbs, GPIO37=RX_LOS */
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
/* Right SFP (logical 3, SDS0): GPIO50=ModAbs, GPIO51=RX_LOS */
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[1].pin_los = GPIO51_I2C_SDA2_UART1_RX,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
/* Copper ports use SET0; SFP ports use SET1 */
.port_led_set = {0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{ /* SET0: copper — LED0=amber (2.5G), LED2=green (1G/100M/10M) */
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
0,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0
},
{ /* SET1: SFP — all speeds link/act */
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0, 0
},
},
.led_mux_custom = 1,
.led_mux = {
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* GPIO0-7: unused */
0x0f, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, /* GPIO8-14 */
0x14, 0x15, 0x16, 0x18, 0x19, 0x1a, /* GPIO15-20 */
0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23 /* GPIO21-27 */
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_FNS1200P_H_
#define _MACHINE_FNS1200P_H_
#define MACHINE_MODEL "FNS-1200P"
#endif
+32
View File
@@ -0,0 +1,32 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.mac_flash_offset = 0x1FC000,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO54_ACL_BIT2_EN,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = { { LEDS_2G5 | LEDS_LINK | LEDS_ACT, // Green LED (right)
0,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // Amber LED (left)
0
},
{ LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT, // SFP LED
0,
0,
0
},
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_HASIVO_S1100WP_8GT_1SX_SE_H_
#define _MACHINE_HASIVO_S1100WP_8GT_1SX_SE_H_
#define MACHINE_MODEL "Hasivo S1100WP-8GT-1SX-SE"
#endif
+43
View File
@@ -0,0 +1,43 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 0,
.n_10g = 2,
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 0},
.reset_pin = GPIO54_ACL_BIT2_EN,
.high_leds = { .mux = LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1 },
/* Ports 1-4: Green: 2.5GBit, Orange: 10/100/1000MBit
* Ports 5-6: Green: 10GBit, Orange: 5/2.5GBit, None: 10/100/1000MBit
*/
.led_sets = {
{
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // Yellow
LEDS_2G5 | LEDS_LINK, // Green
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK, // Orange
0, // Unused
},
{
LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // Yellow
LEDS_10G | LEDS_LINK, // Green
LEDS_5G | LEDS_2G5 | LEDS_LINK, // Orange
0, // Unused
},
},
.led_mux_custom = 1,
.led_mux = {
0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
0x3f, 0x3f, 0x3f, 0x0f, 0x20,
0x21, 0x22, 0x10, 0x11, 0x12,
0x14, 0x15, 0x16, 0x18, 0x19,
0x1a, 0x1c, 0x1d, 0x1e, 0x0c,
0x0d, 0x0e, 0x23
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_HASIVO_S600W_4GT_2XGT_SE_H_
#define _MACHINE_HASIVO_S600W_4GT_2XGT_SE_H_
#define MACHINE_MODEL "Hasivo S600W-4GT-2XGT-SE"
#endif
+38
View File
@@ -0,0 +1,38 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = 50,
.sfp_port[0].pin_los = 10,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
.sfp_port[1].pin_detect = 30,
.sfp_port[1].pin_los = 51,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 , .enable = LED_27 | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
/* The Ethernet ports have 1 amber LED (left) and 1 green LED (right)
* The SFP ports have also 1 amber LED and 1 green LED
* Ethernet ports use LED-set 0, SFP ports use LED-set 1
*/
.led_sets = { { LEDS_10M | LEDS_LINK | LEDS_ACT,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_2G5 | LEDS_LINK | LEDS_ACT,
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
0 },
{ LEDS_100M | LEDS_10M | LEDS_LINK,
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
LEDS_10G | LEDS_LINK,
0 },
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_HG0402XG_V1_1_H_
#define _MACHINE_HG0402XG_V1_1_H_
#define MACHINE_MODEL "HG0402XG V1.1"
#endif
+46
View File
@@ -0,0 +1,46 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
// Left SFP port
.sfp_port[0].pin_detect = GPIO38,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
// Right SFP port
.sfp_port[1].pin_detect = GPIO37,
.sfp_port[1].pin_los = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_28_SYS | LED_29, .enable = LED_27 | LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{
LEDS_2G5 | LEDS_LINK | LEDS_10M | LEDS_ACT,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
LEDS_1G | LEDS_LINK,
0
},
{
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK,
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_ACT,
0,
0
},
},
.led_mux_custom = 1,
.led_mux = {
0x00,0x01,0x04,0x05,0x08,0x09,0x0c,0x3f,0x0d,0x10,0x11,0x0e,0x14,0x11,0x12,0x15,0x15,0x16,0x18,0x19,0x1a,0x19,0x1d,0x1e,0x1c,0x1d,0x20,0x21
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_HI_K0402WS_H_
#define _MACHINE_HI_K0402WS_H_
#define MACHINE_MODEL "PCB-K0402WS-V3.0"
#endif
+45
View File
@@ -0,0 +1,45 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = {
.mux = LED_27 | LED_29,
.enable = LED_28_SYS | LED_29
},
/* Ports 1-8 use set 0, port 9 SFP uses set 1 */
.port_led_set = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = {
{ /* Set 0: RJ45 copper ports
* Amber = 2.5G
* Green = 1G/100M/10M with activity
*/
LEDS_2G5 | LEDS_LINK | LEDS_ACT, /* Amber */
0,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, /* Green */
0
},
{ /* Set 1: SFP port, single green LED for all valid speeds */
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
0
},
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_HI_K0801WS_H_
#define _MACHINE_HI_K0801WS_H_
#define MACHINE_MODEL "Hi-Source HI-k0801WS"
#endif
+34
View File
@@ -0,0 +1,34 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = {
{
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
0,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0
},
{
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
0
},
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_K0501W_V2_0_H_
#define _MACHINE_K0501W_V2_0_H_
#define MACHINE_MODEL "K0501W V2.0"
#endif
+37
View File
@@ -0,0 +1,37 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 1, 0, 0, 0, 0, 2},
// Left SFP port (5)
.sfp_port[0].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[0].pin_los = GPIO10_LED10,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 0,
.sfp_port[0].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
// Right SFP port (6)
.sfp_port[1].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[1].pin_los = GPIO37,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 1,
.sfp_port[1].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO54_ACL_BIT2_EN,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0},
/* Conditions for LED on:
* dual led orange: ledset_0 & ledset_2
* dual led green: ledset_2 & !ledset_0
* single right led green: ledset_0 & !ledset_1
*/
.led_sets = { { LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
LEDS_2G5 | LEDS_LINK | LEDS_10G,
LEDS_1G | LEDS_LINK,
0 },
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_6XHML_X2_H_
#define _MACHINE_KP_9000_6XHML_X2_H_
#define MACHINE_MODEL "keepLink KP-9000-6XHML-X2"
#endif
+1
View File
@@ -0,0 +1 @@
KP_9000_6XHML_X2.c
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_6XHML_X2_V1_1_H_
#define _MACHINE_KP_9000_6XHML_X2_V1_1_H_
#define MACHINE_MODEL "keepLink KP-9000-6XHML V1.1"
#endif
+1
View File
@@ -0,0 +1 @@
KP_9000_6XHML_X2.c
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_6XHML_X2_V1_2_H_
#define _MACHINE_KP_9000_6XHML_X2_V1_2_H_
#define MACHINE_MODEL "keepLink KP-9000-6XHML V1.2"
#endif
+1
View File
@@ -0,0 +1 @@
KP_9000_6XH_X2.c
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_6XHML_X2_V2_1_H_
#define _MACHINE_KP_9000_6XHML_X2_V2_1_H_
#define MACHINE_MODEL "keepLink KP-9000-6XHML V2.1"
#endif
+28
View File
@@ -0,0 +1,28 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
/* Conditions for LED on:
* dual led orange: ledset_0 & ledset_2
* dual led green: ledset_2 & !ledset_0
* single right led green: ledset_0 & !ledset_1
*/
.led_sets = { { LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
LEDS_2G5 | LEDS_LINK | LEDS_10G,
LEDS_1G | LEDS_LINK,
0 },
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_6XH_X_H_
#define _MACHINE_KP_9000_6XH_X_H_
#define MACHINE_MODEL "keepLink KP-9000-6XH-X"
#endif
+48
View File
@@ -0,0 +1,48 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
// Left SFP port
.sfp_port[0].pin_detect = GPIO38,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
// Right SFP port
.sfp_port[1].pin_detect = GPIO37,
.sfp_port[1].pin_los = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO48_I2C_SCL1, // Button-Switch is unpopulated on PCB, but can be added manually (hole in case is already there)
.high_leds = { .mux = LED_28_SYS | LED_29, .enable = LED_27 | LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{
LEDS_2G5 | LEDS_LINK, // Left LED (Amber)
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // Right LED (Green)
0,
0
},
{
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
0
},
},
.led_mux_custom = 1,
.led_mux = {
0x00,0x01,0x04,0x05,0x08,0x09,0x0c,0x3f,0x0d,0x10,
0x11,0x0e,0x14,0x11,0x12,0x15,0x15,0x16,0x18,0x19,
0x1a,0x19,0x1d,0x1e,0x1c,0x1d,0x20,0x21
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_6XH_X2_H_
#define _MACHINE_KP_9000_6XH_X2_H_
#define MACHINE_MODEL "keepLink KP-9000-6XH-X2"
#endif
+1
View File
@@ -0,0 +1 @@
KP_9000_6XHML_X2.c
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_6XH_X2_V1_1_H_
#define _MACHINE_KP_9000_6XH_X2_V1_1_H_
#define MACHINE_MODEL "keepLink KP-9000-6XH V1.1"
#endif
+1
View File
@@ -0,0 +1 @@
KP_9000_6XHML_X2.c
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_6XH_X2_V1_2_H_
#define _MACHINE_KP_9000_6XH_X2_V1_2_H_
#define MACHINE_MODEL "keepLink KP-9000-6XH V1.2"
#endif
+1
View File
@@ -0,0 +1 @@
KP_9000_6XH_X2.c
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_6XH_X2_V2_1_H_
#define _MACHINE_KP_9000_6XH_X2_V2_1_H_
#define MACHINE_MODEL "keepLink KP-9000-6XH-X2 V2.1"
#endif
+51
View File
@@ -0,0 +1,51 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
.phys_to_log_port = { 0, 1, 2, 3, 4, 5, 6, 7, 8 },
.is_sfp = { 0, 0, 0, 0, 0, 0, 0, 0, 1 },
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO54_ACL_BIT2_EN,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1 },
.led_sets = {
{ /* Set 0 for RJ45 connectors */
/* LED0: Right Green */
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
/* LED1: Left Orange */
LEDS_2G5 | LEDS_LINK,
/* LED2: Left Green */
LEDS_1G | LEDS_LINK,
/* LED3: None */
0,
}, { /* Set 1 for SFP port */
/* LED0: Single Green "9" LED */
LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5,
/* LED1: D23 LED on PCB */
LEDS_1G | LEDS_LINK,
/* LED2: D22 LED on PCB */
LEDS_2G5 | LEDS_LINK,
/* LED3: Unused */
LEDS_COL | LEDS_DUPLEX,
}, { /* Set 2: Unused, but set to same things as stock firmware for consistency */
LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
LEDS_1G | LEDS_LINK | LEDS_ACT,
LEDS_2G5 | LEDS_LINK | LEDS_ACT | LEDS_5G,
LEDS_10G | LEDS_ACT | LEDS_LINK,
}, { /* Set 3: Unused, but set to same things as stock firmware for consistency */
LEDS_TX,
LEDS_RX,
LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5,
LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5,
},
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_9XHML_X_V2_2_H_
#define _MACHINE_KP_9000_9XHML_X_V2_2_H_
#define MACHINE_MODEL "keepLink KP-9000-9XHML-X V2.2"
#endif
+37
View File
@@ -0,0 +1,37 @@
#include "machine_defs.h"
// 2M-PCB23-V3.2 is wired like V3.1 (SFP detection, LEDs, factory MAC location)
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO38,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO48_I2C_SCL1,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = {
{ /* RJ45: First LED, yellow, second LED: green */
LEDS_2G5 | LEDS_LINK,
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
}, { /* SFP PORT, SINGLE GREEN LED */
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
0,
0,
0,
}},
.led_mux_custom = 1,
.led_mux = {0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0c, 0x09, 0x0d, 0x10,
0x11, 0x0e, 0x14, 0x11, 0x12, 0x15, 0x15, 0x16, 0x18, 0x19,
0x1a, 0x19, 0x1d, 0x1e, 0x1c, 0x1d, 0x20, 0x21},
.mac_flash_offset = 0x1FC000,
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_9XHML_X_V3_1_H_
#define _MACHINE_KP_9000_9XHML_X_V3_1_H_
#define MACHINE_MODEL "keepLink KP-9000-9XHML-X V3.1"
#endif
+1
View File
@@ -0,0 +1 @@
KP_9000_9XHML_X_V3_1.c
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_9XHML_X_V3_2_H_
#define _MACHINE_KP_9000_9XHML_X_V3_2_H_
#define MACHINE_MODEL "keepLink KP-9000-9XHML-X V3.2"
#endif
+25
View File
@@ -0,0 +1,25 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0},
.led_sets = { { LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5,
LEDS_2G5 | LEDS_LINK,
LEDS_1G | LEDS_LINK,
LEDS_2G5 | LEDS_LINK | LEDS_ACT },
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_KP_9000_9XH_X_EU_H_
#define _MACHINE_KP_9000_9XH_X_EU_H_
#define MACHINE_MODEL "keepLink KP-9000-9XH-X-EU"
#endif
+36
View File
@@ -0,0 +1,36 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {2, 1, 4, 3, 5, 6, 7, 8, 9},
.phys_to_log_port = {1, 0, 3, 2, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = 0, .enable = 0 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1 },
.led_sets = {
{
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // RJ45 Blue LEDs
LEDS_2G5 | LEDS_LINK, // RJ45 White LEDs
0,
0
},
{
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // SFP blue LED?
0,
0,
0
},
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_LIANGUO_HYWS_SGT0108S_H_
#define _MACHINE_LIANGUO_HYWS_SGT0108S_H_
#define MACHINE_MODEL "Lianguo HYWS-SGT0108S"
#endif
+33
View File
@@ -0,0 +1,33 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.mac_flash_offset = 0x1FC000,
.min_port = 3,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO54_ACL_BIT2_EN,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = { { LEDS_2G5 | LEDS_LINK | LEDS_ACT, // Green LED (right)
0, // unused
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // Amber LED (left)
0
}, // unused
{ LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT, // SFP LED
0, // unused
0, // unused
0
}, // unused },
},
.led_mux_custom = 0,
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_LIANGUO_ZX_SWTGW215AS_H_
#define _MACHINE_LIANGUO_ZX_SWTGW215AS_H_
#define MACHINE_MODEL "Lianguo ZX-SWTGW215AS"
#endif
+61
View File
@@ -0,0 +1,61 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 5, 4, 3, 2, 1, 6},
.phys_to_log_port = {7, 6, 5, 4, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 1, 0, 0, 0, 0, 2},
// SFP port on SDS0 / logical port 3
.sfp_port[0].pin_detect = GPIO37,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 0,
.sfp_port[0].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
// SFP port on SDS1 / logical port 8
.sfp_port[1].pin_detect = GPIO38,
.sfp_port[1].pin_los = GPIO_NA,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 1,
.sfp_port[1].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_28_SYS | LED_29, .enable = LED_27 | LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 3, 0, 0, 2, 2, 3},
.mac_flash_offset = 0x1FC000,
.led_sets = {
{ // RJ45 Ports 3-4 (normal wiring)
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
0,
0
},
{ // Unused
0,
0,
0,
0
},
{ // RJ45 Ports 1-2 (reversed wiring)
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0
},
{ // SFP Ports 5-6
LEDS_10G | LEDS_LINK | LEDS_ACT,
LEDS_2G5 | LEDS_1G | LEDS_LINK | LEDS_ACT,
0,
0
},
},
.led_mux_custom = 1,
.led_mux = {
0x00,0x01,0x04,0x05,0x08,0x09,0x0c,0x3f,0x0d,0x10,0x11,0x0e,0x14,0x11,0x12,0x15,0x15,0x16,0x18,0x19,0x1a,0x19,0x1d,0x1e,0x1c,0x1d,0x20,0x21
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_ONT_S207CW_62TS_SE_H_
#define _MACHINE_ONT_S207CW_62TS_SE_H_
#define MACHINE_MODEL "ONT-S207CW-62TS-SE / Binardat 2G06-04210GSM / Binardat 2G06-04210GS"
#endif
+41
View File
@@ -0,0 +1,41 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = {
{
/* LED0 = RJ45: Amber LED: 2.5G */
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
/* LED1 = RJ45: Green LED: 10M / 100M / 1000M */
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0
},
{
/* SFP+ single Green LED. */
LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT,
0,
0,
0
},
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_PB_2132_H_
#define _MACHINE_PB_2132_H_
#define MACHINE_MODEL "PB-2132"
#endif
+55
View File
@@ -0,0 +1,55 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
/* Left SFP (logical 8, SDS1): GPIO30=ModAbs, GPIO37=RX_LOS */
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
/* Right SFP (logical 3, SDS0): GPIO50=ModAbs, GPIO51=RX_LOS */
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[1].pin_los = GPIO51_I2C_SDA2_UART1_RX,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
/* Copper ports use SET0; SFP ports use SET1 */
.port_led_set = {0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{ /* SET0: copper — LED0=amber (2.5G), LED2=green (1G/100M/10M) */
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
0,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0
},
{ /* SET1: SFP — all speeds link/act */
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0, 0
},
},
.led_mux_custom = 1,
.led_mux = {
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* GPIO0-7: unused */
0x0f, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, /* GPIO8-14 */
0x14, 0x15, 0x16, 0x18, 0x19, 0x1a, /* GPIO15-20 */
0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23 /* GPIO21-27 */
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_PCB_K0402WS_V2_H_
#define _MACHINE_PCB_K0402WS_V2_H_
#define MACHINE_MODEL "PCB-K0402WS-V2.0"
#endif
+1
View File
@@ -0,0 +1 @@
HI_K0402WS.c
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_PCB_K0402WS_V3_H_
#define _MACHINE_PCB_K0402WS_V3_H_
#define MACHINE_MODEL "PCB-K0402WS-V3.0"
#endif
+42
View File
@@ -0,0 +1,42 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.mac_flash_offset = 0x1FC000,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO38, // pulled low on module insert
.sfp_port[0].pin_los = GPIO_NA, // no LOS pin wired
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO54_ACL_BIT2_EN,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
// LED wiring matches the SWTG018AS-A V2.0 (same PCB family)
.led_sets = {
{ /* RJ45: First LED, yellow, second LED: green */
LEDS_2G5 | LEDS_LINK,
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
}, { /* SFP set (superseded by the raw register override in machine_custom_init) */
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
0,
0,
0,
}},
.led_mux_custom = 1,
.led_mux = { 0x00, 0x01, 0x04, 0x05, 0x08, // 65e0
0x09, 0x0c, 0x09, 0x0d, 0x10, // 65e4
0x11, 0x0e, 0x14, 0x11, 0x12, // 65e8
0x15, 0x15, 0x16, 0x18, 0x19, // 65ec
0x1a, 0x19, 0x1d, 0x1e, 0x1c, // 65f0
0x1d, 0x20, 0x21 },
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_PCB_SWTG018AS_V2_1_0_H_
#define _MACHINE_PCB_SWTG018AS_V2_1_0_H_
#define MACHINE_MODEL "SWTGW218AS (SWTG018AS-V2.1.0)"
#endif
+48
View File
@@ -0,0 +1,48 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 1, 0, 0, 0, 0, 2},
// SFP port on SDS0 / logical port 3
.sfp_port[0].pin_detect = GPIO37,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 0,
.sfp_port[0].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
// SFP port on SDS1 / logical port 8
.sfp_port[1].pin_detect = GPIO38,
.sfp_port[1].pin_los = GPIO_NA,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 1,
.sfp_port[1].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_28_SYS | LED_29, .enable = LED_27 | LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
LEDS_DUPLEX,
LEDS_2G5 | LEDS_LINK | LEDS_ACT
},
{
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT,
LEDS_10G | LEDS_LINK | LEDS_ACT,
LEDS_2G5 | LEDS_LINK,
LEDS_COL | LEDS_DUPLEX
},
},
.led_mux_custom = 1,
.led_mux = {
0x00,0x01,0x04,0x05,0x08,0x09,0x0c,0x3f,0x0d,0x10,0x11,0x0e,0x14,0x11,0x12,0x15,0x15,0x16,0x18,0x19,0x1a,0x19,0x1d,0x1e,0x1c,0x1d,0x20,0x21
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_PCB_SWTG024AS_A_2_0_1_H_
#define _MACHINE_PCB_SWTG024AS_A_2_0_1_H_
#define MACHINE_MODEL "PCB-SWTG024AS-A-2.0.1"
#endif
+44
View File
@@ -0,0 +1,44 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = {
{
/* SET0: RJ45 2.5G = amber, 1G/100M/10M = green */
LEDS_2G5 | LEDS_LINK | LEDS_ACT, /* amber */
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, /* green */
0,
0
},
{
/* SET1: SFP+ port = green */
LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M |
LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5,
0,
0,
0
}
},
.led_mux_custom = 1,
.led_mux = { 0x00, 0x01, 0x04, 0x05, 0x08,
0x09, 0x0c, 0x09, 0x0d, 0x10,
0x11, 0x0e, 0x14, 0x11, 0x12,
0x15, 0x15, 0x16, 0x18, 0x19,
0x1a, 0x19, 0x1d, 0x1e, 0x1c,
0x1d, 0x20, 0x21 },
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_POE_2G080110GS_H_
#define _MACHINE_POE_2G080110GS_H_
#define MACHINE_MODEL "MokerLink POE-2G080110GS"
#endif
+50
View File
@@ -0,0 +1,50 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
// Left SFP port (5)
// LED pin 9
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
// Right SFP port (6)
// LED pin 24
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[1].pin_los = GPIO51_I2C_SDA2_UART1_RX,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{
// RJ45 Amber LED (left)
LEDS_2G5 | LEDS_LINK,
// RJ45 Green LED (Right)
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
},
{
// SFP LED
LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT,
0, // unused
0, // unused
0
},
},
.led_mux_custom = 1,
.led_mux = {
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x0f, 0x20, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x1e, 0x0c, 0x21, 0x22, 0x23
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_STEAMEMO_IG204_V1_H_
#define _MACHINE_STEAMEMO_IG204_V1_H_
#define MACHINE_MODEL "Steamemo IG204 V1"
#endif
+41
View File
@@ -0,0 +1,41 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp= {0, 0, 0, 2, 0, 0, 0, 0, 1},
// Left SFP port (J4)
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ), /* GPIO 39 */
// Right SFP port (J2)
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[1].pin_los = GPIO_NA,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ), /* GPIO 40 */
.reset_pin = GPIO54_ACL_BIT2_EN,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{ /* RJ45: Green LED */
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
0,
/* Amber LED */
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
0
}, { /* SFP PORT: SINGLE GREEN LED */
LEDS_10M | LEDS_100M | LEDS_1G | LEDS_2G5 | LEDS_10G | LEDS_LINK | LEDS_ACT,
0,
0,
0,
},
},
};
+6
View File
@@ -0,0 +1,6 @@
#ifndef _MACHINE_SWGT024_V2_0_MANAGED_H_
#define _MACHINE_SWGT024_V2_0_MANAGED_H_
#define MACHINE_MODEL "SWGT024 V2.0 Managed"
#endif
+41
View File
@@ -0,0 +1,41 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp= {0, 0, 0, 2, 0, 0, 0, 0, 1},
// Left SFP port (J4)
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ), /* GPIO 39 */
// Right SFP port (J2)
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[1].pin_los = GPIO51_I2C_SDA2_UART1_RX,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ), /* GPIO 40 */
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{ /* RJ45: Green LED */
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
0,
/* Amber LED */
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
0
}, { /* SFP PORT: SINGLE GREEN LED */
LEDS_10M | LEDS_100M | LEDS_1G | LEDS_2G5 | LEDS_10G | LEDS_LINK | LEDS_ACT,
0,
0,
0,
},
},
};
Loaded 100 of 144 files, more files were not shown because too many files have changed in this diff. Show more