Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e11be0d97 | ||
|
|
23862bc648 | ||
|
|
413690a748 | ||
|
|
73bb4c8af2 | ||
|
|
0443ba428b | ||
|
|
62abd08aa2 | ||
|
|
70426ff24a | ||
|
|
2d62cc493d | ||
|
|
36de7b7241 | ||
|
|
ea320d813d | ||
|
|
ca2abcc4e1 | ||
|
|
4d7159092c | ||
|
|
98763e3bff | ||
|
|
80a30b705e | ||
|
|
4c3e1fde81 | ||
|
|
5cd14e6227 | ||
|
|
5105018d90 | ||
|
|
5bc7cf43db | ||
|
|
c776d10129 | ||
|
|
7b4d0d55d2 | ||
|
|
e95e450813 | ||
|
|
fe1d4119d0 | ||
|
|
c5f62bff95 | ||
|
|
7535c0d9b7 | ||
|
|
a57319557d | ||
|
|
1b29fb687f | ||
|
|
2e62f9eea7 | ||
|
|
5c6a82d50f | ||
|
|
1d158d21d1 | ||
|
|
26c420d26a | ||
|
|
eb394af95f | ||
|
|
4a4caeffd7 | ||
|
|
391360f517 | ||
|
|
ed8e4b1a56 | ||
|
|
78f28488c1 | ||
|
|
e1c79ec4cd | ||
|
|
a7db0ca8b6 | ||
|
|
70f59b64f5 | ||
|
|
f0cbaba7b1 | ||
|
|
2d5424fedc | ||
|
|
23c8b2a8b3 | ||
|
|
c9f6362da5 | ||
|
|
742aef5461 | ||
|
|
a77d219baf | ||
|
|
f94204e56f | ||
|
|
8d6adedb56 | ||
|
|
c3f9acea10 | ||
|
|
c46261e052 | ||
|
|
834403b97b | ||
|
|
48087d3520 | ||
|
|
1d359afba5 | ||
|
|
a18c334139 | ||
|
|
337b171ac4 | ||
|
|
53eb3f5486 | ||
|
|
241edfdbda | ||
|
|
714c9eb343 | ||
|
|
f2c89fd75b | ||
|
|
ca2f1d101d | ||
|
|
9cc859ad30 | ||
|
|
0181276ec6 | ||
|
|
905e588071 | ||
|
|
bb16302a80 | ||
|
|
50fda40fd9 | ||
|
|
9c65039bab | ||
|
|
7e0bc93b55 | ||
|
|
e1e1292ab0 | ||
|
|
975caaff02 | ||
|
|
cffe4793b1 | ||
|
|
9ed1e89c8b | ||
|
|
ba2f759df3 | ||
|
|
884a1ac016 | ||
|
|
51ed063dcb | ||
|
|
0da6318777 | ||
|
|
d13a5d125d | ||
|
|
889c94404c | ||
|
|
0f98734ae2 | ||
|
|
2d0abbbca0 | ||
|
|
fdcdfa9b45 | ||
|
|
c043c671d7 | ||
|
|
11a24783e4 | ||
|
|
e864c32980 | ||
|
|
bb329daab0 | ||
|
|
89c8903454 | ||
|
|
63a3bc50d6 | ||
|
|
a94be7d524 | ||
|
|
50be5308d9 | ||
|
|
9731a33fa9 | ||
|
|
c3dddd9c90 | ||
|
|
6e5617c82f | ||
|
|
6638748e3c | ||
|
|
98965b73f6 | ||
|
|
ef0d9d872e | ||
|
|
7d7585fa6d | ||
|
|
13801241ca | ||
|
|
94ca35f65e | ||
|
|
69714c8a75 | ||
|
|
2bc6939f86 | ||
|
|
aea537f8e7 | ||
|
|
7346977f91 | ||
|
|
7b0a07efaa | ||
|
|
3c00ab0ae9 | ||
|
|
7673ef8322 | ||
|
|
c9e8403c6e | ||
|
|
3deee14f94 | ||
|
|
6d539bfb1b | ||
|
|
7a44d8181f | ||
|
|
d698e180e4 | ||
|
|
566e26ace2 | ||
|
|
674dc23a27 | ||
|
|
620edafd62 | ||
|
|
413d10bbcc | ||
|
|
0faceab1d0 | ||
|
|
7e12f0a62c | ||
|
|
491a919105 | ||
|
|
2588965eee | ||
|
|
827d3b389c | ||
|
|
ef224ec8f4 | ||
|
|
0a3d7d360a | ||
|
|
9561f239b4 | ||
|
|
b06ff76a21 | ||
|
|
b28ead65dc | ||
|
|
a079c803d9 | ||
|
|
cc3ae654a0 | ||
|
|
2a9f9b2508 | ||
|
|
57d6337940 | ||
|
|
3b58eb36e5 | ||
|
|
34c0ef77d0 | ||
|
|
e6182dbe0d | ||
|
|
1d5e4cd722 | ||
|
|
a02116a24b | ||
|
|
98369c37fe | ||
|
|
d104b3129d | ||
|
|
138acfadb1 | ||
|
|
08f8498b39 | ||
|
|
dd521cc79d | ||
|
|
723d16b4cb | ||
|
|
2c2349dcef | ||
|
|
6d1380fb36 | ||
|
|
eacf13690c | ||
|
|
a1998c70d7 | ||
|
|
4ed74f05db | ||
|
|
0de18ff457 | ||
|
|
3195a14870 | ||
|
|
3ffb311e95 | ||
|
|
f0c672418c | ||
|
|
41ed689ae0 | ||
|
|
11eadc5a49 | ||
|
|
24d2cd7bab | ||
|
|
28c09737b2 | ||
|
|
3e1d3f40d2 | ||
|
|
389dc2af76 | ||
|
|
4963fbe50a | ||
|
|
44b5ab0e64 | ||
|
|
088321deaf | ||
|
|
3af1b049ee | ||
|
|
6a5d3cdf2c | ||
|
|
d21ea52c46 | ||
|
|
c6cc3ee595 | ||
|
|
424a963301 | ||
|
|
1344e02fb7 | ||
|
|
2ae297bc20 | ||
|
|
ce77cc273d | ||
|
|
6376a10288 | ||
|
|
a202842107 | ||
|
|
6fad2836ae | ||
|
|
2415015a87 | ||
|
|
d9fc20addf | ||
|
|
c15b2d48da | ||
|
|
f17ca1c9fc | ||
|
|
be5dee04e3 | ||
|
|
196d22d7c3 | ||
|
|
496ac8b757 | ||
|
|
bf670aed0b | ||
|
|
6af5580433 | ||
|
|
6194356f66 | ||
|
|
bd56c1a8c5 | ||
|
|
d562fd661e | ||
|
|
0b6b613c03 | ||
|
|
f325bdbd11 | ||
|
|
680a40dab5 | ||
|
|
97b15f4022 | ||
|
|
d5ccd38dd3 | ||
|
|
adecc26ae2 | ||
|
|
44ae7a8d3b | ||
|
|
c3fc541339 | ||
|
|
6fdb19f18c | ||
|
|
70f8964918 | ||
|
|
aba58e7f99 | ||
|
|
2404e7a9b6 | ||
|
|
6a31b4a279 | ||
|
|
6cd1f683bb | ||
|
|
7e90f6a126 | ||
|
|
9bd301447b | ||
|
|
9745dfe6ae | ||
|
|
d4345c1bf8 | ||
|
|
fcaacd4429 | ||
|
|
0f63244ca1 | ||
|
|
913e9780b8 | ||
|
|
0d748fa808 | ||
|
|
bd974e0aaf | ||
|
|
56686185ce | ||
|
|
ed069b67fd | ||
|
|
b1026490a8 | ||
|
|
28ea2184c2 | ||
|
|
d5f84cc2fb | ||
|
|
682ac462c4 | ||
|
|
ecc8356f4d | ||
|
|
3a8d1d323f | ||
|
|
e125ebd097 | ||
|
|
4050555667 | ||
|
|
e890e429a5 | ||
|
|
813a62ca7d | ||
|
|
b096efd63a | ||
|
|
8a7c847ad9 | ||
|
|
b94d2aeabc | ||
|
|
6bae5c5c90 | ||
|
|
c2980e42d8 | ||
|
|
875933b9f9 | ||
|
|
0e85137e7a | ||
|
|
706dea63a2 | ||
|
|
d0374541c5 |
No files matched your search
@@ -3,6 +3,7 @@
|
||||
.gitattributes
|
||||
.github/
|
||||
output/
|
||||
toolchain/
|
||||
installer/output/
|
||||
*.bin
|
||||
html_data.c
|
||||
|
||||
@@ -5,6 +5,11 @@ on:
|
||||
branches: ['**']
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -13,18 +18,41 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: branch
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: main
|
||||
ref: main
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt update
|
||||
apt install make gcc sdcc xxd python-is-python3 libjson-c-dev zlib1g-dev -y
|
||||
apt install make gcc g++ bison flex libboost-dev patch bzip2 curl ca-certificates xxd python-is-python3 libjson-c-dev zlib1g-dev -y
|
||||
- name: Cache the patched SDCC
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: branch/toolchain
|
||||
key: sdcc-${{ hashFiles('branch/sdcc/*') }}
|
||||
- name: Run the host-side unit tests
|
||||
run: make -C test
|
||||
run: cd branch && make -C test
|
||||
- name: Check that every machine definition can be compiled
|
||||
run: make machine_check
|
||||
run: cd branch && make machine_check
|
||||
- name: Make project (4x2/RTL8372)
|
||||
run: make CI=1 MACHINE="KP_9000_6XHML_X2"
|
||||
run: cd branch && make CI=1 MACHINE="KP_9000_6XHML_X2" && cp output/KP_9000_6XHML_X2/rtlplayground.map /tmp/branch.map
|
||||
- name: Make project (8x1/RTL8373)
|
||||
run: make CI=1 MACHINE="KP_9000_9XHML_X_V3_1"
|
||||
run: cd branch && make CI=1 MACHINE="KP_9000_9XHML_X_V3_1"
|
||||
- name: Make project with the health instrumentation
|
||||
run: make clean && make CI=1 MACHINE="KP_9000_6XHML_X2" HEALTH=1
|
||||
run: cd branch && make clean && make CI=1 MACHINE="KP_9000_6XHML_X2" HEALTH=1
|
||||
- name: Make main
|
||||
run: |
|
||||
ln -s ../branch/toolchain main/toolchain
|
||||
PATH="$(echo "$PWD"/branch/toolchain/sdcc-*/bin):$PATH"
|
||||
cd main && make CI=1 MACHINE="KP_9000_6XHML_X2" && cp output/KP_9000_6XHML_X2/rtlplayground.map /tmp/main.map
|
||||
- name: Calculate bank growth
|
||||
run: |
|
||||
sed -rn 's/^([XCD]SEG|(BANK[0-9])).*=\s+([0-9]+)\. bytes.*$/MAIN_\1=\3/p' /tmp/main.map | sort -u >> "$GITHUB_ENV"
|
||||
sed -rn 's/^([XCD]SEG|(BANK[0-9])).*=\s+([0-9]+)\. bytes.*$/BRANCH_\1=\3/p' /tmp/branch.map | sort -u >> "$GITHUB_ENV"
|
||||
du -sb main/output/KP_9000_6XHML_X2/html_min | awk '{print "MAIN_WEB="$1}' >> "$GITHUB_ENV"
|
||||
du -sb branch/output/KP_9000_6XHML_X2/html_min | awk '{print "BRANCH_WEB="$1}' >>"$GITHUB_ENV"
|
||||
@@ -1,13 +1,17 @@
|
||||
.gitignore
|
||||
.idea/
|
||||
output/
|
||||
output-main/
|
||||
toolchain/
|
||||
html_data.c
|
||||
html_data.h
|
||||
version.h
|
||||
tools/httpd_sim
|
||||
tools/injector
|
||||
tools/fileadder
|
||||
build/
|
||||
|
||||
# host-test stand-ins for the two generated headers
|
||||
!test/stub/html_data.h
|
||||
!test/stub/version.h
|
||||
.vscode
|
||||
@@ -4,6 +4,17 @@
|
||||
|
||||
## Added
|
||||
|
||||
- Devices
|
||||
- Support the hongyavision HYWS-SGT0204S (PCB marking `2G5F4_10G2_V1.01`), an
|
||||
RTL8372 based 4x2.5G + 2xSFP+ unmanaged switch with a 512 KB Bright Moon
|
||||
`T25S40` flash. It is a sibling of the KP-9000-6XH-X2 (2M-PCB43-V1.1) with
|
||||
the two SFP+ cages wired the other way round (physical 5 is on SDS1,
|
||||
physical 6 on SDS0), no reset button fitted, wrong silkscreen labels on the
|
||||
serial header, `LED_GLB_IO_EN` bit 6 has to be set for the port LEDs to
|
||||
work, and the fitted T25S40 cannot be read in DIO mode on this board, so the
|
||||
target selects single-IO flash reads (`flash_sio`). New machine target
|
||||
`MACHINE_2G5F4_10G2_V1_01`, see `doc/devices/2G5F4_10G2_V1.01.md`.
|
||||
|
||||
- Web UI
|
||||
- Compress the embedded assets (minify + gzip) and switch to a single-page layout. #315
|
||||
- Replace the multi-page UI with a themed single-page app: light, dark and Selenized themes following the browser by default,
|
||||
@@ -14,12 +25,34 @@
|
||||
|
||||
## Fixed
|
||||
|
||||
- Time
|
||||
- `rtl8372_init()` sets SDS 0 to SGMII as the stock firmware does. The masks were 0, so on RTL8372
|
||||
boards without 10G ports both SerDes stayed off, and with SDS 0 off `RTL837X_REG_SEC_COUNTER`
|
||||
does not hold a written value: NTP never retried after a failed first attempt at boot and
|
||||
froze the clock after a sync.
|
||||
|
||||
- Web UI
|
||||
- Firefox no longer fills a saved login into the new admin password fields. It also put the
|
||||
user name into the NTP poll interval, which marked the Time card as edited, so it kept its
|
||||
defaults (NTP off, no server, UTC-12:00) instead of the switch's settings.
|
||||
- Accept firmware uploads regardless of the file part's MIME type, including
|
||||
`application/macbinary` sent by Chrome on macOS for `.bin` files.
|
||||
|
||||
- Health
|
||||
- `HEALTH=1` builds no longer write past the phase timing arrays at the LLDP checkpoint, which
|
||||
corrupted the `link` slow counter and the DHCP client state. #658
|
||||
- Config
|
||||
- A startup configuration line longer than the command buffer no longer stops the replay:
|
||||
the offending line is skipped and the following lines are still applied.
|
||||
- The web UI and the configuration upload now refuse a line the replay cannot take,
|
||||
instead of writing it to flash.
|
||||
|
||||
- Startup
|
||||
- Initialised and zero-initialised globals above xdata 0x4000 now get their values at boot.
|
||||
Hardware reset leaves SFR 0x97 at 1, which maps xdata 0x4000-0xbfff to the flash image,
|
||||
and it was cleared only in `main()`, after the C startup code had copied and cleared them.
|
||||
This showed as a random web session timeout and LLDP blocked on some ports without config.
|
||||
|
||||
## Breaking changes
|
||||
|
||||
- Config
|
||||
|
||||
@@ -3,7 +3,14 @@ FROM debian:13-slim
|
||||
RUN apt-get update && apt-get install -y \
|
||||
make \
|
||||
gcc \
|
||||
sdcc \
|
||||
g++ \
|
||||
bison \
|
||||
flex \
|
||||
libboost-dev \
|
||||
patch \
|
||||
bzip2 \
|
||||
curl \
|
||||
ca-certificates \
|
||||
xxd \
|
||||
python3 \
|
||||
libjson-c-dev \
|
||||
|
||||
@@ -4,8 +4,25 @@ DEFAULT_CONFIG_LOCATION = 454656
|
||||
CONFIG_LOCATION = 458752
|
||||
HTML_LOCATION = 262144
|
||||
|
||||
# Startup configuration embedded in the image. Override it to build a specific
|
||||
# machine with its own configuration: make MACHINE=<name> CONFIG=<file>
|
||||
CONFIG ?= config.txt
|
||||
|
||||
SDCC_TOOLCHAIN = sdcc-$(shell cat sdcc/* | cksum | cut -d' ' -f1)
|
||||
SDCC_PREFIX = toolchain/$(SDCC_TOOLCHAIN)
|
||||
ifeq ($(origin CC),default)
|
||||
CC = sdcc
|
||||
SDCC = $(SDCC_PREFIX)/bin/sdcc
|
||||
CC = $(SDCC)
|
||||
ASM = $(SDCC_PREFIX)/bin/sdas8051
|
||||
SDCC_REV := $(shell git log -1 --format=%h -- sdcc 2>/dev/null)
|
||||
ifneq ($(SDCC_REV),)
|
||||
ifneq ($(shell git status --porcelain --untracked-files=no -- sdcc 2>/dev/null),)
|
||||
SDCC_REV := $(SDCC_REV)-dirty
|
||||
endif
|
||||
endif
|
||||
SDCC_BANNER = $(if $(SDCC_REV),sdcc/ at $(SDCC_REV),$(SDCC_TOOLCHAIN)) ($(words $(wildcard sdcc/*.patch)) patches)
|
||||
else
|
||||
SDCC_BANNER = system
|
||||
endif
|
||||
CC_FLAGS = -mmcs51 -I. -Imachine -Ihttpd -Iuip
|
||||
ASM ?= sdas8051
|
||||
@@ -15,11 +32,10 @@ SUBDIRS := tools
|
||||
SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS))
|
||||
|
||||
# $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.
|
||||
# on as -DMACHINE_NAME, which machine.h uses to include machine/$(MACHINE).h.
|
||||
# Board selection itself needs no MACHINE_* symbol for #if chains, so the
|
||||
# definition is all the compiler has to know.
|
||||
ifneq ($(MACHINE),)
|
||||
CC_FLAGS += -DMACHINE_$(MACHINE)
|
||||
CC_FLAGS += -DMACHINE_NAME=$(MACHINE)
|
||||
endif
|
||||
# Health instrumentation and the "health" console command: HEALTH=1 gmake ...
|
||||
@@ -34,7 +50,17 @@ endif
|
||||
# The board definition being built: one file per MACHINE_* symbol in machine.h.
|
||||
MACHINE_SRC = machine/$(MACHINE).c
|
||||
|
||||
BUILDDIR = output/$(MACHINE)
|
||||
MACHINE_INIT_DEFAULT := machine/default_machine_init.c
|
||||
MACHINE_INIT_SRC := $(wildcard machine/$(MACHINE)_init.c)
|
||||
ifeq ($(MACHINE_INIT_SRC),)
|
||||
MACHINE_INIT_SRC := $(MACHINE_INIT_DEFAULT)
|
||||
endif
|
||||
|
||||
ifndef BUILDDIR
|
||||
BUILDDIR = output/$(MACHINE)
|
||||
endif
|
||||
|
||||
CONFIG_STAMP := $(BUILDDIR)/.config
|
||||
VERSION_HEADER := version.h
|
||||
|
||||
GIT_VERSION := $(shell git rev-parse --short HEAD)
|
||||
@@ -57,11 +83,15 @@ 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
|
||||
|
||||
# $(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
|
||||
# $(MACHINE_SRC) and $(CONFIG) are listed here so an unknown $MACHINE or a
|
||||
# missing config file fails before anything else is built, including the tools/
|
||||
# subdirectory.
|
||||
all: create_build_dir $(VERSION_HEADER) $(MACHINE_SRC) $(CONFIG) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
|
||||
|
||||
create_build_dir:
|
||||
bank_size:
|
||||
tools/bank_occupancy.sh "$(MACHINE)"
|
||||
|
||||
create_build_dir: $(SDCC)
|
||||
mkdir -p "$(BUILDDIR)"
|
||||
mkdir -p "$(BUILDDIR)/uip"
|
||||
mkdir -p "$(BUILDDIR)/httpd"
|
||||
@@ -77,11 +107,17 @@ $(MACHINE_SRC):
|
||||
@echo " Example: make MACHINE=KP_9000_6XHML_X2" >&2
|
||||
@false
|
||||
|
||||
# Fail with a clear message when CONFIG names a file that does not exist.
|
||||
$(CONFIG):
|
||||
@echo "ERROR: CONFIG='$(CONFIG)' does not exist." >&2
|
||||
@echo " Point CONFIG at a configuration file, or omit it to use config.txt." >&2
|
||||
@false
|
||||
|
||||
# Keep the per-machine definition in first position to fail immediately on an
|
||||
# invalid $MACHINE value
|
||||
SRCS = \
|
||||
$(MACHINE_SRC) \
|
||||
machine_init.c \
|
||||
$(MACHINE_INIT_SRC) \
|
||||
cmd_editor.c \
|
||||
cmd_parser.c \
|
||||
dhcp.c \
|
||||
@@ -91,6 +127,7 @@ SRCS = \
|
||||
sfp.c \
|
||||
dns.c \
|
||||
dns_cli.c \
|
||||
sessions.c \
|
||||
ntp.c \
|
||||
ntp_cli.c \
|
||||
syslog.c \
|
||||
@@ -99,9 +136,11 @@ SRCS = \
|
||||
# RTL837x
|
||||
SRCS += \
|
||||
rtl837x_bandwidth.c \
|
||||
rtl837x_cabletest.c \
|
||||
rtl837x_flash.c \
|
||||
rtl837x_igmp.c \
|
||||
rtl837x_init.c \
|
||||
rtl837x_nic.c \
|
||||
rtl837x_leds.c \
|
||||
rtl837x_leds_dump.c \
|
||||
rtl837x_phy.c \
|
||||
@@ -131,20 +170,31 @@ HTML := $(shell find html -name '*.js' -or -name '*.html' -or -name '*.svg' -or
|
||||
# Minified copy of the web UI sources, used as the fileadder input.
|
||||
# The raw html/ sources stay untouched for development; the minified
|
||||
# copy is a build artifact under output/.
|
||||
HTML_MIN := output/html_min
|
||||
HTML_MIN := $(BUILDDIR)/html_min
|
||||
HTML_MIN_LIST := $(BUILDDIR)/html_min.list
|
||||
HTML_MIN_STAMP := $(BUILDDIR)/html_min.stamp
|
||||
.PHONY: html_min
|
||||
html_min: $(HTML)
|
||||
html_min: $(HTML_MIN_STAMP)
|
||||
|
||||
$(HTML_MIN_LIST): FORCE
|
||||
@mkdir -p $(BUILDDIR)
|
||||
@echo $(sort $(HTML)) > $@.tmp
|
||||
@cmp -s $@.tmp $@ && rm -f $@.tmp || mv $@.tmp $@
|
||||
|
||||
$(HTML_MIN_STAMP): $(HTML) $(HTML_MIN_LIST) tools/minify.py $(if $(wildcard $(HTML_MIN)),,FORCE)
|
||||
rm -rf $(HTML_MIN)
|
||||
mkdir -p $(HTML_MIN)
|
||||
@for f in $(HTML); do python3 tools/minify.py $$f $(HTML_MIN)/$$(basename $$f) || exit 1; done
|
||||
@touch $@
|
||||
|
||||
html_data.c html_data.h &: $(HTML) | tools html_min
|
||||
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -z -d $(HTML_MIN) -p html_data
|
||||
html_data.c html_data.h &: $(HTML_MIN_STAMP) | tools
|
||||
tools/$(BUILDDIR)/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -z -d $(HTML_MIN) -p html_data
|
||||
|
||||
$(VERSION_HEADER): FORCE
|
||||
@printf '%s\n' "#ifndef VERSION_H" "#define VERSION_H" \
|
||||
"#define VERSION_SW \"$(VERSION_EXTENSION)\"" \
|
||||
"#define BUILD_DATE \"$(BUILD_DATE)\"" \
|
||||
"#define SDCC_TOOLCHAIN \"$(SDCC_BANNER)\"" \
|
||||
"#endif" > $(VERSION_HEADER).tmp
|
||||
@cmp -s $(VERSION_HEADER).tmp $(VERSION_HEADER) \
|
||||
&& rm -f $(VERSION_HEADER).tmp \
|
||||
@@ -153,15 +203,21 @@ $(VERSION_HEADER): FORCE
|
||||
httpd: html_data.h
|
||||
|
||||
$(SUBDIRS):
|
||||
$(MAKE) -C $@
|
||||
$(MAKE) -C $@ BUILDDIR=$(BUILDDIR)
|
||||
|
||||
clean: $(SUBDIRSCLEAN)
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER)
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER) $(HTML_MIN_LIST) $(HTML_MIN_STAMP)
|
||||
-if [ -d $(BUILDDIR) ]; then find $(BUILDDIR) -type f ! -name "*.bin" -delete; fi
|
||||
|
||||
distclean: $(SUBDIRSCLEAN)
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER)
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER) $(HTML_MIN_LIST) $(HTML_MIN_STAMP)
|
||||
-rm -rf $(BUILDDIR)
|
||||
-rm -rf toolchain
|
||||
|
||||
ifneq ($(SDCC),)
|
||||
$(SDCC):
|
||||
sh sdcc/build.sh $(abspath $(SDCC_PREFIX))
|
||||
endif
|
||||
|
||||
$(SUBDIRSCLEAN):
|
||||
$(MAKE) -C $(@:clean=) clean
|
||||
@@ -176,6 +232,12 @@ FORCE:
|
||||
$(CCFLAGS_STAMP): FORCE | create_build_dir
|
||||
@echo '$(CC_FLAGS)' | cmp -s - $@ 2>/dev/null || echo '$(CC_FLAGS)' > $@
|
||||
|
||||
# The same for $(CONFIG): its path is stamped so switching to a config file
|
||||
# older than the image still rebuilds it, while $(CONFIG) itself as a normal
|
||||
# prerequisite covers edits to the selected file.
|
||||
$(CONFIG_STAMP): FORCE | create_build_dir
|
||||
@echo '$(CONFIG)' | cmp -s - $@ 2>/dev/null || echo '$(CONFIG)' > $@
|
||||
|
||||
$(BUILDDIR)/%.rel: %.c $(CCFLAGS_STAMP) | create_build_dir html_data.h
|
||||
$(CC) -MMD $(CC_FLAGS) -o $@ -c $<
|
||||
|
||||
@@ -189,33 +251,39 @@ $(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtbank.rel $(BUILDDIR)/crc16
|
||||
$(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx
|
||||
objcopy --input-target=ihex -O binary $< $@
|
||||
|
||||
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img | tools
|
||||
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img $(CONFIG) $(CONFIG_STAMP) | tools
|
||||
if [ -e $@ ]; then rm $@; fi
|
||||
tools/output/imagebuilder -i $^ $@
|
||||
tools/output/fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
|
||||
tools/output/fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
|
||||
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -z -d $(HTML_MIN) -b BANK1 $@
|
||||
tools/output/crc_calculator -u $@
|
||||
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin output/rtlplayground.bin
|
||||
tools/$(BUILDDIR)/imagebuilder -i $(BUILDDIR)/rtlplayground.img $@
|
||||
tools/$(BUILDDIR)/fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d "$(CONFIG)" $@
|
||||
tools/$(BUILDDIR)/fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d "$(CONFIG)" $@
|
||||
tools/$(BUILDDIR)/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -z -d $(HTML_MIN) -b BANK1 $@
|
||||
tools/$(BUILDDIR)/crc_calculator -u $@
|
||||
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin $(BUILDDIR)/../rtlplayground.bin
|
||||
|
||||
.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)))
|
||||
# covered without registering it anywhere. A board only counts once both its
|
||||
# <machine>.c and its <machine>.h are present: the header is what the rest of
|
||||
# the build includes, so a .c without one is an incomplete board. The _init.c
|
||||
# files are excluded here: they are the boot hooks, compiled separately below
|
||||
# (the board's own if it exists, otherwise default_machine_init.c). 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 $(filter $(patsubst machine/%.h,%,$(wildcard machine/*.h)),$(patsubst machine/%.c,%,$(filter-out machine/%_init.c,$(wildcard machine/*.c)))))
|
||||
MACHINE_LESS_CC_FLAGS = $(filter-out -DMACHINE_%,$(CC_FLAGS))
|
||||
|
||||
.PHONY:
|
||||
machine_check:
|
||||
.PHONY: machine_check
|
||||
machine_check: $(SDCC)
|
||||
@mkdir -p $(BUILDDIR)/tmp
|
||||
@set -eo pipefail; \
|
||||
for MACHINE in $(MACHINE_DEFS); \
|
||||
do \
|
||||
echo "Checking $${MACHINE}"; \
|
||||
$(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; \
|
||||
$(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine/$${MACHINE}.c; \
|
||||
INIT=machine/$${MACHINE}_init.c; \
|
||||
if [ ! -e $$INIT ] && [ ! -L $$INIT ]; then INIT=$(MACHINE_INIT_DEFAULT); fi; \
|
||||
$(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c $$INIT; \
|
||||
done
|
||||
@rm -rf $(BUILDDIR)/tmp
|
||||
|
||||
|
||||
@@ -56,12 +56,19 @@ device simulator is provided, which runs entirely under Linux as a local webserv
|
||||
|
||||
## (0) Compiling Requirements
|
||||
|
||||
Install the following particular build requisites (Debian 12/13), note that Ubuntu 24.04
|
||||
still has an older version of sdcc, but you will need sdcc version 4.5 for the code to compile:
|
||||
Install the following particular build requisites (Debian 12/13):
|
||||
```
|
||||
sudo apt install make gcc sdcc xxd python-is-python3 libjson-c-dev zlib1g-dev
|
||||
sudo apt install make gcc g++ bison flex libboost-dev patch bzip2 curl xxd python-is-python3 libjson-c-dev zlib1g-dev
|
||||
```
|
||||
|
||||
The first `make` downloads SDCC 4.6.0, applies the fixes in `sdcc/` and builds it into
|
||||
`toolchain/`, which takes a few minutes. Later builds reuse it. The released SDCC 4.5.0
|
||||
and 4.6.0 miscompile parts of this code, see [SDCC bug #4153](https://sourceforge.net/p/sdcc/bugs/4153/)
|
||||
and [#4154](https://sourceforge.net/p/sdcc/bugs/4154/); both fixes are in SDCC trunk since
|
||||
r17039. The third patch is for [#4070](https://sourceforge.net/p/sdcc/bugs/4070/), where the
|
||||
assembler drops the top byte of a `__sfr32` address list; it is proposed upstream and lets
|
||||
`SFR_DATA_U32` be used again. To use an SDCC you installed yourself instead, run `make CC=sdcc ...`.
|
||||
|
||||
<details>
|
||||
<summary>If using Docker (click to expand)</summary>
|
||||
|
||||
@@ -103,24 +110,36 @@ docker run --rm -p 8080:8080 -v $(pwd):/workspace rtlplayground-dev \
|
||||
tools/output/httpd_sim /workspace/html
|
||||
```
|
||||
|
||||
Edit `machine.h` or `config.txt` on your host, then re-run `make` — the
|
||||
Edit `config.txt` on your host, then re-run `make` — the
|
||||
source directory is mounted into the container, so changes take effect
|
||||
immediately. To build for a different machine, pass `MACHINE=...`.
|
||||
immediately. To build for a different machine, pass `MACHINE=<name>`, which
|
||||
selects `machine/<name>.c` (see [Adding a new device](doc/adding-a-device.md)).
|
||||
|
||||
</details>
|
||||
|
||||
## (1) Compiling for direct chip flashing AND upgrading an existing RTLPlayground running device
|
||||
|
||||
Edit machine.h with an editor like vi or nano. Select the correct machine the firmware should build for.
|
||||
Pass the machine that matches your device, for example:
|
||||
```
|
||||
make MACHINE=DEFAULT_8C_1SFP
|
||||
```
|
||||
The name selects the board definition `machine/<name>.c`; `make` without a
|
||||
`MACHINE` value stops with an error listing what is expected. If your board is
|
||||
not in the list yet, see [Adding a new device](doc/adding-a-device.md).
|
||||
|
||||
To embed a machine-specific startup configuration, pass `CONFIG`:
|
||||
```
|
||||
make MACHINE=DEFAULT_8C_1SFP CONFIG=configs/DEFAULT_8C_1SFP.txt
|
||||
```
|
||||
`CONFIG` defaults to `config.txt`; the selected file is embedded in the image
|
||||
and changing it triggers a rebuild.
|
||||
|
||||
> [!TIP]
|
||||
> You can write configuration parameters in config.txt (see below) in order your switch to get
|
||||
> straight at the first boot, a correct IP configuration.
|
||||
|
||||
Now, building the firmware image should work:
|
||||
```
|
||||
make
|
||||
```
|
||||
Now, building the firmware image should work.
|
||||
|
||||
Note, that the image generated ends in .bin, not .img, in order to make IMSProg happy.
|
||||
|
||||
image location is stored in `RTLPlayground/output/rtlplayground_version_machine.bin`
|
||||
@@ -158,9 +177,9 @@ example of compilation console output
|
||||
RTLPlayground/installer$ make
|
||||
mkdir -p output
|
||||
gcc updatebuilder.c -o output/updatebuilder
|
||||
sdas8051 -plosgff -o output/crtstart.rel crtstart.asm
|
||||
sdcc -mmcs51 --code-loc 0x1000 -o output/installer.rel -c installer.c
|
||||
sdcc -mmcs51 -Wl-bHOME=0x1100 -Wl-r -o output/rtlinstaller.ihx output/crtstart.rel output/installer.rel
|
||||
../toolchain/sdcc-3390765201/bin/sdas8051 -plosgff -o output/crtstart.rel crtstart.asm
|
||||
../toolchain/sdcc-3390765201/bin/sdcc -mmcs51 --code-loc 0x1000 -o output/installer.rel -c installer.c
|
||||
../toolchain/sdcc-3390765201/bin/sdcc -mmcs51 -Wl-bHOME=0x1100 -Wl-r -o output/rtlinstaller.ihx output/crtstart.rel output/installer.rel
|
||||
./output/updatebuilder -i output/rtlinstaller.ihx -o output/rtlplayground_oem_upgrade.bin ../output/rtlplayground.bin
|
||||
Input file size: 524288
|
||||
Bytes read: 524288
|
||||
@@ -186,7 +205,7 @@ Go to "Firmware update" tab, select the correct file.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If your device already runs RTLPlayground, you must upload the binary file /RTLPlayground/output/rtlplayground_Version_Machine.bin
|
||||
> If your device is OEM, you must upload the binary file /RTLPlayground/installer/outputrtlplayground_oem_upgrade.bin
|
||||
> If your device is OEM, you must upload the binary file /RTLPlayground/installer/output/rtlplayground_oem_upgrade.bin
|
||||
|
||||
> [!CAUTION]
|
||||
> Check one more time that your device matches the machine type before flashing.
|
||||
@@ -353,12 +372,13 @@ Enjoy playing!
|
||||
## (11) Other documents
|
||||
|
||||
The following documents give further documentation on specific features of the RTL837x SoCs:
|
||||
- [Adding a new device](doc/adding-a-device.md)
|
||||
- [RTL8372/3 Feature support](doc/hardware.md)
|
||||
- [CPU Port](doc/CpuPort.md)
|
||||
- [L2 learning](doc/l2.md)
|
||||
- [IGMP (IP-MC streaming)](doc/igmp.md)
|
||||
- [SFP+ ports](doc/sfp.md)
|
||||
- [Trunking aka. port aggregation](doc/trunking.md)
|
||||
- [Trunking aka. port aggregation](doc/link_aggregation.md)
|
||||
- [LACP (802.3ad link aggregation)](doc/lacp.md)
|
||||
- [VLAN](doc/vlan.md)
|
||||
- [Storm control](doc/storm_control.md)
|
||||
|
||||
@@ -125,18 +125,6 @@ void early_boot_handle_button(void) __banked
|
||||
void sds_config(uint8_t sds, uint8_t mode) __banked
|
||||
{
|
||||
print_string("sds_config sds: "); print_byte(sds); print_string(", mode: "); print_byte(mode); write_char('\n');
|
||||
sds_config_mac(sds, mode);
|
||||
|
||||
if (mode == SDS_10GR || mode == SDS_QXGMII)
|
||||
sds_write_v(sds, 0x21, 0x10, 0x4480); // Q002110:6480
|
||||
else
|
||||
sds_write_v(sds, 0x21, 0x10, 0x6480); // Q002110:6480
|
||||
sds_write_v(sds, 0x21, 0x13, 0x0400); // Q002113:0400
|
||||
sds_write_v(sds, 0x21, 0x18, 0x6d02); // Q002118:6d02
|
||||
sds_write_v(sds, 0x21, 0x1b, 0x424e); // Q00211b:424e
|
||||
sds_write_v(sds, 0x21, 0x1d, 0x0002); // Q00211d:0002
|
||||
sds_write_v(sds, 0x36, 0x1c, 0x1390); // Q00361c:1390
|
||||
sds_write_v(sds, 0x36, 0x14, 0x003f); // Q003614:003f
|
||||
|
||||
uint8_t page = 0;
|
||||
uint16_t v = 0;
|
||||
@@ -165,6 +153,21 @@ void sds_config(uint8_t sds, uint8_t mode) __banked
|
||||
print_string("Error in SDS Mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sds_config_mac(sds, mode);
|
||||
|
||||
if (mode == SDS_10GR || mode == SDS_QXGMII)
|
||||
sds_write_v(sds, 0x21, 0x10, 0x4480); // Q002110:6480
|
||||
else
|
||||
sds_write_v(sds, 0x21, 0x10, 0x6480); // Q002110:6480
|
||||
|
||||
sds_write_v(sds, 0x21, 0x13, 0x0400); // Q002113:0400
|
||||
sds_write_v(sds, 0x21, 0x18, 0x6d02); // Q002118:6d02
|
||||
sds_write_v(sds, 0x21, 0x1b, 0x424e); // Q00211b:424e
|
||||
sds_write_v(sds, 0x21, 0x1d, 0x0002); // Q00211d:0002
|
||||
sds_write_v(sds, 0x36, 0x1c, 0x1390); // Q00361c:1390
|
||||
sds_write_v(sds, 0x36, 0x14, 0x003f); // Q003614:003f
|
||||
|
||||
sds_write_v(sds, 0x36, 0x10, v); // Q003610:0200
|
||||
|
||||
if (page == 0x2e) { // 10G Fiber / SDS_QXGMII
|
||||
@@ -257,7 +260,7 @@ void nic_setup(void) __banked
|
||||
|
||||
// This sets the size of the RX buffer, the filling level is in 0x7874
|
||||
// R7848-000004ff
|
||||
REG_SET(RTL837X_REG_NIC_RXBUFF_RX, 0x4ff);
|
||||
REG_SET(RTL837X_REG_NIC_RXBUFF_RX, RTL837X_NIC_RX_LAST_SLOT);
|
||||
|
||||
// R7844-000007fe
|
||||
REG_SET(RTL837X_REG_NIC_BUFFSIZE_TX, 0x7fe);
|
||||
@@ -296,6 +299,7 @@ void nic_setup(void) __banked
|
||||
|
||||
// Sequence number of TX packets
|
||||
tx_seq = 0;
|
||||
REG_SET(RTL837X_NIC_INT_MSK, NIC_INT_RXIE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,9 +20,11 @@
|
||||
#include "rtl837x_lldp.h"
|
||||
#include "rtl837x_storm.h"
|
||||
#include "rtl837x_trap.h"
|
||||
#include "rtl837x_cabletest.h"
|
||||
#include "sfp.h"
|
||||
#include "dhcp.h"
|
||||
#include "syslog.h"
|
||||
#include "sessions.h"
|
||||
#include "dns.h"
|
||||
#include "ntp.h"
|
||||
#include "uip/uip.h"
|
||||
@@ -166,10 +168,15 @@ uint8_t atoi_hex(uint8_t idx)
|
||||
break;
|
||||
}
|
||||
|
||||
if (h_idx == 8) {
|
||||
h_idx = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// swap hex nibbles
|
||||
val = (val >> 4) | (val << 4);
|
||||
|
||||
if (c - '0' < 10) {
|
||||
if ((uint8_t)(c - '0') < 10) {
|
||||
val |= c - '0';
|
||||
} else {
|
||||
c |= 0x20;
|
||||
@@ -260,7 +267,7 @@ uint8_t cmd_parse_port(uint8_t idx) {
|
||||
return 0;
|
||||
|
||||
port = machine.phys_to_log_port[port];
|
||||
if (port < machine.min_port || port > machine.max_port)
|
||||
if (!MACHINE_PORT_VALID(port))
|
||||
return 0;
|
||||
|
||||
atoi_results_u8 = port;
|
||||
@@ -737,9 +744,9 @@ void parse_isolate(void)
|
||||
}
|
||||
|
||||
if (cmd_compare(2, "off")) {
|
||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++)
|
||||
for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++)
|
||||
members |= ((uint16_t)1) << i;
|
||||
members |= 0x200; // CPU-port
|
||||
members |= PMASK_CPU; // CPU-port
|
||||
port_isolate(port_configured, members);
|
||||
return;
|
||||
}
|
||||
@@ -791,7 +798,7 @@ void parse_ingress(void)
|
||||
if (!cmd_is_space_or_nul(idx))
|
||||
goto err;
|
||||
// Setting mode for all ports at once
|
||||
for (log_port = machine.min_port; log_port <= machine.max_port; log_port++) {
|
||||
for (log_port = MACHINE_MIN_PORT; log_port <= MACHINE_MAX_PORT; log_port++) {
|
||||
if (!port_ingress_filter(log_port, mode)) {
|
||||
cmd_error("cannot set the ingress filter for port "); print_phys_port(log_port); write_char('\n');
|
||||
return;
|
||||
@@ -843,7 +850,7 @@ void parse_mirror(void)
|
||||
print_string("NOT Enabled: ");
|
||||
}
|
||||
print_string("Mirroring port: ");
|
||||
print_phys_port(mirroring_port);
|
||||
print_phys_port(mPort >> 1);
|
||||
reg_read_m(RTL837x_MIRROR_CONF);
|
||||
uint16_t m = sfr_data[0];
|
||||
m = (m << 8) | sfr_data[1];
|
||||
@@ -903,6 +910,7 @@ void parse_port(void)
|
||||
"\nport <port> [show|on|off]" \
|
||||
"\nport <port> [10m|100m|1g|2g5|duplex] [half|full]" \
|
||||
"\nport <port> lldp [block|permit]" \
|
||||
"\nport <port> cabletest [show]" \
|
||||
"\nport <port> name [custom port name]\n");
|
||||
return;
|
||||
}
|
||||
@@ -945,6 +953,11 @@ void parse_port(void)
|
||||
}
|
||||
} else if (machine.is_sfp[phy_settings.port]) {
|
||||
print_string(" is SFP no PHY information available.\n");
|
||||
} else if (cmd_compare(2, "cabletest")) {
|
||||
if (cmd_words_len > 3 && cmd_compare(3, "show"))
|
||||
cabletest_show();
|
||||
else
|
||||
cabletest_run();
|
||||
} else if (cmd_compare(2, "10m")) {
|
||||
print_string(" 10M\n");
|
||||
phy_settings.speed = PHY_SPEED_10M;
|
||||
@@ -1007,7 +1020,7 @@ void parse_mtu(void)
|
||||
uint8_t p;
|
||||
|
||||
if (cmd_compare(1, "show")) {
|
||||
for (p = machine.min_port; p <= machine.max_port; p++) {
|
||||
for (p = MACHINE_MIN_PORT; p <= MACHINE_MAX_PORT; p++) {
|
||||
reg_read_m(RTL8373_REG_MAC_L2_PORT_MAX_LEN + ((uint16_t) p << 8));
|
||||
uint16_t mtu = SFR_DATA_U16 & 0x3fff;
|
||||
print_string("Port "); print_phys_port(p);
|
||||
@@ -1467,6 +1480,9 @@ void parse_passwd(void)
|
||||
passwd[j++] = c;
|
||||
} while (c != NUL && j < 20);
|
||||
passwd[j] = NUL;
|
||||
/* Logins made with the old password end here. With one session the next
|
||||
* login pushed a leftover one out; with several it would stay valid. */
|
||||
session_init();
|
||||
return;
|
||||
}
|
||||
cmd_error("Missing password\n");
|
||||
@@ -1824,6 +1840,8 @@ void print_gpio_status(void) {
|
||||
void print_sw_version(void) __banked {
|
||||
print_string("Software version: " VERSION_SW);
|
||||
print_string("\nBuild date: " BUILD_DATE);
|
||||
print_string("\nCompiler: SDCC " STR(__SDCC_VERSION_MAJOR) "." STR(__SDCC_VERSION_MINOR) "." STR(__SDCC_VERSION_PATCH) " #" STR(__SDCC_REVISION));
|
||||
print_string("\nToolchain: " SDCC_TOOLCHAIN);
|
||||
print_string("\nHardware: ");
|
||||
print_string(machine.machine_name);
|
||||
write_char('\n');
|
||||
@@ -1999,10 +2017,10 @@ void cmd_parser(void) __banked
|
||||
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)
|
||||
&& atoi_short(cmd_words_b[2]) && atoi_results_short <= 4094)
|
||||
port_pvid_set(atoi_results_u8, atoi_results_short);
|
||||
else {
|
||||
cmd_error("pvid <port> <1-4094>\n");
|
||||
cmd_error("pvid <port> <0-4094>\n");
|
||||
}
|
||||
} else if (cmd_compare(0, "vlan")) {
|
||||
parse_vlan();
|
||||
@@ -2143,7 +2161,7 @@ void execute_config(void) __banked
|
||||
skipping = 1;
|
||||
}
|
||||
c = flash_buf[cfg_idx++];
|
||||
if (c == 0 || c == '\n') {
|
||||
if (c == 0 || c == '\n' || c == '\r') {
|
||||
if (skipping) {
|
||||
skipping = 0;
|
||||
} else {
|
||||
@@ -2317,6 +2335,7 @@ void health_show(void) __banked
|
||||
ph_line("tx ", HEALTH_PH_TX);
|
||||
ph_line("stp ", HEALTH_PH_STP);
|
||||
ph_line("cmd ", HEALTH_PH_CMD);
|
||||
ph_line("lldp", HEALTH_PH_LLDP);
|
||||
|
||||
/* Stack: current depth plus how much of the painted area is untouched */
|
||||
print_string("sp ");
|
||||
|
||||
@@ -19,8 +19,8 @@ extern __xdata uint8_t err_status;
|
||||
#define HEALTH_PH_TX 3
|
||||
#define HEALTH_PH_STP 4
|
||||
#define HEALTH_PH_CMD 5
|
||||
#define HEALTH_PHASES 6
|
||||
#define HEALTH_LLDP 7
|
||||
#define HEALTH_PH_LLDP 6
|
||||
#define HEALTH_PHASES (HEALTH_PH_LLDP + 1) /* last id + 1: sizes the arrays in cmd_parser.c */
|
||||
|
||||
extern __xdata uint16_t health_rx_frames;
|
||||
#define health_rx_frame() health_rx_frames++
|
||||
|
||||
@@ -51,7 +51,7 @@ __xdata uip_ipaddr_t server;
|
||||
#define DHCP_END 255
|
||||
|
||||
#pragma codeseg BANK3
|
||||
#pragma constseg BANK2
|
||||
#pragma constseg BANK3
|
||||
|
||||
struct dhcp_pkt {
|
||||
uint8_t type;
|
||||
|
||||
@@ -34,6 +34,21 @@ Next, transfer the actual packet over by repeating the SFR function with a
|
||||
pointer to the frame on the ASIC directly after the frame header and a
|
||||
length as given by the length in the frame header + 7, again divided by 8.
|
||||
|
||||
The RX ring's inclusive last slot is configured as `0x4ff`, giving a byte
|
||||
range of `0x0000` through `0x27ff`. If the descriptor occupies the last slot
|
||||
at `0x27f8`, its payload starts at `0x0000`, not `0x2800`. The RX copy code
|
||||
normalizes that starting address before DMA. It relies on the hardware to
|
||||
wrap transfers that start inside the ring and cross its end, as observed
|
||||
on SWTGW218AS. Programming an initial address of `0x2800` does not wrap
|
||||
and can instead read zeros or stale TX data outside the RX ring.
|
||||
|
||||
Frame lengths are checked against `UIP_CONF_BUFFER_SIZE` before copying.
|
||||
DMA works in whole eight-byte units. `UIP_CONF_BUFFER_ALLOC_SIZE` rounds
|
||||
the backing storage up to the next complete word: 1,560 bytes for the
|
||||
1,556-byte logical frame limit. This padding allows a maximum-size frame
|
||||
to be transferred directly without a separate tail copy. The logical
|
||||
frame limit and advertised MSS are unchanged.
|
||||
|
||||
The received frame will have an RTL proprietary Ethernet frame type of
|
||||
0x8899 (RRPC) where normally the frame type 0x0800 for IPv4 would be located.
|
||||
Further 6 bytes follow describing the frame, before the normal IPv4 data
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
# Adding a new device
|
||||
|
||||
A device is supported by adding one board header `.h` and board definition `.c` file
|
||||
under `machine/`.
|
||||
the build selects the definition by name, and CI compiles every file it finds.
|
||||
|
||||
To compile for your added device, do:
|
||||
```
|
||||
make MACHINE=<NAME>
|
||||
```
|
||||
|
||||
## What a new device consists of
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `machine/<NAME>.c` | the `struct machine machine` board definition |
|
||||
| `machine/<NAME>.h` | `MACHINE_MODEL` (the model string shown in the UI and the CLI) and `MACHINE_CHIPSET` (`RTL8372` or `RTL8373`) |
|
||||
| `machine/<NAME>_init.c` | optional `machine_custom_init()` boot hook, for registers the machine definition cannot express |
|
||||
| `doc/devices/<name>.md` + `doc/supported_devices.md` | (only if the board is verified and you want to support it publicly) user-facing documentation |
|
||||
|
||||
`<NAME>` is the machine symbol without its `MACHINE_` prefix, so `MACHINE` is
|
||||
passed exactly as spelled on the command line: `make MACHINE=MY_BOARD_1_0`
|
||||
needs `machine/MY_BOARD_1_0.c` and `machine/MY_BOARD_1_0.h`.
|
||||
|
||||
## Step 1: the board header
|
||||
|
||||
`machine/<NAME>.h` carries the product string and the SoC family. Use the
|
||||
existing files as the template:
|
||||
|
||||
```c
|
||||
#ifndef _MACHINE_MY_BOARD_1_0_H_
|
||||
#define _MACHINE_MY_BOARD_1_0_H_
|
||||
|
||||
#define MACHINE_MODEL "Brand Model V1.0"
|
||||
#define MACHINE_CHIPSET RTL8373
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
`MACHINE_CHIPSET` is `RTL8373` or `RTL8372`; a build without it will fail. It selects the default
|
||||
logical port range: `MACHINE_MIN_PORT` is `0` for RTL8373 and `3` for RTL8372, while
|
||||
`MACHINE_MAX_PORT` is `8`, the highest logical port index. A board with a different range defines
|
||||
`MACHINE_MIN_PORT` and/or `MACHINE_MAX_PORT` in its header to override the
|
||||
defaults.
|
||||
|
||||
The device product string is what the CLI or the Web-Interface will print to identify the device; `machine.h` includes it by name.
|
||||
|
||||
> [!NOTE]
|
||||
> `machine_name` is a `char[30]` and `MACHINE_MODEL` is copied into it at
|
||||
> compile time. A longer model string still builds, but SDCC emits
|
||||
> `warning 147: excess elements in array of chars initializer` and the name is
|
||||
> truncated in the UI. Keep it to 29 characters or less.
|
||||
|
||||
## Step 2: the board definition
|
||||
|
||||
`machine/<NAME>.c` starts with the shared prelude and then defines the single
|
||||
`machine` object. Copy the closest existing board and adjust it — do not start
|
||||
from a blank file, the field meanings are easier to see in a real example.
|
||||
The best choice is usually a device that has the same number and type of Ethernet
|
||||
ports and the same number of SFP+ cages.
|
||||
|
||||
```c
|
||||
#include "machine_defs.h"
|
||||
|
||||
__code const struct machine machine = {
|
||||
MACHINE_COMMON_SETTING,
|
||||
.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 = {
|
||||
{ /* RJ45 ports */
|
||||
LEDS_2G5 | LEDS_LINK,
|
||||
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
0
|
||||
}, { /* SFP port, single green LED */
|
||||
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
`MACHINE_COMMON_SETTING` (from `machine_defs.h`) initializes `machine_name` and
|
||||
`isRTL8373` from the header's `MACHINE_MODEL` and `MACHINE_CHIPSET`. The logical
|
||||
port range comes from `MACHINE_MIN_PORT` and `MACHINE_MAX_PORT` in `machine.h`.
|
||||
Keep it as the first initializer and list the board-specific fields after it.
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | Meaning |
|
||||
|-------|---------|
|
||||
| `MACHINE_COMMON_SETTING` | expands to `machine_name` (`MACHINE_MODEL`) and `isRTL8373` (`1` for `RTL8373`, `0` for `RTL8372`); both are derived from the header's `MACHINE_CHIPSET` (see Step 1) |
|
||||
| `n_sfp` | number of SFP+ cages |
|
||||
| `n_10g` | SerDes 10G capability used by the RTL837xN init: `0` none, `1` one, `2` two 10G-capable SerDes |
|
||||
| `log_to_phys_port[9]` | logical port (0-based index) → physical front-panel port number |
|
||||
| `phys_to_log_port[9]` | the inverse, physical port 1 is index 0, unused slots are 0 |
|
||||
| `is_sfp[9]` | `0` for copper, `1` for left slot and `2` for right slot |
|
||||
| `sfp_port[2]` | per-cage wiring, `sfp_port[0]` is the leftmost cage |
|
||||
| `reset_pin` | GPIO of the reset button, `GPIO_NA` if unpopulated |
|
||||
| `high_leds` | mux/enable for the LED pins 27–29 (`LED_27`, `LED_28_SYS`, `LED_29`) |
|
||||
| `port_led_set[9]` | which LED set (0–3) each logical port uses |
|
||||
| `led_sets[4][4]` | Each port can have up to 4 GPIO output pins assigned. 4 sets of LEDs with 4 LED-conditions per set; the conditions define which GPIO pins become active for a port given a port link-state. Which LEDs are then enabled depends on the wiring of the pins to up to 3 LEDs for that port, which can make a logical combination of the 4 LED output-pins. |
|
||||
| `led_mux_custom` / `led_mux[28]` | `1` plus the 28 mux values when the stock LED muxing does not fit the board |
|
||||
| `mac_flash_offset` | flash offset of the factory MAC address, omit or `0` if the board does not store one |
|
||||
|
||||
Each `struct sfp_port` entry holds `pin_detect`, `pin_los`, `pin_tx_disable`,
|
||||
`sds` (which SerDes drives the cage) and `i2c` (built with `I2CBUS(sda, scl)`,
|
||||
or `GPIO_NA`-based values where a cage has no such pin).
|
||||
|
||||
`I2CBUS(...)` only accepts the pin pairs listed in `machine_defs.h`. A wrong
|
||||
pair is caught at compile time: SDCC reports
|
||||
`error 176: sizeof applied to an incomplete type` pointing at the offending
|
||||
`.i2c` line, because the macro deliberately turns an invalid bus number into an
|
||||
array of size 0.
|
||||
|
||||
### Reusing an existing definition
|
||||
|
||||
If the new board is electrically identical to one that already exists — same
|
||||
port mapping, same SFP wiring, same LEDs — do not copy the file. Make the new
|
||||
`.c` a symlink and keep only a distinct `.h`, so the two boards cannot drift
|
||||
apart:
|
||||
|
||||
```
|
||||
ln -s KP_9000_6XHML_X2.c machine/MY_BOARD_1_0.c
|
||||
```
|
||||
|
||||
The new board still needs `machine/MY_BOARD_1_0.h` (pick the version number on
|
||||
the PCB) with its own `MACHINE_MODEL` and `MACHINE_CHIPSET`: `MACHINE_MODEL` is
|
||||
what distinguishes the products, and `MACHINE_CHIPSET` must match the SoC of
|
||||
the board definition being reused.
|
||||
Existing examples: `machine/PCB_K0402WS_V3.c`, `machine/KP_9000_9XHML_X_V3_2.c`
|
||||
and the six `KP_9000_*` revision variants.
|
||||
|
||||
Two files that differ only in whitespace or comments are duplicates and should
|
||||
be collapsed this way.
|
||||
|
||||
### Optional custom init hook
|
||||
|
||||
If the board needs custom initialization, add
|
||||
`machine/<NAME>_init.c` defining `machine_custom_init()`. The Makefile picks the
|
||||
file up by name and compiles it.
|
||||
|
||||
Boards that need the same hook share one file: keep the code in a single
|
||||
`machine/<NAME>_init.c` whose `machine/<NAME>.c` is a real file (not a symlink),
|
||||
and make the other boards' `_init.c` symlinks to it, for example:
|
||||
|
||||
```
|
||||
ln -s KP_9000_6XH_X2_init.c machine/MY_BOARD_1_0_init.c
|
||||
```
|
||||
|
||||
## Step 3: build and verify
|
||||
|
||||
```
|
||||
make MACHINE=MY_BOARD_1_0
|
||||
```
|
||||
|
||||
The generated flash image appears as `output/rtlplayground-<version>-MY_BOARD_1_0.bin`. An
|
||||
unknown or empty `MACHINE` fails immediately with a message naming the expected
|
||||
file, before anything is compiled.
|
||||
|
||||
Then run the checks CI runs:
|
||||
|
||||
```
|
||||
make machine_check # compiles machine/<NAME>.c and its optional _init.c for every machine
|
||||
make -C test # host-side unit tests
|
||||
```
|
||||
|
||||
`make machine_check` discovers the definitions with
|
||||
`$(wildcard machine/*.c)`, so a new file is covered without registering it
|
||||
anywhere. CI (`.github/workflows/build.yml`) runs it on every push and pull
|
||||
request, alongside full builds for a 4+2 and an 8+1 board.
|
||||
|
||||
A successful compile only proves the definition is syntactically valid. The
|
||||
actual behaviour — port numbering, SFP detection, LEDs — has to be confirmed on
|
||||
hardware, and the console commands (`port`, `stat`, `sfp`, `leds`) are the
|
||||
tools for that.
|
||||
|
||||
## Step 4: documentation
|
||||
|
||||
Once the board has been tested on hardware:
|
||||
|
||||
1. Add a row to the table in [Supported devices](supported_devices.md).
|
||||
2. Add `doc/devices/<name>.md` describing the board, the build target
|
||||
(`make MACHINE=MY_BOARD_1_0`), what works and what is unverified, plus
|
||||
photos and the PCB silkscreen marking.
|
||||
3. If the board shares a PCB with other revisions, follow
|
||||
`doc/devices/KP-9000-6XH-X2.md` and document which `MACHINE` to pick for
|
||||
which silkscreen.
|
||||
|
||||
### Identifying the CPU variant
|
||||
|
||||
For RTL8373-based devices, use the read-only console command below to distinguish
|
||||
the N and non-N CPU variants:
|
||||
|
||||
```text
|
||||
regget 4
|
||||
```
|
||||
|
||||
| Register 0x0004 value | CPU |
|
||||
|---|---|
|
||||
| `0x83730000` | RTL8373 (non-N) |
|
||||
| `0x83737000` | RTL8373N |
|
||||
|
||||
Record the identified CPU in the device documentation. These values identify
|
||||
only the CPU variant; document PHY and flash-chip models separately when verified.
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
hongyavision HYWS-SGT0204S
|
||||
|
||||
RTL8372-based 4×2.5G + 2×SFP+ unmanaged switch.
|
||||
|
||||
Also marked on the PCB as `2G5F4_10G2_V1.01`.
|
||||
|
||||
Stock firmware runs a factory test console on UART at 9600 baud 8N1 (banner
|
||||
`RTL8371B start`, prompt `RTL8371B:`). There is no management CLI and no Web
|
||||
interface.
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation and update.
|
||||
Erase the whole chip and verify the write (`flashrom -v`) before powering the
|
||||
board, so an incomplete write is caught before the board is powered up.
|
||||
|
||||
Stock flash chip is 512 KB (Bright Moon `T25S40`, 4 Mbit, SOP-8), which the
|
||||
RTLPlayground image fills exactly.
|
||||
|
||||
### Label specifications
|
||||
|
||||
Case, top / front / nameplate:
|
||||
|
||||
<img src="photos/2G5F4_10G2_V1.01/assembled-top.jpg" width="300" />
|
||||
<img src="photos/2G5F4_10G2_V1.01/assembled-front.jpg" width="300" />
|
||||
<img src="photos/2G5F4_10G2_V1.01/assembled-bottom.jpg" width="300" />
|
||||
|
||||
- **Manufacturer**: hongyavision (Shenzhen Hongyavision Electronic Technology
|
||||
Co., Ltd.)
|
||||
- **Model**: HYWS-SGT0204S — the nameplate is printed in Chinese and reads
|
||||
"10/100/1000/2500M fibre switch" and "4x 2.5G copper port + 2x 10G SFP+
|
||||
optical port"
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1G / 2.5G / 10G
|
||||
- **Power**: 12 V DC, 2 A
|
||||
- **Serial number**: `S/N-YYYYMMDDNNNN`, e.g. `S/N-202312010028`
|
||||
|
||||
The top of the case only carries generic printing ("2.5G+10G High Speed Fiber
|
||||
Transceiver / 4-Port 2.5G Ethernet Switch+10G Fiber"), so the nameplate on the
|
||||
bottom is what identifies the device.
|
||||
|
||||
### What works
|
||||
|
||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- Both SFP+ ports supporting 1G, 2.5G and 10G modules
|
||||
- Copper LEDs: white (2.5G) and blue (link/activity)
|
||||
- SFP LEDs: one single LED per port (link/activity)
|
||||
- SFP EEPROM and DDM readable on both cages, verified with a 10G module
|
||||
(`Rate: 0x67`, module identity and DDM values via the `sfp` console command)
|
||||
- Serial console at 115200 8N1 (RTLPlayground) / 9600 8N1 (stock)
|
||||
|
||||
### Not verified
|
||||
|
||||
- The reset button footprint is unpopulated and the case has no opening for it,
|
||||
so it could not be tested.
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: `2G5F4_10G2_V1.01`
|
||||
|
||||
**Key components**
|
||||
- Main switch: RTL8372 (RTL8371B family), reported as `RTL8372` (non-N) by
|
||||
RTLPlayground. The chip sits under a heatsink and its package marking is not
|
||||
readable.
|
||||
- U1: SPI NOR flash, Bright Moon `T25S40`, 4 Mbit / 512 KB, SOP-8
|
||||
- A 3-hole reset button footprint is present but unpopulated, and the case has
|
||||
no opening for it, so there is no usable reset button
|
||||
|
||||
Top side:
|
||||
|
||||
<img src="photos/2G5F4_10G2_V1.01/pcb_top.jpg" width="600" />
|
||||
|
||||
Bottom:
|
||||
|
||||
<img src="photos/2G5F4_10G2_V1.01/pcb_bottom.jpg" width="600" />
|
||||
|
||||
The stock flash chip, Bright Moon `T25S40` (SOP-8, 4 Mbit / 512 KB):
|
||||
|
||||
<img src="photos/2G5F4_10G2_V1.01/flash_t25s40.jpg" width="300" />
|
||||
|
||||
### Port layout
|
||||
|
||||
| Front panel position | Logical port | Physical port | Type |
|
||||
|----------------------|--------------|---------------|---------|
|
||||
| SFP left | 8 | 5 | SFP+ |
|
||||
| RJ45 1 | 4 | 1 | Copper |
|
||||
| RJ45 2 | 5 | 2 | Copper |
|
||||
| RJ45 3 | 6 | 3 | Copper |
|
||||
| RJ45 4 | 7 | 4 | Copper |
|
||||
| SFP right | 3 | 6 | SFP+ |
|
||||
|
||||
Copper ports 1–4 match the KP-9000-6XH-X2 (2M-PCB43-V1.1) layout, which this
|
||||
board is a sibling of. The two SFP+ cages are wired the other way round
|
||||
compared to that board: physical port 5 is on SDS1 and physical port 6 is on
|
||||
SDS0.
|
||||
|
||||
### Serial console
|
||||
|
||||
The board has three through-holes used as the serial console, next to the
|
||||
heatsink in the middle of the board and visible in the top side photo above (the
|
||||
silkscreen labels are printed rotated by 90°). **The silkscreen labels are
|
||||
wrong**: they are shifted relative to the actual signals.
|
||||
|
||||
| Silkscreen label | Actual signal |
|
||||
|------------------|---------------|
|
||||
| TX | GND |
|
||||
| RX | TX |
|
||||
| GND | RX |
|
||||
|
||||
Wiring (following the measured signals, not the labels):
|
||||
|
||||
| USB-TTL adapter | Board pad |
|
||||
|-----------------|----------------------|
|
||||
| GND | pad labelled `TX` |
|
||||
| RX | pad labelled `RX` |
|
||||
| TX | pad labelled `GND` |
|
||||
|
||||
- **Settings**: 115200 baud / 8N1 / 3.3V TTL (RTLPlayground), 9600 baud for the
|
||||
stock firmware
|
||||
- The stock firmware only prints a few bytes and a factory test menu
|
||||
(`?`, `rst`, `f`, `r`, `10`, `100`, `g1`, `sd`, `eye`, …); it is not an
|
||||
interactive management console
|
||||
|
||||
### LED configuration
|
||||
|
||||
Case silkscreen, below the RJ45 ports:
|
||||
|
||||
```
|
||||
White : 2.5G Blue : 1000M/2500M L/A
|
||||
```
|
||||
|
||||
The front panel also carries a `PWR` LED and one LED per SFP cage (`SFP1`,
|
||||
`SFP2`) on the right hand side.
|
||||
|
||||
| Port | LED | Linked, idle | With traffic |
|
||||
|------------|--------------|--------------|--------------|
|
||||
| Copper | white | 2.5G only | same |
|
||||
| Copper | blue | solid | blinks (L/A) |
|
||||
| SFP | single LED | solid | blinks (L/A) |
|
||||
|
||||
Measured LED-ID mapping (from the RTL837x LED set registers):
|
||||
|
||||
| LED-ID | Function |
|
||||
|--------|---------------------------------|
|
||||
| LED-ID0| copper blue LED |
|
||||
| LED-ID1| copper white LED |
|
||||
| LED-ID2| SFP single LED |
|
||||
|
||||
**Important**: `RTL837X_REG_LED_GLB_IO_EN` bit 6 must be set in
|
||||
`machine_custom_init()`. Without it the RTL837x "solid" conditions (LINK/speed)
|
||||
do not drive the LEDs at all and only `ACT` does, which makes the white LED
|
||||
glow faintly at non-2.5G speeds.
|
||||
|
||||
### SFP GPIO assignments
|
||||
|
||||
| SFP | pin\_detect (ModAbs) | pin\_los | SerDes | I2C SDA | I2C SCL |
|
||||
|-------------------|-------------------------------|------------------|--------|-------------------------|--------------------------|
|
||||
| Left (logical 8, physical 5) | GPIO30\_ACL\_BIT3\_EN | GPIO37 | SDS1 | GPIO39\_I2C\_SDA4 | GPIO40\_I2C\_SCL3\_MDC1 |
|
||||
| Right (logical 3, physical 6)| GPIO50\_I2C\_SCL2\_UART1\_TX | GPIO10\_LED10 | SDS0 | GPIO41\_I2C\_SDA3\_MDIO1 | GPIO40\_I2C\_SCL3\_MDC1 |
|
||||
|
||||
`pin_tx_disable` is GPIO\_NA on both ports. Both I2C buses are confirmed
|
||||
working: with the same 10G module inserted, the `sfp` console command reads its
|
||||
vendor and model from the left cage (`Slot 1`) and from the right cage
|
||||
(`Slot 2`), DDM values included. The insertion also shows which SerDes drives
|
||||
each cage - the left cage reports `sds_config sds: 01` and the right cage
|
||||
`sds: 00`, which matches the table above.
|
||||
|
||||
### Machine target
|
||||
|
||||
Build for this device with `make MACHINE=2G5F4_10G2_V1_01`, which selects the
|
||||
`machine/2G5F4_10G2_V1_01.c` board definition. It is derived from
|
||||
`machine/KP_9000_6XHML_X2.c` with the SFP cage order and the reset pin changed.
|
||||
The fitted T25S40 cannot be read in DIO mode on this board: an image that leaves
|
||||
DIO enabled does not come up at all, both at the default read clock divider of 4
|
||||
and at 8 (two boards tested), while the same image with single-IO boots and runs
|
||||
normally. The board definition therefore sets `flash_sio`, which makes
|
||||
`flash_init()` use `CMD_FREAD` at divider 8. Only the management plane is
|
||||
slower, the ASIC keeps forwarding in hardware.
|
||||
@@ -17,8 +17,8 @@ The original web interface reports this board as hardware version V3.2
|
||||
The component placement matches [2M-PCB23-V3.1](2M-PCB23-V3_1.md): same
|
||||
positions for the flash (U8), the T7/T8/T9/T10 headers, the SFP cage and its
|
||||
LED, and the unpopulated U7/U9 footprints. Build with
|
||||
`MACHINE=KP_9000_9XHML_X_V3_2`, which uses the V3.1 machine definition and
|
||||
only differs in the reported name.
|
||||
`make MACHINE=KP_9000_9XHML_X_V3_2`, whose board file is a symlink to the V3.1
|
||||
definition and only differs in the reported name.
|
||||
|
||||
## Tested
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ and sold by Mokerlink.
|
||||
The device is fully supported:
|
||||
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||
- The SFP+ port supports 1G, 2.5G and 10G modules
|
||||
- LEDs work with the same indiciations as the OEM firmware (use KP_9000_6XHML_X2_V1_1 in machine.h if building yourself or the corresponding pre-compiled binary)
|
||||
- LEDs work with the same indiciations as the OEM firmware (build with `make MACHINE=KP_9000_6XHML_X2_V1_1` if building yourself, or use the corresponding pre-compiled binary)
|
||||
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
|
||||
|
||||
### Hardware overview
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
# MokerLink POE-2G080110GS
|
||||
|
||||
The `POE-2G080110GS` is an unmanaged 8x2.5G RJ45 and 1xSFP+ PoE switch sold by Mokerlink. There is also a `POE-2G080110GSM` managed version of the switch which may be similar but this has not been verified on actual hardware.
|
||||
The`KP-9000-9XHP-X` is the KeepLink rebrand for same product.
|
||||
|
||||
## Brands
|
||||
| Brand | Type |Managed| PCB | Flash | Chip RTL |
|
||||
|--------|------------------|-------|------------------|-----------------|---------------|
|
||||
| Mokerlink | POE-2G080110GS | No | 2M-PCB51-ML-V1.1 | 4MB (W25Q32JV) | 8373N + 8224N |
|
||||
| KeepLink | KP-9000-9XHP-X | No | 2M-PCB51-ML-V1.1 | 4MB (W25Q32JV) | 8373N + 8224N |
|
||||
|
||||
## Hardware overview
|
||||
Front
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# Hasivo S1100P-8GT-1SX-S
|
||||
|
||||
RTL8373N switch with 8 × 2.5G RJ45 ports and 1 × SFP port. GD25Q16 2 MiB flash.
|
||||
|
||||
## Port mapping
|
||||
|
||||
| Front port | ASIC MAC | Interface |
|
||||
| --- | --- | --- |
|
||||
| 1–8 | 0–7 | RJ45 |
|
||||
| 9 | 8 | SFP (SDS1) |
|
||||
|
||||
## Board signals
|
||||
|
||||
| Function | GPIO |
|
||||
| --- | --- |
|
||||
| SFP detect | 38 |
|
||||
| SFP LOS | 37 |
|
||||
| SFP TX disable | Not connected (`GPIO_NA`) |
|
||||
| SFP I2C SDA / SCL | 39 / 40 |
|
||||
| Reset | 54 |
|
||||
|
||||
PoE is managed by an RTL8238B and a separate STC8H8K64U controller, not directly by the RTL8373N. RTLPlayground does not control PoE on this board.
|
||||
|
||||
## Build
|
||||
|
||||
`make MACHINE=HASIVO_S1100P_8GT_1SX_S CI=1`
|
||||
|
||||
## Photos
|
||||
|
||||
Front panel:
|
||||
|
||||

|
||||
|
||||
PCB top:
|
||||
|
||||

|
||||
|
||||
PCB bottom:
|
||||
|
||||

|
||||
|
||||
@@ -90,6 +90,8 @@ Custom mapping for ONT-S207CW-62TS-SE:
|
||||
## Flashing Instructions
|
||||
|
||||
See the [README.md](../../README.md) for general flashing instructions.
|
||||
For compilation, use command `make MACHINE=ONT_S207CW_62TS_SE` to specify the machine.
|
||||
If you are using managed version of the switch, you can then also compile the installer and flash using GUI - run command `cd installer` and finally `make`.
|
||||
|
||||
## Stock Firmware Information
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# PCB-AFGW SWTG218ANS V2.0.2
|
||||
|
||||
RTL8373-based 8×2.5G PoE + 1×10G SFP+ web-managed switch, sold as the
|
||||
**RealHD PSW8-25MG**.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Manufacturer**: RealHD
|
||||
- **Model**: PSW8-25MG
|
||||
- **PCB marking**: `PCB-AFGW SWTG218ANS_V2.0.2` (silkscreened as `PCB-AFGW SWTG218ANS_V2.0.2_23308`)
|
||||
- **Ports**:
|
||||
- 8 × RJ45: 10/100/1000/2500 Mbps with PoE
|
||||
- 1 × SFP+: 1G / 2.5G / 10G (front panel marking `9(10G)`)
|
||||
- **Power input**: internal AC PSU, `100-240V~ 50/60Hz 2A MAX`, DC output `53.5V 2.8A 150W`
|
||||
- **Front panel LEDs**: `PWR`, `SYS`, per RJ45 port `Link/Act` and `PoE`, per SFP port 2.5G (green) and 10G (blue)
|
||||
- **Stock firmware defaults**: web-managed PoE switch
|
||||
|
||||
### What works
|
||||
|
||||
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps (PoE is not configurable via RTLPlayground)
|
||||
- SFP+ port supporting 1G, 2.5G and 10G modules
|
||||
- LEDs: green (2.5G) and amber (1G/100M/10M) per RJ45 port with activity, green (1G/2.5G) and blue (10G) on the SFP port, plus the `SYS` LED
|
||||
|
||||
### Photos
|
||||
|
||||
Front panel:
|
||||
|
||||
<img src="photos/PCB-AFGW_SWTG218ANS_V2.0.2/device_front.jpg" width="800" />
|
||||
|
||||
Board mounted in the case, with the internal PSU above it:
|
||||
|
||||
<img src="photos/PCB-AFGW_SWTG218ANS_V2.0.2/dev_top_w_pcb.jpg" width="800" />
|
||||
|
||||
### PCB overview
|
||||
|
||||
Top side:
|
||||
|
||||
<img src="photos/PCB-AFGW_SWTG218ANS_V2.0.2/pcb_front.jpg" width="800" />
|
||||
|
||||
Bottom side:
|
||||
|
||||
<img src="photos/PCB-AFGW_SWTG218ANS_V2.0.2/pcb_back.jpg" width="800" />
|
||||
|
||||
A 4-pad UART header with `RXD` / `TXD` silkscreened sits next to the right heatsink.
|
||||
|
||||
### Port layout
|
||||
|
||||
| Logical port | Physical port | Type |
|
||||
|--------------|---------------|--------|
|
||||
| 1-8 | 1-8 | RJ45 |
|
||||
| 9 | 9 | SFP+ |
|
||||
|
||||
### LED configuration
|
||||
|
||||
RJ45 ports use LED SET0, the SFP+ port uses LED SET1. The board needs the custom
|
||||
LED mux (`led_mux_custom = 1`), and `RTL837X_REG_LED_GLB_IO_EN` is written to
|
||||
`0x7f24977f` in `machine_custom_init()` so the LED pins are enabled as wired here.
|
||||
|
||||
| SET | LED pin 0 | LED pin 1 |
|
||||
|------|-----------------------------------------------|-------------------------------------------------------|
|
||||
| SET0 | Green — lights on 2.5G link with activity | Amber — lights on 1G / 100M / 10M link with activity |
|
||||
| SET1 | All speeds — lights on any link with activity | 10G — lights on 10G link with activity |
|
||||
|
||||
On the front panel this gives one bi-color `Link/Act` LED per RJ45 port (green at
|
||||
2.5G, amber at 10/100/1000M, blinking with activity) and one `PoE` LED per RJ45
|
||||
port, which is driven by the PoE hardware and not by the switch. The SFP+ port has
|
||||
a green 2.5G LED and a blue 10G LED.
|
||||
|
||||
### SFP GPIO assignments
|
||||
|
||||
| SFP (logical 9) | pin_detect (ModAbs) | pin_los | pin_tx_disable | SerDes | I2C SDA | I2C SCL |
|
||||
|-----------------|---------------------|---------|----------------|--------|------------------|----------------------|
|
||||
| SFP | GPIO38 | GPIO_NA | GPIO_NA | SDS1 | GPIO39_I2C_SDA4 | GPIO40_I2C_SCL3_MDC1 |
|
||||
|
||||
### Machine configuration
|
||||
|
||||
```
|
||||
make MACHINE=REALHD_PSW8_25MG
|
||||
```
|
||||
|
||||
### Programming
|
||||
|
||||
The serial console runs at 8N1 on 115200 baud with the RTLPlayground firmware
|
||||
(see the UART header note under *PCB overview*). The stock firmware baud rate 57600. The flash chip was 2MB.
|
||||
|
||||
### PoE
|
||||
|
||||
The 8 RJ45 ports support PoE, powered by the internal 150W AC PSU (DC output
|
||||
53.5V 2.8A) mounted above the main board.
|
||||
|
||||
Note: RTLPlayground does not provide PoE management for this board. The PoE
|
||||
hardware runs with its own configuration, the same as on the other PoE boards in
|
||||
this project.
|
||||
@@ -0,0 +1,72 @@
|
||||
# PCB-K0402WS-V1.0
|
||||
|
||||
This is the first revision of the PCB-K0402WS series of boards; it's very similar to 2.0 in terms of layout/wiring.
|
||||
|
||||
The board does have footprints for a VLAN modeswitch at the front and a second flash chip on the bottom of the PCB, but these have been seen to ship unpopulated.
|
||||
|
||||
### Brands
|
||||
|
||||
* YuanLey YS25-0402 <sup><sub>Note: there are [multiple revisions](PCB-K0402WS-V3.0.md) of the YS25-0402. This first revision lacks the "Vlan" switch cutout on the front of the enclosure.</sub></sup>
|
||||
|
||||
### Programming
|
||||
|
||||
Use a SOIC-8 clamp to the flash chip (U1 on silkscreen) at the top of the board, leaving it otherwise unpowered.
|
||||
|
||||
The board has been seen to ship with a single [BoyaMicro BY25Q16BSSIG](https://www.lcsc.com/datasheet/C382744.pdf) 16Mbit (2MiB) chip, though exact BOM may vary.
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/flash.jpg"><img src="photos/PCB-K0402WS-V1.0/flash.jpg" width="300" /></a>
|
||||
|
||||
### What works
|
||||
|
||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- Both SFP ports supporting 1G, 2.5G and 10G modules
|
||||
- LEDs (Power LED is always on)
|
||||
|
||||
### PCB overview
|
||||
|
||||
#### Board markings
|
||||
- Top silkscreen: PCB-K0402W-V1.0 / DIP-K0402WS-V1.0
|
||||
|
||||
#### Key components
|
||||
- U1: SPI NOR flash, 2 MiB
|
||||
- S1: unpopulated slide switch footprint (three through-holes used as serial console)
|
||||
|
||||
Front panel
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/ports.jpg"><img src="photos/PCB-K0402WS-V1.0/ports.jpg" width="300" /></a>
|
||||
|
||||
PCB top
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/pcb-top.jpg"><img src="photos/PCB-K0402WS-V1.0/pcb-top.jpg" width="300" /></a>
|
||||
|
||||
PCB bottom
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/pcb-bottom.jpg"><img src="photos/PCB-K0402WS-V1.0/pcb-bottom.jpg" width="300" /></a>
|
||||
|
||||
Bottom and rear
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/bottom.jpg"><img src="photos/PCB-K0402WS-V1.0/bottom.jpg" width="300" /></a>
|
||||
|
||||
### Power supply
|
||||
|
||||
Input power is delivered via a standard DC barrel jack (5.5x2.1mm) with an included 12V 1A adapter.
|
||||
|
||||
There is an optional grounding screw next to the DC input.
|
||||
|
||||
### Serial console
|
||||
|
||||
The PCB has a slide switch footprint (unpopulated) at the front right that is connected to the UART. It is labeled as "S1" on the silkscreen.
|
||||
|
||||
Facing the top front (port) side of the board, the pinout from left to right is:
|
||||
|
||||
| Position | Signal | GPIO |
|
||||
|----------|--------|-------------------|
|
||||
| 1 | RX | GPIO32\_UART0\_RX |
|
||||
| 2 | GND | N/A |
|
||||
| 3 | TX | GPIO31\_UART0\_TX |
|
||||
|
||||
Standard 0.1" / 2.54mm pin headers will not fit, so wires or clips may be used instead.
|
||||
|
||||
The image below shows some oversized clips clumsily attached.
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/uart.jpg"><img src="photos/PCB-K0402WS-V1.0/uart.jpg" width="300" /></a>
|
||||
@@ -19,9 +19,14 @@ of the device just above the big label, might be covered by a QC sticker.
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/Ztyuav_Z-QWYT0402_label.jpg" width="300" />
|
||||
|
||||
* Siscolink SL-G0402F
|
||||
* SICSOLINK SL-G0402F
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/SICSOLINK SL-G0402F.jpg" width="300"/>
|
||||
|
||||
* YuanLey YS25-0402 <sup><sub>Note: there are [multiple revisions](PCB-K0402WS-V1.0.md) of the YS25-0402. This is the newer revision that has a "Vlan" switch on the front.</sub></sup>
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/YuanLey_YS25-0402.jpg" width="300"/>
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/Siscolink SL-G0402F.jpg" width="300"/>
|
||||
### Programming
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
@@ -43,7 +48,7 @@ For the initial flash (at least with flashrom), the bin file produced by the bui
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-KO4022W-V3.0 / DIP-KO4022WS-V3.0
|
||||
- Top silkscreen: PCB-K0402W-V3.0 / DIP-K0402WS-V3.0
|
||||
|
||||
Top side
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
### SIRIVISION_S25G2206FP_V1_1
|
||||
|
||||
## Brands
|
||||
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|
|
||||
| YuanLey | YS25-0402M | Yes | SIRIVISION_S25G2206FP_V1_1 | 2M | 8372 |
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**:
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||
- **Power**: 12V DC, 1A 5525 connector
|
||||
|
||||
### What works
|
||||
The device is fully supported:
|
||||
- ALL 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||
- ALL SFP+ ports support 1G, 2.5G and 10G modules
|
||||
- LEDs work with the same indiciations as the OEM firmware
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: SIRIVISION S25G2206FP V1.1
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/SIRIVISION_S25G2206FP_V1_1/dev_pcb_top.jpg" width="300" />
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
@@ -4,7 +4,8 @@
|
||||
|---------|------------------|-------|------------------|-----------------|---------------|
|
||||
| Ampcom | SWTG018AS-A V2.0 | No | SWTG018AS-A V2.0 | 2MB | 8273N + 8224N |
|
||||
| Horaco | HC-SWTGW218AS-A | Yes | SWTG018AS-A V2.0 | 2MB(25Q16JVSIQ) | 8273N + 8224N |
|
||||
| GoodTop | GT-ST018M | Yes | SWTG018AS-A V2.0 | ? | 8273N + 8224N |
|
||||
| GoodTop | GT-ST018M | Yes | SWTG018AS-A V2.0 | 2MB | 8273N + 8224N |
|
||||
| MokerLink | 2G08110GSN | No | SWTG018AS-A V2.0 | 512KB(25Q40) | 8273N + 8224N |
|
||||
|
||||
|
||||
The following is a documentation for the unmanaged switch marked as `SWTG018AS-A V2.0`.
|
||||
@@ -14,7 +15,7 @@ The original software is running UART on 9600 baud rate.
|
||||
|
||||
Using a SOIC clamp in-board is the only method for initial installation.
|
||||
|
||||
The board has a single flash chips `BS` with 4M-bit size. The front switch, switches between the two flash chips.
|
||||
The board has a single flash chips `BS` with 2M-byte size. The front switch, switches between the two flash chips.
|
||||
These can be programed independently by using said switch - so it is e.g. possible to run the original and new firmware in parallel.
|
||||
|
||||
### Label specifications
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
It is highly similar to SWTG024AS-V2.0, with the only difference being the GPIO configuration for the SFP port.
|
||||
|
||||
## Brands
|
||||
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|
|
||||
| Horaco | ZX-SG4T2 | | PCB-SWTG024AS-A-V2.0.1_19650 | P25D40SH | ??? |
|
||||
|Brand |Type |Managed|PCB |Flash |Chip RTL|
|
||||
|---------|--------------|-------|------------------------------|----------------|--------|
|
||||
| Horaco | ZX-SG4T2 | No | PCB-SWTG024AS-A-V2.0.1_19650 | 512K (P25D40SH)| 8372N |
|
||||
| Horaco | HC-SWTG124AS | Yes | PCB-SWTG024AS-A-V2.0.1_19650 | 2M (W25Q16JV)| 8372N |
|
||||
| GoodTop | GT-ST024M | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M | 8372N |
|
||||
|
||||
### Label specifications
|
||||
|
||||
@@ -33,6 +35,8 @@ Bottom
|
||||
|
||||
<img src="photos/SWTG024AS-A-V2_0_1_19650/horaco-zx-sg4t2-pcb-bottom.jpg" width="300" />
|
||||
|
||||
On Horaco HC-SWTG124AS with board PCB-SWTG024AS-A-V2.0.1_19650 the reset button is soldered at `SW1` (on the top left, GPIO48).
|
||||
|
||||
### J1, serial console
|
||||
|
||||
| `J1` pin | Signal |
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
## RTLPlayground target
|
||||
|
||||
Use machine target `MACHINE_LIANGUO_ZX_SWTGW215AS` for this device.
|
||||
Build for this device with `make MACHINE=LIANGUO_ZX_SWTGW215AS`, which selects the `machine/LIANGUO_ZX_SWTGW215AS.c` board definition.
|
||||
|
||||
Physical hardware verification: 5x RJ45 ports + 1x SFP port.
|
||||
Port 5 RJ45 is interfaced through a RTL8221B IC.
|
||||
|
||||
@@ -5,9 +5,15 @@
|
||||
|---|---|---|---|---|---|
|
||||
| Mokerlink | ZX-SWTGW218AS | Yes| SWTG118AS-V2.0-16029 | 2MB (FM25Q16A)| 8273N + 8224N |
|
||||
| Sodola | | | | | |
|
||||
| Horaco | | | | | |
|
||||
| Horaco | HC-SWTGW218AS | Yes | SWTG118AS-V2.1 | 2MB | 8373 (non-N) |
|
||||
| XikeStor | SKS3200-8E1X | Yes | SWTG118AS-V2.1-17462 | 2MB (25Q16JVSIQ) | |
|
||||
|
||||
All boards in this table use `MACHINE=SWTGW218AS`. The Horaco HC-SWTGW218AS is also sold with the
|
||||
[SWTG018AS-A V2.0](SWTG018AS_A_V2_0.md) board, which needs a different firmware. Check the marking
|
||||
on the PCB before flashing.
|
||||
|
||||
The PHY and flash-chip models for the tested Horaco units remain unverified.
|
||||
|
||||
|
||||
## Photos
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
### HG0402XG V1.1
|
||||
|
||||
## Brands
|
||||
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|
|
||||
| ZoeRax | HG0402XG | No| HG0402XG V1.1 | 1M (Winbond 25Q) | |
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**: ZOERAX 2.5G 2SFP 4-Port Gigabit Switch
|
||||
- **Model**: HG0402XG-EU
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||
<img src="photos/HG0402XG_V1_1/HG0402XG_V1_1_bottom.jpg" width="300" />
|
||||
|
||||
## PCB
|
||||
|
||||
<img src="photos/HG0402XG_V1_1/HG0402XG_V1_1_top.jpg" width="300" />
|
||||
<img src="photos/HG0402XG_V1_1/HG0402XG_V1_1_bottom.jpg" width="300" />
|
||||
|
||||
Be aware that the UART header is metric, the pitch is 2mm. The JST PH2.0mm header shown was addeded after purchase
|
||||
|
||||
The slider switch controls microcontroller U4 in order to configure the VLAN on/off settings. U4 can reset the SoC
|
||||
and also write into its registers to configure VLAN. With RTLPlayground the slider cannot be used for anything else
|
||||
than triggering reset. Any change in the position will trigger this reset.
|
||||
|
||||
### Installation
|
||||
|
||||
Using SPI clamp on-board is the only method for initial installation.
|
||||
|
||||
### What works
|
||||
|
||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- SFP ports with various 1G/10G Fiber and Ethernet modules
|
||||
- LEDs
|
||||
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 234 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 434 KiB |
|
After Width: | Height: | Size: 565 KiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 3.6 MiB |
|
After Width: | Height: | Size: 2.8 MiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 262 KiB |
|
After Width: | Height: | Size: 4.0 MiB |
|
After Width: | Height: | Size: 469 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 944 KiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 229 KiB |
|
After Width: | Height: | Size: 804 KiB |
|
After Width: | Height: | Size: 1.7 MiB |
@@ -14,6 +14,7 @@ rx max 00 slow 0x0000
|
||||
tx max 00 slow 0x0000
|
||||
stp max 04 slow 0x0001
|
||||
cmd max 02 slow 0x0001
|
||||
lldp max 00 slow 0x0000
|
||||
sp 80 untouched 62
|
||||
tcp st 00 tmr 00 rtx 00 rto 00 len 0x0000 mss 0x05b4
|
||||
lport 0x0000 rport 0x0000 rip 0x0000 0x0000
|
||||
@@ -46,7 +47,7 @@ a flooded CPU port from a stalled loop, which look identical from outside.
|
||||
## Phases
|
||||
|
||||
Each line is one section of the main loop: the link poll, SFP handling,
|
||||
frame reception, TCP transmission, the STP timers and the command dispatch.
|
||||
frame reception, TCP transmission, the STP timers, the LLDP timer and the command dispatch.
|
||||
`max` is the worst time that section has taken, in ticks of 5 ms; `slow`
|
||||
counts the passes that took two ticks or more. A misbehaving subsystem
|
||||
names itself here, which is the difference between knowing that the loop is
|
||||
|
||||
@@ -4,44 +4,55 @@ The following devices have been tested and are fully working:
|
||||
| Brand | Type | Managed | PCB | Flash | Ports |
|
||||
|----------|-----------------|---------|---------------------------------------------------------------------------|-------|-------|
|
||||
| Ampcom | WAM902-SWTG018AS| No | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | | 8 + 1 |
|
||||
| Binardat | 2G06-04210GSM | No | [PCB-SWTG024AS-A-2.0.1](devices/ONT-S207CW-62TS-SE.md) | 0.5M | 4 + 2 |
|
||||
| Davuaz | Da-K6501W | No | [PCB-K0501W-V2.0](devices/K0501W_V2_0.md) | | 5 + 1 |
|
||||
| FOXNEO | FNS-1200P | No | [PCB-K0402W-U13-V2.0](devices/FNS-1200P.md) | 2M | 4 + 2 |
|
||||
| Goalake | IG108 | No | [PB-2132](devices/PB-2132.md) | 4M | 8 + 1 |
|
||||
| GoodTop | GT-ST018M | Yes | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | ? | 8 + 1 |
|
||||
| GoodTop | GT-ST018M | Yes | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | 2M | 8 + 1 |
|
||||
| GoodTop | GT-ST024M | Yes | [SWTG024AS-A V2.0.1](devices/SWTG024AS-A-V2.0.1_4C_2SFP.md) | 2M | 4 + 2 |
|
||||
| Guangnianwei | 7018-2.5G | No | [F7008-2.5GPOE-V1.2](devices/F7008-2.5.md) | 8M | 8 + 1 |
|
||||
| Hasivo | S1100WP_8GT_1SX_SE | Yes | [S1100WP_8GT_1SX_SE-V1.05](devices/HASIVO_S1100WP_8GT_1SX_SE.md) | 2M | 8 + 1 |
|
||||
| Hisource | Hi-K0402WS | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
|
||||
| Hisource | Hi-K0402WS | No | [PCB-K0402WS-V2.0](devices/PCB-K0402WS-V2.0.md) | 2M | 4 + 2 |
|
||||
| Hisource | Hi-K0402WS | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
|
||||
| Hisource | Hi-K0801WS | No | [PCB-KO801W-V2.0](devices/HI-K0801WS.md) | | 8 + 1 |
|
||||
| hongyavision | HYWS-SGT0204S | No | [2G5F4_10G2_V1.01](devices/2G5F4_10G2_V1.01.md) | 0.5M | 4 + 2 |
|
||||
| hongyavision | LG-SG5T1 | No | [PCB-SWTG024AS-V2.0_16895](devices/SWTG024AS-V2.0.md) | 0.5M | 5 + 1 |
|
||||
| Horaco | HC-SWTG124AS | Yes | [SWTG024AS-A-V2.0.1](devices/SWTG024AS-A-V2.0.1_4C_2SFP.md) | 2M | 4 + 2 |
|
||||
| Horaco | HC-SWTGW215AS | Yes | [SWTG024AS-A-V2.0.1_19650 5C 1SFP](devices/SWTG024AS-A-V2.0.1_5C_1SFP.md) | ? | 5 + 1 |
|
||||
| Horaco | HC-SWTGW218AS | Yes | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | | 8 + 1 |
|
||||
| Horaco | HC-SWTGW218AS | Yes | [SWTG118AS-V2.1](devices/SWTGW218AS.md) | 2M | 8 + 1 |
|
||||
| Horaco | ZX310S-4T2XH | Yes | [PCB-SL310S-4T1T1X-V1.0.1-24107](devices/ZX310S-4T2XH.md) | 2M | 5 + 1 |
|
||||
| Horaco | ZX310S-4T2XT | Yes | [PCB-SL310S-4T2XT-V1.0.0-22273](devices/ZX310S-4T2XT.md) | 2M | 6 |
|
||||
| Horaco | ZX-SG4T2 | No | [SWTG024AS-A-V2.0.1_19650_4C_2SFP](devices/SWTG024AS-A-V2.0.1_4C_2SFP.md) | 0.5M | 4 + 2 |
|
||||
| Horaco | ZX-SWTG124AS | Yes | [SWTG024AS-v2.0](devices/SWTG024AS.md) | | 4 + 2 |
|
||||
| Keeplink | KP-9000-6XH-X2 / KP-9000-6XHML-X2 | No/Yes | [2M-PCB43-V1.2 / V2.1](devices/KP-9000-6XH-X2.md) | | 4 + 2 |
|
||||
| keepLINK | KP-9000-6XH-X2 / KP-9000-6XHML-X2 | No/Yes | [2M-PCB43-V1.2 / V2.1](devices/KP-9000-6XH-X2.md) | | 4 + 2 |
|
||||
| keepLINK | KP-9000-9XHML-X | Yes | [2M-PCB23-V2.2](devices/2M-PCB23-V2_2.md) | 2M | 8 + 1 |
|
||||
| keepLINK | KP-9000-9XHML-X | Yes | [2M-PCB23-V3.1](devices/2M-PCB23-V3_1.md) | 2M | 8 + 1 |
|
||||
| keepLINK | KP-9000-9XHML-X | Yes | [2M-PCB23-V3.2](devices/2M-PCB23-V3_2.md) | 2M | 8 + 1 |
|
||||
| keepLINK | KP-9000-9XHP-X | No | [2M-PCB51-ML-V1.1](devices/2M-PCB51-ML-V1_1.md) | 4M | 8 + 1 |
|
||||
| LIANGUO | HYWS-SGT0108S | No | [2G5F_20G_V1.01](devices/HYWS-SGT0108S.md) | 0.5M | 8 + 1 |
|
||||
| LIANGUO | SWTG024AS | No | [SWTG024AS-v2.0-17452](devices/SWTG024AS.md) | 0.5M | 4 + 2 |
|
||||
| Lianguo | ZX-SWTGW215AS | Yes | [PCB-SWTG115AS-V2.0 / PCB-SWTG115AS-V2.1](devices/SWTGW215AS.md) | 2M | 5 + 1 |
|
||||
| Lianguo | HYWS-SGT0108S | No | [2G5F_20G_V1.01](devices/HYWS-SGT0108S.md) | 0.5M | 8 + 1 |
|
||||
| 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 |
|
||||
| LIANGUO | ZX-SWTGW215AS | Yes | [PCB-SWTG115AS-V2.0 / PCB-SWTG115AS-V2.1](devices/SWTGW215AS.md) | 2M | 5 + 1 |
|
||||
| MokerLink| 2G040210GSM | Yes | [2M-PCB43-V1.1](devices/2M-PCB43-V1.1.md) | | 4 + 2 |
|
||||
| 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 |
|
||||
| MokerLink| ZX-SWTGW218AS | Yes | [SWTG118AS-V2.0-16029](devices/SWTGW218AS.md) | 2M | 8 + 1 |
|
||||
| MokerLink| 2G08110GSN | No | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | 0.5M | 8 + 1 |
|
||||
| Netcore | GS9 | No | [PB-2132](devices/PB-2132.md) | 4M | 8 + 1 |
|
||||
| ONT | ONT-S207CW-62TS-SE | No | [PCB-SWTG024AS-A-2.0.1](devices/ONT-S207CW-62TS-SE.md) | 0.5M | 4 + 2 |
|
||||
| RealHD | PSW8-25MG | Yes | [PCB-AFGW SWTG218ANS V2.0.2](devices/PCB-AFGW_SWTG218ANS_V2.0.2.md) | 2M | 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 |
|
||||
| SiscoLink | SL-G0402F | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
|
||||
| SICSOLINK| SL-G0402F | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
|
||||
| Sodola | SL-SWTG124AS-D | Yes | [SWTG024AS-v2.0-17452](devices/SWTG024AS.md) | 2M | 4 + 2 |
|
||||
| Steamemo | IG204-V1 | No | [PB-2131](devices/STEAMEMO_IG204_V1.md) | | 4 + 2 |
|
||||
| TrendNet | TEG-S562 | No | [TEG-S563/EU H/W: V1.0R](devices/TEG-S562.md) | 2M | 4 + 2 |
|
||||
| Xikestore| SKS3200M-4GPY2XF| Yes | [SWTG024AS-v1.0](devices/SWTG024AS.md) | | 4 + 2 |
|
||||
| TRENDnet | TEG-S562 | No | [TEG-S563/EU H/W: V1.0R](devices/TEG-S562.md) | 2M | 4 + 2 |
|
||||
| XikeStor | SKS3200M-4GPY2XF| Yes | [SWTG024AS-v1.0](devices/SWTG024AS.md) | | 4 + 2 |
|
||||
| XikeStor | SKS3200-8E1X | Yes | [SWTG118AS-V2.1-17462](devices/SWTGW218AS.md) | 2M | 8 + 1 |
|
||||
| YuanLey | YS25-0402 | No | [PCB-K0402WS-V1.0](devices/PCB-K0402WS-V1.0.md) | 2M | 4 + 2 |
|
||||
| YuanLey | YS25-0402 | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | 2M | 4 + 2 |
|
||||
| YuanLey | YS25-0402M | Yes | [SIRIVISION_S25G2206FP_V1_1](devices/SIRIVISION_S25G2206FP_V1_1.md) | 2M | 4 + 2 |
|
||||
| Ztyuav | Z-QWYT0402 | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
|
||||
| Guangnianwei | 7018-2.5G | No | [F7008-2.5GPOE-V1.2](devices/F7008-2.5.md) | 8M | 8 + 1 |
|
||||
| ZoeRax | HG0402XG | No | [HG0402XG_V1.1](devices/ZOERAX_HG0402XG_V1.1.md) | 1M | 4 + 2 |
|
||||
|
||||
For KP-9000-6XH-X2 / KP-9000-6XHML-X2 / Mokerlink 2G040210GSM devices, select
|
||||
the machine target by PCB revision. The ML/non-ML or managed/unmanaged label
|
||||
|
||||
@@ -79,8 +79,11 @@ JSON polling of the visible section).
|
||||
computation no longer depends on uninitialised buffer content.
|
||||
- `version.h` is now written by a single atomic `printf` (change from
|
||||
upstream) instead of five separate `echo`s, so a parallel build
|
||||
(`make -j`) can no longer read a half-written copy. It stays in
|
||||
`.PHONY` so it is regenerated on every build.
|
||||
(`make -j`) can no longer read a half-written copy. It depends on
|
||||
`FORCE`, so its recipe runs on every build, but the file is only
|
||||
rewritten when its content changes. The minified copy in
|
||||
`output/html_min/` is redone only when a web file, the list of web
|
||||
files or `tools/minify.py` changes.
|
||||
|
||||
## Verification
|
||||
|
||||
|
||||
@@ -11,15 +11,15 @@ th_sel_light:"Selenized Light",th_sel_dark:"Selenized Dark",
|
||||
c_port:"Port",c_name:"Name",c_link:"Link",c_apply:"Apply",c_cancel:"Cancel",c_confirm:"Confirm",
|
||||
c_close:"Close",c_refresh:"Refresh",c_off:"off",c_offc:"Off",c_down:"down",c_on:"On",c_auto:"Auto",c_delete:"Delete",
|
||||
c_type:"Type",c_state:"State",c_enabled:"Enabled",c_load:"Load",c_disable:"Disable",c_sfp:"SFP",
|
||||
c_full:"full",c_half:"half",c_devices:"devices",c_yes:"yes",c_no:"no",
|
||||
d_ports:"Ports",d_ports_h:"click a port for details",d_system:"System",d_traffic:"Traffic",
|
||||
c_full:"full",c_half:"half",c_yes:"yes",c_no:"no",
|
||||
d_system:"System",d_traffic:"Traffic",
|
||||
d_traffic_h:"packets/s, live",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX bad",d_rxbad:"RX bad",
|
||||
i_host:"Hostname",i_ip:"IP address",i_mask:"Netmask",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware",
|
||||
i_built:"Built",i_hw:"Hardware",i_temp:"Temperature",i_flash:"Flash",i_syslog:"Syslog",
|
||||
p_state:"State",p_disabled:"disabled",p_up:"up",p_txgb:"TX good / bad",p_rxgb:"RX good / bad",
|
||||
p_state:"State",p_disabled:"disabled",p_up:"up",
|
||||
p_pkts:"pkts",p_module:"Module",p_temp:"Temperature",p_vcc:"Vcc",p_txbias:"TX bias",p_txpower:"TX power",
|
||||
p_rxpower:"RX power",p_txfault:"TX fault",p_txdis:"TX disabled",p_rxlos:"RX LOS",p_adv:"Advertising",
|
||||
pt_title:"Port configuration",pt_conn:"Connected",pt_speed:"Speed",pt_mtu:"MTU",
|
||||
pt_title:"Port configuration",pt_conn:"Devices learned",pt_speed:"Speed",pt_mtu:"MTU",
|
||||
pt_sfp_note:"SFP speed is set per slot and is not saved in the startup config.",
|
||||
pt_name_err:"Port name: 1-15 characters, no spaces",pt_mtu_err:"MTU must be 64-16383",
|
||||
stp_title:"Spanning tree",stp_h:"RSTP, 802.1w",stp_version:"Version",stp_v_stp:"STP compatible",
|
||||
@@ -44,20 +44,19 @@ lldp_enabled: "LLDP Enabled",lldp_title:"Service Status",lldp_portname:"Name",ll
|
||||
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",
|
||||
v_title:"VLANs",v_vid:"VID",v_members:"Members",v_tagged:"Tagged",v_untagged:"Untagged",v_pvid_on:"PVID on",
|
||||
v_title:"VLANs",v_vid:"VLAN ID",v_members:"Members",v_tagged:"Tagged",v_untagged:"Untagged",v_pvid_on:"PVID on",
|
||||
v_empty:"No VLANs configured.",v_mgmt:"Management VLAN",v_mgmt_none:"untagged",v_editor:"VLAN editor",
|
||||
v_optional:"optional",v_setmgmt:"Set as mgmt VLAN",v_setmgmt_t:"Make this the management VLAN",
|
||||
v_member:"Member",v_pvid:"PVID",
|
||||
v_legend:"U = untagged member, T = tagged member, - = not a member. PVID assigns this VLAN to untagged ingress traffic.",
|
||||
v_ingress:"Ingress filtering",v_ingress_h:"write-only: the state is not readable from the switch",
|
||||
v_accept:"Accept",v_ing_all:"All",v_ing_apply:"Apply ingress modes",v_del_t:"Delete VLAN",
|
||||
v_optional:"optional",v_setmgmt_q:"Set {n} as the management ID?",v_setmgmt_t:"Management VLAN",
|
||||
v_member:"Member",v_pvid:"PVID",v_add:"Add a new VLAN", v_mgmt_c:"WARNING: You must be able to access this VLAN to continue to manage the switch.",
|
||||
v_legend:"U = untagged member, T = tagged member, - = not a member. PVID is automatically assigned based on the untagged membership.",
|
||||
v_accept:"Accept",v_ing_all:"All",v_del_t:"Delete VLAN",v_rename:"Rename",v_rename_t:"Rename VLAN",
|
||||
v_del_q:"Delete VLAN {n}?",v_del_d:"Ports keep their PVID until reassigned.",
|
||||
v_vid_err:"Enter a VLAN ID (1-4094)",v_name_err:"Name must start with a letter (letters, digits, _)",
|
||||
v_vid_err:"Enter a VLAN ID (1-4094)",v_name_err:"Name must start with a letter (letters, digits, _) and cannot be just 'd' or 'mgmt'",
|
||||
v_loaded:"Loaded VLAN {n}",v_notfound:"VLAN {n} not found (a new one can still be created)",
|
||||
v_nomember:"Select at least one member port (or delete the VLAN instead)",
|
||||
v_ing_none:"Pick an ingress mode for at least one port",v_vid_first:"Enter a VLAN ID first",
|
||||
v_mgmt_q:"Set VLAN {n} as management VLAN?",
|
||||
v_nomember:"Select at least one member port (or delete the VLAN instead)",v_vid_first:"Enter a VLAN ID first",
|
||||
v_mgmt_q:"Set VLAN {n} as management VLAN?",v_vid_err:"VLAN ID already exists",
|
||||
v_mgmt_d:"The switch will start tagging its own traffic with that VLAN. If the port you are connected through does not carry it, this page becomes unreachable and the setting can only be undone over the console.",
|
||||
v_mgmt_tt:"The management VLAN cannot be deleted, you need to assign management to another VLAN first.",
|
||||
l2_title:"MAC address table",l2_filter:"filter...",l2_flush:"Flush learned entries",l2_static:"static",
|
||||
l2_learned:"learned",l2_loading:"loading...",l2_failed:"load failed",l2_entries:"entries",
|
||||
l2_del_t:"Delete entry",l2_flush_q:"Flush all learned MAC entries?",
|
||||
@@ -142,15 +141,15 @@ th_sel_light:"Selenized ライト",th_sel_dark:"Selenized ダーク",
|
||||
c_port:"ポート",c_name:"名前",c_link:"リンク",c_apply:"適用",c_cancel:"キャンセル",c_confirm:"確認",
|
||||
c_close:"閉じる",c_refresh:"更新",c_off:"オフ",c_offc:"オフ",c_down:"リンクダウン",c_on:"オン",c_auto:"自動",c_delete:"削除",
|
||||
c_type:"タイプ",c_state:"状態",c_enabled:"有効",c_load:"読み込み",c_disable:"無効化",c_sfp:"SFP",
|
||||
c_full:"全二重",c_half:"半二重",c_devices:"デバイス",c_yes:"はい",c_no:"いいえ",
|
||||
d_ports:"ポート",d_ports_h:"ポートをクリックすると詳細を表示",d_system:"システム",d_traffic:"トラフィック",
|
||||
c_full:"全二重",c_half:"半二重",c_yes:"はい",c_no:"いいえ",
|
||||
d_system:"システム",d_traffic:"トラフィック",
|
||||
d_traffic_h:"パケット/秒、リアルタイム",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 異常",d_rxbad:"RX 異常",
|
||||
i_host:"ホスト名",i_ip:"IP アドレス",i_mask:"ネットマスク",i_gw:"ゲートウェイ",i_mac:"MAC",i_fw:"ファームウェア",
|
||||
i_built:"ビルド日",i_hw:"ハードウェア",i_temp:"温度",i_flash:"フラッシュ",i_syslog:"Syslog",
|
||||
p_state:"状態",p_disabled:"無効",p_up:"アップ",p_txgb:"TX 正常 / 異常",p_rxgb:"RX 正常 / 異常",
|
||||
p_state:"状態",p_disabled:"無効",p_up:"アップ",
|
||||
p_pkts:"pkts",p_module:"モジュール",p_temp:"温度",p_vcc:"電圧",p_txbias:"TX バイアス",p_txpower:"TX 電力",
|
||||
p_rxpower:"RX 電力",p_txfault:"TX 障害",p_txdis:"TX 無効",p_rxlos:"RX 信号ロス",p_adv:"アドバタイズ",
|
||||
pt_title:"ポート設定",pt_conn:"接続デバイス",pt_speed:"速度",pt_mtu:"MTU",
|
||||
pt_title:"ポート設定",pt_conn:"学習済みデバイス",pt_speed:"速度",pt_mtu:"MTU",
|
||||
pt_sfp_note:"SFP の速度はスロット単位で設定され、起動設定には保存されません。",
|
||||
pt_name_err:"ポート名: 1〜15 文字、空白不可",pt_mtu_err:"MTU は 64〜16383 の範囲で指定してください",
|
||||
stp_title:"スパニングツリー",stp_h:"RSTP, 802.1w",stp_version:"バージョン",stp_v_stp:"STP 互換",
|
||||
@@ -179,14 +178,12 @@ v_empty:"VLAN は設定されていません。",v_mgmt:"管理 VLAN",v_mgmt_non
|
||||
v_optional:"任意",v_setmgmt:"管理 VLAN に設定",v_setmgmt_t:"この VLAN を管理 VLAN にする",
|
||||
v_member:"メンバー",v_pvid:"PVID",
|
||||
v_legend:"U = タグ無しメンバー、T = タグ付きメンバー、- = 非メンバー。PVID はタグ無し受信トラフィックをこの VLAN に割り当てます。",
|
||||
v_ingress:"受信フィルタ",v_ingress_h:"書き込み専用: 現在の状態はスイッチから読み取れません",
|
||||
v_accept:"受け入れ",v_ing_all:"すべて",v_ing_apply:"受信モードを適用",v_del_t:"VLAN を削除",
|
||||
v_del_q:"VLAN {n} を削除しますか?",v_del_d:"ポートの PVID は再割り当てされるまで維持されます。",
|
||||
v_vid_err:"VLAN ID (1〜4094) を入力してください",v_name_err:"名前は英字で始めてください (英字、数字、_)",
|
||||
v_loaded:"VLAN {n} を読み込みました",v_notfound:"VLAN {n} は存在しません (新規作成は可能です)",
|
||||
v_nomember:"メンバーポートを 1 つ以上選択してください (または VLAN を削除してください)",
|
||||
v_ing_none:"1 つ以上のポートの受信モードを選択してください",v_vid_first:"先に VLAN ID を入力してください",
|
||||
v_mgmt_q:"VLAN {n} を管理 VLAN に設定しますか?",
|
||||
v_vid_first:"先に VLAN ID を入力してください",v_mgmt_q:"VLAN {n} を管理 VLAN に設定しますか?",
|
||||
v_mgmt_d:"スイッチは自身のトラフィックにこの VLAN のタグを付けるようになります。接続中のポートがこの VLAN を通さない場合、このページにアクセスできなくなり、コンソールからしか元に戻せません。",
|
||||
l2_title:"MAC アドレステーブル",l2_filter:"フィルタ...",l2_flush:"学習エントリを消去",l2_static:"静的",
|
||||
l2_learned:"学習",l2_loading:"読み込み中...",l2_failed:"読み込み失敗",l2_entries:"エントリ",
|
||||
@@ -255,15 +252,15 @@ th_sel_light:"Selenized 浅色",th_sel_dark:"Selenized 深色",
|
||||
c_port:"端口",c_name:"名称",c_link:"链路",c_apply:"应用",c_cancel:"取消",c_confirm:"确认",
|
||||
c_close:"关闭",c_refresh:"刷新",c_off:"关",c_offc:"关",c_down:"未连接",c_on:"开",c_auto:"自动",c_delete:"删除",
|
||||
c_type:"类型",c_state:"状态",c_enabled:"启用",c_load:"读取",c_disable:"禁用",c_sfp:"SFP",
|
||||
c_full:"全双工",c_half:"半双工",c_devices:"台设备",c_yes:"是",c_no:"否",
|
||||
d_ports:"端口",d_ports_h:"点击端口查看详情",d_system:"系统",d_traffic:"流量",
|
||||
c_full:"全双工",c_half:"半双工",c_yes:"是",c_no:"否",
|
||||
d_system:"系统",d_traffic:"流量",
|
||||
d_traffic_h:"包/秒,实时",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 错误",d_rxbad:"RX 错误",
|
||||
i_host:"主机名",i_ip:"IP 地址",i_mask:"子网掩码",i_gw:"网关",i_mac:"MAC",i_fw:"固件",
|
||||
i_built:"构建日期",i_hw:"硬件",i_temp:"温度",i_flash:"Flash",i_syslog:"Syslog",
|
||||
p_state:"状态",p_disabled:"已禁用",p_up:"已连接",p_txgb:"TX 正常 / 错误",p_rxgb:"RX 正常 / 错误",
|
||||
p_state:"状态",p_disabled:"已禁用",p_up:"已连接",
|
||||
p_pkts:"个包",p_module:"模块",p_temp:"温度",p_vcc:"供电电压",p_txbias:"TX 偏置电流",p_txpower:"TX 光功率",
|
||||
p_rxpower:"RX 光功率",p_txfault:"TX 故障",p_txdis:"TX 禁用",p_rxlos:"RX 信号丢失",p_adv:"通告能力",
|
||||
pt_title:"端口配置",pt_conn:"已连接设备",pt_speed:"速率",pt_mtu:"MTU",
|
||||
pt_title:"端口配置",pt_conn:"已学习设备",pt_speed:"速率",pt_mtu:"MTU",
|
||||
pt_sfp_note:"SFP 速率按插槽设置,不会保存到启动配置。",
|
||||
pt_name_err:"端口名称: 1-15 个字符,不能包含空格",pt_mtu_err:"MTU 范围为 64-16383",
|
||||
stp_title:"生成树",stp_h:"RSTP, 802.1w",stp_version:"版本",stp_v_stp:"STP 兼容",
|
||||
@@ -292,14 +289,12 @@ v_empty:"尚未配置 VLAN。",v_mgmt:"管理 VLAN",v_mgmt_none:"untagged",v_edi
|
||||
v_optional:"可选",v_setmgmt:"设为管理 VLAN",v_setmgmt_t:"将此 VLAN 设为管理 VLAN",
|
||||
v_member:"成员",v_pvid:"PVID",
|
||||
v_legend:"U = untagged 成员,T = tagged 成员,- = 非成员。PVID 将入方向的未标记流量归入此 VLAN。",
|
||||
v_ingress:"入方向过滤",v_ingress_h:"只写: 当前状态无法从交换机读取",
|
||||
v_accept:"接受",v_ing_all:"全部",v_ing_apply:"应用入方向模式",v_del_t:"删除 VLAN",
|
||||
v_del_q:"删除 VLAN {n}?",v_del_d:"端口的 PVID 在重新分配前保持不变。",
|
||||
v_vid_err:"请输入 VLAN ID (1-4094)",v_name_err:"名称必须以字母开头 (字母、数字、_)",
|
||||
v_loaded:"已读取 VLAN {n}",v_notfound:"VLAN {n} 不存在 (仍可新建)",
|
||||
v_nomember:"请至少选择一个成员端口 (或改为删除该 VLAN)",
|
||||
v_ing_none:"请至少为一个端口选择入方向模式",v_vid_first:"请先输入 VLAN ID",
|
||||
v_mgmt_q:"将 VLAN {n} 设为管理 VLAN?",
|
||||
v_vid_first:"请先输入 VLAN ID",v_mgmt_q:"将 VLAN {n} 设为管理 VLAN?",
|
||||
v_mgmt_d:"交换机将开始为自身流量打上该 VLAN 标签。如果您所连接的端口不属于该 VLAN,本页面将无法访问,且只能通过控制台撤销此设置。",
|
||||
l2_title:"MAC 地址表",l2_filter:"筛选...",l2_flush:"清除学习条目",l2_static:"静态",
|
||||
l2_learned:"动态学习",l2_loading:"加载中...",l2_failed:"加载失败",l2_entries:"条",
|
||||
@@ -368,15 +363,15 @@ th_sel_light:"Selenized claro",th_sel_dark:"Selenized oscuro",
|
||||
c_port:"Puerto",c_name:"Nombre",c_link:"Enlace",c_apply:"Aplicar",c_cancel:"Cancelar",c_confirm:"Confirmar",
|
||||
c_close:"Cerrar",c_refresh:"Actualizar",c_off:"apagado",c_offc:"Apagado",c_down:"caído",c_on:"Encendido",c_auto:"Auto",c_delete:"Eliminar",
|
||||
c_type:"Tipo",c_state:"Estado",c_enabled:"Habilitado",c_load:"Cargar",c_disable:"Deshabilitar",c_sfp:"SFP",
|
||||
c_full:"dúplex completo",c_half:"semidúplex",c_devices:"dispositivos",c_yes:"sí",c_no:"no",
|
||||
d_ports:"Puertos",d_ports_h:"pulsa un puerto para ver detalles",d_system:"Sistema",d_traffic:"Tráfico",
|
||||
c_full:"dúplex completo",c_half:"semidúplex",c_yes:"sí",c_no:"no",
|
||||
d_system:"Sistema",d_traffic:"Tráfico",
|
||||
d_traffic_h:"paquetes/s, en vivo",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX erróneos",d_rxbad:"RX erróneos",
|
||||
i_host:"Nombre de host",i_ip:"Dirección IP",i_mask:"Máscara de red",i_gw:"Puerta de enlace",i_mac:"MAC",i_fw:"Firmware",
|
||||
i_built:"Compilado",i_hw:"Hardware",i_flash:"Flash",i_syslog:"Syslog",
|
||||
p_state:"Estado",p_disabled:"deshabilitado",p_up:"activo",p_txgb:"TX correctos / erróneos",p_rxgb:"RX correctos / erróneos",
|
||||
p_state:"Estado",p_disabled:"deshabilitado",p_up:"activo",
|
||||
p_pkts:"paquetes",p_module:"Módulo",p_temp:"Temperatura",p_vcc:"Vcc",p_txbias:"Polarización TX",p_txpower:"Potencia TX",
|
||||
p_rxpower:"Potencia RX",p_txfault:"Fallo TX",p_txdis:"TX deshabilitado",p_rxlos:"Pérdida RX (LOS)",p_adv:"Anunciado",
|
||||
pt_title:"Configuración de puerto",pt_conn:"Conectado",pt_speed:"Velocidad",pt_mtu:"MTU",
|
||||
pt_title:"Configuración de puerto",pt_conn:"Dispositivos aprendidos",pt_speed:"Velocidad",pt_mtu:"MTU",
|
||||
pt_sfp_note:"La velocidad del SFP se ajusta por ranura y no se guarda en la configuración de inicio.",
|
||||
pt_name_err:"Nombre de puerto: 1-15 caracteres, sin espacios",pt_mtu_err:"El MTU debe estar entre 64 y 16383",
|
||||
stp_title:"Árbol de expansión",stp_h:"RSTP, 802.1w",stp_version:"Versión",stp_v_stp:"STP compatible",
|
||||
@@ -405,14 +400,12 @@ v_empty:"No hay VLANs configuradas.",v_mgmt:"VLAN de gestión",v_mgmt_none:"sin
|
||||
v_optional:"opcional",v_setmgmt:"Establecer como VLAN de gestión",v_setmgmt_t:"Hacer esta la VLAN de gestión",
|
||||
v_member:"Miembro",v_pvid:"PVID",
|
||||
v_legend:"U = miembro sin etiquetar, T = miembro etiquetado, - = no miembro. PVID asigna esta VLAN al tráfico entrante sin etiquetar.",
|
||||
v_ingress:"Filtrado de entrada",v_ingress_h:"solo escritura: el estado no se puede leer desde el switch",
|
||||
v_accept:"Aceptar",v_ing_all:"Todos",v_ing_apply:"Aplicar modos de entrada",v_del_t:"Eliminar VLAN",
|
||||
v_del_q:"¿Eliminar VLAN {n}?",v_del_d:"Los puertos conservan su PVID hasta que se reasignen.",
|
||||
v_vid_err:"Introduce un ID de VLAN (1-4094)",v_name_err:"El nombre debe empezar por una letra (letras, dígitos, _)",
|
||||
v_loaded:"VLAN {n} cargada",v_notfound:"VLAN {n} no encontrada (aún se puede crear una nueva)",
|
||||
v_nomember:"Selecciona al menos un puerto miembro (o elimina la VLAN)",
|
||||
v_ing_none:"Elige un modo de entrada para al menos un puerto",v_vid_first:"Introduce primero un ID de VLAN",
|
||||
v_mgmt_q:"¿Establecer VLAN {n} como VLAN de gestión?",
|
||||
v_vid_first:"Introduce primero un ID de VLAN",v_mgmt_q:"¿Establecer VLAN {n} como VLAN de gestión?",
|
||||
v_mgmt_d:"El switch empezará a etiquetar su propio tráfico con esa VLAN. Si el puerto por el que te conectas no la transporta, esta página dejará de ser accesible y el ajuste solo podrá deshacerse por la consola.",
|
||||
l2_title:"Tabla de direcciones MAC",l2_filter:"filtrar...",l2_flush:"Vaciar entradas aprendidas",l2_static:"estática",
|
||||
l2_learned:"aprendida",l2_loading:"cargando...",l2_failed:"error de carga",l2_entries:"entradas",
|
||||
@@ -472,7 +465,7 @@ fw_timeout:"el switch no ha vuelto tras 150 s: comprueba la alimentación / cons
|
||||
fr:{
|
||||
nav_dash:"Tableau de bord",nav_ports:"Ports",nav_stp:"Arborescence",nav_stats:"Statistiques",
|
||||
nav_vlan:"LANs virtuels",nav_l2:"Table MAC",nav_mirror:"Mise en mirroir",nav_lag:"Aggrégation",nav_eee:"Energie",
|
||||
nav_bw:"Bande passante",nav_system:"Système",nav_fw:"Micro logiciel",
|
||||
nav_bw:"Bande passante",nav_system:"Système",nav_fw:"Micro logiciel",nav_lldp:"Couche de Liaison",
|
||||
hdr_dirty:"Changements non sauvegardés",hdr_dirty_t:"La configuration utilisée diffère de celle au démarrage",
|
||||
hdr_save:"Sauvegarder en flash",hdr_save_t:"Maintenir la configuration actuelle en flash",
|
||||
th_auto:"Système",th_auto_sel:"Système (sélénisé)",sy_display:"Affichage",sy_theme:"Thème",sy_display_note:"Enregistré seulement dans ce navigateur.",th_light:"Clair",th_dark:"Sombre",
|
||||
@@ -480,15 +473,15 @@ th_sel_light:"Clair (sélénisé)",th_sel_dark:"Sombre (sélénisé)",
|
||||
c_port:"Port",c_name:"Nom",c_link:"Lien",c_apply:"Appliquer",c_cancel:"Annuler",c_confirm:"Confirmer",
|
||||
c_close:"Fermer",c_refresh:"Raffraichir",c_off:"arrêt",c_offc:"Arrêt",c_down:"arrêt",c_on:"Marche",c_auto:"Auto",c_delete:"Supprimer",
|
||||
c_type:"Type",c_state:"Etat",c_enabled:"Activé",c_load:"Charger",c_disable:"Désactivé",c_sfp:"SFP",
|
||||
c_full:"full",c_half:"half",c_devices:"Equipements",c_yes:"oui",c_no:"non",
|
||||
d_ports:"Ports",d_ports_h:"Cliquez ou survollez pour plus de détails",d_system:"Système",d_traffic:"Trafic",
|
||||
c_full:"full",c_half:"half",c_yes:"oui",c_no:"non",
|
||||
d_system:"Système",d_traffic:"Trafic",
|
||||
d_traffic_h:"paquets/s (en direct)",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX KO",d_rxbad:"RX KO",
|
||||
i_host:"Nom d'hote",i_ip:"Adresse IP",i_mask:"Masque réseau",i_gw:"Passerelle",i_mac:"Adresse MAC",i_fw:"Micro logiciel",
|
||||
i_built:"Compilé le",i_hw:"Matériel",i_temp:"Température",i_flash:"Taille Flash",i_syslog:"Journal système",
|
||||
p_state:"Etat",p_disabled:"Inactif",p_up:"Actif",p_txgb:"TX bon / mauvais",p_rxgb:"RX bon / mauvais",
|
||||
p_state:"Etat",p_disabled:"Inactif",p_up:"Actif",
|
||||
p_pkts:"paquets",p_module:"Module",p_temp:"Température",p_vcc:"Vcc",p_txbias:"TX biais",p_txpower:"TX puissance",
|
||||
p_rxpower:"RX puissance",p_txfault:"TX erreur",p_txdis:"TX désactivé",p_rxlos:"RX pertes de signaux",p_adv:"Capacités",
|
||||
pt_title:"Configuration du port",pt_conn:"Connecté à",pt_speed:"Vitesse",pt_mtu:"MTU",
|
||||
pt_title:"Configuration du port",pt_conn:"Appareils appris",pt_speed:"Vitesse",pt_mtu:"MTU",
|
||||
pt_sfp_note:"La vitesse SFP est paramétrée pour le port et n'est pas enregistrée dans la configuration de démarrage.",
|
||||
pt_name_err:"Nom du port: 1 à 15 caractères, sans espaces",pt_mtu_err:"MTU doit être comrpis entre 64 et 16383",
|
||||
stp_title:"Arborescence",stp_h:"RSTP, 802.1w",stp_version:"Protocole",stp_v_stp:"Compatible STP",
|
||||
@@ -509,6 +502,7 @@ stp_en_q:"Activer l'arbrescence?",
|
||||
stp_en_d:"Les ports sont d'abord bloqués et cela prend deux fois le délai de retransmission pour atteindre l'état de retransmission; les ports en bordures recouvrent immédiatement leur état.",
|
||||
stp_dis_q:"Désactiver l'arborescence ?",stp_dis_d:"Tous les ports vont être retransmis; la protection de boucles est perdue.",
|
||||
stp_cost_err:"Le coût du chemin doit être compris entre 0 et 200000000",
|
||||
lldp_enabled: "Activer LLDP",lldp_title:"Protocole de découverte de la couche de liason (LLDP)",lldp_portname:"Nom",lldp_enable:"Envoi de trames",
|
||||
st_title:"Statiqtique du port",st_h:"cumul depuis le démarrage",st_txg:"TX OK",st_txb:"TX KO",st_rxg:"RX OK",
|
||||
st_rxb:"RX KO",st_details:"Détails",st_counters:"Compteur MIB",st_nonzero:"non-zero seulement",
|
||||
st_autoref:"rafraichissement automatique",st_counter:"Compteur",st_value:"Valeur",st_fail:"Erreur au chargement des compteurs",
|
||||
@@ -517,14 +511,12 @@ v_empty:"Aucun VLANs configuré.",v_mgmt:"VLAN de management",v_mgmt_none:"déta
|
||||
v_optional:"optionel",v_setmgmt:"Mette en VLAN de management",v_setmgmt_t:"Mettre celui-ci en VLAN de management",
|
||||
v_member:"Membre",v_pvid:"PVID",
|
||||
v_legend:"U = Membre détagué (UnTagged), T = membre tagué (Tagged), - = non membre. PVID (Port VLan ID) assigne ce VLAN au trafic entrant non tagué.",
|
||||
v_ingress:"Filtrage entrant",v_ingress_h:"en ériture seule: cet état n'est pas lisible depuis le communtateur réseau",
|
||||
v_accept:"Accepté",v_ing_all:"Tous",v_ing_apply:"Appliquer les filtes",v_del_t:"Supprimer le VLAN",
|
||||
v_del_q:"Supprimer le VLAN {n}?",v_del_d:"Les ports conservent leur PVID tant qu'ils ne sont pas réassignés.",
|
||||
v_vid_err:"Entrez un identifiant VLAN (1-4094)",v_name_err:"Le nom doit commencer par une lettre (lettre, chiffres, _)",
|
||||
v_loaded:"VLAN chargés {n}",v_notfound:"VLAN {n} non trouvé (un nouveau peut toutefois être créé)",
|
||||
v_nomember:"Selectionnez au moins un port membre (ou supprimez le VLAN)",
|
||||
v_ing_none:"Sélectionnez le mode entrant pour au moins un port",v_vid_first:"Entrez un identifiant VLAN d'abord",
|
||||
v_mgmt_q:"Mettre ce VLAN {n} en tant que VLAN de management?",
|
||||
v_vid_first:"Entrez un identifiant VLAN d'abord",v_mgmt_q:"Mettre ce VLAN {n} en tant que VLAN de management?",
|
||||
v_mgmt_d:"Ce commutateur commencera par taguer son propre trafic avec ce VLAN. Si le port avec lequel vous êtes connecté ne le permet pas, cette page deviendra inaccessible et les paramètres ne pourront plus être changés que via la console.",
|
||||
l2_title:"Table des adresses MAC",l2_filter:"filtre...",l2_flush:"Effacer les entrées apprises",l2_static:"static",
|
||||
l2_learned:"appris",l2_loading:"chargement...",l2_failed:"chargement non réussi",l2_entries:"entrées",
|
||||
@@ -542,6 +534,9 @@ e_idle:"Inactif",e_na:"N/A",
|
||||
bw_title:"Limitations de bande passante",bw_h:"Mbit/s, 0.016-10000",bw_in:"Limite entrante",bw_out:"Limite sortante",
|
||||
bw_exceed:"Lorsque dépassé",bw_fc:"Limiter",bw_drop:"Rejetter",
|
||||
bw_in_err:"La limite entrante doit être comprise entre 0.016 et 10000 Mbit/s",bw_out_err:"La limite sortante doit être comprise entre 0.016 et 10000 Mbit/s",
|
||||
sc_title:"Contrôle des tempêtes",sc_h:"par port et par type de diffusion (générale ou groupée), vide = inactif",sc_bcast:"Générale (Broadcast)",sc_mcast:"Groupée (Multicast)",
|
||||
sc_ucast:"Unicast inconnu",sc_umcast:"Multicast inconnu",sc_err:" La limite de tempête doit être comprise entre 1 à 1048575 pps ou 1 à 10000000 kbit/s",
|
||||
sc_note:"Les trames de chacun des types ci-dessus dépassant les limites sont abandonnées lorsqu'elles arrivent sur le communtateur.",
|
||||
sy_network:"Réseau",sy_dhcp:"Uiliser DHCP",sy_dhcp_t:"Aquérir l'adresse via le protocole DHCP",sy_services:"Services",
|
||||
sy_igmp:"Surveillance IGMP",sy_sysip:"IP du serveur...",sy_server:"Serveur",sy_port:"Port",
|
||||
sy_sesstmo:"Temps mort de session (s)",sy_sesstmo_err:"Le temps morts de session doit être compris en 1-65535 s",
|
||||
@@ -555,7 +550,14 @@ sy_ip_err:"Erreur d'IP / masque réseau / passerelle",sy_host_err:"Nom d'hôte :
|
||||
sy_net_q:"Appliquer les paramètres réseau?",sy_net_d:"L'adresse IP de management va devenir {ip}: merci de réouvrir le page depuis cette adresse.",
|
||||
sy_ip_changed:"L'adresse IP a changée, reconnectez-vous à http://{ip}/",sy_dhcp_q:"Passer en DHCP?",
|
||||
sy_dhcp_d:"Le commutateur va demander une addresse via le DHCP. Vous devrez rechercher sa prochaine adresse IP pour vous reconnecter.",
|
||||
sy_sysip_err:"Adresse IP du serveur Syslog invalide",sy_sysport_err:"Le port Syslog doit être compris entre 1 et 65535",
|
||||
sy_sysip_err:"Adresse IP du serveur Syslog invalide",sy_dns1:"DNS principal",sy_dns2:"DNS secondaire",sy_dns_err:"Adresse IP du DNS invalide",sy_dns_dhcp:"émis par le DHCP: {ip}",
|
||||
sy_time:"Temps",sy_ntp:"NTP",sy_ntpsrv:"Serveur NTP",sy_ntpsrv_p:"Nom d'hôte ou adresse IPv4",sy_ntpint:"intervalle de scrutation [min]",
|
||||
sy_tz:"Fuseau horaire",sy_dst:"Heure d'été",sy_dst_eu:"Europe",
|
||||
sy_dst_us:"Etats-Unis",sy_now:"Heure locale",
|
||||
sy_sync:"Dernière synchronisation",sy_ntpaddr:"Adresse du serveur",sy_nosync:"Désynchronisé",sy_waiting:"En attente du serveur",
|
||||
sy_ago:"depuis {n} minutes",sy_ntp_err:"Entrez le nom d'hôte ou l'adresse IPv4 du serveur NTP",sy_ntpint_err:"L'intervalle de scrutation doit être compris entre 1 et 1440",
|
||||
sy_time_note:"Le commutateur n'a pas d'horloge sauvegardée par batterie: L'heure est donc perdue à chaque redémarrage et doit être récupérée grâce au serveur NTP une fois le réseau fonctionnel. Sauvegardez en mémoire flash pour enregistrer les paramètres.",
|
||||
sy_sysport_err:"Le port Syslog doit être compris entre 1 et 65535",
|
||||
sy_pw_len:"Mot de passe : 1 à 20 caractères",sy_pw_space:"Le mot de passe ne doit pas contenir d'espaces",sy_pw_match:"Les mots de passe ne correspondent pas",
|
||||
sy_pw_q:"Changer le mot de passe d'administration?",sy_pw_d:"Cela prend effet immédiatement dès la prochaine connection. Enregistrez en Flash pour rendre la modification persistante.",
|
||||
sy_reboot_q:"Redémarrer le commutateur ?",sy_reboot_d:"Il y a des paramètres NON SAUVEGARDES qui vont être perdus. Sauvegardez-les au préalable en mémoire flash si vous souhaitez les conserver.",
|
||||
@@ -588,7 +590,7 @@ fw_timeout:"Le commutateur n'est plus joignable depuis 150 s: verifiez l'aliment
|
||||
},
|
||||
de:{
|
||||
nav_dash:"Übersicht",nav_ports:"Ports",nav_stp:"Spanning Tree",nav_stats:"Statistik",
|
||||
nav_vlan:"VLANs",nav_l2:"MAC-Tabelle",nav_mirror:"Spiegelung",nav_lag:"LAG",nav_eee:"EEE",
|
||||
nav_vlan:"VLANs",nav_l2:"MAC-Tabelle",nav_mirror:"Spiegelung",nav_isolate:"Isolation",nav_lag:"LAG",nav_eee:"EEE",
|
||||
nav_bw:"Bandbreite",nav_system:"System",nav_fw:"Firmware",
|
||||
hdr_dirty:"ungespeicherte Änderungen",hdr_dirty_t:"Laufende Konfiguration weicht von der Startkonfiguration ab",
|
||||
hdr_save:"Im Flash speichern",hdr_save_t:"Laufende Konfiguration dauerhaft im Flash speichern",
|
||||
@@ -597,15 +599,15 @@ th_sel_light:"Selenized Hell",th_sel_dark:"Selenized Dunkel",
|
||||
c_port:"Port",c_name:"Name",c_link:"Link",c_apply:"Übernehmen",c_cancel:"Abbrechen",c_confirm:"Bestätigen",
|
||||
c_close:"Schliessen",c_refresh:"Aktualisieren",c_off:"aus",c_offc:"Aus",c_down:"getrennt",c_on:"Ein",c_auto:"Auto",c_delete:"Löschen",
|
||||
c_type:"Typ",c_state:"Zustand",c_enabled:"Aktiviert",c_load:"Laden",c_disable:"Deaktivieren",c_sfp:"SFP",
|
||||
c_full:"voll",c_half:"halb",c_devices:"Geräte",c_yes:"ja",c_no:"nein",
|
||||
d_ports:"Ports",d_ports_h:"Port anklicken für Details",d_system:"System",d_traffic:"Datenverkehr",
|
||||
c_full:"voll",c_half:"halb",c_yes:"ja",c_no:"nein",
|
||||
d_system:"System",d_traffic:"Datenverkehr",
|
||||
d_traffic_h:"Pakete/s, live",d_txpps:"TX Pakete/s",d_rxpps:"RX Pakete/s",d_txbad:"TX fehlerhaft",d_rxbad:"RX fehlerhaft",
|
||||
i_host:"Hostname",i_ip:"IP-Adresse",i_mask:"Netzmaske",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware",
|
||||
i_built:"Erstellt",i_hw:"Hardware",i_temp:"Temperatur",i_flash:"Flash",i_syslog:"Syslog",
|
||||
p_state:"Zustand",p_disabled:"deaktiviert",p_up:"verbunden",p_txgb:"TX gut / fehlerhaft",p_rxgb:"RX gut / fehlerhaft",
|
||||
p_state:"Zustand",p_disabled:"deaktiviert",p_up:"verbunden",
|
||||
p_pkts:"Pakete",p_module:"Modul",p_temp:"Temperatur",p_vcc:"Vcc",p_txbias:"TX-Bias",p_txpower:"Sendeleistung",
|
||||
p_rxpower:"Empfangsleistung",p_txfault:"TX-Fehler",p_txdis:"TX deaktiviert",p_rxlos:"RX LOS",p_adv:"Angeboten",
|
||||
pt_title:"Port-Konfiguration",pt_conn:"Verbunden",pt_speed:"Geschwindigkeit",pt_mtu:"MTU",
|
||||
pt_title:"Port-Konfiguration",pt_conn:"Gelernte Geräte",pt_speed:"Geschwindigkeit",pt_mtu:"MTU",
|
||||
pt_sfp_note:"Die SFP-Geschwindigkeit wird pro Steckplatz gesetzt und nicht in der Startkonfiguration gespeichert.",
|
||||
pt_name_err:"Port-Name: 1-15 Zeichen, keine Leerzeichen",pt_mtu_err:"MTU muss zwischen 64 und 16383 liegen",
|
||||
stp_title:"Spanning Tree",stp_h:"RSTP, 802.1w",stp_version:"Version",stp_v_stp:"STP-kompatibel",
|
||||
@@ -626,30 +628,36 @@ stp_en_q:"Spanning Tree aktivieren?",
|
||||
stp_en_d:"Die Ports starten blockiert und brauchen bis zum doppelten Forward Delay, bis sie weiterleiten; Edge-Ports sind sofort wieder aktiv.",
|
||||
stp_dis_q:"Spanning Tree deaktivieren?",stp_dis_d:"Alle Ports leiten sofort weiter; der Schutz vor Netzwerkschleifen entfällt.",
|
||||
stp_cost_err:"Pfadkosten müssen zwischen 0 und 200000000 liegen",
|
||||
nav_lldp:"LLDP",lldp_enabled:"LLDP aktiv",lldp_title:"Dienststatus",lldp_portname:"Name",lldp_enable:"Pakete senden",
|
||||
st_title:"Port-Statistik",st_h:"Summen seit dem Start",st_txg:"TX gut",st_txb:"TX fehlerhaft",st_rxg:"RX gut",
|
||||
st_rxb:"RX fehlerhaft",st_details:"Details",st_counters:"MIB-Zähler",st_nonzero:"nur ungleich null",
|
||||
st_autoref:"automatisch aktualisieren",st_counter:"Zähler",st_value:"Wert",st_fail:"Zähler konnten nicht geladen werden",
|
||||
v_title:"VLANs",v_vid:"VID",v_members:"Mitglieder",v_tagged:"Tagged",v_untagged:"Untagged",v_pvid_on:"PVID auf",
|
||||
v_empty:"Keine VLANs konfiguriert.",v_mgmt:"Management-VLAN",v_mgmt_none:"untagged",v_editor:"VLAN-Editor",
|
||||
v_optional:"optional",v_setmgmt:"Als Management-VLAN",v_setmgmt_t:"Dieses VLAN zum Management-VLAN machen",
|
||||
v_setmgmt_q:"{n} als Management-VLAN setzen?",v_add:"Neues VLAN hinzufügen",
|
||||
v_mgmt_c:"WARNUNG: Du musst dieses VLAN erreichen können, um den Switch weiter verwalten zu können.",
|
||||
v_member:"Mitglied",v_pvid:"PVID",
|
||||
v_legend:"U = Mitglied untagged, T = Mitglied tagged, - = kein Mitglied. PVID ordnet eingehenden Verkehr ohne Tag diesem VLAN zu.",
|
||||
v_ingress:"Ingress-Filter",v_ingress_h:"nur schreibbar: der Zustand lässt sich vom Switch nicht auslesen",
|
||||
v_accept:"Annehmen",v_ing_all:"Alle",v_ing_apply:"Ingress-Modi übernehmen",v_del_t:"VLAN löschen",
|
||||
v_accept:"Annehmen",v_ing_all:"Alle",v_ing_apply:"Ingress-Modi übernehmen",v_del_t:"VLAN löschen",v_rename:"Umbenennen",v_rename_t:"VLAN umbenennen",
|
||||
v_del_q:"VLAN {n} löschen?",v_del_d:"Die Ports behalten ihre PVID, bis sie neu zugewiesen wird.",
|
||||
v_vid_err:"VLAN-ID eingeben (1-4094)",v_name_err:"Der Name muss mit einem Buchstaben beginnen (Buchstaben, Ziffern, _)",
|
||||
v_loaded:"VLAN {n} geladen",v_notfound:"VLAN {n} nicht gefunden (es kann neu angelegt werden)",
|
||||
v_nomember:"Mindestens einen Mitglieds-Port wählen (oder das VLAN stattdessen löschen)",
|
||||
v_ing_none:"Für mindestens einen Port einen Ingress-Modus wählen",v_vid_first:"Zuerst eine VLAN-ID eingeben",
|
||||
v_mgmt_q:"VLAN {n} als Management-VLAN setzen?",
|
||||
v_vid_first:"Zuerst eine VLAN-ID eingeben",v_mgmt_q:"VLAN {n} als Management-VLAN setzen?",
|
||||
v_mgmt_d:"Der Switch versieht dann seinen eigenen Verkehr mit diesem VLAN-Tag. Führt der Port, über den du verbunden bist, dieses VLAN nicht, ist diese Seite nicht mehr erreichbar und die Einstellung lässt sich nur noch über die serielle Konsole zurücknehmen.",
|
||||
v_mgmt_tt:"Das Management-VLAN lässt sich nicht löschen. Lege zuerst ein anderes VLAN als Management-VLAN fest.",
|
||||
l2_title:"MAC-Adresstabelle",l2_filter:"filtern...",l2_flush:"Gelernte Einträge löschen",l2_static:"statisch",
|
||||
l2_learned:"gelernt",l2_loading:"lädt...",l2_failed:"Laden fehlgeschlagen",l2_entries:"Einträge",
|
||||
l2_del_t:"Eintrag löschen",l2_flush_q:"Alle gelernten MAC-Einträge löschen?",
|
||||
m_title:"Port-Spiegelung",m_active:"aktiv",m_monitor:"Monitor-Port",m_mirror:"Spiegeln",m_both:"Beide",
|
||||
m_note:"Beide = RX und TX des Ports auf den Monitor-Port spiegeln.",m_none:"Mindestens einen zu spiegelnden Port wählen",
|
||||
iso_title:"Port-Isolation",iso_from:"Von Port",iso_to:"Zu Port",iso_all:"Alle erlauben",
|
||||
iso_intro:"Ein Paket, das über einen Port hereinkommt, darf den Switch nur über die Ports verlassen, die in seiner Zeile angehakt sind. Die Isolation wirkt vor der Weiterleitung: Ein nicht angehakter Port ist direkt nicht erreichbar, egal was in der MAC-Tabelle steht.",
|
||||
iso_legend:"Das Feld des Ports selbst ist immer erlaubt. Eine rote Portnummer markiert einen Port, der nicht ganz offen ist.",
|
||||
lag_hash:"Hash:",lag_note:"Eine LAG braucht mindestens ein Mitglied, um in der Startkonfiguration gespeichert zu werden; eine leere Gruppe zu übernehmen löscht sie.",
|
||||
lag_clear_q:"LAG {n} auflösen?",lag_clear_d:"Alle Mitglieds-Ports kehren in den Normalbetrieb zurück.",
|
||||
lacp_heading:"LACP (802.3ad)",lag_mode:"Modus",lag_static:"Statisch",lacp_neg:"wird ausgehandelt",lacp_agg:"Aggregator",lacp_members:"aktive Mitglieder",lacp_hint:"LACP: Ports auswählen und Übernehmen drücken, um die Aushandlung zu starten",lacp_actor:"Lokal",lacp_partner:"Partner",lacp_rxstate:"Empfangsstatus",lacp_rx:"Empfangene LACPDUs",lacp_psys:"Partner-System",
|
||||
e_title:"Energy Efficient Ethernet",e_adv:"Angeboten",e_lp:"Gegenstelle",e_active:"Aktiv",e_enable:"Aktivieren",
|
||||
e_note:"Angebotene und von der Gegenstelle unterstützte Stufen je Geschwindigkeit: 100M, 1G, 2.5G. SFP-Ports unterstützen kein EEE.",
|
||||
e_idle:"inaktiv",e_na:"k. A.",
|
||||
@@ -672,7 +680,8 @@ sy_ip_err:"Ungültige IP / Netzmaske / Gateway",sy_host_err:"Hostname: 1-23 druc
|
||||
sy_net_q:"Netzwerkeinstellungen übernehmen?",sy_net_d:"Die Management-IP ändert sich auf {ip}: Diese Seite muss dort neu geöffnet werden.",
|
||||
sy_ip_changed:"IP geändert, neu verbinden unter http://{ip}/",sy_dhcp_q:"Auf DHCP umstellen?",
|
||||
sy_dhcp_d:"Der Switch bezieht seine Adresse per DHCP. Du musst seine neue IP herausfinden, um dich wieder zu verbinden.",
|
||||
sy_sysip_err:"Ungültige IP des Syslog-Servers",sy_sysport_err:"Syslog-Port muss zwischen 1 und 65535 liegen",
|
||||
sy_sysip_err:"Ungültige IP des Syslog-Servers",sy_dns1:"DNS-Server",sy_dns2:"Zweiter DNS-Server",sy_dns_err:"Ungültige IP des DNS-Servers",sy_dns_dhcp:"von DHCP: {ip}",sy_sysport_err:"Syslog-Port muss zwischen 1 und 65535 liegen",
|
||||
sy_time:"Uhrzeit",sy_ntp:"NTP",sy_ntpsrv:"NTP-Server",sy_ntpsrv_p:"Hostname oder IPv4-Adresse",sy_ntpint:"Abfrageintervall [min]",sy_tz:"Zeitzone",sy_dst:"Sommerzeit",sy_dst_eu:"Europa",sy_dst_us:"USA",sy_now:"Lokale Zeit",sy_sync:"Letzte Synchronisation",sy_ntpaddr:"Server-Adresse",sy_nosync:"nicht synchronisiert",sy_waiting:"warte auf den Server",sy_ago:"vor {n} min",sy_ntp_err:"Hostname oder IPv4-Adresse des NTP-Servers eingeben",sy_ntpint_err:"Abfrageintervall muss zwischen 1 und 1440 liegen",sy_time_note:"Der Switch hat keine batteriegepufferte Uhr: Die Zeit geht bei jedem Neustart verloren und wird neu vom NTP-Server bezogen, sobald das Netzwerk bereit ist. Im Flash speichern, damit die Einstellungen erhalten bleiben.",
|
||||
sy_pw_len:"Passwort: 1-20 Zeichen",sy_pw_space:"Das Passwort darf keine Leerzeichen enthalten",sy_pw_match:"Die Passwörter stimmen nicht überein",
|
||||
sy_pw_q:"Admin-Passwort ändern?",sy_pw_d:"Gilt sofort für neue Anmeldungen. Im Flash speichern, damit es erhalten bleibt.",
|
||||
sy_reboot_q:"Switch neu starten?",sy_reboot_d:"Es gibt UNGESPEICHERTE Änderungen, sie gehen verloren. Zuerst im Flash speichern, wenn du sie behalten willst.",
|
||||
@@ -794,34 +803,49 @@ function getJSON(p){return api(p).then(function(r){if(!r.ok)throw new Error(p+"
|
||||
function getText(p){return api(p).then(function(r){if(!r.ok)throw new Error(p+" "+r.status);return r.body})}
|
||||
|
||||
var CONF_CMDS=[
|
||||
/^ip\s+(\d{1,3}\.){3}\d{1,3}$/,/^ip\s+dhcp$/,
|
||||
/^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}$/,
|
||||
/^ip\s+(\d{1,3}\.){3}\d{1,3}$/,
|
||||
/^ip\s+dhcp$/,
|
||||
/^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)$/,
|
||||
/^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?)+$/,
|
||||
/^pvid\s+\d{1,2}\s+\d{1,4}$/,
|
||||
/^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$/,/^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}$/,
|
||||
/^vlan\s+\d+\s+(d|mgmt)$/m,
|
||||
/^vlan\s+\d+(\s+[a-zA-Z]\w*)?(\s+\d+t?)*$/m,
|
||||
/^pvid\s+\d+\s+\d+$/m,
|
||||
/^ingress(\s+\d+[tua])+$/,/^ingress\s+[tua]$/,
|
||||
/^port\s+\d+\s+(10m|100m|1g|2g5|5g|10g|auto|on|off)(\s+(half|full))?$/,
|
||||
/^port\s+\d+\s+name\s+\S+$/,
|
||||
/^port\s+\d+\s+lldp\s+(permit|block)+$/,
|
||||
/^eee\s+(on|off)(\s+\d+)?(\s+(100m|1g|2g5))?$/,
|
||||
/^mirror(\s+\d+)(\s+\d+[tr]?)+$/,/^mirror\s+off$/,
|
||||
/^lag\s+[1-4](\s+\d+)+$/,/^lag\s+[1-4]\s+d$/,
|
||||
/^lag\s+[1-4]\s+lacp(\s+\d+)+$/,
|
||||
/^lag\s+[1-4]\s+lacp\s+off$/,
|
||||
/^laghash\s+[1-4](\s+\w+)+$/,
|
||||
/^isolate\s+\d+(\s+(off|\d+))+$/,
|
||||
/^stp\s+(on|off)$/,/^stp\s+(prio|hello|maxage|fwd|txhold)\s+\d+$/,
|
||||
/^stp\s+version\s+(rstp|stp)$/,
|
||||
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+(on|off)$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+edge\s+(on|off|auto)$/,
|
||||
/^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+$/,/^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))$/,
|
||||
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+(on|off)$/,
|
||||
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+edge\s+(on|off|auto)$/,
|
||||
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+cost\s+\d+$/,
|
||||
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+prio\s+\d+$/,
|
||||
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+guard\s+(none|bpdu|root)$/,
|
||||
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+filter\s+(on|off)$/,
|
||||
/^stp\s+(port\s+\d=|lag\s+[1-4])\s+p2p\s+(auto|on|off)$/,
|
||||
/^igmp\s+(on|off)$/,
|
||||
/^mtu\s+\d+\s+\d+$/,
|
||||
/^lldp\s+(on|off)$/,
|
||||
/^bw\s+(in|out)\s+\d+\s+\S+$/,
|
||||
/^storm\s+\d+\s+(bcast|mcast|ucast|umcast)\s+(off|\d+\s+(pps|kbps))$/,
|
||||
];
|
||||
function isConfCmd(line){
|
||||
for(var i=0;i<CONF_CMDS.length;i++)if(CONF_CMDS[i].test(line))return true;
|
||||
@@ -830,6 +854,7 @@ function isConfCmd(line){
|
||||
function setDirty(d){
|
||||
S.dirty=d;
|
||||
$("dirty").classList.toggle("show",d);
|
||||
$("saveBtn").classList.toggle("pri",d);
|
||||
}
|
||||
function postCmd(cmd,quiet){
|
||||
return api("/cmd",{method:"POST",body:cmd}).then(function(r){
|
||||
@@ -844,7 +869,6 @@ function postCmds(list){
|
||||
list.forEach(function(c){p=p.then(function(){return postCmd(c,true)})});
|
||||
return p.then(function(){toast(t("t_cmds",{n:list.length}),"ok")});
|
||||
}
|
||||
|
||||
function toast(msg,cls){
|
||||
var el=h("div",{class:"toast "+(cls||""),text:msg});
|
||||
$("toasts").appendChild(el);
|
||||
@@ -930,6 +954,7 @@ function byPort(a){return a.sort(function(x,y){return x.portNum-y.portNum})}
|
||||
function pollStatus(){
|
||||
return getJSON("/status.json").then(function(s){
|
||||
byPort(s);
|
||||
S.ports=s;
|
||||
var now=Date.now();
|
||||
if(!S.n){
|
||||
S.n=s.length;
|
||||
@@ -951,13 +976,14 @@ function pollStatus(){
|
||||
};
|
||||
});
|
||||
}
|
||||
S.prev=s;S.prevT=now;S.ports=s;
|
||||
S.prev=s;S.prevT=now;
|
||||
updateStrip();
|
||||
var hk=tabHooks[curTab];
|
||||
if(hk&&hk.status)hk.status();
|
||||
});
|
||||
}
|
||||
var statusPoller=new Poller(pollStatus,2500);
|
||||
statusPoller.start();
|
||||
function needPorts(fn){
|
||||
if(S.n)return fn();
|
||||
pollStatus().then(fn).catch(function(){});
|
||||
@@ -1017,8 +1043,10 @@ function portRows(p){
|
||||
var rows=[[t("c_port"),String(p.portNum)],[t("c_type"),p.isSFP?"SFP":"RJ45"]];
|
||||
if(p.name)rows.push([t("c_name"),p.name]);
|
||||
rows.push([t("p_state"),!p.enabled?t("p_disabled"):(p.link>0?t("p_up")+" "+LINKS[p.link]:t("c_down"))]);
|
||||
rows.push([t("p_txgb"),BigInt(p.txG)+" / "+BigInt(p.txB)+" "+t("p_pkts")]);
|
||||
rows.push([t("p_rxgb"),BigInt(p.rxG)+" / "+BigInt(p.rxB)+" "+t("p_pkts")]);
|
||||
rows.push([t("st_txg"),BigInt(p.txG)+" "+t("p_pkts")]);
|
||||
rows.push([t("st_txb"),BigInt(p.txB)+" "+t("p_pkts")]);
|
||||
rows.push([t("st_rxg"),BigInt(p.rxG)+" "+t("p_pkts")]);
|
||||
rows.push([t("st_rxb"),BigInt(p.rxB)+" "+t("p_pkts")]);
|
||||
if(p.isSFP){
|
||||
if(p.sfp_vendor)rows.push([t("p_module"),[p.sfp_vendor,p.sfp_model,p.sfp_serial].filter(Boolean).join(" / ")]);
|
||||
var ext=p.sfp_options&0x40;
|
||||
@@ -1102,8 +1130,7 @@ function dashStatus(){
|
||||
});
|
||||
}
|
||||
tabHooks.dash={
|
||||
enter:function(){statusPoller.start();pollInfo().catch(function(){})},
|
||||
leave:function(){statusPoller.stop()},
|
||||
enter:function(){pollInfo().catch(function(){})},
|
||||
status:dashStatus,
|
||||
};
|
||||
|
||||
@@ -1147,31 +1174,12 @@ function loadMtu(){
|
||||
});
|
||||
});
|
||||
}
|
||||
/* One learned MAC is the attached device; several means a switch or AP
|
||||
* sits behind the port, so only the count is shown. */
|
||||
function portsMacs(){
|
||||
l2Load().then(function(all){
|
||||
var by={};
|
||||
all.forEach(function(e){
|
||||
if(e.pport==="CPU")return;
|
||||
var l=by[e.pport]=by[e.pport]||[];
|
||||
if(l.indexOf(e.mac)<0)l.push(e.mac);
|
||||
});
|
||||
S.ports.forEach(function(p){
|
||||
var el=$("pmac"+(p.portNum-1));
|
||||
if(!el)return;
|
||||
var m=by[p.portNum]||[];
|
||||
el.textContent=!m.length?"-":(m.length===1?m[0]:m.length+" "+t("c_devices"));
|
||||
el.title=m.join("\n");
|
||||
});
|
||||
}).catch(function(){});
|
||||
}
|
||||
var _macTick=0;
|
||||
function portsStatus(){
|
||||
buildPorts();
|
||||
if(++_macTick%10===0)portsMacs();
|
||||
S.ports.forEach(function(p){
|
||||
var i=p.portNum-1,el=$("plink"+i);
|
||||
var mc=$("pmac"+i);
|
||||
if(mc)mc.textContent=parseInt(p.macs,16)&0x1fff;
|
||||
if(el)el.innerHTML=linkBadge(p);
|
||||
var sel=$("pspd"+i),v=p.isSFP?0:ADVSEL[parseInt(p.adv,2)];
|
||||
if(sel&&v&&document.activeElement!==sel)sel.value=v;
|
||||
@@ -1199,8 +1207,7 @@ function applyPort(i){
|
||||
postCmds(cmds).then(loadMtu).catch(function(){});
|
||||
}
|
||||
tabHooks.ports={
|
||||
enter:function(){statusPoller.start();needPorts(function(){buildPorts();portsMacs()})},
|
||||
leave:function(){statusPoller.stop();l2Gen++},
|
||||
enter:function(){needPorts(buildPorts)},
|
||||
status:portsStatus,
|
||||
};
|
||||
|
||||
@@ -1456,8 +1463,7 @@ function statsStatus(){
|
||||
});
|
||||
}
|
||||
tabHooks.stats={
|
||||
enter:function(){statusPoller.start()},
|
||||
leave:function(){statusPoller.stop();if(ctrPoll)ctrPoll.stop()},
|
||||
leave:function(){if(ctrPoll)ctrPoll.stop()},
|
||||
status:statsStatus,
|
||||
};
|
||||
|
||||
@@ -1476,131 +1482,282 @@ function rangeStr(list){
|
||||
}
|
||||
return parts.join(", ");
|
||||
}
|
||||
function vlanRefresh(){
|
||||
var tb=$("vtable").tBodies[0];
|
||||
return getJSON("/vlanlist").then(function(d){
|
||||
var vl=d.vlan||[];
|
||||
$("vmgmtcur").textContent=d.mgmt?String(d.mgmt):t("v_mgmt_none");
|
||||
$("vempty").style.display=vl.length?"none":"";
|
||||
tb.innerHTML="";
|
||||
var p=Promise.resolve();
|
||||
vl.forEach(function(v){
|
||||
p=p.then(function(){return getJSON("/vlan.json?vid="+v.id).catch(function(){return null})}).then(function(d){
|
||||
var tr=tb.insertRow();
|
||||
tr.insertCell().appendChild(h("a",{href:"#vlan",text:String(v.id),onclick:function(e){
|
||||
e.preventDefault();$("vvid").value=v.id;vlanLoad();
|
||||
}}));
|
||||
tr.insertCell().textContent=v.name||"";
|
||||
if(!d){for(var c=0;c<4;c++)tr.insertCell().textContent="?";}
|
||||
else{
|
||||
var m=parseInt(d.members,16),mem=m&0x3ff,unt=((m>>10)&0x3ff)&mem;
|
||||
var pv=parseInt(d.pvid,16)&0x3ff;
|
||||
tr.insertCell().textContent=rangeStr(maskToPorts(mem));
|
||||
tr.insertCell().textContent=rangeStr(maskToPorts(mem&~unt));
|
||||
tr.insertCell().textContent=rangeStr(maskToPorts(unt));
|
||||
tr.insertCell().textContent=rangeStr(maskToPorts(pv));
|
||||
|
||||
function vlanRefresh() {
|
||||
var tb = $("vtable").tBodies[0];
|
||||
tb.style="cursor:pointer;"
|
||||
return getJSON("/vlanlist").then(function(d) {
|
||||
var vl = d.vlan || [];
|
||||
$("vmgmtcur").dataset.id = d.mgmt;
|
||||
$("vempty").style.display = vl.length ? "none" : "";
|
||||
tb.innerHTML = "";
|
||||
var p = Promise.resolve();
|
||||
vl.forEach(function(v) {
|
||||
p = p.then(function() {
|
||||
return getJSON("/vlan.json?vid=" + v.id).catch(function() {
|
||||
return null
|
||||
})
|
||||
}).then(function(d) {
|
||||
var tr = tb.insertRow();
|
||||
tr.onclick = function(e) {
|
||||
e.preventDefault();
|
||||
vlanLoad(v.id);
|
||||
};
|
||||
var l = h("a", {
|
||||
href: "#vlan",
|
||||
text: String(v.id) + ($("vmgmtcur").dataset.id == v.id ? " ("+t("v_mgmt")+")":""),
|
||||
"data-id": v.id,
|
||||
"data-name": v.name
|
||||
});
|
||||
tr.insertCell().appendChild(l);
|
||||
tr.insertCell().textContent = v.name || "";
|
||||
if (!d) {
|
||||
for (var c = 0; c < 4; c++) tr.insertCell().textContent = "?";
|
||||
} else {
|
||||
var m = parseInt(d.members, 16),
|
||||
mem = m & 0x3ff,
|
||||
unt = ((m >> 10) & 0x3ff) & mem,
|
||||
tag = mem & ~unt;
|
||||
var pv = parseInt(d.pvid, 16) & 0x3ff;
|
||||
tr.insertCell().textContent = rangeStr(maskToPorts(mem));
|
||||
tr.insertCell().textContent = rangeStr(maskToPorts(tag));
|
||||
tr.insertCell().textContent = rangeStr(maskToPorts(unt));
|
||||
tr.insertCell().textContent = rangeStr(maskToPorts(pv));
|
||||
l.dataset.t = maskToPorts(tag);
|
||||
l.dataset.u = maskToPorts(unt);
|
||||
}
|
||||
var del=tr.insertCell();
|
||||
if(v.id!==1)del.appendChild(h("button",{class:"ctl",text:"\u2715",title:t("v_del_t"),onclick:function(){
|
||||
confirmModal(t("v_del_q",{n:v.id}),t("v_del_d"),function(){
|
||||
postCmd("vlan "+v.id+" d").then(vlanRefresh).catch(function(){});
|
||||
});
|
||||
}}));
|
||||
}).catch(function(){});
|
||||
var act = tr.insertCell();
|
||||
act.onclick=function(e){e.stopPropagation()};
|
||||
act.appendChild(h("button", {
|
||||
class: "ctl",
|
||||
text: t("v_rename"),
|
||||
title: t("v_rename_t"),
|
||||
onclick: function() {
|
||||
var body = h("div");
|
||||
body.appendChild(h("p", null, [
|
||||
h("label", {class: "row"}, [
|
||||
h("span",{class:"lb", "data-i18n":"c_name"},[document.createTextNode(t("c_name"))]),
|
||||
h("input", {id: "nvlrename", class: "in", size: "12", maxlength: "15", "data-i18n-p": "v_optional", value:(v.name||"")})
|
||||
])
|
||||
]));
|
||||
modal("Rename VLAN "+v.id, body, [h("button", {
|
||||
class: "ctl pri", text: t("v_rename_t"),
|
||||
onclick: function(){
|
||||
if(!validVlanName($("nvlrename").value)) return;
|
||||
postCmd(vlan2str(v.id,$("nvlrename").value,mySplit(l.dataset.t),mySplit(l.dataset.u))).then(function(){closeModal();vlanRefresh()});
|
||||
}
|
||||
})]);
|
||||
},
|
||||
}));
|
||||
if (v.id == $("vmgmtcur").dataset.id) {
|
||||
act.appendChild(h("span",{class:"ctl", title:t("v_mgmt_tt"), class:"hint", style:"color: var(--fg2); font-size: 150%; padding-left: 10px;"},[document.createTextNode("\u{1F6C8}")]));
|
||||
} else {
|
||||
act.appendChild(h("button", {
|
||||
class: "ctl",
|
||||
text: "\u2715",
|
||||
title: t("v_del_t"),
|
||||
style: "margin-left: 5px;",
|
||||
onclick: function() {
|
||||
confirmModal(t("v_del_q", { n: v.id }), t("v_del_d"), function() {
|
||||
postCmd("vlan " + v.id + " d").then(vlanRefresh).catch(function() {});
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
}).catch(function() {});
|
||||
});
|
||||
return p;
|
||||
});
|
||||
}
|
||||
function buildVlanEdit(){
|
||||
var tb=$("vedit").tBodies[0];
|
||||
if(tb.rows.length||!S.n)return;
|
||||
var hd=tb.insertRow();hd.insertCell().className="mut";
|
||||
var rM=tb.insertRow();rM.insertCell().textContent=t("v_member");
|
||||
var rP=tb.insertRow();rP.insertCell().textContent=t("v_pvid");
|
||||
for(var p=1;p<=S.n;p++)(function(p){
|
||||
hd.insertCell().innerHTML='<b>'+p+'</b>';
|
||||
var seg=h("span",{class:"seg",id:"vm"+p});
|
||||
["-","U","T"].forEach(function(s,ix){
|
||||
seg.appendChild(h("button",{text:s,"data-v":ix,onclick:function(){
|
||||
seg.querySelectorAll("button").forEach(function(b){b.classList.remove("on")});
|
||||
this.classList.add("on");
|
||||
}}));
|
||||
|
||||
function buildVlanEdit() {
|
||||
var tb = $("vedit").tBodies[0];
|
||||
if (tb.rows.length || !S.n) return;
|
||||
var hd = tb.insertRow();
|
||||
hd.insertCell().className = "mut";
|
||||
var rN = tb.insertRow();
|
||||
rN.insertCell().textContent = t("c_name");
|
||||
var rM = tb.insertRow();
|
||||
rM.insertCell().textContent = t("v_member");
|
||||
var rP = tb.insertRow();
|
||||
rP.insertCell().textContent = t("v_pvid");
|
||||
for (var p = 1; p <= S.n; p++)(function(p) {
|
||||
hd.insertCell().innerHTML = '<b>' + p + '</b>';
|
||||
var seg = h("span", { class: "seg", id: "vm" + p });
|
||||
["-", "U", "T"].forEach(function(s, ix) {
|
||||
seg.appendChild(h("button", {
|
||||
text: s,
|
||||
"data-v": ix,
|
||||
onclick: function() {
|
||||
seg.querySelectorAll("button").forEach(function(b) { b.classList.remove("on") });
|
||||
this.classList.add("on");
|
||||
}
|
||||
}));
|
||||
});
|
||||
seg.children[0].classList.add("on");
|
||||
rN.insertCell().appendChild(document.createTextNode((S.ports.filter(x=>x.portNum==p)[0]).name));
|
||||
rM.insertCell().appendChild(seg);
|
||||
rP.insertCell().appendChild(h("input",{type:"checkbox",id:"vp"+p}));
|
||||
rP.insertCell().appendChild(h("span", { id: "vp" + p }));
|
||||
})(p);
|
||||
var it=$("ingress").tBodies[0];
|
||||
var ih=it.insertRow();ih.insertCell().className="mut";
|
||||
var ir=it.insertRow();ir.insertCell().textContent=t("v_accept");
|
||||
for(var q=1;q<=S.n;q++)(function(q){
|
||||
ih.insertCell().innerHTML='<b>'+q+'</b>';
|
||||
var sel=h("select",{class:"in",id:"ing"+q});
|
||||
[["","-"],["a",t("v_ing_all")],["u",t("v_untagged")],["t",t("v_tagged")]].forEach(function(o){
|
||||
sel.appendChild(h("option",{value:o[0],text:o[1]}));
|
||||
});
|
||||
ir.insertCell().appendChild(sel);
|
||||
})(q);
|
||||
}
|
||||
function segVal(p){
|
||||
return Number($("vm"+p).querySelector("button.on").getAttribute("data-v"));
|
||||
}
|
||||
function segSet(p,v){
|
||||
$("vm"+p).querySelectorAll("button").forEach(function(b,i){b.classList.toggle("on",i===v)});
|
||||
}
|
||||
function vlanLoad(){
|
||||
var vid=parseInt($("vvid").value,10);
|
||||
if(!vid||vid<1||vid>4094){toast(t("v_vid_err"),"err");return;}
|
||||
getJSON("/vlan.json?vid="+vid).then(function(d){
|
||||
$("vname").value=d.name||"";
|
||||
var m=parseInt(d.members,16),mem=m&0x3ff,unt=((m>>10)&0x3ff)&mem;
|
||||
var pv=parseInt(d.pvid,16)&0x3ff;
|
||||
for(var p=1;p<=S.n;p++){
|
||||
var bit=S.physToLog[p-1];
|
||||
segSet(p,(mem>>bit)&1?(((unt>>bit)&1)?1:2):0);
|
||||
$("vp"+p).checked=!!((pv>>bit)&1);
|
||||
}
|
||||
toast(t("v_loaded",{n:vid}),"ok");
|
||||
}).catch(function(){toast(t("v_notfound",{n:vid}),"err")});
|
||||
}
|
||||
function vlanApply(){
|
||||
var vid=parseInt($("vvid").value,10);
|
||||
if(!vid||vid<1||vid>4094){toast(t("v_vid_err"),"err");return;}
|
||||
var name=$("vname").value.trim();
|
||||
if(name&&!/^[a-zA-Z]\w*$/.test(name)){toast(t("v_name_err"),"err");return;}
|
||||
var cmd="vlan "+vid+(name?" "+name:""),members=0;
|
||||
for(var p=1;p<=S.n;p++){
|
||||
var v=segVal(p);
|
||||
if(v===1){cmd+=" "+p;members++;}
|
||||
else if(v===2){cmd+=" "+p+"t";members++;}
|
||||
}
|
||||
if(!members){toast(t("v_nomember"),"err");return;}
|
||||
var cmds=[cmd];
|
||||
for(var q=1;q<=S.n;q++)if($("vp"+q).checked)cmds.push("pvid "+q+" "+vid);
|
||||
postCmds(cmds).then(vlanRefresh).catch(function(){});
|
||||
}
|
||||
function ingressApply(){
|
||||
var cmd="ingress",any=false;
|
||||
for(var p=1;p<=S.n;p++){
|
||||
var v=$("ing"+p).value;
|
||||
if(v){cmd+=" "+p+v;any=true;}
|
||||
}
|
||||
if(!any){toast(t("v_ing_none"),"err");return;}
|
||||
postCmd(cmd).catch(function(){});
|
||||
}
|
||||
$("vload").addEventListener("click",vlanLoad);
|
||||
$("vapply").addEventListener("click",vlanApply);
|
||||
$("ingapply").addEventListener("click",ingressApply);
|
||||
$("vmgmt").addEventListener("click",function(){
|
||||
var vid=parseInt($("vvid").value,10);
|
||||
if(!vid){toast(t("v_vid_first"),"err");return;}
|
||||
confirmModal(t("v_mgmt_q",{n:vid}),t("v_mgmt_d"),
|
||||
function(){postCmd("vlan "+vid+" mgmt").then(vlanRefresh).catch(function(){})});
|
||||
});
|
||||
tabHooks.vlan={
|
||||
enter:function(){needPorts(function(){buildVlanEdit();vlanRefresh().catch(function(){})})},
|
||||
};
|
||||
|
||||
function segVal(p) {
|
||||
return Number($("vm" + p).querySelector("button.on").getAttribute("data-v"));
|
||||
}
|
||||
|
||||
function segSet(p, v) {
|
||||
$("vm" + p).querySelectorAll("button").forEach(function(b, i) { b.classList.toggle("on", i === v) });
|
||||
}
|
||||
|
||||
function vlanLoad(vid) {
|
||||
if (!vid || vid < 1 || vid > 4094) {
|
||||
toast(t("v_vid_err"), "err");
|
||||
return;
|
||||
}
|
||||
getJSON("/vlan.json?vid=" + vid).then(function(d) {
|
||||
$("vtitle").innerText = "VLAN " + vid + (d.name ? " (" + (d.name) + ")" : "");
|
||||
$("vtitle").dataset.id = vid;
|
||||
$("vtitle").dataset.name = d.name;
|
||||
var m = parseInt(d.members, 16),
|
||||
mem = m & 0x3ff,
|
||||
unt = ((m >> 10) & 0x3ff) & mem;
|
||||
var pv = parseInt(d.pvid, 16) & 0x3ff;
|
||||
for (var p = 1; p <= S.n; p++) {
|
||||
var bit = S.physToLog[p - 1];
|
||||
segSet(p, (mem >> bit) & 1 ? (((unt >> bit) & 1) ? 1 : 2) : 0);
|
||||
$("vp" + p).innerText = (!!((pv >> bit) & 1))?"Y":"N";
|
||||
}
|
||||
$("vmgmtpromote").checked = ($("vmgmtcur").dataset.id == vid);
|
||||
toast(t("v_loaded", {n: vid}), "ok");
|
||||
for(const vlanRow of $("vtable").tBodies[0].rows) {
|
||||
vlanRow.className=vlanRow.firstChild.firstChild.dataset.id == vid ? "sel":"";
|
||||
}
|
||||
}).catch(function() {toast(t("v_notfound", {n: vid}), "err")});
|
||||
}
|
||||
|
||||
function vlan2str(i, n, t, u){
|
||||
return ("vlan " + i + (n ? " " + n : "") + " " + t.map((x)=>x+"t").concat(u).join(" ")).trim();
|
||||
}
|
||||
function pvidcmd(i, p){
|
||||
return "pvid " + p + " " + i;
|
||||
}
|
||||
function mySplit(a){
|
||||
if(a.trim()=="") return [];
|
||||
return a.trim().split(",");
|
||||
}
|
||||
function vlanApply() {
|
||||
var vid = $("vtitle").dataset.id;
|
||||
var vname = $("vtitle").dataset.name;
|
||||
if (!vid || vid < 1 || vid > 4094) {
|
||||
toast(t("v_vid_err"), "err");
|
||||
return;
|
||||
}
|
||||
var top_cmds = [], tail_cmds = [], vlansPerPort=[], thisVlanInStructure={id:vid, tagged:[], untagged:[]};
|
||||
for (var p = 1; p <= S.n; p++) {
|
||||
var v = segVal(p);
|
||||
vlansPerPort[p]={t:[],u:[]};
|
||||
if (v === 1) {
|
||||
thisVlanInStructure.untagged.push(p);
|
||||
vlansPerPort[p].u.push(vid);
|
||||
} else if (v === 2) {
|
||||
thisVlanInStructure.tagged.push(p);
|
||||
vlansPerPort[p].t.push(vid);
|
||||
}
|
||||
}
|
||||
if (thisVlanInStructure.tagged.length + thisVlanInStructure.untagged.length == 0) {
|
||||
toast(t("v_nomember"), "err");
|
||||
return;
|
||||
}
|
||||
for(const vlanRow of $("vtable").tBodies[0].rows){
|
||||
var rowData = vlanRow.firstChild.firstChild.dataset,
|
||||
rowUntagged = mySplit(rowData.u),
|
||||
rowTagged = mySplit(rowData.t);
|
||||
if(rowData.id == vid) continue;
|
||||
for(const newVlanPort of thisVlanInStructure.untagged) {
|
||||
if(rowUntagged.includes(""+newVlanPort)) rowUntagged.splice(rowUntagged.indexOf(""+newVlanPort),1);
|
||||
}
|
||||
for(const rut of rowUntagged) {
|
||||
vlansPerPort[rut].u.push(rowData.id);
|
||||
}
|
||||
for(const rt of rowTagged) {
|
||||
vlansPerPort[rt].t.push(rowData.id)
|
||||
}
|
||||
top_cmds.push(vlan2str(rowData.id,rowData.name,rowTagged,rowUntagged));
|
||||
}
|
||||
tail_cmds.push(vlan2str(vid, vname, thisVlanInStructure.tagged, thisVlanInStructure.untagged));
|
||||
|
||||
for (p in vlansPerPort){/*park all ports with only tagged membership*/
|
||||
if (vlansPerPort[p].u.length == 0 && vlansPerPort[p].t.length > 0) {
|
||||
tail_cmds.push(pvidcmd(0, p));
|
||||
}
|
||||
}
|
||||
for(const up of thisVlanInStructure.untagged){
|
||||
tail_cmds.push(pvidcmd(vid,up));
|
||||
}
|
||||
if($("vmgmtpromote").checked){/*must be the last command*/
|
||||
tail_cmds.push("vlan " + vid + " mgmt");
|
||||
}
|
||||
var cmd = top_cmds.concat(tail_cmds);
|
||||
postCmd(cmd.join("\n"),true).then(function(){toast(t("t_cmds",{n:cmd.length}),"ok")}).then(vlanRefresh).catch(function() {}).then(function() {
|
||||
vlanLoad(vid)
|
||||
});
|
||||
}
|
||||
$("vapply").addEventListener("click", vlanApply);
|
||||
$("vlan_add").addEventListener("click", function() {
|
||||
var body = h("div");
|
||||
body.appendChild(h("p", null, [
|
||||
h("label", {class: "row"}, [
|
||||
h("span",{class:"lb", "data-i18n":"v_vid"},[document.createTextNode(t("v_vid"))]),
|
||||
h("input", {id: "nvlid", class: "in sm", type: "number", min: "1", max: "4094"})
|
||||
])
|
||||
]));
|
||||
body.appendChild(h("p", null, [
|
||||
h("label", {class: "row"}, [
|
||||
h("span",{class:"lb", "data-i18n":"c_name"},[document.createTextNode(t("c_name"))]),
|
||||
h("input", {id: "nvlname", class: "in", size: "12", maxlength: "15", "data-i18n-p": "v_optional"})
|
||||
])
|
||||
]));
|
||||
modal("Add VLAN", body, [h("button", {
|
||||
class: "ctl pri", text: t("v_add"),
|
||||
onclick: addVlan
|
||||
})]);
|
||||
});
|
||||
function validVlanName(n){
|
||||
if (n && (!/^[a-zA-Z]\w*$/.test(n) || n == "d" || n == "mgmt")) {
|
||||
toast(t("v_name_err"), "err");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function addVlan() {
|
||||
var vid = parseInt($("nvlid").value, 10);
|
||||
for (const r of $("vtable").tBodies[0].rows) {
|
||||
if (r.firstChild.firstChild.dataset.id == vid) {
|
||||
toast(t("v_vid_err"), "err");
|
||||
return;
|
||||
}
|
||||
}
|
||||
var name = $("nvlname").value;
|
||||
if(!validVlanName(name)) return false;
|
||||
var cmd = "vlan " + vid + (name ? " " + name : "");
|
||||
postCmd(cmd).then(function() {
|
||||
closeModal();
|
||||
vlanRefresh().then(function(){vlanLoad(vid)});
|
||||
}).catch(function() {});
|
||||
}
|
||||
tabHooks.vlan = {
|
||||
enter: function() {
|
||||
needPorts(function() {
|
||||
buildVlanEdit();
|
||||
vlanRefresh().catch(function() {}).then(function() {
|
||||
VlanInit();
|
||||
})
|
||||
})
|
||||
},
|
||||
};
|
||||
function VlanInit() {
|
||||
vlanLoad($("vtable").tBodies[0].firstChild.firstChild.firstChild.dataset.id)
|
||||
};
|
||||
var l2Rows=[],l2SortCol="pport",l2SortDir=1,l2Gen=0;
|
||||
function l2Load(){
|
||||
var seen={},all=[],idx=0,guard=0,gen=++l2Gen;
|
||||
@@ -2258,14 +2415,14 @@ var CONF_OVERWRITE=[
|
||||
/^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/,
|
||||
/^port\s+\d{1,2}(?!\s+(name|lldp)\b)/,/^port\s+\d{1,2}\s+name\b/,
|
||||
/^mirror\b/,
|
||||
/^lag\s+\d\b/,/^laghash\s+\d\b/,/^isolate\s+\d{1,2}\b/,
|
||||
/^stp\s+(prio|hello|maxage|fwd|txhold|version)\b/,
|
||||
/^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)$/,/^(ntp)\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)$/,/^(lldp)\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)})}
|
||||
@@ -2283,6 +2440,7 @@ function mergeConf(base,texts){
|
||||
}
|
||||
if((m=line.match(/^lag (\d) lacp off$/))){drop(new RegExp("^lag "+m[1]+" lacp( |$)"));return;}
|
||||
if(line==="mirror off"){drop(/^mirror /);return;}
|
||||
if((m=line.match(/^(port \d{1,2} lldp) (permit|block)$/))){drop(new RegExp("^"+m[1]+" (permit|block)$"));conf.push(line);return;}
|
||||
if(!isConfCmd(line))return;
|
||||
if((m=line.match(/^ingress (.+)$/))){
|
||||
if(/^[tua]$/.test(m[1])){drop(/^ingress /);conf.push(line);return;}
|
||||
@@ -2315,7 +2473,7 @@ function mergeConf(base,texts){
|
||||
var key=line.match(rx)[0];
|
||||
conf=conf.filter(function(item){
|
||||
return!(item===key||(item.indexOf(key+" ")===0
|
||||
&&!/\smgmt$/.test(item)&&item.indexOf(key+" name ")!==0));
|
||||
&&!/\smgmt$/.test(item)&&item.indexOf(key+" name ")!==0&&item.indexOf(key+" lldp ")!==0));
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
html,body{height:100%}
|
||||
body{
|
||||
font:14px/1.45 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
|
||||
background:var(--bg);color:var(--fg);display:flex;
|
||||
background:var(--bg);color:var(--fg);display:flex;overflow:hidden;
|
||||
}
|
||||
button,input,select,textarea{font:inherit;color:var(--fg)}
|
||||
a{color:var(--ac);text-decoration:none}
|
||||
@@ -55,11 +55,11 @@ a{color:var(--ac);text-decoration:none}
|
||||
#navfoot{padding:10px 16px;border-top:1px solid var(--bd);font-size:12px;color:var(--fg2)}
|
||||
#wrap{flex:1;min-width:0;display:flex;flex-direction:column}
|
||||
#top{
|
||||
display:flex;align-items:center;gap:10px;padding:10px 20px;
|
||||
display:flex;align-items:center;flex-wrap:wrap;gap:10px;padding:8px 20px;
|
||||
background:var(--panel);border-bottom:1px solid var(--bd);position:sticky;top:0;z-index:5;
|
||||
}
|
||||
#burger{display:none;background:none;border:0;cursor:pointer;padding:4px}
|
||||
#ttitle{font-size:16px;font-weight:650;flex:1}
|
||||
#ttitle{font-size:16px;font-weight:650;min-width:120px}
|
||||
#dirty{
|
||||
display:none;font-size:12px;font-weight:600;color:var(--warn);
|
||||
border:1px solid var(--warn);border-radius:20px;padding:2px 10px;
|
||||
@@ -72,8 +72,8 @@ select.ctl,button.ctl{
|
||||
button.pri{background:var(--ac);color:var(--acfg);border-color:transparent;font-weight:600}
|
||||
button.pri:hover,button.ctl:hover{filter:brightness(1.07)}
|
||||
button:disabled{opacity:.45;cursor:default;filter:none}
|
||||
main{padding:18px 20px 40px;max-width:1400px;width:100%}
|
||||
section.tab{display:none}
|
||||
main{padding:18px 20px 40px;width:100%;overflow-y:auto;}
|
||||
section.tab{display:none;max-width:1400px;}
|
||||
section.tab.act{display:block}
|
||||
.card{
|
||||
background:var(--panel);border:1px solid var(--bd);border-radius:10px;
|
||||
@@ -89,9 +89,11 @@ table.t th{
|
||||
padding:6px 8px;border-bottom:1px solid var(--bd);white-space:nowrap;
|
||||
}
|
||||
table.t th[data-sort]{cursor:pointer;user-select:none}
|
||||
table.t th.num{text-align:right}
|
||||
table.t td{padding:6px 8px;border-bottom:1px solid var(--bd);vertical-align:middle}
|
||||
table.t tr:last-child td{border-bottom:0}
|
||||
table.t tr:hover td{background:var(--sel)}
|
||||
table.t tr.sel{background:var(--panel2); font-weight: bold;}
|
||||
.num{font-variant-numeric:tabular-nums;text-align:right}
|
||||
.scrollx{overflow-x:auto}
|
||||
input.in,select.in,textarea.in{
|
||||
@@ -112,21 +114,31 @@ label.row span.lb{width:110px;flex:none;color:var(--fg2);font-size:13px}
|
||||
}
|
||||
.switch input:checked+i{background:var(--ok)}
|
||||
.switch input:checked+i:before{transform:translateX(15px)}
|
||||
#strip{display:flex;gap:8px;flex-wrap:wrap;padding:4px 0 2px}
|
||||
#strip{display:flex;gap:6px;flex:1;min-width:0;overflow-x:auto;scrollbar-width:thin}
|
||||
.port:first-child{margin-left:auto}
|
||||
.port:last-child{margin-right:auto}
|
||||
.port{
|
||||
width:46px;border:2px solid var(--bd);border-radius:7px;padding:5px 0 3px;
|
||||
width:40px;border:2px solid var(--bd);border-radius:7px;padding:3px 0 2px;
|
||||
text-align:center;cursor:pointer;background:var(--panel2);position:relative;
|
||||
}
|
||||
.port.sfp{width:56px}
|
||||
.port .pn{font-weight:650;font-size:13px}
|
||||
.port .ps{font-size:10px;color:var(--fg2);display:block;line-height:1.2}
|
||||
.port.sfp{width:50px}
|
||||
.port .pn{font-weight:650;font-size:12px}
|
||||
.port .ps{font-size:9px;color:var(--fg2);display:block;line-height:1.2}
|
||||
.port .jack{
|
||||
display:block;width:18px;height:12px;margin:3px auto 2px;border-radius:2px;
|
||||
border:2px solid var(--fg2);border-top-width:5px;opacity:.55;
|
||||
display:block;width:21px;height:12px;margin:4px auto 2px;border-radius:2px;
|
||||
border:2px solid var(--fg2);border-top-width:8px;opacity:.55;position:relative;
|
||||
}
|
||||
.port.sfp .jack{width:28px;height:10px;border-top-width:3px}
|
||||
.port .jack:before{content:"";
|
||||
position:absolute;bottom:100%;left:50%;transform:translateX(-50%);
|
||||
width:6px;height:5px;margin-bottom:7px;border-radius: 1px 1px 0 0;
|
||||
background-color:var(--fg2);
|
||||
}
|
||||
.port.sfp .jack{width:24px;height:16px;margin:0 auto 2px;border-top-width:5px}
|
||||
.port.sfp .jack:before{width:10px;margin-bottom:2px;border-radius:0 0 1px 1px;background-color:var(--panel2)}
|
||||
.port.up{border-color:var(--pc);background:color-mix(in srgb,var(--pc) 10%,var(--panel2))}
|
||||
.port.up .jack{border-color:var(--pc);opacity:1}
|
||||
.port.up .jack:before{background-color:var(--pc)}
|
||||
.port.up.sfp .jack:before{background-color:color-mix(in srgb,var(--pc) 10%,var(--panel2))}
|
||||
.port.up .ps{color:var(--pc);font-weight:600}
|
||||
.port.dis{opacity:.45;border-style:dashed}
|
||||
.badge{font-size:11px;font-weight:600;border-radius:10px;padding:1px 8px;background:var(--panel2);color:var(--fg2)}
|
||||
@@ -183,6 +195,10 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
|
||||
#ttitle{font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
#dirty{padding:2px 7px}
|
||||
}
|
||||
@media (max-width:720px){
|
||||
#ttitle{flex:1}
|
||||
#strip{order:3;flex-basis:100%}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
(function(){
|
||||
@@ -215,15 +231,13 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--fg)" stroke-width="2"><path d="M4 6h16M4 12h16M4 18h16"/></svg>
|
||||
</button>
|
||||
<span id="ttitle"></span>
|
||||
<div id="strip"></div>
|
||||
<span id="dirty" data-i18n="hdr_dirty" data-i18n-t="hdr_dirty_t">unsaved changes</span>
|
||||
<button class="ctl pri" id="saveBtn" data-i18n="hdr_save" data-i18n-t="hdr_save_t">Save to flash</button>
|
||||
<button class="ctl" id="saveBtn" data-i18n="hdr_save" data-i18n-t="hdr_save_t">Save to flash</button>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="tab act" id="tab-dash">
|
||||
<div class="card"><h2><span data-i18n="d_ports">Ports</span> <span class="hint" data-i18n="d_ports_h">click a port for details</span></h2>
|
||||
<div id="strip"></div>
|
||||
</div>
|
||||
<div class="grid2">
|
||||
<div class="card"><h2 data-i18n="d_system">System</h2><table class="t" id="sysinfo"></table></div>
|
||||
<div class="card"><h2><span data-i18n="d_traffic">Traffic</span> <span class="hint" data-i18n="d_traffic_h">packets/s, live</span></h2>
|
||||
@@ -237,7 +251,7 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
|
||||
<section class="tab" id="tab-ports">
|
||||
<div class="card"><h2 data-i18n="pt_title">Port configuration</h2>
|
||||
<div class="scrollx"><table class="t" id="ptable">
|
||||
<thead><tr><th data-i18n="c_port">Port</th><th data-i18n="c_name">Name</th><th data-i18n="c_link">Link</th><th data-i18n="pt_conn">Connected</th><th data-i18n="pt_speed">Speed</th><th data-i18n="c_enabled">Enabled</th><th data-i18n="pt_mtu">MTU</th><th></th></tr></thead>
|
||||
<thead><tr><th data-i18n="c_port">Port</th><th data-i18n="c_name">Name</th><th data-i18n="c_link">Link</th><th data-i18n="pt_conn">Devices learned</th><th data-i18n="pt_speed">Speed</th><th data-i18n="c_enabled">Enabled</th><th data-i18n="pt_mtu">MTU</th><th></th></tr></thead>
|
||||
<tbody></tbody></table></div>
|
||||
<p class="small mut" style="margin-top:8px" data-i18n="pt_sfp_note">SFP speed is set per slot and is not saved in the startup config.</p>
|
||||
</div>
|
||||
@@ -281,27 +295,21 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
|
||||
</section>
|
||||
|
||||
<section class="tab" id="tab-vlan">
|
||||
<div class="card"><h2><span data-i18n="v_title">VLANs</span> <span class="hint"><span data-i18n="v_mgmt">Management VLAN</span>: <span id="vmgmtcur">-</span></span></h2>
|
||||
<div class="card"><h2><span data-i18n="v_title">VLANs</span><span id="vmgmtcur"></span></h2>
|
||||
<div class="scrollx"><table class="t" id="vtable">
|
||||
<thead><tr><th data-i18n="v_vid">VID</th><th data-i18n="c_name">Name</th><th data-i18n="v_members">Members</th><th data-i18n="v_tagged">Tagged</th><th data-i18n="v_untagged">Untagged</th><th data-i18n="v_pvid_on">PVID on</th><th></th></tr></thead>
|
||||
<tbody></tbody></table></div>
|
||||
<p class="small mut" id="vempty" style="display:none;margin-top:6px" data-i18n="v_empty">No VLANs configured.</p>
|
||||
<button class="ctl pri" id="vlan_add" data-i18n="v_add">Add a new VLAN</button>
|
||||
</div>
|
||||
<div class="card"><h2 data-i18n="v_editor">VLAN editor</h2>
|
||||
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:10px">
|
||||
<label><span data-i18n="v_vid">VID</span> <input class="in sm" id="vvid" type="number" min="1" max="4094"></label>
|
||||
<label><span data-i18n="c_name">Name</span> <input class="in" id="vname" size="12" maxlength="15" data-i18n-p="v_optional"></label>
|
||||
<button class="ctl" id="vload" data-i18n="c_load">Load</button>
|
||||
<button class="ctl pri" id="vapply" data-i18n="c_apply">Apply</button>
|
||||
<button class="ctl" id="vmgmt" data-i18n="v_setmgmt" data-i18n-t="v_setmgmt_t">Set as mgmt VLAN</button>
|
||||
</div>
|
||||
<div class="card"><h2><span data-i18n="v_editor">VLAN editor</span> <span class="hint" id="vtitle"></span></h2>
|
||||
<div><label class="row"><span class="lb" style="width:150px;" data-i18n="v_setmgmt_t"></span>
|
||||
<span class="switch"><input type="checkbox" id="vmgmtpromote"><i></i></span>
|
||||
</label></div>
|
||||
<div class="scrollx"><table class="t" id="vedit"><tbody></tbody></table></div>
|
||||
<div style="margin-top:10px"><button class="ctl pri" id="vapply" data-i18n="c_apply">Apply</button></div>
|
||||
<p class="small mut" style="margin-top:6px" data-i18n="v_legend">U = untagged member, T = tagged member, - = not a member. PVID assigns this VLAN to untagged ingress traffic.</p>
|
||||
</div>
|
||||
<div class="card"><h2><span data-i18n="v_ingress">Ingress filtering</span> <span class="hint" data-i18n="v_ingress_h">write-only: the state is not readable from the switch</span></h2>
|
||||
<div class="scrollx"><table class="t" id="ingress"><tbody></tbody></table></div>
|
||||
<div style="margin-top:10px"><button class="ctl pri" id="ingapply" data-i18n="v_ing_apply">Apply ingress modes</button></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="tab" id="tab-l2">
|
||||
@@ -433,8 +441,8 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
|
||||
<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>
|
||||
<label class="row"><span class="lb" data-i18n="sy_newpw">New password</span><input class="in" id="sy-pw1" type="password" autocomplete="new-password" maxlength="20"></label>
|
||||
<label class="row"><span class="lb" data-i18n="sy_repeat">Repeat</span><input class="in" id="sy-pw2" type="password" autocomplete="new-password" maxlength="20"></label>
|
||||
<button class="ctl pri" id="sy-pwapply" style="margin-top:8px" data-i18n="sy_pwapply">Change password</button>
|
||||
<p class="small mut" style="margin-top:8px" data-i18n="sy_pw_note">Takes effect immediately; save to flash to keep it after reboot.</p>
|
||||
</div>
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
#include "cmd_parser.h"
|
||||
#include "rtl837x_flash.h"
|
||||
#include "uip.h"
|
||||
#include "sessions.h"
|
||||
#include "html_data.h"
|
||||
|
||||
// #define DEBUG
|
||||
#include "debug.h"
|
||||
|
||||
#define SESSION_ID_LENGTH 12
|
||||
#define SESSION_TIMEOUT_DEFAULT 200
|
||||
|
||||
/* Seconds of inactivity after which a session cookie stops validating.
|
||||
@@ -55,8 +55,8 @@ __xdata uint8_t boundary[72];
|
||||
#define CONFIG_UPLOAD_BUF (CONFIG_LEN + 384)
|
||||
__xdata uint8_t config_upload;
|
||||
__xdata uint8_t config_buf[CONFIG_UPLOAD_BUF];
|
||||
// bytes buffered in config_buf so far (config body, or a firmware part
|
||||
// header); accumulates across TCP segments
|
||||
// bytes buffered in config_buf so far (HTTP header, POST body, or a firmware
|
||||
// part header); accumulates across TCP segments
|
||||
__xdata uint16_t pre_acc;
|
||||
__xdata uint8_t * __xdata content_type = 0;
|
||||
__xdata uint8_t * __xdata session = 0;
|
||||
@@ -75,13 +75,9 @@ __xdata uint8_t postbody_endpoint;
|
||||
__xdata uint16_t postbody_start;
|
||||
|
||||
__xdata char passwd[21];
|
||||
// Set when a verified firmware upload awaits its response ACK, after
|
||||
// which the chip resets to apply the staged image
|
||||
__xdata uint8_t fw_reset_pending;
|
||||
__xdata char session_id[SESSION_ID_LENGTH + 1];
|
||||
// Up to four logins at once, see sessions.c
|
||||
__xdata uint8_t authenticated;
|
||||
__xdata uint32_t now;
|
||||
__xdata uint32_t last_session_use;
|
||||
|
||||
#define TSTATE_NONE 0
|
||||
#define TSTATE_TX 1
|
||||
@@ -90,6 +86,7 @@ __xdata uint32_t last_session_use;
|
||||
#define TSTATE_POST 4
|
||||
#define TSTATE_MULTIPART 5
|
||||
#define TSTATE_POSTBODY 6
|
||||
#define TSTATE_HEADER 7
|
||||
|
||||
extern __xdata uint16_t crc_value;
|
||||
__xdata uint16_t crc_final;
|
||||
@@ -109,8 +106,9 @@ void httpd_init(void) __banked
|
||||
uip_listen(HTONS(80));
|
||||
// Not through uip_conn: it only points at a connection while uIP is
|
||||
// handling one, and nothing has set it yet at init time.
|
||||
uip_conns[0].appstate.tstate = TSTATE_CLOSED;
|
||||
fw_reset_pending = 0; // xdata is not zeroed by the startup code
|
||||
for (uint8_t i = 0; i < UIP_CONNS; i++)
|
||||
uip_conns[i].appstate.tstate = TSTATE_CLOSED;
|
||||
session_init();
|
||||
}
|
||||
|
||||
|
||||
@@ -345,38 +343,11 @@ __xdata uint8_t *scan_header(__xdata uint8_t * __xdata p)
|
||||
|
||||
read_reg_timer(&now);
|
||||
|
||||
if (session && session_id[0]) {
|
||||
if (now - last_session_use > session_timeout) {
|
||||
dbg_string("Session expired\n");
|
||||
} else {
|
||||
if (is_word_x(session, session_id)) {
|
||||
authenticated = 1;
|
||||
last_session_use = now;
|
||||
} else {
|
||||
dbg_string("Invalid session cookie!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (session)
|
||||
session_check();
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate random HEX-chars at the buffer location.
|
||||
*/
|
||||
void gen_random_hex_chars(__xdata uint8_t * b, __xdata uint8_t bytes)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
while (bytes) {
|
||||
if (!i)
|
||||
get_random_32();
|
||||
b[--bytes] = itohex(sfr_data[i]);
|
||||
if (!bytes) { break; }
|
||||
b[--bytes] = itohex(sfr_data[i] >> 4 | sfr_data[i] << 4);
|
||||
i = (i + 1) & 0x3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 0: body incomplete, 1: configuration stored, 2: malformed */
|
||||
static uint8_t config_take(void)
|
||||
{
|
||||
@@ -450,15 +421,9 @@ static uint8_t config_take(void)
|
||||
// unlike scan_header(), keeps no auth state, so it may run on every buffered segment
|
||||
static uint16_t preamble_payload_start(uint16_t n)
|
||||
{
|
||||
uint16_t pos;
|
||||
// Skip the HTTP header separator retained by handle_post().
|
||||
uint16_t pos = 4;
|
||||
|
||||
for (pos = 0; pos + 24 <= n; pos++) {
|
||||
if (strstart(&config_buf[pos], "application/octet-stream"))
|
||||
break;
|
||||
}
|
||||
if (pos + 24 > n)
|
||||
return 0;
|
||||
pos += 24;
|
||||
while (pos + 3 < n && !strstart(&config_buf[pos], "\r\n\r\n"))
|
||||
pos++;
|
||||
if (pos + 3 >= n)
|
||||
@@ -511,7 +476,7 @@ uint8_t stream_upload(void)
|
||||
"Content-Type: text/plain\r\n\r\n"
|
||||
"OK: checksum verified, rebooting\n");
|
||||
// Reset once the response is fully ACKed
|
||||
fw_reset_pending = 1;
|
||||
s->fw_reset_pending = 1;
|
||||
} else {
|
||||
print_string("Checksum incorrect! Aborting.\n");
|
||||
slen = strtox(outbuf, "HTTP/1.1 400 Bad Request\r\nContent-Length: 33\r\n"
|
||||
@@ -539,9 +504,10 @@ uint8_t stream_upload(void)
|
||||
memcpy(flash_buf + write_len, boundary, bindex);
|
||||
write_len += bindex;
|
||||
bindex = 0;
|
||||
} else {
|
||||
crc16_bank1(upload_settings.p + upload_settings.bptr);
|
||||
flash_buf[write_len++] = upload_settings.p[upload_settings.bptr++];
|
||||
}
|
||||
crc16_bank1(upload_settings.p + upload_settings.bptr);
|
||||
flash_buf[write_len++] = upload_settings.p[upload_settings.bptr++];
|
||||
if (write_len >= FLASH_PAGE_SIZE) {
|
||||
/* The staged image spans FIRMWARE_UPLOAD_START to twice that,
|
||||
* the span check_and_flash_update_image() reads back. Nothing
|
||||
@@ -573,7 +539,6 @@ uint8_t stream_upload(void)
|
||||
memcpy(flash_buf, flash_buf + FLASH_PAGE_SIZE, write_len);
|
||||
}
|
||||
}
|
||||
bindex = 0;
|
||||
}
|
||||
} while(1);
|
||||
}
|
||||
@@ -683,13 +648,10 @@ static void run_login_body(__xdata uint8_t *body)
|
||||
{
|
||||
if (strstart(body, "pwd=") && is_url_word_x(body + 4, passwd)) {
|
||||
dbg_string("Password accepted!\n");
|
||||
read_reg_timer(&last_session_use);
|
||||
gen_random_hex_chars(session_id, SESSION_ID_LENGTH);
|
||||
session_id[SESSION_ID_LENGTH] = NUL;
|
||||
read_reg_timer(&now);
|
||||
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\nConnection: close\r\nLocation: index.html\r\n" \
|
||||
"Set-Cookie: session=");
|
||||
for (uint8_t i = 0; i < SESSION_ID_LENGTH; i++)
|
||||
outbuf[slen++] = session_id[i];
|
||||
session_new();
|
||||
slen += strtox(outbuf + slen, "; SameSite=Strict\r\n\r\n");
|
||||
} else {
|
||||
dbg_string("Password invalid!\n");
|
||||
@@ -746,7 +708,42 @@ static void post_body_continue(void)
|
||||
}
|
||||
|
||||
|
||||
void handle_post(void)
|
||||
|
||||
/*
|
||||
* Buffer an HTTP request header across TCP receive events. Stop copying at
|
||||
* CRLFCRLF so any body bytes in the final segment stay in uip_appdata.
|
||||
*
|
||||
* Return the body offset in the current receive buffer, 0 while incomplete,
|
||||
* or 0xffff after sending an error response.
|
||||
*/
|
||||
static uint16_t request_header_take(void)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
for (i = 0; i < uip_len; i++) {
|
||||
if (pre_acc + 1 >= CONFIG_UPLOAD_BUF) {
|
||||
uip_conn->appstate.tstate = TSTATE_NONE;
|
||||
send_bad_request();
|
||||
return 0xffff;
|
||||
}
|
||||
config_buf[pre_acc++] = ((__xdata uint8_t *)uip_appdata)[i];
|
||||
config_buf[pre_acc] = NUL;
|
||||
if (pre_acc >= 4
|
||||
&& config_buf[pre_acc - 4] == '\r'
|
||||
&& config_buf[pre_acc - 3] == '\n'
|
||||
&& config_buf[pre_acc - 2] == '\r'
|
||||
&& config_buf[pre_acc - 1] == '\n') {
|
||||
uip_conn->appstate.tstate = TSTATE_NONE;
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
postbody_start = ticks;
|
||||
uip_conn->appstate.tstate = TSTATE_HEADER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void handle_post(uint16_t body_off)
|
||||
{
|
||||
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
|
||||
__xdata uint8_t *p = uip_appdata;
|
||||
@@ -759,6 +756,9 @@ void handle_post(void)
|
||||
|
||||
// Was the multipart header sent in multiple packets?
|
||||
if (s->tstate != TSTATE_MULTIPART) {
|
||||
p = config_buf;
|
||||
request_path = p + 6;
|
||||
|
||||
dbg_string("Is POST\n");
|
||||
p += 5; // Skip post
|
||||
// Find end of request path
|
||||
@@ -772,9 +772,12 @@ void handle_post(void)
|
||||
dbg_string("Boundary: >"); dbg_string_x(boundary); dbg_string("<\n");
|
||||
if (!*p || !content_type) {
|
||||
dbg_string("Bad Request!\n");
|
||||
send_not_found();
|
||||
send_bad_request();
|
||||
return;
|
||||
}
|
||||
|
||||
pre_acc = 0;
|
||||
p = (__xdata uint8_t *)uip_appdata + body_off;
|
||||
if (is_word(request_path, "upload")) {
|
||||
if (!authenticated) {
|
||||
send_unauthorized();
|
||||
@@ -800,7 +803,10 @@ void handle_post(void)
|
||||
dbg_string("Configuration upload\n");
|
||||
verify_crc = 0;
|
||||
config_upload = 1;
|
||||
pre_acc = 0;
|
||||
// config_take() matches CRLF-prefixed delimiters, including the first.
|
||||
config_buf[0] = '\r';
|
||||
config_buf[1] = '\n';
|
||||
pre_acc = 2;
|
||||
}
|
||||
// Check for other POST requests, which are not multipart, below
|
||||
} else {
|
||||
@@ -824,7 +830,6 @@ void handle_post(void)
|
||||
handle_firmware_fragment(p);
|
||||
return;
|
||||
} else if (is_word(request_path, "cmd")) {
|
||||
p += 4;
|
||||
if (!authenticated) {
|
||||
send_unauthorized();
|
||||
return;
|
||||
@@ -843,7 +848,6 @@ void handle_post(void)
|
||||
return;
|
||||
}
|
||||
|
||||
p += 4;
|
||||
postbody_endpoint = POSTBODY_LOGIN;
|
||||
if (!post_body_take(p))
|
||||
return;
|
||||
@@ -874,9 +878,10 @@ void httpd_appcall(void)
|
||||
print_byte(s->tstate);
|
||||
write_char(' ');
|
||||
#endif
|
||||
if(uip_connected() && s->tstate == TSTATE_CLOSED) {
|
||||
if(uip_connected()) {
|
||||
dbg_string("Connected...\n");
|
||||
s->tstate = TSTATE_NONE;
|
||||
s->fw_reset_pending = 0; // explicitly initialize reused XDATA appstate
|
||||
} else if (uip_closed()) {
|
||||
dbg_string("Connection closed\n");
|
||||
s->tstate = TSTATE_CLOSED;
|
||||
@@ -890,9 +895,9 @@ void httpd_appcall(void)
|
||||
dbg_string("Closing because everything has been transmitted\n");
|
||||
uip_close();
|
||||
s->tstate = TSTATE_CLOSED;
|
||||
} else if (s->tstate == TSTATE_POSTBODY
|
||||
} else if ((s->tstate == TSTATE_POSTBODY || s->tstate == TSTATE_HEADER)
|
||||
&& (uint16_t)ticks - postbody_start > POSTBODY_TIMEOUT) {
|
||||
dbg_string("Body never arrived\n");
|
||||
dbg_string("HTTP request never completed\n");
|
||||
uip_abort();
|
||||
s->tstate = TSTATE_CLOSED;
|
||||
}
|
||||
@@ -928,7 +933,7 @@ void httpd_appcall(void)
|
||||
cont_len -= slen;
|
||||
cont_addr += slen;
|
||||
s->tstate = TSTATE_TX;
|
||||
} else if (fw_reset_pending) {
|
||||
} else if (s->fw_reset_pending) {
|
||||
// The upload verdict has been fully ACKed by the client;
|
||||
// now it is safe to reset and apply the staged image
|
||||
print_string("Resetting to apply update\n");
|
||||
@@ -955,6 +960,7 @@ void httpd_appcall(void)
|
||||
cont_len = 0;
|
||||
dbg_char('<'); dbg_short(uip_len); dbg_char('\n');
|
||||
__xdata uint8_t *p = uip_appdata;
|
||||
uint16_t body_off = 0;
|
||||
// Mark end of request header with \0
|
||||
p[uip_len] = 0;
|
||||
#ifdef DEBUG
|
||||
@@ -963,9 +969,21 @@ void httpd_appcall(void)
|
||||
dbg_char('\n');
|
||||
#endif
|
||||
p = uip_appdata;
|
||||
if (is_word(p, "POST") || s->tstate == TSTATE_MULTIPART
|
||||
|| s->tstate == TSTATE_POSTBODY) {
|
||||
handle_post();
|
||||
if (s->tstate != TSTATE_MULTIPART && s->tstate != TSTATE_POSTBODY) {
|
||||
if (s->tstate != TSTATE_HEADER)
|
||||
pre_acc = 0;
|
||||
body_off = request_header_take();
|
||||
if (!body_off) {
|
||||
uip_len = 0;
|
||||
return;
|
||||
}
|
||||
if (body_off == 0xffff)
|
||||
goto do_send;
|
||||
}
|
||||
|
||||
if (s->tstate == TSTATE_MULTIPART || s->tstate == TSTATE_POSTBODY
|
||||
|| is_word(config_buf, "POST")) {
|
||||
handle_post(body_off);
|
||||
// If this is an ongoing post stream, then wait for the next packet
|
||||
if (s->tstate == TSTATE_POST || s->tstate == TSTATE_MULTIPART
|
||||
|| s->tstate == TSTATE_POSTBODY) {
|
||||
@@ -975,12 +993,11 @@ void httpd_appcall(void)
|
||||
goto do_send;
|
||||
}
|
||||
|
||||
// We only expect a GET request here.
|
||||
p = config_buf;
|
||||
if (!is_word(p, "GET")) {
|
||||
send_bad_request();
|
||||
goto do_send;
|
||||
}
|
||||
|
||||
dbg_string("GET request ");
|
||||
p += 4;
|
||||
scan_header(p);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
for each TCP connection. */
|
||||
typedef struct httpd_state {
|
||||
uint8_t tstate;
|
||||
uint8_t fw_reset_pending;
|
||||
} uip_tcp_appstate_t;
|
||||
|
||||
/* Finally we define the application function to be called by uIP. */
|
||||
|
||||
@@ -341,7 +341,7 @@ void send_vlan(uint16_t vlan)
|
||||
}
|
||||
slen += strtox(outbuf + slen, "\",\"pvid\":\"0x");
|
||||
uint16_t pvid_mask = 0;
|
||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||
for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) {
|
||||
if (port_pvid_get(i) == vlan)
|
||||
pvid_mask |= (1 << i);
|
||||
}
|
||||
@@ -357,7 +357,7 @@ void send_vlan(uint16_t vlan)
|
||||
bool send_counters(uint8_t phys_port)
|
||||
{
|
||||
uint8_t phys_port_idx = phys_port - 1;
|
||||
if (phys_port_idx > (machine.max_port - machine.min_port))
|
||||
if (phys_port_idx > (MACHINE_MAX_PORT - MACHINE_MIN_PORT))
|
||||
goto err;
|
||||
uint8_t log_port = machine.phys_to_log_port[phys_port_idx];
|
||||
|
||||
@@ -676,7 +676,7 @@ void send_stp(void)
|
||||
slen += strtox(outbuf + slen, "\",\"ports\":[");
|
||||
reg_read_m(RTL837X_MSTP_STATES);
|
||||
for (i = 0; i < STP_ENTITIES; i++) {
|
||||
if (i < STP_LAG_BASE && (i < machine.min_port || i > machine.max_port))
|
||||
if (i < STP_LAG_BASE && !MACHINE_PORT_VALID(i))
|
||||
continue;
|
||||
if (i < STP_LAG_BASE && stp_ent_of[i] != i)
|
||||
continue;
|
||||
@@ -761,7 +761,7 @@ void send_lacp(void)
|
||||
}
|
||||
slen -= 1; // remove comma
|
||||
slen += strtox(outbuf + slen, "],\"ports\":[");
|
||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||
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\":");
|
||||
@@ -793,7 +793,7 @@ void send_lldp(void)
|
||||
bool_to_html(lldp_enabled);
|
||||
slen += strtox(outbuf + slen, ",\"portStatus\":[");
|
||||
|
||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||
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]);
|
||||
|
||||
@@ -808,7 +808,7 @@ void send_lldp(void)
|
||||
bool_to_html(1 & (lldp_logical_port_status >> i));
|
||||
slen += strtox(outbuf + slen, "}");
|
||||
|
||||
if (i < machine.max_port)
|
||||
if (i < MACHINE_MAX_PORT)
|
||||
char_to_html(',');
|
||||
else
|
||||
char_to_html(']');
|
||||
@@ -825,7 +825,7 @@ void send_eee(void)
|
||||
uint8_t eee_ablty = sfr_data[3];
|
||||
|
||||
char_to_html('[');
|
||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||
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]);
|
||||
|
||||
@@ -857,7 +857,7 @@ void send_eee(void)
|
||||
bool_to_html(eee_ablty & (1 << i));
|
||||
}
|
||||
char_to_html('}');
|
||||
if (i < machine.max_port)
|
||||
if (i < MACHINE_MAX_PORT)
|
||||
char_to_html(',');
|
||||
else
|
||||
char_to_html(']');
|
||||
@@ -870,7 +870,7 @@ void send_bandwidth(void)
|
||||
dbg_string("send_bandwidth called\n");
|
||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||
char_to_html('[');
|
||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||
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, ",\"iLimited\":");
|
||||
@@ -900,7 +900,7 @@ void send_bandwidth(void)
|
||||
byte_to_html(sfr_data[3]);
|
||||
char_to_html('"');
|
||||
char_to_html('}');
|
||||
if (i < machine.max_port)
|
||||
if (i < MACHINE_MAX_PORT)
|
||||
char_to_html(',');
|
||||
else
|
||||
char_to_html(']');
|
||||
@@ -914,7 +914,7 @@ void send_storm(void)
|
||||
|
||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||
char_to_html('[');
|
||||
for (i = machine.min_port; i <= machine.max_port; i++) {
|
||||
for (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, ",\"en\":\"");
|
||||
@@ -934,7 +934,7 @@ void send_storm(void)
|
||||
}
|
||||
char_to_html('"');
|
||||
char_to_html('}');
|
||||
if (i < machine.max_port)
|
||||
if (i < MACHINE_MAX_PORT)
|
||||
char_to_html(',');
|
||||
else
|
||||
char_to_html(']');
|
||||
@@ -949,7 +949,7 @@ void send_isolation(void)
|
||||
dbg_string("send_isolation called\n");
|
||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||
char_to_html('[');
|
||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||
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, ",\"allow\":\"");
|
||||
@@ -958,7 +958,7 @@ void send_isolation(void)
|
||||
byte_to_html(allow & 0xff);
|
||||
char_to_html('"');
|
||||
char_to_html('}');
|
||||
if (i < machine.max_port)
|
||||
if (i < MACHINE_MAX_PORT)
|
||||
char_to_html(',');
|
||||
}
|
||||
char_to_html(']');
|
||||
@@ -970,7 +970,7 @@ void send_mtu(void)
|
||||
dbg_string("send_mtu called\n");
|
||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||
char_to_html('[');
|
||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||
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, ",\"mtu\":\"0x");
|
||||
@@ -980,7 +980,7 @@ void send_mtu(void)
|
||||
byte_to_html(mtu & 0xff);
|
||||
char_to_html('"');
|
||||
char_to_html('}');
|
||||
if (i < machine.max_port)
|
||||
if (i < MACHINE_MAX_PORT)
|
||||
char_to_html(',');
|
||||
else
|
||||
char_to_html(']');
|
||||
@@ -994,7 +994,7 @@ void send_status(void)
|
||||
dbg_string("sending status\n");
|
||||
char_to_html('[');
|
||||
|
||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||
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\":");
|
||||
@@ -1111,8 +1111,11 @@ void send_status(void)
|
||||
slen += strtox(outbuf + slen, "\",\"rxB\":\"0x");
|
||||
STAT_GET(STAT_COUNTER_ERR_PKTS, i);
|
||||
reg_to_html(RTL837X_STAT_V_HIGH); // 32bit RX packet errors
|
||||
|
||||
slen += strtox(outbuf + slen, "\",\"macs\":\"0x");
|
||||
reg_to_html(RTL837X_L2_LRN_PORT_CONSTRT_CNT + (i << 2));
|
||||
slen += strtox(outbuf + slen, "\"}");
|
||||
if (i < machine.max_port)
|
||||
if (i < MACHINE_MAX_PORT)
|
||||
char_to_html(',');
|
||||
else
|
||||
char_to_html(']');
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
CODE_LOCATION=0x1000
|
||||
INSTALLER_ADDRESS=0x1100
|
||||
|
||||
CC = sdcc
|
||||
SDCC_PREFIX = ../toolchain/sdcc-$(shell cat ../sdcc/* | cksum | cut -d' ' -f1)
|
||||
ifeq ($(origin CC),default)
|
||||
SDCC = $(SDCC_PREFIX)/bin/sdcc
|
||||
CC = $(SDCC)
|
||||
ASM = $(SDCC_PREFIX)/bin/sdas8051
|
||||
endif
|
||||
CC_FLAGS = -mmcs51
|
||||
ASM = sdas8051
|
||||
ASM ?= sdas8051
|
||||
AFLAGS= -plosgff
|
||||
|
||||
BUILDDIR = output
|
||||
@@ -13,9 +18,14 @@ OBJS = ${SRCS:%.c=$(BUILDDIR)/%.rel}
|
||||
|
||||
all: create_build_dir $(BUILDDIR)/updatebuilder $(BUILDDIR)/rtlplayground_oem_upgrade.bin
|
||||
|
||||
create_build_dir:
|
||||
create_build_dir: $(SDCC)
|
||||
mkdir -p $(BUILDDIR)
|
||||
|
||||
ifneq ($(SDCC),)
|
||||
$(SDCC):
|
||||
sh ../sdcc/build.sh $(abspath $(SDCC_PREFIX))
|
||||
endif
|
||||
|
||||
$(BUILDDIR)/updatebuilder: updatebuilder.c
|
||||
gcc $^ -o $@
|
||||
|
||||
|
||||
@@ -348,7 +348,7 @@ void installer(void)
|
||||
{
|
||||
|
||||
CKCON = 0; // Initial Clock configuration
|
||||
SFR_97 = 0; // HADDR?
|
||||
MAP_FLASH_PAGE_TO_XDATA = 0; // HADDR?
|
||||
|
||||
// Set in managed mode:
|
||||
SFR_b9 = 0x00;
|
||||
|
||||
@@ -15,8 +15,51 @@
|
||||
|
||||
#define MACHINE_INC(dir,file) MACHINE_STR(dir/file)
|
||||
|
||||
#define RTL8370 0x70
|
||||
#define RTL8372 0x72
|
||||
#define RTL8373 0x73
|
||||
|
||||
#include MACHINE_INC(MACHINE_DEF_DIR,MACHINE_NAME.h)
|
||||
|
||||
|
||||
#ifndef MACHINE_CHIPSET
|
||||
#error "MACHINE_CHIPSET shall be defined in <machine>.h file"
|
||||
#endif
|
||||
|
||||
#ifndef MACHINE_MIN_PORT
|
||||
#if MACHINE_CHIPSET == RTL8372
|
||||
#define MACHINE_MIN_PORT 3
|
||||
#else
|
||||
#define MACHINE_MIN_PORT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MACHINE_MAX_PORT
|
||||
#if MACHINE_CHIPSET == RTL8370
|
||||
#define MACHINE_MAX_PORT 7
|
||||
#else
|
||||
#define MACHINE_MAX_PORT 8
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MACHINE_PORT_VALID(p) \
|
||||
((uint8_t)((p) - MACHINE_MIN_PORT) <= (MACHINE_MAX_PORT - MACHINE_MIN_PORT))
|
||||
|
||||
// auto derive SOC_FAMILY
|
||||
#define RTL836X 6
|
||||
#define RTL837X 7
|
||||
|
||||
#ifdef SOC_FAMILY
|
||||
#error "SOC_FAMILY can not be manually defined, shall be auto derived"
|
||||
#endif
|
||||
#if (MACHINE_CHIPSET == RTL8372) || (MACHINE_CHIPSET == RTL8373)
|
||||
#define SOC_FAMILY RTL837X
|
||||
#elif (MACHINE_CHIPSET == RTL8370 )
|
||||
#define SOC_FAMILY RTL836X
|
||||
#else
|
||||
#error "Unsupported MACHINE_CHIPSET is specified!"
|
||||
#endif
|
||||
|
||||
#define LED_27 1
|
||||
// SYSTEM LED
|
||||
#define LED_28_SYS 2
|
||||
@@ -41,10 +84,6 @@ struct sfp_port
|
||||
struct machine {
|
||||
char machine_name[30];
|
||||
uint8_t isRTL8373;
|
||||
// Lowest logical port number
|
||||
uint8_t min_port;
|
||||
// Highest logical port number
|
||||
uint8_t max_port;
|
||||
uint8_t n_sfp;
|
||||
uint8_t n_10g;
|
||||
uint8_t log_to_phys_port[9];
|
||||
@@ -64,6 +103,12 @@ struct machine {
|
||||
uint8_t led_mux_custom;
|
||||
uint8_t led_mux[28];
|
||||
uint32_t mac_flash_offset;
|
||||
// Read the flash with single-IO (CMD_FREAD) instead of DIO for MMIO/code
|
||||
// fetch. Set for boards whose flash chip is not usable in DIO mode, which
|
||||
// shows up as a board that does not boot at all, garbled console output or
|
||||
// random resets. Costs management-plane speed only, the ASIC keeps
|
||||
// forwarding in hardware.
|
||||
uint8_t flash_sio;
|
||||
};
|
||||
|
||||
struct machine_runtime
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
SWTG018AS_A_V_2_0.c
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef _MACHINE_2G08110GSN_H_
|
||||
#define _MACHINE_2G08110GSN_H_
|
||||
|
||||
#define MACHINE_MODEL "MokerLink 2G08110GSN"
|
||||
#define MACHINE_CHIPSET RTL8373
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "machine_defs.h"
|
||||
|
||||
__code const struct machine machine = {
|
||||
MACHINE_COMMON_SETTING,
|
||||
.n_sfp = 2,
|
||||
/* Same 2M-PCB43-V1.1 board family as the KP-9000-6XH-X2 (see
|
||||
* machine/KP_9000_6XHML_X2.c), but the two SFP+ cages (physical ports 5 and
|
||||
* 6) are wired the other way round: physical 5 is on SDS1, physical 6 on
|
||||
* SDS0. Copper ports 1-4 match the KP-9000 layout. */
|
||||
.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 cage (physical port 5) = SDS1
|
||||
.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 cage (physical port 6) = SDS0
|
||||
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
|
||||
.sfp_port[1].pin_los = GPIO10_LED10,
|
||||
.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 ),
|
||||
/* The board has a 3-hole reset button footprint, but it is unpopulated and
|
||||
* the case has no opening for it, so reset_pin stays GPIO_NA. GPIO54, the
|
||||
* reset pin on the KP-9000 layout, reads as permanently pressed here. */
|
||||
.reset_pin = GPIO_NA,
|
||||
/* The fitted T25S40 does not work in DIO mode on this board, so read the flash
|
||||
* with single-IO; see doc/devices/2G5F4_10G2_V1.01.md. */
|
||||
.flash_sio = 1,
|
||||
.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
|
||||
*
|
||||
* Measured on this board: LED-ID0 is the copper blue LED, LED-ID1 the
|
||||
* copper white one (setting LED-ID0 to 0 killed blue while leaving white on
|
||||
* at 2.5G only) and LED-ID2 carries the SFP single LED. The "solid"
|
||||
* conditions (LINK/speed) barely drive the LEDs here and ACT is what
|
||||
* actually lights them, which is why the white LED used to glow faintly at
|
||||
* non-2.5G speeds; the fix for that is LED_GLB_IO_EN bit 6, set in the
|
||||
* shared machine_custom_init() hook (machine/2G5F4_10G2_V1_01_init.c). */
|
||||
.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 },
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef _MACHINE_2G5F4_10G2_V1_01_H_
|
||||
#define _MACHINE_2G5F4_10G2_V1_01_H_
|
||||
|
||||
#define MACHINE_MODEL "2G5F4_10G2_V1.01 / SGT0204S"
|
||||
#define MACHINE_CHIPSET RTL8372
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
KP_9000_6XH_X2_init.c
|
||||
@@ -1,25 +0,0 @@
|
||||
#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 },
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
KP_9000_9XH_X_EU.c
|
||||
@@ -2,5 +2,6 @@
|
||||
#define _MACHINE_DEFAULT_8C_1SFP_H_
|
||||
|
||||
#define MACHINE_MODEL "8+1 SFP Port Switch"
|
||||
#define MACHINE_CHIPSET RTL8373
|
||||
|
||||
#endif
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "machine_defs.h"
|
||||
|
||||
__code const struct machine machine = {
|
||||
.machine_name = MACHINE_MODEL,
|
||||
.isRTL8373 = 1,
|
||||
.min_port = 0,
|
||||
.max_port = 8,
|
||||
MACHINE_COMMON_SETTING,
|
||||
.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},
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
#define _MACHINE_F7008_2_5_H_
|
||||
|
||||
#define MACHINE_MODEL "F7008-2.5 8+1 SFP Port Switch"
|
||||
#define MACHINE_CHIPSET RTL8373
|
||||
|
||||
#endif
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "machine_defs.h"
|
||||
|
||||
__code const struct machine machine = {
|
||||
.machine_name = MACHINE_MODEL,
|
||||
.isRTL8373 = 0,
|
||||
.min_port = 3,
|
||||
.max_port = 8,
|
||||
MACHINE_COMMON_SETTING,
|
||||
.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},
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
#define _MACHINE_FG_4GT_2SX_V2_0_H_
|
||||
|
||||
#define MACHINE_MODEL "FG-4GT-2SX_V2.0"
|
||||
#define MACHINE_CHIPSET RTL8372
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "machine_init_defs.h"
|
||||
|
||||
void machine_custom_init(void) __banked
|
||||
{
|
||||
REG_SET(RTL837X_REG_LED_GLB_IO_EN, 0x7624155b);
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "machine_defs.h"
|
||||
|
||||
__code const struct machine machine = {
|
||||
.machine_name = MACHINE_MODEL,
|
||||
.isRTL8373 = 1,
|
||||
.min_port = 0,
|
||||
.max_port = 8,
|
||||
MACHINE_COMMON_SETTING,
|
||||
.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},
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
#define _MACHINE_FG_8GT_1SX_H_
|
||||
|
||||
#define MACHINE_MODEL "FG-8GT-1SX"
|
||||
#define MACHINE_CHIPSET RTL8373
|
||||
|
||||
#endif
|
||||
@@ -1,55 +0,0 @@
|
||||
#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 */
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
PCB_K0402WS_V2.c
|
||||
@@ -2,5 +2,6 @@
|
||||
#define _MACHINE_FNS1200P_H_
|
||||
|
||||
#define MACHINE_MODEL "FNS-1200P"
|
||||
#define MACHINE_CHIPSET RTL8372
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
KP_9000_6XH_X2_init.c
|
||||
@@ -0,0 +1 @@
|
||||
SWTG018AS_A_V_2_0.c
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef _MACHINE_GT_ST018M_H_
|
||||
#define _MACHINE_GT_ST018M_H_
|
||||
|
||||
#define MACHINE_MODEL "GoodTop GT-ST018M"
|
||||
#define MACHINE_CHIPSET RTL8373
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
PCB_SWTG024AS_A_2_0_1.c
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef _MACHINE_GT_ST024M_H_
|
||||
#define _MACHINE_GT_ST024M_H_
|
||||
|
||||
#define MACHINE_MODEL "GoodTop GT-ST024M"
|
||||
#define MACHINE_CHIPSET RTL8372
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
#include "machine_defs.h"
|
||||
|
||||
__code const struct machine machine = {
|
||||
MACHINE_COMMON_SETTING,
|
||||
.mac_flash_offset = 0x1FC000,
|
||||
.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 = 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_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // LED0: orange
|
||||
0,
|
||||
LEDS_2G5 | LEDS_LINK | LEDS_ACT, // LED2: green
|
||||
0
|
||||
},
|
||||
{
|
||||
LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT, // SFP LED0: green (both SFP LEDs are green)
|
||||
0, 0, 0
|
||||
}
|
||||
},
|
||||
.led_mux_custom = 1,
|
||||
.led_mux = {
|
||||
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x09,
|
||||
0x0e, 0x10, 0x12, 0x0e, 0x14, 0x11, 0x12, 0x16,
|
||||
0x15, 0x16, 0x18, 0x19, 0x1a, 0x1a, 0x1d, 0x1e,
|
||||
0x1c, 0x1e, 0x20, 0x21
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef _MACHINE_HASIVO_S1100P_8GT_1SX_S_H_
|
||||
#define _MACHINE_HASIVO_S1100P_8GT_1SX_S_H_
|
||||
|
||||
#define MACHINE_MODEL "Hasivo S1100P-8GT-1SX-S"
|
||||
#define MACHINE_CHIPSET RTL8373
|
||||
|
||||
#endif
|
||||
@@ -1,32 +0,0 @@
|
||||
#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
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
SWTGW218AS.c
|
||||
@@ -2,5 +2,6 @@
|
||||
#define _MACHINE_HASIVO_S1100WP_8GT_1SX_SE_H_
|
||||
|
||||
#define MACHINE_MODEL "Hasivo S1100WP-8GT-1SX-SE"
|
||||
#define MACHINE_CHIPSET RTL8373
|
||||
|
||||
#endif
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "machine_defs.h"
|
||||
|
||||
__code const struct machine machine = {
|
||||
.machine_name = MACHINE_MODEL,
|
||||
.isRTL8373 = 0,
|
||||
.min_port = 3,
|
||||
.max_port = 8,
|
||||
MACHINE_COMMON_SETTING,
|
||||
.n_sfp = 0,
|
||||
.n_10g = 2,
|
||||
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
#define _MACHINE_HASIVO_S600W_4GT_2XGT_SE_H_
|
||||
|
||||
#define MACHINE_MODEL "Hasivo S600W-4GT-2XGT-SE"
|
||||
#define MACHINE_CHIPSET RTL8372
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
PCB_SWTG024AS_A_2_0_1.c
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef _MACHINE_HC_SWTG124AS_H_
|
||||
#define _MACHINE_HC_SWTG124AS_H_
|
||||
|
||||
#define MACHINE_MODEL "Horaco HC-SWTG124AS"
|
||||
#define MACHINE_CHIPSET RTL8372
|
||||
|
||||
#endif
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "machine_defs.h"
|
||||
|
||||
__code const struct machine machine = {
|
||||
.machine_name = MACHINE_MODEL,
|
||||
.isRTL8373 = 0,
|
||||
.min_port = 3,
|
||||
.max_port = 8,
|
||||
MACHINE_COMMON_SETTING,
|
||||
.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},
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
#define _MACHINE_HG0402XG_V1_1_H_
|
||||
|
||||
#define MACHINE_MODEL "HG0402XG V1.1"
|
||||
#define MACHINE_CHIPSET RTL8372
|
||||
|
||||
#endif
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "machine_defs.h"
|
||||
|
||||
__code const struct machine machine = {
|
||||
.machine_name = MACHINE_MODEL,
|
||||
.isRTL8373 = 0,
|
||||
.min_port = 3,
|
||||
.max_port = 8,
|
||||
MACHINE_COMMON_SETTING,
|
||||
.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},
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
#define _MACHINE_HI_K0402WS_H_
|
||||
|
||||
#define MACHINE_MODEL "PCB-K0402WS-V3.0"
|
||||
#define MACHINE_CHIPSET RTL8372
|
||||
|
||||
#endif
|
||||