Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1db30f22de | ||
|
|
4c70e654d1 | ||
|
|
3c24f2bdea | ||
|
|
3e610392a9 | ||
|
|
146771f5ca | ||
|
|
bf0bea1edd | ||
|
|
907ad08830 | ||
|
|
7cf0115182 | ||
|
|
adfbead438 | ||
|
|
301774040b | ||
|
|
683037f410 | ||
|
|
57b820c4e8 | ||
|
|
801150431b | ||
|
|
45d0aac118 | ||
|
|
ee05cd4000 | ||
|
|
74013bb14f | ||
|
|
beb14deba5 | ||
|
|
1212def799 | ||
|
|
95b3bde822 | ||
|
|
f511453f79 | ||
|
|
8653216047 | ||
|
|
e62e0fc8bd | ||
|
|
2ff418f80f | ||
|
|
5d42e8843e | ||
|
|
3c183f73f8 | ||
|
|
3776f12f5c | ||
|
|
5ddec9710a | ||
|
|
f627559005 | ||
|
|
dca92d7f45 | ||
|
|
149dc8537f | ||
|
|
42f7b4fba1 | ||
|
|
17642699d4 | ||
|
|
724fd1e061 | ||
|
|
3eb2dfe0c9 | ||
|
|
73df006d39 | ||
|
|
175f3bb185 | ||
|
|
57061161b6 | ||
|
|
80f97a50e0 | ||
|
|
c265a20d83 | ||
|
|
4937618684 | ||
|
|
1a743b3889 | ||
|
|
425283b774 | ||
|
|
f582576b10 | ||
|
|
16b0f207ed | ||
|
|
fe2bcc7f2d | ||
|
|
a0628c7df5 | ||
|
|
cefe48fe51 | ||
|
|
e8e7fcbe7f | ||
|
|
8a28b4fc88 | ||
|
|
9a96c80af2 | ||
|
|
772e9dc526 | ||
|
|
025f72c876 | ||
|
|
52cf759bec | ||
|
|
cbbc6160f4 | ||
|
|
a8d3b7d39a | ||
|
|
80095ba617 | ||
|
|
a3d1a35e2f | ||
|
|
47b3ee60b6 | ||
|
|
59d20ed9b6 | ||
|
|
f41ed2b943 | ||
|
|
56fa96c494 | ||
|
|
6bfcbd2f9a | ||
|
|
fa7895ad62 | ||
|
|
1ed8b131bc | ||
|
|
9ada6adad7 | ||
|
|
719c6db228 | ||
|
|
a96fdfe10c | ||
|
|
1d1e33f4d5 | ||
|
|
3fda9ccd86 | ||
|
|
3be6667789 | ||
|
|
5103d1c168 | ||
|
|
ce85576882 | ||
|
|
59c60504e7 | ||
|
|
a3c586ef38 | ||
|
|
8bc530d3d0 | ||
|
|
f2c6ac01d9 | ||
|
|
94d9f2c8e8 | ||
|
|
0503e7952d | ||
|
|
787d593996 | ||
|
|
db2a541e5f | ||
|
|
11be13fe53 | ||
|
|
65f8afb908 | ||
|
|
0126b159bf | ||
|
|
31024388ba | ||
|
|
9f2d6b72b7 | ||
|
|
5c5dcb5209 | ||
|
|
be6d47a3ab | ||
|
|
4ff009dbfc | ||
|
|
0998b7381f | ||
|
|
0c339e9123 | ||
|
|
75151e0b00 | ||
|
|
43845b911b | ||
|
|
0ed45e0710 | ||
|
|
5e30f8e6c0 | ||
|
|
7f3c91ac0c | ||
|
|
3853a2701d | ||
|
|
00a5f81871 | ||
|
|
53d865059d | ||
|
|
b90aedd8f2 | ||
|
|
6b190eb9f3 | ||
|
|
fae16dabf5 | ||
|
|
52692d05b1 | ||
|
|
d364bd69e4 | ||
|
|
70ab7ff769 | ||
|
|
e30976be76 | ||
|
|
1a55a134c7 | ||
|
|
23f0ba995c | ||
|
|
22a09bd06a | ||
|
|
930a08ec52 | ||
|
|
1701d4dc53 | ||
|
|
1e19a9abe2 | ||
|
|
1098e73337 | ||
|
|
99b0fc4b32 | ||
|
|
10d472d8a6 | ||
|
|
6254f44001 | ||
|
|
c435838376 | ||
|
|
3f7db7e430 | ||
|
|
f98fe32d0c | ||
|
|
d2e8ee0e41 | ||
|
|
a9a455e447 | ||
|
|
3f26bf7348 | ||
|
|
ac302d4a67 | ||
|
|
409bc58e17 | ||
|
|
fbcec2cb5a | ||
|
|
ccb90ed16f | ||
|
|
4389cfcd8b | ||
|
|
5e901fb5c2 | ||
|
|
2974e4b66a | ||
|
|
108ac9b8fc | ||
|
|
de3eca26c3 | ||
|
|
8164166465 | ||
|
|
87fe1e77ae | ||
|
|
a753f6f02e | ||
|
|
c86d4b31f2 | ||
|
|
3c89b22207 | ||
|
|
bebe79c4c9 | ||
|
|
adb0b54691 | ||
|
|
b99436543a | ||
|
|
1194823cd5 | ||
|
|
94716ceb5d | ||
|
|
13120127df | ||
|
|
46037cd54d | ||
|
|
e6cd362a1e | ||
|
|
f21b3a32bd | ||
|
|
35941dd19f | ||
|
|
0f257d38df | ||
|
|
912e68d6eb | ||
|
|
c473646389 | ||
|
|
51cf40d040 | ||
|
|
3fd9cdfa7e | ||
|
|
3189820ba0 | ||
|
|
ed74ec1e97 | ||
|
|
dd95a05487 | ||
|
|
481c02c740 | ||
|
|
0a31a65477 | ||
|
|
2d176b7ccc | ||
|
|
a1fac63710 | ||
|
|
5c7f82e2fe | ||
|
|
e765d17c2b | ||
|
|
8fb9afb955 | ||
|
|
e96780fadb | ||
|
|
2221f0fa32 | ||
|
|
f86b8f32de | ||
|
|
9389db9e9b | ||
|
|
519c3a8df3 | ||
|
|
64422367d5 | ||
|
|
dc2b03e331 | ||
|
|
fcf1b3c310 | ||
|
|
1dd6156a1f | ||
|
|
e75a4c2a95 | ||
|
|
05d8c36afe | ||
|
|
b6c9eaf00f | ||
|
|
ecf5f47960 | ||
|
|
457f117216 | ||
|
|
ebf6ed7526 | ||
|
|
96f2c860fc | ||
|
|
dd52e8e85e | ||
|
|
ecf8c999b1 | ||
|
|
64a1d252cd | ||
|
|
b80d46955c | ||
|
|
0a18c64dcc | ||
|
|
b53c56e7f6 | ||
|
|
17d41b53b7 | ||
|
|
bd98cb0312 | ||
|
|
5566d71522 | ||
|
|
5e1396cc42 | ||
|
|
7fe0678c92 | ||
|
|
7ec25a39a2 | ||
|
|
98e3cde2f5 | ||
|
|
d90c02f951 | ||
|
|
bbb92c86db | ||
|
|
1635236a05 | ||
|
|
5e3a280b5c | ||
|
|
a56e2a419b | ||
|
|
9c01227572 | ||
|
|
6d37a47481 | ||
|
|
87b9e59cdb | ||
|
|
0e86b84efa | ||
|
|
bd595b7f94 | ||
|
|
06d4a3504a | ||
|
|
d68534e833 | ||
|
|
e0356bd751 | ||
|
|
4b770a8abc | ||
|
|
709436ca13 | ||
|
|
28856ef495 | ||
|
|
113bb654aa | ||
|
|
efc1883685 | ||
|
|
72921ba3be | ||
|
|
70be673fca | ||
|
|
bf5205258e | ||
|
|
98ddb0bb29 | ||
|
|
d152f89549 | ||
|
|
c61e94527e | ||
|
|
f76ccaf3d8 | ||
|
|
ebc6cd06ad | ||
|
|
017aaf71d6 | ||
|
|
4eaf16f96d | ||
|
|
718745e7b5 | ||
|
|
06ee1ce38e | ||
|
|
d3e8698e40 | ||
|
|
f122402bdd | ||
|
|
7a7ffd3bf8 | ||
|
|
592b903305 |
@@ -0,0 +1,19 @@
|
|||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.gitattributes
|
||||||
|
.github/
|
||||||
|
output/
|
||||||
|
installer/output/
|
||||||
|
*.bin
|
||||||
|
html_data.c
|
||||||
|
html_data.h
|
||||||
|
*.o
|
||||||
|
*.rel
|
||||||
|
*.lst
|
||||||
|
*.sym
|
||||||
|
*.asm
|
||||||
|
*.ihx
|
||||||
|
*.img
|
||||||
|
*.map
|
||||||
|
*.mem
|
||||||
|
*.lk
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
FROM debian:13-slim
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
make \
|
||||||
|
gcc \
|
||||||
|
sdcc \
|
||||||
|
xxd \
|
||||||
|
python3 \
|
||||||
|
libjson-c-dev \
|
||||||
|
golang-go \
|
||||||
|
git \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# git safe.directory for mounted repos (Makefile uses git describe)
|
||||||
|
RUN git config --global --add safe.directory /workspace
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
|
||||||
|
CMD ["bash"]
|
||||||
@@ -4,9 +4,11 @@ DEFAULT_CONFIG_LOCATION = 454656
|
|||||||
CONFIG_LOCATION = 458752
|
CONFIG_LOCATION = 458752
|
||||||
HTML_LOCATION = 262144
|
HTML_LOCATION = 262144
|
||||||
|
|
||||||
|
ifeq ($(origin CC),default)
|
||||||
CC = sdcc
|
CC = sdcc
|
||||||
|
endif
|
||||||
CC_FLAGS = -mmcs51 -I. -Ihttpd -Iuip
|
CC_FLAGS = -mmcs51 -I. -Ihttpd -Iuip
|
||||||
ASM = sdas8051
|
ASM ?= sdas8051
|
||||||
AFLAGS= -plosgff
|
AFLAGS= -plosgff
|
||||||
|
|
||||||
SUBDIRS := tools
|
SUBDIRS := tools
|
||||||
@@ -30,30 +32,71 @@ endif
|
|||||||
VERSION_EXTENSION = v$(VERSION)-$(GIT_VERSION)
|
VERSION_EXTENSION = v$(VERSION)-$(GIT_VERSION)
|
||||||
FILENAME_EXTENSION = $(VERSION_EXTENSION)-$(MACHINE)
|
FILENAME_EXTENSION = $(VERSION_EXTENSION)-$(MACHINE)
|
||||||
|
|
||||||
|
# Deterministic build date: honor SOURCE_DATE_EPOCH, else the HEAD commit date,
|
||||||
|
# else wall-clock (no-git fallback). Keeps same-commit builds byte-identical
|
||||||
|
# (BUILD_DATE is baked into the image and covered by the trailing CRC).
|
||||||
|
SOURCE_DATE_EPOCH ?= $(shell git show -s --format=%ct HEAD 2>/dev/null)
|
||||||
|
ifeq ($(SOURCE_DATE_EPOCH),)
|
||||||
|
BUILD_DATE := $(shell date +"%Y-%m-%d %H:%M:%S")
|
||||||
|
else
|
||||||
|
BUILD_DATE := $(shell date -u -d @$(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S" 2>/dev/null \
|
||||||
|
|| date -u -r $(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S")
|
||||||
|
endif
|
||||||
|
|
||||||
all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
|
all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
|
||||||
|
|
||||||
create_build_dir:
|
create_build_dir:
|
||||||
mkdir -p $(BUILDDIR)
|
mkdir -p "$(BUILDDIR)"
|
||||||
mkdir -p $(BUILDDIR)/uip
|
mkdir -p "$(BUILDDIR)/uip"
|
||||||
mkdir -p $(BUILDDIR)/httpd
|
mkdir -p "$(BUILDDIR)/httpd"
|
||||||
|
|
||||||
|
# Keep machine.c in first position to fail immediately on invalid $MACHINE value
|
||||||
|
SRCS = \
|
||||||
|
machine.c \
|
||||||
|
machine_init.c \
|
||||||
|
cmd_editor.c \
|
||||||
|
cmd_parser.c \
|
||||||
|
dhcp.c \
|
||||||
|
html_data.c \
|
||||||
|
rtlplayground.c \
|
||||||
|
syslog.c \
|
||||||
|
udp_apps.c
|
||||||
|
|
||||||
|
# RTL837x
|
||||||
|
SRCS += \
|
||||||
|
rtl837x_bandwidth.c \
|
||||||
|
rtl837x_flash.c \
|
||||||
|
rtl837x_igmp.c \
|
||||||
|
rtl837x_init.c \
|
||||||
|
rtl837x_leds.c \
|
||||||
|
rtl837x_phy.c \
|
||||||
|
rtl837x_pins.c\
|
||||||
|
rtl837x_port.c \
|
||||||
|
rtl837x_stp.c
|
||||||
|
SRCS += \
|
||||||
|
httpd/httpd.c \
|
||||||
|
httpd/page_impl.c
|
||||||
|
SRCS += \
|
||||||
|
uip/timer.c \
|
||||||
|
uip/uip.c \
|
||||||
|
uip/uiplib.c \
|
||||||
|
uip/uip_arp.c \
|
||||||
|
uip/uip-fw.c \
|
||||||
|
uip/uip-neighbor.c \
|
||||||
|
uip/uip-split.c
|
||||||
|
|
||||||
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_leds.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c
|
|
||||||
SRCS += rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c cmd_editor.c rtl837x_bandwidth.c rtl837x_init.c syslog.c
|
|
||||||
SRCS += uip/timer.c uip/uip.c uip/uip_arp.c uip/uiplib.c uip/uip-fw.c uip/uip-neighbor.c uip/uip-split.c udp_apps.c
|
|
||||||
SRCS += httpd/httpd.c httpd/page_impl.c
|
|
||||||
OBJS = ${SRCS:%.c=$(BUILDDIR)/%.rel}
|
OBJS = ${SRCS:%.c=$(BUILDDIR)/%.rel}
|
||||||
DEPS := ${SRCS:%.c=$(BUILDDIR)/%.d}
|
DEPS := ${SRCS:%.c=$(BUILDDIR)/%.d}
|
||||||
HTML := $(shell find $(html) -name '*.js' -or -name '*.html' -or -name '*.svg')
|
HTML := $(shell find html -name '*.js' -or -name '*.html' -or -name '*.svg')
|
||||||
|
|
||||||
html_data.c html_data.h: $(HTML) tools/output/fileadder
|
html_data.c html_data.h &: $(HTML) | tools
|
||||||
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -d html -p html_data
|
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -d html -p html_data
|
||||||
|
|
||||||
$(VERSION_HEADER):
|
$(VERSION_HEADER):
|
||||||
@echo "#ifndef VERSION_H" > $(VERSION_HEADER)
|
@printf '%s\n' "#ifndef VERSION_H" "#define VERSION_H" \
|
||||||
@echo "#define VERSION_H" >> $(VERSION_HEADER)
|
"#define VERSION_SW \"$(VERSION_EXTENSION)\"" \
|
||||||
@echo "#define VERSION_SW \"$(VERSION_EXTENSION)\"" >> $(VERSION_HEADER)
|
"#define BUILD_DATE \"$(BUILD_DATE)\"" \
|
||||||
@echo "#define BUILD_DATE \"$(shell date +"%Y-%m-%d %H:%M:%S")\"" >> $(VERSION_HEADER)
|
"#endif" > $(VERSION_HEADER)
|
||||||
@echo "#endif" >> $(VERSION_HEADER)
|
|
||||||
|
|
||||||
httpd: html_data.h
|
httpd: html_data.h
|
||||||
|
|
||||||
@@ -68,20 +111,20 @@ distclean:
|
|||||||
-rm -f html_data.c html_data.h $(VERSION_HEADER)
|
-rm -f html_data.c html_data.h $(VERSION_HEADER)
|
||||||
-rm -rf $(BUILDDIR)
|
-rm -rf $(BUILDDIR)
|
||||||
|
|
||||||
$(BUILDDIR)/%.rel: %.c
|
$(BUILDDIR)/%.rel: %.c | create_build_dir html_data.h
|
||||||
$(CC) -MMD $(CC_FLAGS) -o $@ -c $<
|
$(CC) -MMD $(CC_FLAGS) -o $@ -c $<
|
||||||
|
|
||||||
$(BUILDDIR)/%.rel: %.asm
|
$(BUILDDIR)/%.rel: %.asm | create_build_dir
|
||||||
${ASM} ${AFLAGS} -o $@ $<
|
${ASM} ${AFLAGS} -o $@ $<
|
||||||
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
|
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
|
||||||
|
|
||||||
$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtstart.rel $(BUILDDIR)/crc16.rel
|
$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtbank.rel $(BUILDDIR)/crc16.rel
|
||||||
$(CC) $(CC_FLAGS) -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-r -o $@ $^
|
$(CC) $(CC_FLAGS) -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-r -o $@ $^
|
||||||
|
|
||||||
$(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx
|
$(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx
|
||||||
objcopy --input-target=ihex -O binary $< $@
|
objcopy --input-target=ihex -O binary $< $@
|
||||||
|
|
||||||
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img
|
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img | tools
|
||||||
if [ -e $@ ]; then rm $@; fi
|
if [ -e $@ ]; then rm $@; fi
|
||||||
tools/output/imagebuilder -i $^ $@
|
tools/output/imagebuilder -i $^ $@
|
||||||
tools/output/fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
|
tools/output/fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
|
||||||
@@ -90,16 +133,17 @@ $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.i
|
|||||||
tools/output/crc_calculator -u $@
|
tools/output/crc_calculator -u $@
|
||||||
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin output/rtlplayground.bin
|
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin output/rtlplayground.bin
|
||||||
|
|
||||||
.PHONY: clean all $(SUBDIRS) $(VERSION_HEADER)
|
.PHONY: clean all $(SUBDIRS) $(VERSION_HEADER) create_build_dir
|
||||||
|
|
||||||
.PHONY:
|
.PHONY:
|
||||||
machine_check:
|
machine_check:
|
||||||
@mkdir -p $(BUILDDIR)/tmp
|
@mkdir -p $(BUILDDIR)/tmp
|
||||||
@set -eo pipefail; \
|
@set -eo pipefail; \
|
||||||
for MACHINE in `grep -e ' MACHINE_' machine.c | sed -e 's%^.* MACHINE_%%' -e 's%[ ]*//.*$$%%' | sort -u`; \
|
for MACHINE in `grep -E '^[[:space:]]*(//[[:space:]]*)?#define MACHINE_' machine.h | sed -E 's%^[[:space:]]*(//[[:space:]]*)?#define MACHINE_%%' | awk '{print $$1}' | sort -u`; \
|
||||||
do \
|
do \
|
||||||
echo "Checking $${MACHINE}"; \
|
echo "Checking $${MACHINE}"; \
|
||||||
$(CC) $(CC_FLAGS) -DMACHINE_$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine.c; \
|
$(CC) $(CC_FLAGS) -DMACHINE_$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine.c; \
|
||||||
|
$(CC) $(CC_FLAGS) -DMACHINE_$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine_init.c; \
|
||||||
done
|
done
|
||||||
@rm -rf $(BUILDDIR)/tmp
|
@rm -rf $(BUILDDIR)/tmp
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,53 @@ still has an older version of sdcc, but you will need sdcc version 4.5 for the c
|
|||||||
sudo apt install make gcc sdcc xxd python-is-python3 libjson-c-dev
|
sudo apt install make gcc sdcc xxd python-is-python3 libjson-c-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>If using Docker (click to expand)</summary>
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
Install Docker for your platform:
|
||||||
|
|
||||||
|
- **Linux (Debian/Ubuntu)**: `sudo apt install docker.io` then `sudo usermod -aG docker $USER` (log out and back in)
|
||||||
|
- **Linux (other distros)**: Follow the [Docker Engine install guide](https://docs.docker.com/engine/install/)
|
||||||
|
- **Windows**: Install [Docker Desktop for Windows](https://docs.docker.com/desktop/setup/install/windows-install/)
|
||||||
|
- **macOS**: Install [Docker Desktop for Mac](https://docs.docker.com/desktop/setup/install/mac-install/)
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
A Dockerfile is provided for a reproducible build environment:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t rtlplayground-dev .
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the firmware (replace MACHINE with your target, e.g. `DEFAULT_8C_1SFP`):
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run --rm -v $(pwd):/workspace rtlplayground-dev make MACHINE=DEFAULT_8C_1SFP
|
||||||
|
```
|
||||||
|
|
||||||
|
The resulting `.bin` file appears in `output/` on your host.
|
||||||
|
|
||||||
|
Build host tools only:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run --rm -v $(pwd):/workspace rtlplayground-dev make -C tools
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the web-interface simulator locally:
|
||||||
|
|
||||||
|
```
|
||||||
|
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
|
||||||
|
source directory is mounted into the container, so changes take effect
|
||||||
|
immediately. To build for a different machine, pass `MACHINE=...`.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
## (1) Compiling for direct chip flashing AND upgrading an existing RTLPlayground running device
|
## (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.
|
Edit machine.h with an editor like vi or nano. Select the correct machine the firmware should build for.
|
||||||
|
|||||||
@@ -40,21 +40,24 @@ void cmd_edit(void) __banked
|
|||||||
{
|
{
|
||||||
while (l != sbuf_ptr) {
|
while (l != sbuf_ptr) {
|
||||||
if (sbuf[l] >= ' ' && sbuf[l] < 127) { // A printable character, copy to command line
|
if (sbuf[l] >= ' ' && sbuf[l] < 127) { // A printable character, copy to command line
|
||||||
if (cmd_line_len >= CMD_BUF_SIZE)
|
// Reserve one byte for the terminating NUL written on Enter. When the
|
||||||
continue;
|
// line is full, drop the character but still fall through to advance the
|
||||||
write_char(sbuf[l]);
|
// serial-ring read pointer below; a 'continue' here would spin forever.
|
||||||
// Shift buffer to right
|
if (cmd_line_len < CMD_BUF_SIZE - 1) {
|
||||||
for (uint8_t i = cmd_line_len; i > cursor; i--)
|
write_char(sbuf[l]);
|
||||||
cmd_buffer[i] = cmd_buffer[i-1];
|
// Shift buffer to right
|
||||||
// Insert char in comand buffer
|
for (uint8_t i = cmd_line_len; i > cursor; i--)
|
||||||
cmd_buffer[cursor++] = sbuf[l];
|
cmd_buffer[i] = cmd_buffer[i-1];
|
||||||
cmd_line_len++;
|
// Insert char in comand buffer
|
||||||
// Print rest of line
|
cmd_buffer[cursor++] = sbuf[l];
|
||||||
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
cmd_line_len++;
|
||||||
write_char(cmd_buffer[i]);
|
// Print rest of line
|
||||||
// Move backwards
|
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
||||||
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
write_char(cmd_buffer[i]);
|
||||||
write_char('\010'); // BS works like cursor-left
|
// Move backwards
|
||||||
|
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
||||||
|
write_char('\010'); // BS works like cursor-left
|
||||||
|
}
|
||||||
} else if (sbuf[l] == '\033') { // ESC-Sequence
|
} else if (sbuf[l] == '\033') { // ESC-Sequence
|
||||||
// Wait until we have at least 3 characters including the ESC character in the serial buffer
|
// Wait until we have at least 3 characters including the ESC character in the serial buffer
|
||||||
if (((sbuf_ptr + SBUF_SIZE - l) & SBUF_MASK) < 3)
|
if (((sbuf_ptr + SBUF_SIZE - l) & SBUF_MASK) < 3)
|
||||||
@@ -190,7 +193,7 @@ void cmd_edit(void) __banked
|
|||||||
// Check whether return was pressed:
|
// Check whether return was pressed:
|
||||||
if (sbuf[l] == '\n' || sbuf[l] == '\r') {
|
if (sbuf[l] == '\n' || sbuf[l] == '\r') {
|
||||||
write_char('\n');
|
write_char('\n');
|
||||||
cmd_buffer[cmd_line_len] = '\0';
|
cmd_buffer[cmd_line_len] = NUL;
|
||||||
// write_char('>'); print_string_x(cmd_buffer); write_char('<');
|
// write_char('>'); print_string_x(cmd_buffer); write_char('<');
|
||||||
// If there is a command we print the prompt after execution
|
// If there is a command we print the prompt after execution
|
||||||
// otherwise immediately because there is nothing to execute
|
// otherwise immediately because there is nothing to execute
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
.area HOME (CODE)
|
||||||
|
.area GSINIT0 (CODE)
|
||||||
|
.area GSINIT1 (CODE)
|
||||||
|
.area GSINIT2 (CODE)
|
||||||
|
.area GSINIT3 (CODE)
|
||||||
|
.area GSINIT4 (CODE)
|
||||||
|
.area GSINIT5 (CODE)
|
||||||
|
.area GSINIT (CODE)
|
||||||
|
.area GSFINAL (CODE)
|
||||||
|
.area CSEG (CODE)
|
||||||
|
|
||||||
|
|
||||||
|
.area HOME (CODE)
|
||||||
|
|
||||||
|
__sdcc_banked_call::
|
||||||
|
push _PSBANK
|
||||||
|
xch a,r0
|
||||||
|
push a
|
||||||
|
mov a,r1
|
||||||
|
push a
|
||||||
|
mov a,r2
|
||||||
|
anl a,#0x1f
|
||||||
|
mov _PSBANK, a
|
||||||
|
xch a, r0
|
||||||
|
ret
|
||||||
|
|
||||||
|
__sdcc_banked_ret::
|
||||||
|
pop _PSBANK
|
||||||
|
ret
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
.area GSFINAL (CODE)
|
|
||||||
|
|
||||||
__sdcc_banked_call::
|
|
||||||
push _PSBANK
|
|
||||||
xch a,r0
|
|
||||||
push a
|
|
||||||
mov a,r1
|
|
||||||
push a
|
|
||||||
mov a,r2
|
|
||||||
anl a,#0x1f
|
|
||||||
mov _PSBANK, a
|
|
||||||
xch a, r0
|
|
||||||
ret
|
|
||||||
|
|
||||||
__sdcc_banked_ret::
|
|
||||||
pop _PSBANK
|
|
||||||
ret
|
|
||||||
@@ -41,6 +41,7 @@ __xdata uip_ipaddr_t server;
|
|||||||
#define DHCP_REBIND_LEN 4
|
#define DHCP_REBIND_LEN 4
|
||||||
#define DHCP_CLIENT_ID 61
|
#define DHCP_CLIENT_ID 61
|
||||||
#define DHCP_CLIENT_ID_LEN 7
|
#define DHCP_CLIENT_ID_LEN 7
|
||||||
|
#define DHCP_HOSTNAME 12
|
||||||
#define DHCP_REQUEST_IP 50
|
#define DHCP_REQUEST_IP 50
|
||||||
#define DHCP_REQUEST_IP_LEN 4
|
#define DHCP_REQUEST_IP_LEN 4
|
||||||
#define DHCP_PARAMS 55
|
#define DHCP_PARAMS 55
|
||||||
@@ -116,6 +117,20 @@ void dhcp_addopt_client_id(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dhcp_addopt_hostname(void)
|
||||||
|
{
|
||||||
|
uint8_t len = 0;
|
||||||
|
while (hostname[len])
|
||||||
|
len++;
|
||||||
|
if (!len)
|
||||||
|
return;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_HOSTNAME;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = len;
|
||||||
|
memcpy(&DHCP_OPT[dhcp_state.opt_ptr], hostname, len);
|
||||||
|
dhcp_state.opt_ptr += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dhcp_addopt_request_ip(void)
|
void dhcp_addopt_request_ip(void)
|
||||||
{
|
{
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REQUEST_IP;
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REQUEST_IP;
|
||||||
@@ -152,6 +167,7 @@ void dhcp_send_discover(void)
|
|||||||
|
|
||||||
dhcp_addopt_client_id();
|
dhcp_addopt_client_id();
|
||||||
dhcp_addopt_request_ip();
|
dhcp_addopt_request_ip();
|
||||||
|
dhcp_addopt_hostname();
|
||||||
|
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
|
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
|
||||||
@@ -188,6 +204,7 @@ void dhcp_send_request(void)
|
|||||||
dhcp_addopt_client_id();
|
dhcp_addopt_client_id();
|
||||||
dhcp_addopt_request_ip();
|
dhcp_addopt_request_ip();
|
||||||
dhcp_addopt_server_id();
|
dhcp_addopt_server_id();
|
||||||
|
dhcp_addopt_hostname();
|
||||||
|
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
|
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# 2G040210GSM
|
||||||
|
|
||||||
|
The following is a documentation for the managed switch marked as `2G040210GSM`
|
||||||
|
and sold by Mokerlink.
|
||||||
|
|
||||||
|
### Label specifications
|
||||||
|
|
||||||
|
- **Name**: 4-port 2.5G Web Managed Switch
|
||||||
|
- **Ports**:
|
||||||
|
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||||
|
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||||
|
- **Power**: 12V DC, 1A barrel connector
|
||||||
|
|
||||||
|
### What works
|
||||||
|
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)
|
||||||
|
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
|
||||||
|
|
||||||
|
### Hardware overview
|
||||||
|
Front
|
||||||
|
|
||||||
|
<img src="photos/2M-PCB43-V1.1-managed/2M-PCB43-V1.1-front.jpeg" width="300" />
|
||||||
|
|
||||||
|
Label
|
||||||
|
|
||||||
|
<img src="photos/2M-PCB43-V1.1-managed/2M-PCB43-V1.1-label.jpeg" width="300" />
|
||||||
|
|
||||||
|
### PCB overview
|
||||||
|
|
||||||
|
**Board markings**
|
||||||
|
- Top silkscreen: 2M-PCB43-V1.1
|
||||||
|
|
||||||
|
Top side
|
||||||
|
|
||||||
|
<img src="photos/2M-PCB43-V1.1-managed/2M-PCB43-V1.1-top.jpeg" width="300" />
|
||||||
|
|
||||||
|
Bottom
|
||||||
|
|
||||||
|
<img src="photos/2M-PCB43-V1.1-managed/2M-PCB43-V1.1-bottom.jpeg" width="300" />
|
||||||
|
|
||||||
|
### J1, serial console
|
||||||
|
|
||||||
|
| `J8` pin | Signal |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| 1 | RX (Input) |
|
||||||
|
| 2 | TX (Output) |
|
||||||
|
| 3 | GND |
|
||||||
|
| 4 | 3V3 |
|
||||||
|
|
||||||
|
|
||||||
|
## Power supply
|
||||||
|
|
||||||
|
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# FG-4GT-2SX_V2.0
|
||||||
|
|
||||||
|
Following is documentation for unmanaged switch marked as `FG-4GT-2SX_V2.0`.
|
||||||
|
|
||||||
|
Original software is running UART on 9600 baud rate.
|
||||||
|
|
||||||
|
## Brands
|
||||||
|
|
||||||
|
* Ruiying RY-4GT-2SX
|
||||||
|
|
||||||
|
<img src="photos/FG-4GT-2SX_V2.0/RY-4GT-2SX_label.jpg" width="300" />
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
## PCB overview
|
||||||
|
|
||||||
|
**Board markings**
|
||||||
|
|
||||||
|
- Top silkscreen: FG-4GT-2SX_V2.0
|
||||||
|
|
||||||
|
Front panel
|
||||||
|
|
||||||
|
<img src="photos/FG-4GT-2SX_V2.0/chassis-front.jpg" width="300" />
|
||||||
|
|
||||||
|
Top side
|
||||||
|
|
||||||
|
<img src="photos/FG-4GT-2SX_V2.0/PCB-top.jpg" width="300" />
|
||||||
|
|
||||||
|
Bottom
|
||||||
|
|
||||||
|
<img src="photos/FG-4GT-2SX_V2.0/PCB-bottom.jpg" width="300" />
|
||||||
|
|
||||||
|
## Power supply
|
||||||
|
|
||||||
|
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||||
@@ -1,17 +1,36 @@
|
|||||||
# Keeplink KP-9000-6XH-X2
|
# Keeplink KP-9000-6XH-X2 / KP-9000-6XHML-X2
|
||||||
|
|
||||||
Following is documentation for unmanaged switch marked as `KP-9000-6XH-X2`.
|
Following is documentation for switches marked as `KP-9000-6XH-X2` or
|
||||||
|
`KP-9000-6XHML-X2`.
|
||||||
|
|
||||||
Using SPI clamp in-board is the only method for initial installation.
|
Using SPI clamp in-board is the only method for initial installation.
|
||||||
|
|
||||||
### Label specifications
|
### Label specifications
|
||||||
|
|
||||||
- **Name**: 4X 2.5G RJ45 Port + 2 X 10G SFP+ Port
|
- **Name**: 4X 2.5G RJ45 Port + 2 X 10G SFP+ Port
|
||||||
- **Model**: KP-9000-6XH-X2
|
- **Model**: KP-9000-6XH-X2 / KP-9000-6XHML-X2
|
||||||
- **Ports**:
|
- **Ports**:
|
||||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||||
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||||
|
|
||||||
|
### Machine target
|
||||||
|
|
||||||
|
These devices exist with different PCB revisions. Select the machine target by
|
||||||
|
the PCB silkscreen, not by the label on the case. The `6XH` / `6XHML`
|
||||||
|
distinction appears to be a stock firmware, SKU or label difference, not a
|
||||||
|
reliable indicator of PCB wiring. The PCB revision defines the hardware layout.
|
||||||
|
|
||||||
|
| PCB silkscreen | Known labels / devices | Recommended machine target | Equivalent target | Legacy target |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| `2M-PCB43-V1.1` | Mokerlink 2G040210GSM web-managed 4+2 switch | `MACHINE_KP_9000_6XHML_X2_V1_1` | `MACHINE_KP_9000_6XH_X2_V1_1` | `MACHINE_KP_9000_6XHML_X2` |
|
||||||
|
| `2M-PCB43-V1.2` | `KP-9000-6XHML-X2` | `MACHINE_KP_9000_6XHML_X2_V1_2` | `MACHINE_KP_9000_6XH_X2_V1_2` | `MACHINE_KP_9000_6XHML_X2` |
|
||||||
|
| `2M-PCB43-V2.1` | `KP-9000-6XH-X2`, `KP-9000-6XHML-X2` | `MACHINE_KP_9000_6XH_X2_V2_1` or `MACHINE_KP_9000_6XHML_X2_V2_1` | same V2.1 layout | `MACHINE_KP_9000_6XH_X2` |
|
||||||
|
|
||||||
|
The V1.1 and V1.2 boards currently use the same V1.x GPIO, SFP, port and LED
|
||||||
|
layout. The V2.1 board uses a different V2.1 layout with custom LED muxing.
|
||||||
|
Legacy targets are preserved for compatibility with already-tested devices, but
|
||||||
|
new builds should prefer the explicit PCB-revision targets.
|
||||||
|
|
||||||
### What works
|
### What works
|
||||||
|
|
||||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||||
@@ -19,7 +38,7 @@ Using SPI clamp in-board is the only method for initial installation.
|
|||||||
- LEDs
|
- LEDs
|
||||||
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
|
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
|
||||||
|
|
||||||
### Hardware overview
|
### Hardware overview: 2M-PCB43-V2.1
|
||||||
|
|
||||||
Front side:
|
Front side:
|
||||||
|
|
||||||
@@ -44,6 +63,24 @@ Bottom
|
|||||||
|
|
||||||
<img src="photos/2M-PCB43-V2.1-unmanaged/2M-PCB43-V2.1-bottom.jpg" width="600" />
|
<img src="photos/2M-PCB43-V2.1-unmanaged/2M-PCB43-V2.1-bottom.jpg" width="600" />
|
||||||
|
|
||||||
|
### Hardware overview: 2M-PCB43-V1.1 / V1.2
|
||||||
|
|
||||||
|
The V1.1 board has been reported in the Mokerlink 2G040210GSM web-managed 4+2
|
||||||
|
switch. The V1.2 board has been seen in managed `KP-9000-6XHML-X2` devices.
|
||||||
|
Both use the same V1.x layout.
|
||||||
|
|
||||||
|
Label:
|
||||||
|
|
||||||
|
<img src="photos/KP-9000-6XHML-X2/label.jpg" width="600" />
|
||||||
|
|
||||||
|
Top side:
|
||||||
|
|
||||||
|
<img src="photos/KP-9000-6XHML-X2/pcb_top.jpg" width="600" />
|
||||||
|
|
||||||
|
Bottom:
|
||||||
|
|
||||||
|
<img src="photos/KP-9000-6XHML-X2/pcb_bottom.jpg" width="600" />
|
||||||
|
|
||||||
## Reset Button
|
## Reset Button
|
||||||
|
|
||||||
There's an unpopulated Reset button on the front left side of the PCB.
|
There's an unpopulated Reset button on the front left side of the PCB.
|
||||||
@@ -54,4 +91,3 @@ The front case has already the hole in the metal case, you just have to punch a
|
|||||||
## Power supply
|
## Power supply
|
||||||
|
|
||||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
# SWTG018AS-A V2.0
|
# SWTG018AS-A V2.0
|
||||||
|
## Brands
|
||||||
|
| Brand | Type |Managed| PCB | Flash | Chip RTL |
|
||||||
|
|--------|------------------|-------|------------------|-----------------|---------------|
|
||||||
|
| 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 |
|
||||||
|
|
||||||
|
|
||||||
The following is a documentation for the unmanaged switch marked as `SWTG018AS-A V2.0`.
|
The following is a documentation for the unmanaged switch marked as `SWTG018AS-A V2.0`.
|
||||||
It is e.g. sold under the Ampcom brand, but no branh-markings are found on the device.
|
It is e.g. sold under the Ampcom brand, but no branh-markings are found on the device.
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
### SWTG024AS-A-V2.0.1_4C_2SFP
|
||||||
|
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 | ??? |
|
||||||
|
|
||||||
|
### Label specifications
|
||||||
|
|
||||||
|
- **Name**:
|
||||||
|
- **Ports**:
|
||||||
|
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||||
|
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||||
|
|
||||||
|
<img src="photos/SWTG024AS-A-V2_0_1_19650/horaco-zx-sg4t2-label.jpg" width="300" />
|
||||||
|
|
||||||
|
### What works
|
||||||
|
The device is fully supported:
|
||||||
|
- ALL 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||||
|
- The SFP+ port supports 1G, 2.5G and 10G modules
|
||||||
|
|
||||||
|
### PCB overview
|
||||||
|
|
||||||
|
**Board markings**
|
||||||
|
- Top silkscreen: PCB-SWTG024AS-A-V2.0.1_19650
|
||||||
|
|
||||||
|
Top side
|
||||||
|
|
||||||
|
<img src="photos/SWTG024AS-A-V2_0_1_19650/horaco-zx-sg4t2-pcb-top.jpg" width="300" />
|
||||||
|
|
||||||
|
Bottom
|
||||||
|
|
||||||
|
<img src="photos/SWTG024AS-A-V2_0_1_19650/horaco-zx-sg4t2-pcb-bottom.jpg" width="300" />
|
||||||
|
|
||||||
|
### J1, serial console
|
||||||
|
|
||||||
|
| `J1` pin | Signal |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| 1 | 3V3 |
|
||||||
|
| 2 | GND |
|
||||||
|
| 3 | RX (Input) |
|
||||||
|
| 4 | TX (Output) |
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
### SWTG024AS-A-V2.0.1_5C_1SFP
|
||||||
|
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 | HC-SWTGW215AS | | PCB-SWTG024AS-A-V2.0.1_19650 | W25Q16JV | 8272N |
|
||||||
|
|
||||||
|
### Label specifications
|
||||||
|
|
||||||
|
- **Name**:
|
||||||
|
- **Ports**:
|
||||||
|
- 5 × RJ45: 10/100/1000/2500 Mbps
|
||||||
|
- 1 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||||
|
|
||||||
|
<!-- <img src="" width="300" /> -->
|
||||||
|
|
||||||
|
### What works
|
||||||
|
The device is fully supported:
|
||||||
|
- ALL 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
|
||||||
|
|
||||||
|
### PCB overview
|
||||||
|
|
||||||
|
**Board markings**
|
||||||
|
- Top silkscreen: PCB-SWTG024AS-A-V2.0.1_19650
|
||||||
|
|
||||||
|
Top side
|
||||||
|
|
||||||
|
<!-- <img src="" width="300" /> -->
|
||||||
|
|
||||||
|
Bottom
|
||||||
|
|
||||||
|
<!-- <img src="" width="300" /> -->
|
||||||
|
|
||||||
|
### J1, serial console
|
||||||
|
|
||||||
|
| `J1` pin | Signal |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| 1 | 3V3 |
|
||||||
|
| 2 | GND |
|
||||||
|
| 3 | RX (Input) |
|
||||||
|
| 4 | TX (Output) |
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
### SWTG024AS-V2.0
|
||||||
|
|
||||||
|
## Brands
|
||||||
|
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| hongyavision | LG-SG5T1 | No | PCB-SWTG024AS-V2.0_16895 | 25Q40 | 8272 |
|
||||||
|
|
||||||
|
### Label specifications
|
||||||
|
|
||||||
|
- **Name**:
|
||||||
|
- **Ports**:
|
||||||
|
- 5 × RJ45: 10/100/1000/2500 Mbps
|
||||||
|
- 1 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||||
|
- **Power**: 12V DC, 1A 5525 connector
|
||||||
|
|
||||||
|
<img src="photos/SWTG024AS-V2.0/label.jpg" width="300" />
|
||||||
|
|
||||||
|
### What works
|
||||||
|
The device is fully supported:
|
||||||
|
- ALL 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
|
||||||
|
- Online update does not work with 512KiB flash.
|
||||||
|
### PCB overview
|
||||||
|
|
||||||
|
**Board markings**
|
||||||
|
- Top silkscreen: PCB-SWTG024AS-V2.0
|
||||||
|
|
||||||
|
Top side
|
||||||
|
|
||||||
|
<img src="photos/SWTG024AS-V2.0/pcb_top.jpg" width="300" />
|
||||||
|
|
||||||
|
Bottom
|
||||||
|
|
||||||
|
<img src="photos/SWTG024AS-V2.0/pcb_bottom.jpg" width="300" />
|
||||||
|
|
||||||
|
### J1, serial console
|
||||||
|
|
||||||
|
| `J1` pin | Signal |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| 1 | GND |
|
||||||
|
| 2 | RX (Input) |
|
||||||
|
| 3 | TX (Output) |
|
||||||
|
|
||||||
|
Note,`R52`、`R53`may not be installed.You need to bridge them using either solder or resistors.
|
||||||
|
|
||||||
|
## Power supply
|
||||||
|
|
||||||
|
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||||
@@ -9,8 +9,8 @@ Also the RJ45 connectors can be all plastic/non-shielded or with metal shielding
|
|||||||
|Brand|Type|Managed|PCB|PCB Label|Flash|Chip RTL|
|
|Brand|Type|Managed|PCB|PCB Label|Flash|Chip RTL|
|
||||||
|---|---|---|---|---|---|---|
|
|---|---|---|---|---|---|---|
|
||||||
| LIANGUO |SWTG024AS |No| SWTG024AS-v2.0-17452 | CM-23-11-2336 023-17453| 512 KiB | 8272 |
|
| LIANGUO |SWTG024AS |No| SWTG024AS-v2.0-17452 | CM-23-11-2336 023-17453| 512 KiB | 8272 |
|
||||||
| Haraco |ZX-SWTG124AS | Yes | SWTG024AS-v2.0 | ??? | ??? | 8272 |
|
| Horaco |ZX-SWTG124AS | Yes | SWTG024AS-v2.0 | ??? | ??? | 8272 |
|
||||||
| Xikestore |SKS3200M-4GPY2XF | Yes | SWTG024AS-v1.0 | CM-23-08-2043 023-16721 | ??? | 8272 |
|
| Xikestore |SKS3200M-4GPY2XF | Yes | SWTG024AS-v1.0 | CM-23-08-2043 023-16721 | 2048 KiB | 8272 |
|
||||||
| Sodola | SL-SWTG124AS-D | Yes | SWTG024AS-v2.0-17452 | ??? | 2048 KiB | 8272 |
|
| Sodola | SL-SWTG124AS-D | Yes | SWTG024AS-v2.0-17452 | ??? | 2048 KiB | 8272 |
|
||||||
|
|
||||||
## PCB
|
## PCB
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
| Mokerlink | ZX-SWTGW218AS | Yes| SWTG118AS-V2.0-16029 | 2MB (FM25Q16A)| 8273N + 8224N |
|
| Mokerlink | ZX-SWTGW218AS | Yes| SWTG118AS-V2.0-16029 | 2MB (FM25Q16A)| 8273N + 8224N |
|
||||||
| Sodola | | | | | |
|
| Sodola | | | | | |
|
||||||
| Horaco | | | | | |
|
| Horaco | | | | | |
|
||||||
|
| XikeStor | SKS3200-8E1X | Yes | SWTG118AS-V2.1-17462 | 2MB (25Q16JVSIQ) | |
|
||||||
|
|
||||||
|
|
||||||
## Photos
|
## Photos
|
||||||
|
|||||||
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 715 KiB |
|
After Width: | Height: | Size: 615 KiB |
|
After Width: | Height: | Size: 2.1 MiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 207 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 203 KiB |
|
After Width: | Height: | Size: 455 KiB |
|
After Width: | Height: | Size: 710 KiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 3.2 MiB |
|
After Width: | Height: | Size: 9.7 MiB |
|
After Width: | Height: | Size: 36 MiB |
@@ -92,7 +92,7 @@ The following shows the network configuration
|
|||||||
On _both_ switches create a LAG with ports 1 and 2 inside and the default hash algorithm which takes
|
On _both_ switches create a LAG with ports 1 and 2 inside and the default hash algorithm which takes
|
||||||
source and destination ports into account, e.g. just use the default:
|
source and destination ports into account, e.g. just use the default:
|
||||||
```
|
```
|
||||||
> lag 0 1 2
|
> lag 1 1 2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,12 +37,13 @@ This list is incomplete.
|
|||||||
| Brand | Partnumber |
|
| Brand | Partnumber |
|
||||||
| ---------- |----------- |
|
| ---------- |----------- |
|
||||||
| GigaDevice | GD25Q32E |
|
| GigaDevice | GD25Q32E |
|
||||||
|
| Fundan | FM25Q16A |
|
||||||
|
| Puya | P25D40SH |
|
||||||
| Winbond | W25Q16JV |
|
| Winbond | W25Q16JV |
|
||||||
| Winbond | W25Q32FV |
|
| Winbond | W25Q32FV |
|
||||||
| Winbond | W25Q32JV |
|
| Winbond | W25Q32JV |
|
||||||
| Winbond | W25Q16JL |
|
| Winbond | W25Q16JL |
|
||||||
| Winbond | W25Q16DV |
|
| Winbond | W25Q16DV |
|
||||||
| Winbond | W25Q80DV |
|
| Winbond | W25Q80DV |
|
||||||
| Fundan | FM25Q16A |
|
|
||||||
|
|
||||||
*NOTE*: Part numbers are incomplete. Part numbers may contain additional information such as package, temperature specifications, and even the number of devices on a reel. So always check the datasheet so that you have the right orderable partnumber.
|
*NOTE*: Part numbers are incomplete. Part numbers may contain additional information such as package, temperature specifications, and even the number of devices on a reel. So always check the datasheet so that you have the right orderable partnumber.
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
# Supporting Multiple Languages in the Web UI
|
||||||
|
|
||||||
|
The firmware uses a client-side i18n approach
|
||||||
|
all translations are stored in a single JavaScript dictionary embedded in the firmware.
|
||||||
|
No server-side changes are needed.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
All translation logic lives in `html/i18n.js`. The file contains:
|
||||||
|
|
||||||
|
- A `LANG` object with one sub-object per language (`en`, `ja`, ...)
|
||||||
|
- Language auto-detection (browser language → `localStorage` override)
|
||||||
|
- `t(key)` — look up a translated string
|
||||||
|
- `setLang(lang)` — switch language and update the page
|
||||||
|
- `applyTranslation(el)` — apply translation to one DOM element
|
||||||
|
|
||||||
|
Translation keys are **flat strings** (no nesting). The English keys in `LANG.en` also serve as the fallback when a key is missing in another language.
|
||||||
|
|
||||||
|
## How to Add a New Language
|
||||||
|
|
||||||
|
### 1. Add a dictionary entry in `html/i18n.js`
|
||||||
|
|
||||||
|
Append a new sub-object to the `LANG` object. Every key from `LANG.en` must be present:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var LANG = {
|
||||||
|
en: {
|
||||||
|
nav_overview: 'Overview',
|
||||||
|
nav_port_config: 'Port Configuration',
|
||||||
|
// ... all keys for English
|
||||||
|
},
|
||||||
|
ja: {
|
||||||
|
nav_overview: '概要',
|
||||||
|
nav_port_config: 'ポート設定',
|
||||||
|
// ... all keys for Japanese
|
||||||
|
},
|
||||||
|
LANGCODE: { // ← add your language here
|
||||||
|
nav_overview: '...',
|
||||||
|
nav_port_config: '...',
|
||||||
|
// ... translate every key
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Add the language to the navigation sidebar
|
||||||
|
|
||||||
|
In `html/navigation.js`, add an `<option>` to the language selector:
|
||||||
|
|
||||||
|
```js
|
||||||
|
+ "<option value='en'>English</option><option value='ja'>日本語</option>"
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace with:
|
||||||
|
|
||||||
|
```js
|
||||||
|
+ "<option value='en'>English</option><option value='ja'>日本語</option><option value='LANGCODE'>Native Name</option>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Verify auto-detection
|
||||||
|
|
||||||
|
The language detection code in `i18n.js` reads `navigator.language` and normalises it to the first two characters:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var browser = (navigator.language || navigator.userLanguage || 'en').substring(0, 2);
|
||||||
|
return LANG[browser] ? browser : 'en';
|
||||||
|
```
|
||||||
|
|
||||||
|
If the two-letter code matches a key in `LANG`, it will be auto-selected. No changes needed here.
|
||||||
|
|
||||||
|
## Two Translation Mechanisms
|
||||||
|
|
||||||
|
### (A) `data-i18n` attribute (declarative — for HTML)
|
||||||
|
|
||||||
|
Add `data-i18n="key_name"` to any HTML element. The English text goes in the element content as a fallback:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<h1 data-i18n="port_heading">Port Configuration</h1>
|
||||||
|
<input type="button" data-i18n="port_apply" value="Apply">
|
||||||
|
<option data-i18n="port_auto">Auto</option>
|
||||||
|
<title data-i18n="port_title">Port Configuration</title>
|
||||||
|
```
|
||||||
|
|
||||||
|
On page load, `applyTranslation()` sets:
|
||||||
|
|
||||||
|
- `el.value` for `<input type="submit|button">`
|
||||||
|
- `el.textContent` for `<option>`, `<title>`
|
||||||
|
- `el.innerHTML` for everything else
|
||||||
|
|
||||||
|
### (B) `t('key')` call (imperative — for JavaScript strings)
|
||||||
|
|
||||||
|
When generating HTML or text in JavaScript, wrap translatable strings with `t()`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
td.appendChild(document.createTextNode(t('common_port') + i));
|
||||||
|
td.innerHTML = t('port_auto');
|
||||||
|
iHTML += "<tr><td>" + t('port_vendor') + "</td></tr>";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Special Case: Link Speed Display
|
||||||
|
|
||||||
|
The `linkS` array in `html/main.js` maps numeric link states to display strings. The first two entries (`speed_disabled`, `speed_down`) use `t()` for translation; the remaining entries are static literals (they are the same in all languages):
|
||||||
|
|
||||||
|
```js
|
||||||
|
const linkS = [
|
||||||
|
function(){return t('speed_disabled')},
|
||||||
|
function(){return t('speed_down')},
|
||||||
|
"10M", "100M", "1000M", "500M", "10G", "2.5G", "5G"
|
||||||
|
];
|
||||||
|
function linkText(idx) { var v = linkS[idx]; return typeof v === 'function' ? v() : v; }
|
||||||
|
```
|
||||||
|
|
||||||
|
Always use `linkText(idx)` (not `linkS[idx]`) to read these values.
|
||||||
|
|
||||||
|
## Size Considerations
|
||||||
|
|
||||||
|
- `html/i18n.js` is embedded in the firmware filesystem (~14 KB for two languages)
|
||||||
|
- Each new language adds roughly the same number of bytes as the English dictionary (~3–4 KB)
|
||||||
|
- The firmware binary is padded to 512 KiB, so a few extra KB do not change the flash footprint
|
||||||
|
- Values that are identical in all languages should be inlined as literals rather than added to the dictionary (e.g., `"10M"`, `"2.5G"`, `"MAC"`, `"VLAN"`, `"CPU"`)
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
No special flags are needed. The `html/` directory is embedded by `fileadder` during the build.
|
||||||
|
|
||||||
|
## Script Load Order
|
||||||
|
|
||||||
|
`i18n.js` must be loaded after `main.js` (which defines `t()`'s dependencies like `LANG`) but before any page-specific JS that calls `t()`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="/main.js"></script>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
|
<script src="/eee.js"></script> <!-- uses t() -->
|
||||||
|
```
|
||||||
|
|
||||||
|
The `navigation.js` script is loaded last (bottom of `<body>`).
|
||||||
@@ -1,18 +1,40 @@
|
|||||||
# Supported Hardware
|
# Supported Hardware
|
||||||
The following devices have been tested and are fully working:
|
The following devices have been tested and are fully working:
|
||||||
- Horaco ZX_SG4T2
|
|
||||||
- keepLINK kp-9000-6hx-x2 (RTL8372: 4x 2.5GBit + 2x 10GBit SFP+)
|
|
||||||
- keepLINK KP-9000-6XHML-X2, same as above, but Managed
|
|
||||||
- keepLINK kp-9000-6hx-x (RTL8372 + RTL8221B 2.5GBit PHY: 5 x 2.5GBit + 1x 10GBit SFP+)
|
|
||||||
- keepLINK kp-9000-9xh-x-eu (1 x RTL8373 + RTL8224: 8x 2.5GBit + 1x 10GBit SFP+)
|
|
||||||
- Lianguo LG-SWTGW218AS (RTL8373 + RTL8224 PHY: 8x 2.5GBit + 1x 10GBit SFP+)
|
|
||||||
- No-Name ZX-SWTGW215AS, managed version of kp-9000-6hx-x, ordered on
|
|
||||||
AliExpress as keepLINK 5+1 port managed
|
|
||||||
- TrendNet TEG-S562 (RTL8372: 4x 2.5GBit + 2x 10GBit SFP+)
|
|
||||||
- FNS-1200P (RTL8372: 4x 2.5GBit + 2x 10GBit SFP+)
|
|
||||||
|
|
||||||
Other device based on RTL8272/3 that may work are described here: [Up-N-Atoms 2.5 GBit RTL Switch hacking guide]
|
| Brand | Type | Managed | PCB | Flash | Ports |
|
||||||
(https://github.com/up-n-atom/SWTG118AS)
|
|----------|-----------------|---------|---------------------------------------------------------------------------|-------|-------|
|
||||||
|
| Ampcom | WAM902-SWTG018AS| No | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | | 8 + 1 |
|
||||||
|
| 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 |
|
||||||
|
| 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 | LG-SG5T1 | No | [PCB-SWTG024AS-V2.0_16895](devices/SWTG024AS-V2.0.md) | 0.5M | 5 + 1 |
|
||||||
|
| 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 | 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-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 |
|
||||||
|
| LIANGUO | SWTG024AS | No | [SWTG024AS-v2.0-17452](devices/SWTG024AS.md) | 0.5M | 4 + 2 |
|
||||||
|
| Lianguo | ZX-SWTGW215AS | Yes | [PCB-SWTG115AS-V2.0](devices/SWTGW215AS.md) | 2M | 5 + 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 |
|
||||||
|
| Ruiying | RY-4GT-2SX | No | [FG-4GT-2SX_V2.0](devices/FG-4GT-2SX_V2.0.md) | 4M | 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 |
|
||||||
|
| XikeStor | SKS3200-8E1X | Yes | [SWTG118AS-V2.1-17462](devices/SWTGW218AS.md) | 2M | 8 + 1 |
|
||||||
|
| Ztyuav | Z-QWYT0402 | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 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
|
||||||
|
alone does not identify the wiring.
|
||||||
|
|
||||||
|
Other device based on RTL8272/3 that may work are described here: [Up-N-Atoms 2.5 GBit RTL Switch hacking guide](https://github.com/up-n-atom/SWTG118AS)
|
||||||
|
|
||||||
Many of the RTL8272/3 devices come in versions with PoE support. The RTLPlayground usually also
|
Many of the RTL8272/3 devices come in versions with PoE support. The RTLPlayground usually also
|
||||||
works on these, however, no support for configuring PoE is provided, simply because these
|
works on these, however, no support for configuring PoE is provided, simply because these
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>Ingress and Egress Bandwidth</title>
|
<title data-i18n="bw_title">Ingress and Egress Bandwidth</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
<h1>Ingress and Egress Bandwidth</h1>
|
<h1 data-i18n="bw_heading">Ingress and Egress Bandwidth</h1>
|
||||||
<table id="bwtable">
|
<table id="bwtable">
|
||||||
<tr> <th> </th> <th colspan="3"> Ingress </th> <th colspan="2">Egress</th> <th></th></tr>
|
<tr> <th> </th> <th colspan="3" data-i18n="bw_ingress"> Ingress </th> <th colspan="2" data-i18n="bw_egress">Egress</th> <th></th></tr>
|
||||||
<tr> <th>Port</th> <th>Limit</th> <th>Bandwidth [kBit/s]</th> <th>Flow Control</th> <th>Limit</th> <th>Bandwidth [kBit/s]</th> <th>Apply</th></tr>
|
<tr> <th data-i18n="bw_col_port">Port</th> <th data-i18n="bw_col_limit">Limit</th> <th data-i18n="bw_col_bandwidth">Bandwidth [kBit/s]</th> <th data-i18n="bw_col_flow">Flow Control</th> <th data-i18n="bw_col_limit">Limit</th> <th data-i18n="bw_col_bandwidth">Bandwidth [kBit/s]</th> <th data-i18n="bw_col_apply">Apply</th></tr>
|
||||||
</table>
|
</table>
|
||||||
<script src="/bandwidth.js"></script>
|
<script src="/bandwidth.js"></script>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,18 +6,18 @@ function createBW() {
|
|||||||
console.log("CREATING TABLE ", tbl.rows.length);
|
console.log("CREATING TABLE ", tbl.rows.length);
|
||||||
for (let i = 2; i < 2 + numPorts; i++) {
|
for (let i = 2; i < 2 + numPorts; i++) {
|
||||||
const tr = tbl.insertRow();
|
const tr = tbl.insertRow();
|
||||||
let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i-1}`));
|
let td = tr.insertCell(); td.appendChild(document.createTextNode(t('common_port') + (i-1)));
|
||||||
td = tr.insertCell();
|
td = tr.insertCell();
|
||||||
td.innerHTML = limit.replaceAll("limit_port", "ilimit_port_" + i).replace("exec()", "iClicked(" + i + ")");
|
td.innerHTML = limit.replaceAll("limit_port", "ilimit_port_" + i).replace("exec()", "iClicked(" + i + ")");
|
||||||
td = tr.insertCell();
|
td = tr.insertCell();
|
||||||
td.innerHTML = 'UNLIMITED';
|
td.innerHTML = t('bw_unlimited');
|
||||||
td = tr.insertCell();
|
td = tr.insertCell();
|
||||||
td.innerHTML = limit.replaceAll("limit_port", "fc_port_" + i).replace("exec()", "document.getElementById('bwapply_" + i + "').disabled=false;");
|
td.innerHTML = limit.replaceAll("limit_port", "fc_port_" + i).replace("exec()", "document.getElementById('bwapply_" + i + "').disabled=false;");
|
||||||
td = tr.insertCell();
|
td = tr.insertCell();
|
||||||
td.innerHTML = limit.replaceAll("limit_port", "elimit_port_" + i).replace("exec()", "eClicked(" + i + ")");
|
td.innerHTML = limit.replaceAll("limit_port", "elimit_port_" + i).replace("exec()", "eClicked(" + i + ")");
|
||||||
td = tr.insertCell();
|
td = tr.insertCell();
|
||||||
td.innerHTML = 'UNLIMITED';
|
td.innerHTML = t('bw_unlimited');
|
||||||
var button = '<button type="button" id="bwapply_' + i + '" style="margin: 0 0 0 24px" onclick="applyBandwidth(' + i + ');">Apply</button>';
|
var button = '<button type="button" id="bwapply_' + i + '" style="margin: 0 0 0 24px" onclick="applyBandwidth(' + i + ');">' + t('bw_col_apply') + '</button>';
|
||||||
td = tr.insertCell();
|
td = tr.insertCell();
|
||||||
td.innerHTML = button;
|
td.innerHTML = button;
|
||||||
document.getElementById("bwapply_" + i).disabled = true;
|
document.getElementById("bwapply_" + i).disabled = true;
|
||||||
@@ -31,7 +31,7 @@ function iClicked(i)
|
|||||||
var tbl = document.getElementById('bwtable');
|
var tbl = document.getElementById('bwtable');
|
||||||
var tr = tbl.rows[i];
|
var tr = tbl.rows[i];
|
||||||
if (!document.getElementById("ilimit_port_" + i).checked) {
|
if (!document.getElementById("ilimit_port_" + i).checked) {
|
||||||
tr.cells[2].innerHTML = "UNLIMITED";
|
tr.cells[2].innerHTML = t('bw_unlimited');
|
||||||
document.getElementById("fc_port_" + i).disabled = true;
|
document.getElementById("fc_port_" + i).disabled = true;
|
||||||
document.getElementById("fc_port_" + i).checked = true;
|
document.getElementById("fc_port_" + i).checked = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -47,7 +47,7 @@ function eClicked(i)
|
|||||||
var tbl = document.getElementById('bwtable');
|
var tbl = document.getElementById('bwtable');
|
||||||
var tr = tbl.rows[i];
|
var tr = tbl.rows[i];
|
||||||
if (!document.getElementById("elimit_port_" + i).checked) {
|
if (!document.getElementById("elimit_port_" + i).checked) {
|
||||||
tr.cells[5].innerHTML = "UNLIMITED";
|
tr.cells[5].innerHTML = t('bw_unlimited');
|
||||||
} else {
|
} else {
|
||||||
tr.cells[5].innerHTML = '<input id="ebw_' + i + iLayout + i + ')" value="0"/>';
|
tr.cells[5].innerHTML = '<input id="ebw_' + i + iLayout + i + ')" value="0"/>';
|
||||||
}
|
}
|
||||||
@@ -110,12 +110,12 @@ function getBW() {
|
|||||||
document.getElementById("ilimit_port_" + (n+1)).checked = p.iLimited;
|
document.getElementById("ilimit_port_" + (n+1)).checked = p.iLimited;
|
||||||
document.getElementById("elimit_port_" + (n+1)).checked = p.eLimited;
|
document.getElementById("elimit_port_" + (n+1)).checked = p.eLimited;
|
||||||
if (!p.iLimited) {
|
if (!p.iLimited) {
|
||||||
tr.cells[2].innerHTML = "UNLIMITED";
|
tr.cells[2].innerHTML = t('bw_unlimited');
|
||||||
} else {
|
} else {
|
||||||
tr.cells[2].innerHTML = '<input id="ibw_' + (n+1) + iLayout + (n+1) + ')" value="' + iBW +'"/>';
|
tr.cells[2].innerHTML = '<input id="ibw_' + (n+1) + iLayout + (n+1) + ')" value="' + iBW +'"/>';
|
||||||
}
|
}
|
||||||
if (!p.eLimited) {
|
if (!p.eLimited) {
|
||||||
tr.cells[5].innerHTML = "UNLIMITED";
|
tr.cells[5].innerHTML = t('bw_unlimited');
|
||||||
} else {
|
} else {
|
||||||
tr.cells[5].innerHTML = '<input id="ebw_' + (n+1) + iLayout + (n+1) + ')" value="' + eBW +'"/>';
|
tr.cells[5].innerHTML = '<input id="ebw_' + (n+1) + iLayout + (n+1) + ')" value="' + eBW +'"/>';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const conf_cmds = [
|
|||||||
/^pvid\s+\d{1,2}\s+\d{1,4}$/,
|
/^pvid\s+\d{1,2}\s+\d{1,4}$/,
|
||||||
/^ingress(\s+\d{1,2}[tua])+$/,
|
/^ingress(\s+\d{1,2}[tua])+$/,
|
||||||
/^ingress\s+[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+name\s+\S+$/,
|
||||||
/^eee(\s+\d{1,2})?\s+(on|off)$/,
|
/^eee(\s+\d{1,2})?\s+(on|off)$/,
|
||||||
/^mirror(\s+\d{1,2})(\s+\d{1,2}[tr]?)+$/,
|
/^mirror(\s+\d{1,2})(\s+\d{1,2}[tr]?)+$/,
|
||||||
@@ -24,6 +25,7 @@ const conf_cmds = [
|
|||||||
/^igmp\s+(on|off)$/,
|
/^igmp\s+(on|off)$/,
|
||||||
/^mtu\s+\d{1,2}\s+\d+$/,
|
/^mtu\s+\d{1,2}\s+\d+$/,
|
||||||
/^bw\s+(in|out)\s+\d{1,2}\s+\S+$/,
|
/^bw\s+(in|out)\s+\d{1,2}\s+\S+$/,
|
||||||
|
/^hostname\s+.{1,23}$/,
|
||||||
];
|
];
|
||||||
const conf_overwrite = [
|
const conf_overwrite = [
|
||||||
/^ip\b/,
|
/^ip\b/,
|
||||||
@@ -36,6 +38,7 @@ const conf_overwrite = [
|
|||||||
/^vlan\s+\d{1,4}(?!\s+mgmt\b)/,
|
/^vlan\s+\d{1,4}(?!\s+mgmt\b)/,
|
||||||
/^pvid\s+\d{1,2}\b/,
|
/^pvid\s+\d{1,2}\b/,
|
||||||
/^ingress\b/,
|
/^ingress\b/,
|
||||||
|
/^port\s+\d{1,2}(?!\s+name\b)/,
|
||||||
/^port\s+\d{1,2}\s+name\b/,
|
/^port\s+\d{1,2}\s+name\b/,
|
||||||
/^eee\s+\d{1,2}\b/,
|
/^eee\s+\d{1,2}\b/,
|
||||||
/^eee\b/,
|
/^eee\b/,
|
||||||
@@ -47,6 +50,7 @@ const conf_overwrite = [
|
|||||||
/^igmp\b/,
|
/^igmp\b/,
|
||||||
/^mtu\s+\d{1,2}\b/,
|
/^mtu\s+\d{1,2}\b/,
|
||||||
/^bw\s+(in|out)\s+\d{1,2}\b/,
|
/^bw\s+(in|out)\s+\d{1,2}\b/,
|
||||||
|
/^hostname\b/,
|
||||||
];
|
];
|
||||||
|
|
||||||
function parseConf(s){
|
function parseConf(s){
|
||||||
@@ -57,8 +61,7 @@ function parseConf(s){
|
|||||||
const deleteMatch = line.match(/^vlan\s+(\d{1,4})\s+d$/);
|
const deleteMatch = line.match(/^vlan\s+(\d{1,4})\s+d$/);
|
||||||
if (deleteMatch) {
|
if (deleteMatch) {
|
||||||
const prefix = "vlan " + deleteMatch[1] + " ";
|
const prefix = "vlan " + deleteMatch[1] + " ";
|
||||||
configuration = configuration.filter(c =>
|
configuration = configuration.filter(c => !c.startsWith(prefix));
|
||||||
c !== "vlan " + deleteMatch[1] && !c.startsWith(prefix));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
console.log(l + ' --> ' + line);
|
console.log(l + ' --> ' + line);
|
||||||
@@ -71,10 +74,13 @@ function parseConf(s){
|
|||||||
let m = line.match(x);
|
let m = line.match(x);
|
||||||
let matchStr = m[0];
|
let matchStr = m[0];
|
||||||
configuration = configuration.filter(item =>
|
configuration = configuration.filter(item =>
|
||||||
!(item === matchStr || item.startsWith(matchStr + " ")));
|
!(item === matchStr || (item.startsWith(matchStr + " ") && !item.endsWith(" mgmt") && !item.startsWith(matchStr + " name "))));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Only one management VLAN can be active, so drop any previous mgmt entry
|
||||||
|
if (/^vlan\s+\d{1,4}\s+mgmt$/.test(line))
|
||||||
|
configuration = configuration.filter(item => !/^vlan\s+\d{1,4}\s+mgmt$/.test(item));
|
||||||
configuration.push(line);
|
configuration.push(line);
|
||||||
}
|
}
|
||||||
console.log("Configuration now:");
|
console.log("Configuration now:");
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>EEE Configuration</title>
|
<title data-i18n="eee_title">EEE Configuration</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
<h1>EEE Status</h1>
|
<h1 data-i18n="eee_heading">EEE Status</h1>
|
||||||
<table id="eeetable">
|
<table id="eeetable">
|
||||||
<tr> <th> </th> <th colspan="3"> Advertising </th> <th colspan="3">Link-Partner advertises</th> <th></th></tr>
|
<tr> <th> </th> <th colspan="3" data-i18n="eee_advertising"> Advertising </th> <th colspan="3" data-i18n="eee_partner">Link-Partner advertises</th> <th></th></tr>
|
||||||
<tr> <th>Port</th> <th>2.5G</th> <th>1G</th> <th>100M</th> <th>2.5G</th> <th>1G</th> <th>100M</th> <th>Active?</th></tr>
|
<tr> <th data-i18n="eee_port">Port</th> <th>2.5G</th> <th>1G</th> <th>100M</th> <th>2.5G</th> <th>1G</th> <th>100M</th> <th data-i18n="eee_active">Active?</th></tr>
|
||||||
</table>
|
</table>
|
||||||
<div>
|
<div>
|
||||||
<input style="width:20%;" class="action" id="eee_enable" onclick="eeeSub(0, 1);" type="button" value="Enable EEE">
|
<input style="width:20%;" class="action" id="eee_enable" onclick="eeeSub(0, 1);" type="button" data-i18n="eee_enable" value="Enable EEE">
|
||||||
<input style="width:20%;" class="action" id="eee_enable" onclick="eeeSub(0, 0);" type="button" value="Disable EEE">
|
<input style="width:20%;" class="action" id="eee_disable" onclick="eeeSub(0, 0);" type="button" data-i18n="eee_disable" value="Disable EEE">
|
||||||
</div>
|
</div>
|
||||||
<script src="/eee.js"></script>
|
<script src="/eee.js"></script>
|
||||||
<script src="/eee_sub.js"></script>
|
<script src="/eee_sub.js"></script>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ function createEEE() {
|
|||||||
for (let i = 2; i < 2 + numPorts; i++) {
|
for (let i = 2; i < 2 + numPorts; i++) {
|
||||||
console.log("Table row: " + i + "pState: " + pState[i-2]);
|
console.log("Table row: " + i + "pState: " + pState[i-2]);
|
||||||
const tr = tbl.insertRow();
|
const tr = tbl.insertRow();
|
||||||
let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i-1}`));
|
let td = tr.insertCell(); td.appendChild(document.createTextNode(t('common_port') + (i-1)));
|
||||||
for (let j = 0; j < 7; j++) {
|
for (let j = 0; j < 7; j++) {
|
||||||
td = tr.insertCell(); td.appendChild(document.createTextNode(" "));
|
td = tr.insertCell(); td.appendChild(document.createTextNode(" "));
|
||||||
}
|
}
|
||||||
@@ -28,8 +28,8 @@ function getEEE() {
|
|||||||
let tr = tbl.rows[n+1];
|
let tr = tbl.rows[n+1];
|
||||||
if (!p.isSFP) {
|
if (!p.isSFP) {
|
||||||
let eee = parseInt(p.eee,2); let lp = parseInt(p.eee_lp,2);
|
let eee = parseInt(p.eee,2); let lp = parseInt(p.eee_lp,2);
|
||||||
tr.cells[1].innerHTML = `${eee&4?"ON":"OFF"}`; tr.cells[2].innerHTML = `${eee&2?"ON":"OFF"}`; tr.cells[3].innerHTML = `${eee&1?"ON":"OFF"}`;
|
tr.cells[1].innerHTML = `${eee&4?t('eee_on'):t('eee_off')}`; tr.cells[2].innerHTML = `${eee&2?t('eee_on'):t('eee_off')}`; tr.cells[3].innerHTML = `${eee&1?t('eee_on'):t('eee_off')}`;
|
||||||
tr.cells[4].innerHTML = `${lp&4?"ON":"OFF"}`; tr.cells[5].innerHTML = `${lp&2?"ON":"OFF"}`; tr.cells[6].innerHTML = `${lp&1?"ON":"OFF"}`;
|
tr.cells[4].innerHTML = `${lp&4?t('eee_on'):t('eee_off')}`; tr.cells[5].innerHTML = `${lp&2?t('eee_on'):t('eee_off')}`; tr.cells[6].innerHTML = `${lp&1?t('eee_on'):t('eee_off')}`;
|
||||||
tr.cells[7].innerHTML = `${p.active}`;
|
tr.cells[7].innerHTML = `${p.active}`;
|
||||||
tr.classList.toggle('disabled', pState[i-2] < 0); tr.classList.toggle('isNOK', !p.active); tr.classList.toggle('isOK', p.active);
|
tr.classList.toggle('disabled', pState[i-2] < 0); tr.classList.toggle('isNOK', !p.active); tr.classList.toggle('isOK', p.active);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,603 @@
|
|||||||
|
var LANG = {
|
||||||
|
en: {
|
||||||
|
nav_overview: 'Overview',
|
||||||
|
nav_port_config: 'Port Configuration',
|
||||||
|
nav_port_stat: 'Port Statistics',
|
||||||
|
nav_l2: 'L2 Configuration',
|
||||||
|
nav_mirror: 'Mirroring',
|
||||||
|
nav_lag: 'Link Aggregation',
|
||||||
|
nav_eee: 'EEE',
|
||||||
|
nav_bandwidth: 'Bandwidth Limits',
|
||||||
|
nav_system: 'System Settings',
|
||||||
|
nav_fw_update: 'Firmware Update',
|
||||||
|
|
||||||
|
port_name: 'Name',
|
||||||
|
port_status: 'Status',
|
||||||
|
port_not_enabled: 'Not enabled.',
|
||||||
|
port_link_speed: 'Link speed',
|
||||||
|
port_vendor: 'Vendor',
|
||||||
|
port_model: 'Model',
|
||||||
|
port_serial: 'Serial',
|
||||||
|
port_temp: 'Temp',
|
||||||
|
port_vcc: 'Vcc',
|
||||||
|
port_tx_fault: 'TX-Fault',
|
||||||
|
port_tx_disabled: 'TX-Disabled',
|
||||||
|
port_tx_bias: 'TX-Bias',
|
||||||
|
port_tx_power: 'TX-Power',
|
||||||
|
port_rx_power: 'RX-Power',
|
||||||
|
port_rx_los: 'RX-LOS',
|
||||||
|
|
||||||
|
speed_disabled: 'Disabled',
|
||||||
|
speed_down: 'Down',
|
||||||
|
|
||||||
|
port_title: 'FreeSwitchOS Port Configuration',
|
||||||
|
port_heading: 'Port Configuration',
|
||||||
|
port_col_port: 'Port',
|
||||||
|
port_col_name: 'Name',
|
||||||
|
port_col_speed: 'Current Link Speed',
|
||||||
|
port_col_set_speed: 'Set Speed',
|
||||||
|
port_col_disabled: 'Disabled',
|
||||||
|
port_col_apply: 'Apply',
|
||||||
|
port_mtu_heading: 'Configure Maximum Frame Size (MTU) forwarded at Port',
|
||||||
|
port_auto: 'Auto',
|
||||||
|
port_2500m: '2500MBit/Full',
|
||||||
|
port_1000m: '1000MBit/Full',
|
||||||
|
port_100m_f: '100MBit/Full',
|
||||||
|
port_100m_h: '100MBit/Half',
|
||||||
|
port_10m_f: '10MBit/Full',
|
||||||
|
port_10m_h: '10MBit/Half',
|
||||||
|
port_apply: 'Apply',
|
||||||
|
|
||||||
|
stat_title: 'FreeSwitchOS Port Statistics',
|
||||||
|
stat_heading: 'Port Statistics',
|
||||||
|
stat_detailed: 'Detailed Port Statistics',
|
||||||
|
stat_close: 'Close',
|
||||||
|
stat_col_port: 'Port',
|
||||||
|
stat_col_name: 'Name',
|
||||||
|
stat_col_link: 'link',
|
||||||
|
stat_col_tx_good: 'TX Good',
|
||||||
|
stat_col_tx_bad: 'TX Bad',
|
||||||
|
stat_col_rx_good: 'RX Good',
|
||||||
|
stat_col_rx_bad: 'RX Bad',
|
||||||
|
stat_col_all: 'All Counters',
|
||||||
|
stat_counter: 'Counter',
|
||||||
|
stat_value: 'Value',
|
||||||
|
stat_show: 'Show',
|
||||||
|
|
||||||
|
vlan_title: 'FreeSwitchOS VLAN Configuration',
|
||||||
|
vlan_heading: 'VLAN Configuration',
|
||||||
|
vlan_select: 'VLAN Select:',
|
||||||
|
vlan_choose: '— VLAN Choose —',
|
||||||
|
vlan_id: 'VLAN ID:',
|
||||||
|
vlan_get_config: 'Get Configuration',
|
||||||
|
vlan_name: 'VLAN Name:',
|
||||||
|
vlan_tagged: 'Tagged Ports',
|
||||||
|
vlan_untagged: 'Untagged Ports',
|
||||||
|
vlan_select_all: 'Select all',
|
||||||
|
vlan_pvid: 'Use as default VLAN for incoming traffic (PVID)',
|
||||||
|
vlan_update: 'Update / Create',
|
||||||
|
vlan_configured: 'Configured VLANs',
|
||||||
|
vlan_col_name: 'Name',
|
||||||
|
vlan_col_member: 'Member Ports',
|
||||||
|
vlan_col_tagged: 'Tagged Ports',
|
||||||
|
vlan_col_untagged: 'Untagged Ports',
|
||||||
|
vlan_col_pvid: 'PVID Ports',
|
||||||
|
vlan_col_delete: 'Delete',
|
||||||
|
vlan_set_id_first: 'Set VLAN ID first',
|
||||||
|
vlan_delete_confirm: 'Delete VLAN ',
|
||||||
|
|
||||||
|
lag_title: 'Link Aggregation Configuration',
|
||||||
|
lag_heading: 'Link Aggregation Groups Configuration',
|
||||||
|
lag_update: 'Update / Create',
|
||||||
|
|
||||||
|
mirror_title: 'Mirror Configuration',
|
||||||
|
mirror_heading: 'Mirror Configuration',
|
||||||
|
mirror_enabled: 'Enabled:',
|
||||||
|
mirror_port: 'Mirroring Port:',
|
||||||
|
mirror_tx: 'Mirrored Ports (TX)',
|
||||||
|
mirror_rx: 'Mirrored Ports (RX)',
|
||||||
|
mirror_update: 'Update / Create',
|
||||||
|
mirror_disable: 'Disable Mirroring',
|
||||||
|
mirror_set_port_first: 'Set Mirroring Port first',
|
||||||
|
mirror_select_ports: 'Select Mirrored Ports',
|
||||||
|
|
||||||
|
eee_title: 'EEE Configuration',
|
||||||
|
eee_heading: 'EEE Status',
|
||||||
|
eee_advertising: 'Advertising',
|
||||||
|
eee_partner: 'Link-Partner advertises',
|
||||||
|
eee_port: 'Port',
|
||||||
|
eee_active: 'Active?',
|
||||||
|
eee_enable: 'Enable EEE',
|
||||||
|
eee_disable: 'Disable EEE',
|
||||||
|
eee_on: 'ON',
|
||||||
|
eee_off: 'OFF',
|
||||||
|
|
||||||
|
l2_title: 'FreeSwitchOS L2 Configuration',
|
||||||
|
l2_heading: 'L2 Configuration',
|
||||||
|
l2_col_port: 'Port',
|
||||||
|
l2_col_type: 'Type',
|
||||||
|
l2_col_remove: 'Remove Entry',
|
||||||
|
l2_shown: 'Shown:',
|
||||||
|
l2_delete: 'Delete',
|
||||||
|
l2_static: 'static',
|
||||||
|
l2_learned: 'learned',
|
||||||
|
|
||||||
|
bw_title: 'Ingress and Egress Bandwidth',
|
||||||
|
bw_heading: 'Ingress and Egress Bandwidth',
|
||||||
|
bw_ingress: 'Ingress',
|
||||||
|
bw_egress: 'Egress',
|
||||||
|
bw_col_port: 'Port',
|
||||||
|
bw_col_limit: 'Limit',
|
||||||
|
bw_col_bandwidth: 'Bandwidth [kBit/s]',
|
||||||
|
bw_col_flow: 'Flow Control',
|
||||||
|
bw_col_apply: 'Apply',
|
||||||
|
bw_unlimited: 'UNLIMITED',
|
||||||
|
|
||||||
|
sys_title: 'System Settings',
|
||||||
|
sys_tab_system: 'System',
|
||||||
|
sys_tab_advanced: 'Advanced',
|
||||||
|
sys_tab_console: 'Console',
|
||||||
|
sys_heading: 'System Settings',
|
||||||
|
sys_ip: 'IP address:',
|
||||||
|
sys_model: 'Model:',
|
||||||
|
sys_hostname: 'Hostname:',
|
||||||
|
sys_apply: 'Apply',
|
||||||
|
sys_netmask: 'Netmask:',
|
||||||
|
sys_gateway: 'Gateway:',
|
||||||
|
sys_language: 'Language:',
|
||||||
|
sys_mgmt_vlan: 'Management VLAN:',
|
||||||
|
sys_mgmt_untagged: 'untagged',
|
||||||
|
sys_mgmt_confirm: 'Move switch management to VLAN ',
|
||||||
|
sys_mgmt_warn: '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. Continue?',
|
||||||
|
sys_ip_note: 'When updating the above settings, remember to point your browser to the new IP afterwards:',
|
||||||
|
sys_update: 'Update Settings',
|
||||||
|
sys_save_label: 'Save all current settings to Flash:',
|
||||||
|
sys_save: 'Save Settings to Flash',
|
||||||
|
sys_advanced: 'Advanced Settings',
|
||||||
|
sys_startup_config: 'Startup configuration:',
|
||||||
|
sys_startup_warn: 'Be careful when saving the directly edited startup configuration, you can lock yourself out:',
|
||||||
|
sys_clear_config: 'Clear Startup Config',
|
||||||
|
sys_save_startup: 'Save Startup Settings to Flash',
|
||||||
|
sys_reset: 'Reset Switch',
|
||||||
|
sys_console: 'Console Command',
|
||||||
|
sys_enter_cmd: 'Enter command:',
|
||||||
|
sys_send_cmd: 'Send Command',
|
||||||
|
sys_console_warn: 'Be careful when entering console commands, you can lock yourself out!',
|
||||||
|
sys_invalid_ip: 'Invalid ip:',
|
||||||
|
sys_reset_confirm: 'Are you sure you want to reset the switch?',
|
||||||
|
sys_resetting: 'Switch is resetting. Please wait and refresh the page.',
|
||||||
|
|
||||||
|
login_title: 'RTL Switch Login',
|
||||||
|
login_heading: 'RTL Switch Login',
|
||||||
|
login_wrong: 'Wrong password!',
|
||||||
|
login_password: 'Password',
|
||||||
|
login_login: 'Login',
|
||||||
|
|
||||||
|
index_title: 'FreeSwitchOS Main Page',
|
||||||
|
index_heading: 'Switch Configuration',
|
||||||
|
index_settings: 'Settings',
|
||||||
|
|
||||||
|
update_title: 'Firmware update',
|
||||||
|
update_heading: 'Firmware Update',
|
||||||
|
update_instruction: 'Choose a firmware update file to upload:',
|
||||||
|
update_upload: 'Upload File',
|
||||||
|
|
||||||
|
common_port: 'Port ',
|
||||||
|
common_pkts: ' pkts',
|
||||||
|
},
|
||||||
|
|
||||||
|
ja: {
|
||||||
|
nav_overview: '概要',
|
||||||
|
nav_port_config: 'ポート設定',
|
||||||
|
nav_port_stat: 'ポート統計',
|
||||||
|
nav_l2: 'L2 設定',
|
||||||
|
nav_mirror: 'ミラーリング',
|
||||||
|
nav_lag: 'リンクアグリゲーション',
|
||||||
|
nav_eee: 'EEE',
|
||||||
|
nav_bandwidth: '帯域制限',
|
||||||
|
nav_system: 'システム設定',
|
||||||
|
nav_fw_update: 'ファームウェア更新',
|
||||||
|
|
||||||
|
port_name: '名前',
|
||||||
|
port_status: '状態',
|
||||||
|
port_not_enabled: '無効',
|
||||||
|
port_link_speed: 'リンク速度',
|
||||||
|
port_vendor: 'ベンダー',
|
||||||
|
port_model: 'モデル',
|
||||||
|
port_serial: 'シリアル',
|
||||||
|
port_temp: '温度',
|
||||||
|
port_vcc: '電圧',
|
||||||
|
port_tx_fault: 'TX 障害',
|
||||||
|
port_tx_disabled: 'TX 無効',
|
||||||
|
port_tx_bias: 'TX バイアス',
|
||||||
|
port_tx_power: 'TX 電力',
|
||||||
|
port_rx_power: 'RX 電力',
|
||||||
|
port_rx_los: 'RX 信号ロス',
|
||||||
|
|
||||||
|
speed_disabled: '無効',
|
||||||
|
speed_down: 'リンクダウン',
|
||||||
|
|
||||||
|
port_title: 'FreeSwitchOS ポート設定',
|
||||||
|
port_heading: 'ポート設定',
|
||||||
|
port_col_port: 'ポート',
|
||||||
|
port_col_name: '名前',
|
||||||
|
port_col_speed: '現在のリンク速度',
|
||||||
|
port_col_set_speed: '速度設定',
|
||||||
|
port_col_disabled: '無効',
|
||||||
|
port_col_apply: '適用',
|
||||||
|
port_mtu_heading: 'ポートの最大フレームサイズ (MTU) 設定',
|
||||||
|
port_auto: '自動',
|
||||||
|
port_2500m: '2500Mbps/全二重',
|
||||||
|
port_1000m: '1000Mbps/全二重',
|
||||||
|
port_100m_f: '100Mbps/全二重',
|
||||||
|
port_100m_h: '100Mbps/半二重',
|
||||||
|
port_10m_f: '10Mbps/全二重',
|
||||||
|
port_10m_h: '10Mbps/半二重',
|
||||||
|
port_apply: '適用',
|
||||||
|
|
||||||
|
stat_title: 'FreeSwitchOS ポート統計',
|
||||||
|
stat_heading: 'ポート統計',
|
||||||
|
stat_detailed: '詳細ポート統計',
|
||||||
|
stat_close: '閉じる',
|
||||||
|
stat_col_port: 'ポート',
|
||||||
|
stat_col_name: '名前',
|
||||||
|
stat_col_link: 'リンク',
|
||||||
|
stat_col_tx_good: 'TX 正常',
|
||||||
|
stat_col_tx_bad: 'TX 異常',
|
||||||
|
stat_col_rx_good: 'RX 正常',
|
||||||
|
stat_col_rx_bad: 'RX 異常',
|
||||||
|
stat_col_all: '全カウンタ',
|
||||||
|
stat_counter: 'カウンタ',
|
||||||
|
stat_value: '値',
|
||||||
|
stat_show: '表示',
|
||||||
|
|
||||||
|
vlan_title: 'FreeSwitchOS VLAN 設定',
|
||||||
|
vlan_heading: 'VLAN 設定',
|
||||||
|
vlan_select: 'VLAN 選択:',
|
||||||
|
vlan_choose: '— VLAN 選択 —',
|
||||||
|
vlan_id: 'VLAN ID:',
|
||||||
|
vlan_get_config: '設定取得',
|
||||||
|
vlan_name: 'VLAN 名:',
|
||||||
|
vlan_tagged: 'タグ付きポート',
|
||||||
|
vlan_untagged: 'タグ無しポート',
|
||||||
|
vlan_select_all: 'すべて選択',
|
||||||
|
vlan_pvid: '受信トラフィックのデフォルト VLAN (PVID)',
|
||||||
|
vlan_update: '更新 / 作成',
|
||||||
|
vlan_configured: '設定済み VLAN',
|
||||||
|
vlan_col_name: '名前',
|
||||||
|
vlan_col_member: 'メンバーポート',
|
||||||
|
vlan_col_tagged: 'タグ付きポート',
|
||||||
|
vlan_col_untagged: 'タグ無しポート',
|
||||||
|
vlan_col_pvid: 'PVID ポート',
|
||||||
|
vlan_col_delete: '削除',
|
||||||
|
vlan_set_id_first: 'VLAN ID を先に設定してください',
|
||||||
|
vlan_delete_confirm: 'VLAN 削除 ',
|
||||||
|
|
||||||
|
lag_title: 'リンクアグリゲーション設定',
|
||||||
|
lag_heading: 'リンクアグリゲーショングループ設定',
|
||||||
|
lag_update: '更新 / 作成',
|
||||||
|
|
||||||
|
mirror_title: 'ミラーリング設定',
|
||||||
|
mirror_heading: 'ミラーリング設定',
|
||||||
|
mirror_enabled: '有効:',
|
||||||
|
mirror_port: 'ミラーポート:',
|
||||||
|
mirror_tx: 'ミラー元ポート (TX)',
|
||||||
|
mirror_rx: 'ミラー元ポート (RX)',
|
||||||
|
mirror_update: '更新 / 作成',
|
||||||
|
mirror_disable: 'ミラーリング無効化',
|
||||||
|
mirror_set_port_first: 'ミラーポートを先に設定してください',
|
||||||
|
mirror_select_ports: 'ミラー元ポートを選択してください',
|
||||||
|
|
||||||
|
eee_title: 'EEE 設定',
|
||||||
|
eee_heading: 'EEE 状態',
|
||||||
|
eee_advertising: 'EEE アドバタイジング',
|
||||||
|
eee_partner: 'リンクパートナー広告',
|
||||||
|
eee_port: 'ポート',
|
||||||
|
eee_active: '有効?',
|
||||||
|
eee_enable: 'EEE 有効化',
|
||||||
|
eee_disable: 'EEE 無効化',
|
||||||
|
eee_on: 'オン',
|
||||||
|
eee_off: 'オフ',
|
||||||
|
|
||||||
|
l2_title: 'FreeSwitchOS L2 設定',
|
||||||
|
l2_heading: 'L2 設定',
|
||||||
|
l2_col_port: 'ポート',
|
||||||
|
l2_col_type: 'タイプ',
|
||||||
|
l2_col_remove: 'エントリ削除',
|
||||||
|
l2_shown: 'Shown:',
|
||||||
|
l2_delete: '削除',
|
||||||
|
l2_static: '静的',
|
||||||
|
l2_learned: '学習',
|
||||||
|
|
||||||
|
bw_title: '入力/出力帯域制限',
|
||||||
|
bw_heading: '入力/出力帯域制限',
|
||||||
|
bw_ingress: '入力',
|
||||||
|
bw_egress: '出力',
|
||||||
|
bw_col_port: 'ポート',
|
||||||
|
bw_col_limit: '制限',
|
||||||
|
bw_col_bandwidth: '帯域 [kbps]',
|
||||||
|
bw_col_flow: 'フロー制御',
|
||||||
|
bw_col_apply: '適用',
|
||||||
|
bw_unlimited: '制限無し',
|
||||||
|
|
||||||
|
sys_title: 'システム設定',
|
||||||
|
sys_tab_system: 'システム',
|
||||||
|
sys_tab_advanced: '詳細設定',
|
||||||
|
sys_tab_console: 'コンソール',
|
||||||
|
sys_heading: 'システム設定',
|
||||||
|
sys_ip: 'IP アドレス:',
|
||||||
|
sys_model: 'モデル:',
|
||||||
|
sys_hostname: 'ホスト名:',
|
||||||
|
sys_apply: '適用',
|
||||||
|
sys_netmask: 'ネットマスク:',
|
||||||
|
sys_gateway: 'ゲートウェイ:',
|
||||||
|
sys_language: '言語:',
|
||||||
|
sys_mgmt_vlan: 'Management VLAN:',
|
||||||
|
sys_mgmt_untagged: 'untagged',
|
||||||
|
sys_mgmt_confirm: 'Move switch management to VLAN ',
|
||||||
|
sys_mgmt_warn: '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. Continue?',
|
||||||
|
sys_ip_note: '上記設定を変更した場合は、ブラウザで新しい IP にアクセスしてください:',
|
||||||
|
sys_update: '設定更新',
|
||||||
|
sys_save_label: '現在の設定をフラッシュに保存:',
|
||||||
|
sys_save: '設定をフラッシュに保存',
|
||||||
|
sys_advanced: '詳細設定',
|
||||||
|
sys_startup_config: '起動設定:',
|
||||||
|
sys_startup_warn: '起動設定を直接編集する際は注意してください。ロックアウトされる可能性があります:',
|
||||||
|
sys_clear_config: '起動設定クリア',
|
||||||
|
sys_save_startup: '起動設定をフラッシュに保存',
|
||||||
|
sys_reset: 'スイッチ再起動',
|
||||||
|
sys_console: 'コンソールコマンド',
|
||||||
|
sys_enter_cmd: 'コマンド入力:',
|
||||||
|
sys_send_cmd: 'コマンド送信',
|
||||||
|
sys_console_warn: 'コンソールコマンドは注意して入力してください。ロックアウトされる可能性があります!',
|
||||||
|
sys_invalid_ip: '無効な IP: ',
|
||||||
|
sys_reset_confirm: 'スイッチを再起動してもよろしいですか?',
|
||||||
|
sys_resetting: 'スイッチを再起動中です。しばらく待ってからページをリロードしてください。',
|
||||||
|
|
||||||
|
login_title: 'RTL スイッチ ログイン',
|
||||||
|
login_heading: 'RTL スイッチ ログイン',
|
||||||
|
login_wrong: 'パスワードが違います!',
|
||||||
|
login_password: 'パスワード',
|
||||||
|
login_login: 'ログイン',
|
||||||
|
|
||||||
|
index_title: 'FreeSwitchOS メインページ',
|
||||||
|
index_heading: 'スイッチ設定',
|
||||||
|
index_settings: '設定',
|
||||||
|
|
||||||
|
update_title: 'ファームウェア更新',
|
||||||
|
update_heading: 'ファームウェア更新',
|
||||||
|
update_instruction: 'アップロードするファームウェアファイルを選択:',
|
||||||
|
update_upload: 'ファイルをアップロード',
|
||||||
|
|
||||||
|
common_port: 'ポート ',
|
||||||
|
common_pkts: ' pkts',
|
||||||
|
},
|
||||||
|
|
||||||
|
zh: {
|
||||||
|
nav_overview: '概览',
|
||||||
|
nav_port_config: '端口配置',
|
||||||
|
nav_port_stat: '端口统计',
|
||||||
|
nav_l2: 'L2 配置',
|
||||||
|
nav_mirror: '端口镜像',
|
||||||
|
nav_lag: '链路聚合',
|
||||||
|
nav_eee: 'EEE',
|
||||||
|
nav_bandwidth: '带宽限制',
|
||||||
|
nav_system: '系统设置',
|
||||||
|
nav_fw_update: '固件升级',
|
||||||
|
|
||||||
|
port_name: '名称',
|
||||||
|
port_status: '状态',
|
||||||
|
port_not_enabled: '未启用。',
|
||||||
|
port_link_speed: '链路速率',
|
||||||
|
port_vendor: '厂商',
|
||||||
|
port_model: '型号',
|
||||||
|
port_serial: '序列号',
|
||||||
|
port_temp: '温度',
|
||||||
|
port_vcc: '供电电压',
|
||||||
|
port_tx_fault: 'TX 故障',
|
||||||
|
port_tx_disabled: 'TX 禁用',
|
||||||
|
port_tx_bias: 'TX 偏置电流',
|
||||||
|
port_tx_power: 'TX 光功率',
|
||||||
|
port_rx_power: 'RX 光功率',
|
||||||
|
port_rx_los: 'RX 信号丢失',
|
||||||
|
|
||||||
|
speed_disabled: '禁用',
|
||||||
|
speed_down: '未连接',
|
||||||
|
|
||||||
|
port_title: 'FreeSwitchOS 端口配置',
|
||||||
|
port_heading: '端口配置',
|
||||||
|
port_col_port: '端口',
|
||||||
|
port_col_name: '名称',
|
||||||
|
port_col_speed: '当前链路速率',
|
||||||
|
port_col_set_speed: '设置速率',
|
||||||
|
port_col_disabled: '禁用',
|
||||||
|
port_col_apply: '应用',
|
||||||
|
port_mtu_heading: '配置端口转发的最大帧大小 (MTU)',
|
||||||
|
port_auto: '自动',
|
||||||
|
port_2500m: '2500Mbps/全双工',
|
||||||
|
port_1000m: '1000Mbps/全双工',
|
||||||
|
port_100m_f: '100Mbps/全双工',
|
||||||
|
port_100m_h: '100Mbps/半双工',
|
||||||
|
port_10m_f: '10Mbps/全双工',
|
||||||
|
port_10m_h: '10Mbps/半双工',
|
||||||
|
port_apply: '应用',
|
||||||
|
|
||||||
|
stat_title: 'FreeSwitchOS 端口统计',
|
||||||
|
stat_heading: '端口统计',
|
||||||
|
stat_detailed: '详细端口统计',
|
||||||
|
stat_close: '关闭',
|
||||||
|
stat_col_port: '端口',
|
||||||
|
stat_col_name: '名称',
|
||||||
|
stat_col_link: '链路',
|
||||||
|
stat_col_tx_good: 'TX 正常包',
|
||||||
|
stat_col_tx_bad: 'TX 错误包',
|
||||||
|
stat_col_rx_good: 'RX 正常包',
|
||||||
|
stat_col_rx_bad: 'RX 错误包',
|
||||||
|
stat_col_all: '所有计数器',
|
||||||
|
stat_counter: '计数器',
|
||||||
|
stat_value: '值',
|
||||||
|
stat_show: '查看',
|
||||||
|
|
||||||
|
vlan_title: 'FreeSwitchOS VLAN 配置',
|
||||||
|
vlan_heading: 'VLAN 配置',
|
||||||
|
vlan_select: 'VLAN 选择:',
|
||||||
|
vlan_choose: '-- 请选择 VLAN --',
|
||||||
|
vlan_id: 'VLAN ID:',
|
||||||
|
vlan_get_config: '获取配置',
|
||||||
|
vlan_name: 'VLAN 名称:',
|
||||||
|
vlan_tagged: 'Tagged 端口',
|
||||||
|
vlan_untagged: 'Untagged 端口',
|
||||||
|
vlan_select_all: '全选',
|
||||||
|
vlan_pvid: '作为入方向流量的默认 VLAN (PVID)',
|
||||||
|
vlan_update: '更新 / 创建',
|
||||||
|
vlan_configured: '已配置 VLAN',
|
||||||
|
vlan_col_name: '名称',
|
||||||
|
vlan_col_member: '成员端口',
|
||||||
|
vlan_col_tagged: 'Tagged 端口',
|
||||||
|
vlan_col_untagged: 'Untagged 端口',
|
||||||
|
vlan_col_pvid: 'PVID 端口',
|
||||||
|
vlan_col_delete: '删除',
|
||||||
|
vlan_set_id_first: '请先设置 VLAN ID',
|
||||||
|
vlan_delete_confirm: '删除 VLAN ',
|
||||||
|
|
||||||
|
lag_title: '链路聚合配置',
|
||||||
|
lag_heading: '链路聚合组配置',
|
||||||
|
lag_update: '更新 / 创建',
|
||||||
|
|
||||||
|
mirror_title: '端口镜像配置',
|
||||||
|
mirror_heading: '端口镜像配置',
|
||||||
|
mirror_enabled: '启用:',
|
||||||
|
mirror_port: '镜像目的端口:',
|
||||||
|
mirror_tx: '被镜像端口 (TX)',
|
||||||
|
mirror_rx: '被镜像端口 (RX)',
|
||||||
|
mirror_update: '更新 / 创建',
|
||||||
|
mirror_disable: '禁用端口镜像',
|
||||||
|
mirror_set_port_first: '请先设置镜像目的端口',
|
||||||
|
mirror_select_ports: '请选择被镜像端口',
|
||||||
|
|
||||||
|
eee_title: 'EEE 配置',
|
||||||
|
eee_heading: 'EEE 状态',
|
||||||
|
eee_advertising: '本端通告',
|
||||||
|
eee_partner: '链路伙伴通告',
|
||||||
|
eee_port: '端口',
|
||||||
|
eee_active: '已生效?',
|
||||||
|
eee_enable: '启用 EEE',
|
||||||
|
eee_disable: '禁用 EEE',
|
||||||
|
eee_on: '开',
|
||||||
|
eee_off: '关',
|
||||||
|
|
||||||
|
l2_title: 'FreeSwitchOS L2 配置',
|
||||||
|
l2_heading: 'L2 配置',
|
||||||
|
l2_col_port: '端口',
|
||||||
|
l2_col_type: '类型',
|
||||||
|
l2_col_remove: '删除条目',
|
||||||
|
l2_shown: 'Shown:',
|
||||||
|
l2_delete: '删除',
|
||||||
|
l2_static: '静态',
|
||||||
|
l2_learned: '动态学习',
|
||||||
|
|
||||||
|
bw_title: '入方向/出方向带宽限制',
|
||||||
|
bw_heading: '入方向/出方向带宽限制',
|
||||||
|
bw_ingress: '入方向',
|
||||||
|
bw_egress: '出方向',
|
||||||
|
bw_col_port: '端口',
|
||||||
|
bw_col_limit: '限速',
|
||||||
|
bw_col_bandwidth: '带宽 [kbit/s]',
|
||||||
|
bw_col_flow: '流量控制',
|
||||||
|
bw_col_apply: '应用',
|
||||||
|
bw_unlimited: '不限速',
|
||||||
|
|
||||||
|
sys_title: '系统设置',
|
||||||
|
sys_tab_system: '系统',
|
||||||
|
sys_tab_advanced: '高级',
|
||||||
|
sys_tab_console: '控制台',
|
||||||
|
sys_heading: '系统设置',
|
||||||
|
sys_ip: 'IP 地址:',
|
||||||
|
sys_model: '型号:',
|
||||||
|
sys_hostname: '主机名:',
|
||||||
|
sys_apply: '应用',
|
||||||
|
sys_netmask: '子网掩码:',
|
||||||
|
sys_gateway: '网关:',
|
||||||
|
sys_language: '语言:',
|
||||||
|
sys_mgmt_vlan: 'Management VLAN:',
|
||||||
|
sys_mgmt_untagged: 'untagged',
|
||||||
|
sys_mgmt_confirm: 'Move switch management to VLAN ',
|
||||||
|
sys_mgmt_warn: '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. Continue?',
|
||||||
|
sys_ip_note: '更新上述设置后,请使用新的 IP 地址重新访问管理界面:',
|
||||||
|
sys_update: '更新设置',
|
||||||
|
sys_save_label: '将当前全部设置保存到 Flash:',
|
||||||
|
sys_save: '保存设置到 Flash',
|
||||||
|
sys_advanced: '高级设置',
|
||||||
|
sys_startup_config: '启动配置:',
|
||||||
|
sys_startup_warn: '直接编辑启动配置时请谨慎,错误配置可能导致无法访问设备:',
|
||||||
|
sys_clear_config: '清除启动配置',
|
||||||
|
sys_save_startup: '保存启动配置到 Flash',
|
||||||
|
sys_reset: '重启交换机',
|
||||||
|
sys_console: '控制台命令',
|
||||||
|
sys_enter_cmd: '输入命令:',
|
||||||
|
sys_send_cmd: '发送命令',
|
||||||
|
sys_console_warn: '输入控制台命令时请谨慎,错误命令可能导致无法访问设备!',
|
||||||
|
sys_invalid_ip: '无效 IP: ',
|
||||||
|
sys_reset_confirm: '确定要重启交换机吗?',
|
||||||
|
sys_resetting: '交换机正在重启。请稍候并刷新页面。',
|
||||||
|
|
||||||
|
login_title: 'RTL 交换机登录',
|
||||||
|
login_heading: 'RTL 交换机登录',
|
||||||
|
login_wrong: '密码错误!',
|
||||||
|
login_password: '密码',
|
||||||
|
login_login: '登录',
|
||||||
|
|
||||||
|
index_title: 'FreeSwitchOS 主页',
|
||||||
|
index_heading: '交换机配置',
|
||||||
|
index_settings: '设置',
|
||||||
|
|
||||||
|
update_title: '固件升级',
|
||||||
|
update_heading: '固件升级',
|
||||||
|
update_instruction: '请选择要上传的固件文件:',
|
||||||
|
update_upload: '上传文件',
|
||||||
|
|
||||||
|
common_port: '端口 ',
|
||||||
|
common_pkts: ' 个包',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var rtlLang = (function() {
|
||||||
|
var saved = localStorage.getItem('rtl_lang');
|
||||||
|
if (saved && LANG[saved]) return saved;
|
||||||
|
var browser = (navigator.language || navigator.userLanguage || 'en').substring(0, 2);
|
||||||
|
return LANG[browser] ? browser : 'en';
|
||||||
|
})();
|
||||||
|
|
||||||
|
function t(key) {
|
||||||
|
return LANG[rtlLang][key] || LANG['en'][key] || key;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLang(lang) {
|
||||||
|
if (LANG[lang]) {
|
||||||
|
localStorage.setItem('rtl_lang', lang);
|
||||||
|
rtlLang = lang;
|
||||||
|
document.querySelectorAll('[data-i18n]').forEach(function(el) {
|
||||||
|
applyTranslation(el);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyTranslation(el) {
|
||||||
|
var key = el.getAttribute('data-i18n');
|
||||||
|
if (!key) return;
|
||||||
|
if (el.tagName === 'INPUT' && (el.type === 'submit' || el.type === 'button')) {
|
||||||
|
el.value = t(key);
|
||||||
|
} else if (el.tagName === 'OPTION') {
|
||||||
|
el.textContent = t(key);
|
||||||
|
} else if (el.tagName === 'TITLE') {
|
||||||
|
el.textContent = t(key);
|
||||||
|
} else {
|
||||||
|
el.innerHTML = t(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
document.querySelectorAll('[data-i18n]').forEach(function(el) {
|
||||||
|
applyTranslation(el);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
<script src="/main_info.js"></script>
|
<script src="/main_info.js"></script>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<script>
|
<script>
|
||||||
window.addEventListener("load", function() {
|
window.addEventListener("load", function() {
|
||||||
update( () => {
|
update( () => {
|
||||||
@@ -10,17 +11,17 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>FreeSwitchOS Main Page</title>
|
<title data-i18n="index_title">FreeSwitchOS Main Page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
<h1>Switch Configuration</h1>
|
<h1 data-i18n="index_heading">Switch Configuration</h1>
|
||||||
<table id="infoTable">
|
<table id="infoTable">
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2">Settings</th>
|
<th colspan="2" data-i18n="index_settings">Settings</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tbody>
|
<tbody>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -1,16 +1,27 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>FreeSwitchOS L2 Configuration</title>
|
<title data-i18n="l2_title">FreeSwitchOS L2 Configuration</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
<h1>L2 Configuration</h1>
|
<h1 data-i18n="l2_heading">L2 Configuration</h1>
|
||||||
|
<p><span data-i18n="l2_shown">Shown:</span> <span id="l2count">-</span></p>
|
||||||
<table id="l2table">
|
<table id="l2table">
|
||||||
<tr> <th>Port</th> <th>MAC</th> <th>VLAN</th> <th>Type</th> <th>Remove Entry</th></tr>
|
<tr>
|
||||||
|
<th><span class="l2sort" onclick="l2SortBy('port')"><span data-i18n="l2_col_port">Port</span><span id="l2a_port" class="l2arrow"></span></span><br>
|
||||||
|
<input id="l2f_port" class="l2filter" oninput="l2FilterChanged()" size="5"></th>
|
||||||
|
<th><span class="l2sort" onclick="l2SortBy('mac')">MAC<span id="l2a_mac" class="l2arrow"></span></span><br>
|
||||||
|
<input id="l2f_mac" class="l2filter" oninput="l2FilterChanged()" size="14"></th>
|
||||||
|
<th><span class="l2sort" onclick="l2SortBy('vlan')">VLAN<span id="l2a_vlan" class="l2arrow"></span></span><br>
|
||||||
|
<input id="l2f_vlan" class="l2filter" oninput="l2FilterChanged()" size="5"></th>
|
||||||
|
<th><span class="l2sort" onclick="l2SortBy('type')"><span data-i18n="l2_col_type">Type</span><span id="l2a_type" class="l2arrow"></span></span><br>
|
||||||
|
<input id="l2f_type" class="l2filter" oninput="l2FilterChanged()" size="8"></th>
|
||||||
|
<th data-i18n="l2_col_remove">Remove Entry</th></tr>
|
||||||
<script src="/l2.js"></script>
|
<script src="/l2.js"></script>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
var l2GetInterval;
|
|
||||||
var l2Entries = [];
|
|
||||||
var l2CurrentEntry = 0;
|
|
||||||
|
|
||||||
function fillStats() {
|
function fillStats() {
|
||||||
var tbl = document.getElementById('statstable');
|
var tbl = document.getElementById('statstable');
|
||||||
if (!numPorts)
|
if (!numPorts)
|
||||||
@@ -9,22 +5,22 @@ function fillStats() {
|
|||||||
if (tbl.rows.length > 1) {
|
if (tbl.rows.length > 1) {
|
||||||
for (let i = 0; i < numPorts; i++) {
|
for (let i = 0; i < numPorts; i++) {
|
||||||
console.log("Table Update row: " + i + " state " + pState[i] + " is " + linkS[pState[i] +1]);
|
console.log("Table Update row: " + i + " state " + pState[i] + " is " + linkS[pState[i] +1]);
|
||||||
tbl.rows[i+1].cells[1].innerHTML = `${linkS[pState[i]+1]}`;
|
tbl.rows[i+1].cells[1].innerHTML = linkText(pState[i]+1);
|
||||||
tbl.rows[i+1].cells[2].innerHTML = `${txG[i]} pkts`;
|
tbl.rows[i+1].cells[2].innerHTML = `${txG[i]}` + t('common_pkts');
|
||||||
tbl.rows[i+1].cells[3].innerHTML = `${txB[i]} pkts`;
|
tbl.rows[i+1].cells[3].innerHTML = `${txB[i]}` + t('common_pkts');
|
||||||
tbl.rows[i+1].cells[4].innerHTML = `${rxG[i]} pkts`;
|
tbl.rows[i+1].cells[4].innerHTML = `${rxG[i]}` + t('common_pkts');
|
||||||
tbl.rows[i+1].cells[5].innerHTML = `${rxB[i]} pkts`;
|
tbl.rows[i+1].cells[5].innerHTML = `${rxB[i]}` + t('common_pkts');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < numPorts; i++) {
|
for (let i = 0; i < numPorts; i++) {
|
||||||
console.log("Table row: " + i);
|
console.log("Table row: " + i);
|
||||||
const tr = tbl.insertRow();
|
const tr = tbl.insertRow();
|
||||||
let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i+1}`));
|
let td = tr.insertCell(); td.appendChild(document.createTextNode(t('common_port') + (i+1)));
|
||||||
td = tr.insertCell(); td.appendChild(document.createTextNode(`${linkS[pState[i]+1]}`));
|
td = tr.insertCell(); td.appendChild(document.createTextNode(linkText(pState[i]+1)));
|
||||||
td = tr.insertCell(); td.appendChild(document.createTextNode(`${txG[i]} pkts`));
|
td = tr.insertCell(); td.appendChild(document.createTextNode(`${txG[i]}` + t('common_pkts')));
|
||||||
td = tr.insertCell();td.appendChild(document.createTextNode(`${txB[i]} pkts`));
|
td = tr.insertCell();td.appendChild(document.createTextNode(`${txB[i]}` + t('common_pkts')));
|
||||||
td = tr.insertCell();td.appendChild(document.createTextNode(`${rxG[i]} pkts`));
|
td = tr.insertCell();td.appendChild(document.createTextNode(`${rxG[i]}` + t('common_pkts')));
|
||||||
td = tr.insertCell();td.appendChild(document.createTextNode(`${rxB[i]} pkts`));
|
td = tr.insertCell();td.appendChild(document.createTextNode(`${rxB[i]}` + t('common_pkts')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +60,51 @@ function delL2(idx) {
|
|||||||
xhttp.timeout = 1500; xhttp.send();
|
xhttp.timeout = 1500; xhttp.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var l2All = [];
|
||||||
|
const l2Cols = ['port', 'mac', 'vlan', 'type'];
|
||||||
|
var l2SortCol = 'port';
|
||||||
|
var l2SortDir = 1;
|
||||||
|
|
||||||
|
function l2Key(e, col) {
|
||||||
|
if (col === 'port') return e.port === 'CPU' ? Number.MAX_SAFE_INTEGER : Number(e.port);
|
||||||
|
if (col === 'vlan') return Number(e.vlan);
|
||||||
|
return String(e[col]).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function l2SortBy(col) {
|
||||||
|
l2SortDir = (col === l2SortCol) ? -l2SortDir : 1;
|
||||||
|
l2SortCol = col;
|
||||||
|
renderL2();
|
||||||
|
}
|
||||||
|
|
||||||
|
function l2FilterChanged() { renderL2(); }
|
||||||
|
|
||||||
|
function renderL2() {
|
||||||
|
var tbl = document.getElementById('l2table');
|
||||||
|
if (!tbl) return;
|
||||||
|
var f = {};
|
||||||
|
l2Cols.forEach(function(c) {
|
||||||
|
var el = document.getElementById('l2f_' + c);
|
||||||
|
f[c] = el ? el.value.trim().toLowerCase() : '';
|
||||||
|
});
|
||||||
|
var rows = l2All.filter(function(e) {
|
||||||
|
return l2Cols.every(function(c) {
|
||||||
|
return !f[c] || String(e[c]).toLowerCase().indexOf(f[c]) !== -1;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
rows.sort(function(a, b) {
|
||||||
|
var x = l2Key(a, l2SortCol), y = l2Key(b, l2SortCol);
|
||||||
|
return (x < y ? -1 : x > y ? 1 : 0) * l2SortDir;
|
||||||
|
});
|
||||||
|
l2Cols.forEach(function(c) {
|
||||||
|
var a = document.getElementById('l2a_' + c);
|
||||||
|
if (a) a.textContent = (c === l2SortCol) ? (l2SortDir > 0 ? ' \u25b2' : ' \u25bc') : ' \u21c5';
|
||||||
|
});
|
||||||
|
paintL2(tbl, rows);
|
||||||
|
var cnt = document.getElementById('l2count');
|
||||||
|
if (cnt) cnt.textContent = rows.length + ' / ' + l2All.length;
|
||||||
|
}
|
||||||
|
|
||||||
function fillL2(s)
|
function fillL2(s)
|
||||||
{
|
{
|
||||||
var tbl = document.getElementById('l2table');
|
var tbl = document.getElementById('l2table');
|
||||||
@@ -71,7 +112,12 @@ function fillL2(s)
|
|||||||
return;
|
return;
|
||||||
s.sort(l2CMP);
|
s.sort(l2CMP);
|
||||||
s = uniq(s);
|
s = uniq(s);
|
||||||
var s = s.map(function(e) { e.port = e.port != 9 ? e.port : "CPU"; return e; });
|
l2All = s;
|
||||||
|
renderL2();
|
||||||
|
}
|
||||||
|
|
||||||
|
function paintL2(tbl, s)
|
||||||
|
{
|
||||||
console.log("L2: ", JSON.stringify(s));
|
console.log("L2: ", JSON.stringify(s));
|
||||||
for (let i = 0; i < s.length; i++) {
|
for (let i = 0; i < s.length; i++) {
|
||||||
var e = s[i];
|
var e = s[i];
|
||||||
@@ -80,64 +126,36 @@ function fillL2(s)
|
|||||||
tbl.rows[i+1].cells[0].innerHTML = `${e.port}`;
|
tbl.rows[i+1].cells[0].innerHTML = `${e.port}`;
|
||||||
tbl.rows[i+1].cells[1].innerHTML = `${e.mac}`;
|
tbl.rows[i+1].cells[1].innerHTML = `${e.mac}`;
|
||||||
tbl.rows[i+1].cells[2].innerHTML = `${e.vlan}`;
|
tbl.rows[i+1].cells[2].innerHTML = `${e.vlan}`;
|
||||||
tbl.rows[i+1].cells[4].innerHTML = '<button type="button" onclick="delL2(' + e.idx + ');">Delete</button>';
|
tbl.rows[i+1].cells[3].innerHTML = `${e.type}`;
|
||||||
|
tbl.rows[i+1].cells[4].innerHTML = '<button type="button" onclick="delL2(' + e.idx + ');">' + t('l2_delete') + '</button>';
|
||||||
} else {
|
} else {
|
||||||
const tr = tbl.insertRow();
|
const tr = tbl.insertRow();
|
||||||
let td = tr.insertCell(); td.innerHTML = `${e.port}`;
|
let td = tr.insertCell(); td.innerHTML = `${e.port}`;
|
||||||
td = tr.insertCell(); td.innerHTML = `${e.mac}`;
|
td = tr.insertCell(); td.innerHTML = `${e.mac}`;
|
||||||
td = tr.insertCell(); td.innerHTML = `${e.vlan}`;
|
td = tr.insertCell(); td.innerHTML = `${e.vlan}`;
|
||||||
td = tr.insertCell(); td.innerHTML = `${e.type}`;
|
td = tr.insertCell(); td.innerHTML = `${e.type}`;
|
||||||
td = tr.insertCell(); td.innerHTML = '<button type="button" onclick="delL2(' + e.idx + ');">Delete</button>';
|
td = tr.insertCell(); td.innerHTML = '<button type="button" onclick="delL2(' + e.idx + ');">' + t('l2_delete') + '</button>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let i = tbl.rows.length - 1; i > s.length; i--)
|
for (let i = tbl.rows.length - 1; i > s.length; i--)
|
||||||
tbl.deleteRow(i);
|
tbl.deleteRow(i);
|
||||||
l2Entries = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getL2() {
|
function getL2() {
|
||||||
var xhttp = new XMLHttpRequest();
|
walkL2(function(entries, ok) {
|
||||||
xhttp.onreadystatechange = function() {
|
if (ok) {
|
||||||
if (this.readyState == 4 && this.status == 200) {
|
for (var i = 0; i < entries.length; i++)
|
||||||
var s = JSON.parse(xhttp.responseText);
|
entries[i].type = entries[i].type == "s" ? t('l2_static') : t('l2_learned');
|
||||||
var s = s.map(function(e) {
|
fillL2(entries);
|
||||||
e.vlan = parseInt(e.vlan, 16);
|
|
||||||
e.idx = parseInt(e.idx, 16);
|
|
||||||
e.type = e.type == "s" ? "static" : "learned";
|
|
||||||
e.port = e.port == 9 ? 9 : logToPhysPort[e.port];
|
|
||||||
return e;
|
|
||||||
});
|
|
||||||
l2Entries.push(...s);
|
|
||||||
if (l2Entries >= 4096) {
|
|
||||||
l2Entries = [];
|
|
||||||
l2CurrentEntry = 0;
|
|
||||||
clearInterval(l2GetInterval);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var w = 0;
|
|
||||||
for (var i = l2Entries.length-1; i > 0; i--) {
|
|
||||||
if (l2Entries[0].idx == l2Entries[i].idx) {
|
|
||||||
w = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (w) {
|
|
||||||
l2CurrentEntry = 0;
|
|
||||||
fillL2(l2Entries);
|
|
||||||
} else {
|
|
||||||
l2CurrentEntry = s[s.length-1].idx + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
setTimeout(getL2, 1000);
|
||||||
xhttp.open("GET", "/l2.json?idx=" + l2CurrentEntry, true);
|
});
|
||||||
xhttp.timeout = 1500; sendXHTTP(xhttp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
window.addEventListener("load", function() {
|
||||||
update( () => {
|
update( () => {
|
||||||
getL2();
|
getL2();
|
||||||
const interval = setInterval(update, 2000);
|
const interval = setInterval(update, 2000);
|
||||||
l2GetInterval = setInterval(getL2, 1000);
|
|
||||||
});;
|
});;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>Link Aggregation Configuration</title>
|
<title data-i18n="lag_title">Link Aggregation Configuration</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
<h1>Link Aggregation Groups Configuration</h1>
|
<h1 data-i18n="lag_heading">Link Aggregation Groups Configuration</h1>
|
||||||
<h2>LAG 1 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub0" onclick="lagSub(0);" type="button" value="Update / Create"></h2>
|
<h2>LAG 1 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub0" onclick="lagSub(0);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
||||||
<div id="mLAG0"></div>
|
<div id="mLAG0"></div>
|
||||||
<br />
|
<br />
|
||||||
<h2>LAG 2 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub1" onclick="lagSub(1);" type="button" value="Update / Create"></h2>
|
<h2>LAG 2 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub1" onclick="lagSub(1);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
||||||
<div id="mLAG1"></div>
|
<div id="mLAG1"></div>
|
||||||
<br />
|
<br />
|
||||||
<h2>LAG 3 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub2" onclick="lagSub(2);" type="button" value="Update / Create"></h2>
|
<h2>LAG 3 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub2" onclick="lagSub(2);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
||||||
<div id="mLAG2"></div>
|
<div id="mLAG2"></div>
|
||||||
<br />
|
<br />
|
||||||
<h2>LAG 4 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub3" onclick="lagSub(3);" type="button" value="Update / Create"></h2>
|
<h2>LAG 4 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub3" onclick="lagSub(3);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
||||||
<div id="mLAG3"></div>
|
<div id="mLAG3"></div>
|
||||||
<script src="/lag.js"></script>
|
<script src="/lag.js"></script>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<title>RTL Switch Login</title>
|
<title data-i18n="login_title">RTL Switch Login</title>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function removeNote() {
|
function removeNote() {
|
||||||
document.getElementById("incorrect").innerHTML = "";
|
document.getElementById("incorrect").innerHTML = "";
|
||||||
}
|
}
|
||||||
window.addEventListener("load", function() {
|
window.addEventListener("load", function() {
|
||||||
if (document.referrer.endsWith("login.html"))
|
if (document.referrer.endsWith("login.html"))
|
||||||
document.getElementById("incorrect").innerHTML = "Wrong password!";
|
document.getElementById("incorrect").innerHTML = t('login_wrong');
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="login_page">
|
<body class="login_page">
|
||||||
<div class = "center">
|
<div class = "center">
|
||||||
<h1> RTL Switch Login</h1>
|
<h1 data-i18n="login_heading"> RTL Switch Login</h1>
|
||||||
<form method="post" action="login">
|
<form method="post" action="login">
|
||||||
<div class="txt_field">
|
<div class="txt_field">
|
||||||
<input name="pwd" type="password" onclick="removeNote()" required />
|
<input name="pwd" type="password" autocomplete="current-password" onclick="removeNote()" required />
|
||||||
<span></span>
|
<span></span>
|
||||||
<label>Password</label>
|
<label data-i18n="login_password">Password</label>
|
||||||
</div>
|
</div>
|
||||||
<input type="submit" value="Login"/>
|
<input type="submit" data-i18n="login_login" value="Login"/>
|
||||||
<h3 id="incorrect" style="margin-top: 5em;"></h3>
|
<h3 id="incorrect" style="margin-top: 5em;"></h3>
|
||||||
</form>
|
</form>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ var txG = new BigInt64Array(10);
|
|||||||
var txB = new BigInt64Array(10);
|
var txB = new BigInt64Array(10);
|
||||||
var rxG = new BigInt64Array(10);
|
var rxG = new BigInt64Array(10);
|
||||||
var rxB = new BigInt64Array(10);
|
var rxB = new BigInt64Array(10);
|
||||||
const linkS = ["Disabled", "Down", "10M", "100M", "1000M", "500M", "10G", "2.5G", "5G"];
|
const linkS = [function(){return t('speed_disabled')}, function(){return t('speed_down')}, "10M", "100M", "1000M", "500M", "10G", "2.5G", "5G"];
|
||||||
var pState = new Int8Array(10);
|
var pState = new Int8Array(10);
|
||||||
var pIsSFP = new Int8Array(10);
|
var pIsSFP = new Int8Array(10);
|
||||||
var pAdvertised = new Int8Array(10);
|
var pAdvertised = new Int8Array(10);
|
||||||
var numPorts = 0;
|
var numPorts = 0;
|
||||||
|
function linkText(idx) { var v = linkS[idx]; return typeof v === 'function' ? v() : v; }
|
||||||
var logToPhysPort = new Int8Array(10);
|
var logToPhysPort = new Int8Array(10);
|
||||||
var physToLogPort = new Int8Array(10);
|
var physToLogPort = new Int8Array(10);
|
||||||
var portNames = new Array(10);
|
var portNames = new Array(10);
|
||||||
@@ -21,7 +22,7 @@ function drawPorts() {
|
|||||||
d.classList.add('tooltip');
|
d.classList.add('tooltip');
|
||||||
const s = document.createElement("span");
|
const s = document.createElement("span");
|
||||||
s.classList.add("tooltiptext");
|
s.classList.add("tooltiptext");
|
||||||
s.innerHTML = "Tooltip text";
|
s.innerHTML = t('common_port');
|
||||||
s.id="tt_" + (i+1);
|
s.id="tt_" + (i+1);
|
||||||
const l = document.createElement("object");
|
const l = document.createElement("object");
|
||||||
d.appendChild(l);
|
d.appendChild(l);
|
||||||
@@ -152,13 +153,13 @@ function update(callback) {
|
|||||||
continue;
|
continue;
|
||||||
const portName = p.name || portNames[p.logPort] || '';
|
const portName = p.name || portNames[p.logPort] || '';
|
||||||
var iHTML = "<table border=\"0\" class=\"tt_table\">";
|
var iHTML = "<table border=\"0\" class=\"tt_table\">";
|
||||||
if (portName) iHTML += "<tr><td align=\"left\">Name</td><td>:</td><td>" + portName + "</td></tr>";
|
if (portName) iHTML += "<tr><td align=\"left\">" + t('port_name') + "</td><td>:</td><td>" + portName + "</td></tr>";
|
||||||
if (p.enabled == 0) {
|
if (p.enabled == 0) {
|
||||||
pState[n] = -1;
|
pState[n] = -1;
|
||||||
bgs[0].style.fill = "red";
|
bgs[0].style.fill = "red";
|
||||||
leds[0].style.fill = "black"; leds[1].style.fill = "black";
|
leds[0].style.fill = "black"; leds[1].style.fill = "black";
|
||||||
psvg.style.opacity = 0.4;
|
psvg.style.opacity = 0.4;
|
||||||
iHTML += "<tr><td align=\"left\">Status</td><td>:</td><td>Not enabled.</td></tr>";
|
iHTML += "<tr><td align=\"left\">" + t('port_status') + "</td><td>:</td><td>" + t('port_not_enabled') + "</td></tr>";
|
||||||
iHTML += "</table>";
|
iHTML += "</table>";
|
||||||
tt.innerHTML = iHTML;
|
tt.innerHTML = iHTML;
|
||||||
} else {
|
} else {
|
||||||
@@ -174,31 +175,31 @@ function update(callback) {
|
|||||||
leds[0].style.fill = "black"; leds[1].style.fill = "black";
|
leds[0].style.fill = "black"; leds[1].style.fill = "black";
|
||||||
psvg.style.opacity = 0.4
|
psvg.style.opacity = 0.4
|
||||||
}
|
}
|
||||||
iHTML += "<tr><td align=\"left\">Link speed</td><td>:</td><td>" + linkS[p.link + 1] + "</td></tr>";
|
iHTML += "<tr><td align=\"left\">" + t('port_link_speed') + "</td><td>:</td><td>" + linkText(p.link + 1) + "</td></tr>";
|
||||||
if (p.isSFP) {
|
if (p.isSFP) {
|
||||||
pAdvertised[n] = 0;
|
pAdvertised[n] = 0;
|
||||||
const hasExtendedStatus = p.sfp_options & 0x40;
|
const hasExtendedStatus = p.sfp_options & 0x40;
|
||||||
iHTML += "<tr><td>Vendor</td><td>:</td><td>" + p.sfp_vendor + "</td></tr>";
|
iHTML += "<tr><td>" + t('port_vendor') + "</td><td>:</td><td>" + p.sfp_vendor + "</td></tr>";
|
||||||
iHTML += "<tr><td>Model</td><td>:</td><td>" + p.sfp_model + "</td></tr>";
|
iHTML += "<tr><td>" + t('port_model') + "</td><td>:</td><td>" + p.sfp_model + "</td></tr>";
|
||||||
iHTML += "<tr><td>Serial</td><td>:</td><td>" + p.sfp_serial + "</td></tr>";
|
iHTML += "<tr><td>" + t('port_serial') + "</td><td>:</td><td>" + p.sfp_serial + "</td></tr>";
|
||||||
if (hasExtendedStatus) {
|
if (hasExtendedStatus) {
|
||||||
let txPower = decodeSfpTxPower(p.sfp_txpower, p.sfp_txpower_cal);
|
let txPower = decodeSfpTxPower(p.sfp_txpower, p.sfp_txpower_cal);
|
||||||
let txPowerdBm = convertPowerTodBm(txPower);
|
let txPowerdBm = convertPowerTodBm(txPower);
|
||||||
let rxPower = decodeSfpRxPower(p.sfp_rxpower, p.sfp_rxpower_cal);
|
let rxPower = decodeSfpRxPower(p.sfp_rxpower, p.sfp_rxpower_cal);
|
||||||
let rxPowerdBm = convertPowerTodBm(rxPower);
|
let rxPowerdBm = convertPowerTodBm(rxPower);
|
||||||
iHTML += "<tr><td>Temp</td><td>:</td><td>" + decodeSfpTemp(p.sfp_temp, p.sfp_temp_cal).toFixed(2) + " ℃</td></tr>";
|
iHTML += "<tr><td>" + t('port_temp') + "</td><td>:</td><td>" + decodeSfpTemp(p.sfp_temp, p.sfp_temp_cal).toFixed(2) + " ℃</td></tr>";
|
||||||
iHTML += "<tr><td>Vcc</td><td>:</td><td>" + decodeSfpVcc(p.sfp_vcc, p.sfp_vcc_cal).toFixed(2) + " V</td></tr>";
|
iHTML += "<tr><td>" + t('port_vcc') + "</td><td>:</td><td>" + decodeSfpVcc(p.sfp_vcc, p.sfp_vcc_cal).toFixed(2) + " V</td></tr>";
|
||||||
iHTML += "<tr><td>TX-Fault</td><td>:</td><td>" + (Boolean(Number(p.sfp_state) & 0x4)) + "</td></tr>";
|
iHTML += "<tr><td>" + t('port_tx_fault') + "</td><td>:</td><td>" + (Boolean(Number(p.sfp_state) & 0x4)) + "</td></tr>";
|
||||||
iHTML += "<tr><td>TX-Disabled</td><td>:</td><td>" + (Boolean(Number(p.sfp_state) & 0x80)) + "</td></tr>";
|
iHTML += "<tr><td>" + t('port_tx_disabled') + "</td><td>:</td><td>" + (Boolean(Number(p.sfp_state) & 0x80)) + "</td></tr>";
|
||||||
iHTML += "<tr><td>TX-Bias</td><td>:</td><td>" + decodeSfpTxBias(p.sfp_txbias, p.sfp_txbias_cal).toFixed(1) + " mA</td></tr>";
|
iHTML += "<tr><td>" + t('port_tx_bias') + "</td><td>:</td><td>" + decodeSfpTxBias(p.sfp_txbias, p.sfp_txbias_cal).toFixed(1) + " mA</td></tr>";
|
||||||
iHTML += "<tr><td>TX-Power</td><td>:</td><td>" + txPower.toFixed(3) + " mW / " + txPowerdBm.toFixed(2) + " dBm</td></tr>";
|
iHTML += "<tr><td>" + t('port_tx_power') + "</td><td>:</td><td>" + txPower.toFixed(3) + " mW / " + txPowerdBm.toFixed(2) + " dBm</td></tr>";
|
||||||
iHTML += "<tr><td>RX-Power</td><td>:</td><td>" + rxPower.toFixed(3) + " mW / " + rxPowerdBm.toFixed(2) + " dBm</td></tr>";
|
iHTML += "<tr><td>" + t('port_rx_power') + "</td><td>:</td><td>" + rxPower.toFixed(3) + " mW / " + rxPowerdBm.toFixed(2) + " dBm</td></tr>";
|
||||||
}
|
}
|
||||||
// Not all devices & modules have LOS pin...
|
// Not all devices & modules have LOS pin...
|
||||||
const rx_los_pin = p.sfp_los !== null ? Boolean(Number(p.sfp_los)) : null;
|
const rx_los_pin = p.sfp_los !== null ? Boolean(Number(p.sfp_los)) : null;
|
||||||
const rx_los_module = hasExtendedStatus ? Boolean(Number(p.sfp_state) & 0x2) : null;
|
const rx_los_module = hasExtendedStatus ? Boolean(Number(p.sfp_state) & 0x2) : null;
|
||||||
if (rx_los_module !== null || rx_los_pin !== null) {
|
if (rx_los_module !== null || rx_los_pin !== null) {
|
||||||
iHTML += `<tr><td>RX-LOS</td><td>:</td><td>${rxLosHTML(rx_los_pin, rx_los_module)}</td></tr>`;
|
iHTML += `<tr><td>` + t('port_rx_los') + `</td><td>:</td><td>${rxLosHTML(rx_los_pin, rx_los_module)}</td></tr>`;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pAdvertised[n] = parseInt(p.adv, 2);
|
pAdvertised[n] = parseInt(p.adv, 2);
|
||||||
@@ -284,3 +285,66 @@ function sendXHTTP(x)
|
|||||||
currentRequests.push(x);
|
currentRequests.push(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function walkL2(onDone)
|
||||||
|
{
|
||||||
|
var entries = [];
|
||||||
|
var idx = 0;
|
||||||
|
var tries = 0;
|
||||||
|
|
||||||
|
function retry() {
|
||||||
|
if (++tries < 3) {
|
||||||
|
setTimeout(page, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onDone(entries, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function page() {
|
||||||
|
var xhttp = new XMLHttpRequest();
|
||||||
|
xhttp.onreadystatechange = function() {
|
||||||
|
if (this.readyState != 4)
|
||||||
|
return;
|
||||||
|
if (this.status != 200) {
|
||||||
|
retry();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var s;
|
||||||
|
try {
|
||||||
|
s = JSON.parse(xhttp.responseText);
|
||||||
|
} catch (err) {
|
||||||
|
retry();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tries = 0;
|
||||||
|
s = s.map(function(e) {
|
||||||
|
e.vlan = parseInt(e.vlan, 16);
|
||||||
|
e.idx = parseInt(e.idx, 16);
|
||||||
|
e.port = e.port == 9 ? 'CPU' : logToPhysPort[e.port];
|
||||||
|
return e;
|
||||||
|
});
|
||||||
|
if (!s.length) {
|
||||||
|
onDone(entries, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entries.push(...s);
|
||||||
|
for (var i = entries.length - 1; i > 0; i--) {
|
||||||
|
if (entries[0].idx == entries[i].idx) {
|
||||||
|
onDone(entries, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (entries.length >= 4096) {
|
||||||
|
onDone(entries, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
idx = s[s.length - 1].idx + 1;
|
||||||
|
setTimeout(page, 1000);
|
||||||
|
};
|
||||||
|
xhttp.open("GET", "/l2.json?idx=" + idx, true);
|
||||||
|
xhttp.timeout = 1500;
|
||||||
|
sendXHTTP(xhttp);
|
||||||
|
}
|
||||||
|
|
||||||
|
page();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,23 +1,24 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>Mirror Configuration</title>
|
<title data-i18n="mirror_title">Mirror Configuration</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
<h1>Mirror Configuration</h1>
|
<h1 data-i18n="mirror_heading">Mirror Configuration</h1>
|
||||||
<label class="tswitch">Enabled: <input id="me" type="checkbox"></label><br/>
|
<label class="tswitch"><span data-i18n="mirror_enabled">Enabled:</span> <input id="me" type="checkbox"></label><br/>
|
||||||
<label for="mp">Mirroring Port:</label> <input type="number" id="mp" name="mp" min="1" max="9"/>
|
<label for="mp"><span data-i18n="mirror_port">Mirroring Port:</span></label> <input type="number" id="mp" name="mp" min="1" max="9"/>
|
||||||
<h2>Mirrored Ports (TX)</h2>
|
<h2 data-i18n="mirror_tx">Mirrored Ports (TX)</h2>
|
||||||
<div id="mPortsTX"></div>
|
<div id="mPortsTX"></div>
|
||||||
<br />
|
<br />
|
||||||
<h2>Mirrored Ports (RX)</h2>
|
<h2 data-i18n="mirror_rx">Mirrored Ports (RX)</h2>
|
||||||
<div id="mPortsRX"></div>
|
<div id="mPortsRX"></div>
|
||||||
<br/> <input style="width:15%;" class="action" id="mirror_sub" onclick="mirrorSub();" type="button" value="Update / Create">
|
<br/> <input style="width:15%;" class="action" id="mirror_sub" onclick="mirrorSub();" type="button" data-i18n="mirror_update" value="Update / Create">
|
||||||
<input style="width:15%;" class="action" id="mirror_del" onclick="mirrorDel();" type="button" value="Disable Mirroring">
|
<input style="width:15%;" class="action" id="mirror_del" onclick="mirrorDel();" type="button" data-i18n="mirror_disable" value="Disable Mirroring">
|
||||||
<script src="/mirror.js"></script>
|
<script src="/mirror.js"></script>
|
||||||
<script src="/mirror_sub.js"></script>
|
<script src="/mirror_sub.js"></script>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ async function mirrorSub() {
|
|||||||
var cmd = "mirror ";
|
var cmd = "mirror ";
|
||||||
var mp=document.getElementById('mp').value
|
var mp=document.getElementById('mp').value
|
||||||
if (!mp) {
|
if (!mp) {
|
||||||
alert("Set Mirroring Port first");
|
alert(t('mirror_set_port_first'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
document.getElementById(mirrors[0]+mp).checked=false;document.getElementById(mirrors[1]+mp).checked=false;
|
document.getElementById(mirrors[0]+mp).checked=false;document.getElementById(mirrors[1]+mp).checked=false;
|
||||||
@@ -16,7 +16,7 @@ async function mirrorSub() {
|
|||||||
cmd = cmd + ` ${i}r`;
|
cmd = cmd + ` ${i}r`;
|
||||||
}
|
}
|
||||||
if (cmd.length < 10) {
|
if (cmd.length < 10) {
|
||||||
alert("Select Mirrored Ports");
|
alert(t('mirror_select_ports'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
document.getElementById('sidebar').innerHTML =
|
document.getElementById('sidebar').innerHTML =
|
||||||
"<ul><li><a href='index.html'>Overview</a></li>"
|
"<ul><li><a href='index.html' data-i18n='nav_overview'>Overview</a></li>"
|
||||||
+ "<li><a href='ports.html'>Port Configuration</a></li>"
|
+ "<li><a href='ports.html' data-i18n='nav_port_config'>Port Configuration</a></li>"
|
||||||
+ "<li><a href='stat.html'>Port Statistics</a></li>"
|
+ "<li><a href='stat.html' data-i18n='nav_port_stat'>Port Statistics</a></li>"
|
||||||
+ "<li><a href='vlan.html'>VLAN</a></li>"
|
+ "<li><a href='vlan.html' >VLAN</a></li>"
|
||||||
+ "<li><a href='l2.html'>L2 Configuration</a></li>"
|
+ "<li><a href='l2.html' data-i18n='nav_l2'>L2 Configuration</a></li>"
|
||||||
+ "<li><a href='mirror.html'>Mirroring</a></li>"
|
+ "<li><a href='mirror.html' data-i18n='nav_mirror'>Mirroring</a></li>"
|
||||||
+ "<li><a href='lag.html'>Link Aggregation</a></li>"
|
+ "<li><a href='lag.html' data-i18n='nav_lag'>Link Aggregation</a></li>"
|
||||||
+ "<li><a href='eee.html'>EEE</a></li>"
|
+ "<li><a href='eee.html' data-i18n='nav_eee'>EEE</a></li>"
|
||||||
+ "<li><a href='bandwidth.html'>Bandwidth Limits</a></li>"
|
+ "<li><a href='bandwidth.html' data-i18n='nav_bandwidth'>Bandwidth Limits</a></li>"
|
||||||
+ "<li><a href='system.html'>System Settings</a></li>"
|
+ "<li><a href='system.html' data-i18n='nav_system'>System Settings</a></li>"
|
||||||
+ "<li><a href='update.html'>Firmware Update</a></li></ul>";
|
+ "<li><a href='update.html' data-i18n='nav_fw_update'>Firmware Update</a></li></ul>";
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var links = document.querySelectorAll('#sidebar a[data-i18n]');
|
||||||
|
links.forEach(function(el) {
|
||||||
|
var key = el.getAttribute('data-i18n');
|
||||||
|
if (key) el.textContent = t(key);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>FreeSwitchOS Port Configuration</title>
|
<title data-i18n="port_title">FreeSwitchOS Port Configuration</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
<h1>Port Configuration</h1>
|
<h1 data-i18n="port_heading">Port Configuration</h1>
|
||||||
<form id="vform" action="/vlan.html">
|
<form id="vform" action="/vlan.html">
|
||||||
<table id="speedtable">
|
<table id="speedtable">
|
||||||
<tr> <th>Port</th> <th>Name</th> <th>Current Link Speed</th><th>Set Speed</th><th>Disabled</th><th>Apply</th></tr>
|
<tr> <th data-i18n="port_col_port">Port</th> <th data-i18n="port_col_name">Name</th> <th data-i18n="port_col_speed">Current Link Speed</th><th data-i18n="port_col_set_speed">Set Speed</th><th data-i18n="port_col_disabled">Disabled</th><th data-i18n="port_col_apply">Apply</th></tr>
|
||||||
</table>
|
</table>
|
||||||
<h2 style="margin-top:3em">Configure Maximum Frame Size (MTU) forwarded at Port</h2>
|
<h2 style="margin-top:3em" data-i18n="port_mtu_heading">Configure Maximum Frame Size (MTU) forwarded at Port</h2>
|
||||||
<table id="mtutable" style="margin-top:1em">
|
<table id="mtutable" style="margin-top:1em">
|
||||||
</table>
|
</table>
|
||||||
<script src="/ports.js"></script>
|
<script src="/ports.js"></script>
|
||||||
|
|||||||
@@ -3,29 +3,29 @@ var clicked = new Int8Array(10);
|
|||||||
function createPortTable() {
|
function createPortTable() {
|
||||||
var tbl = document.getElementById('speedtable');
|
var tbl = document.getElementById('speedtable');
|
||||||
if (tbl.rows.length <= 2 && numPorts) {
|
if (tbl.rows.length <= 2 && numPorts) {
|
||||||
const sSelect = '<select name="speed_sel" id="speed_sel">'
|
const sSelect = '<select name="speed_sel" id="speed_sel">'
|
||||||
+ '<option value="auto">Auto</option>'
|
+ '<option value="auto">' + t('port_auto') + '</option>'
|
||||||
+ '<option value="2g5">2500MBit/Full</option>'
|
+ '<option value="2g5">' + t('port_2500m') + '</option>'
|
||||||
+ '<option value="1g">1000MBit/Full</option>'
|
+ '<option value="1g">' + t('port_1000m') + '</option>'
|
||||||
+ '<option value="100m full">100MBit/Full</option>'
|
+ '<option value="100m full">' + t('port_100m_f') + '</option>'
|
||||||
+ '<option value="100m half">100MBit/Half</option>'
|
+ '<option value="100m half">' + t('port_100m_h') + '</option>'
|
||||||
+ '<option value="10m full">10MBit/Full</option>'
|
+ '<option value="10m full">' + t('port_10m_f') + '</option>'
|
||||||
+ '<option value="10m half">10MBit/Half</option>'
|
+ '<option value="10m half">' + t('port_10m_h') + '</option>'
|
||||||
+ '</select>';
|
+ '</select>';
|
||||||
const dSwitch = '<input type="checkbox" id="disable_port" onchange="portOnOff();">'
|
const dSwitch = '<input type="checkbox" id="disable_port" onchange="portOnOff();">'
|
||||||
for (let i = 1; i <= numPorts; i++) {
|
for (let i = 1; i <= numPorts; i++) {
|
||||||
if (pIsSFP[i-1])
|
if (pIsSFP[i-1])
|
||||||
continue;
|
continue;
|
||||||
console.log("Table row: " + i + "pState: " + pState[i-2]);
|
console.log("Table row: " + i + "pState: " + pState[i-2]);
|
||||||
const tr = tbl.insertRow();
|
const tr = tbl.insertRow();
|
||||||
let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i}`));
|
let td = tr.insertCell(); td.appendChild(document.createTextNode(t('common_port') + i));
|
||||||
let portName = portNames[physToLogPort[i-1]] || '';
|
let portName = portNames[physToLogPort[i-1]] || '';
|
||||||
td = tr.insertCell(); td.appendChild(document.createTextNode(portName));
|
td = tr.insertCell(); td.appendChild(document.createTextNode(portName));
|
||||||
td = tr.insertCell(); td.innerHTML = linkS[pState[i] + 1];
|
td = tr.insertCell(); td.innerHTML = linkText(pState[i] + 1);
|
||||||
td = tr.insertCell(); td.innerHTML = sSelect.replaceAll("speed_sel", "speed_sel_" + i);
|
td = tr.insertCell(); td.innerHTML = sSelect.replaceAll("speed_sel", "speed_sel_" + i);
|
||||||
td = tr.insertCell(); td.innerHTML = dSwitch.replaceAll("disable_port", "disable_port_" + i)
|
td = tr.insertCell(); td.innerHTML = dSwitch.replaceAll("disable_port", "disable_port_" + i)
|
||||||
.replace("portOnOff()", "portOnOff(" + i + ")");
|
.replace("portOnOff()", "portOnOff(" + i + ")");
|
||||||
var button = '<button type="button" style="margin: 0 0 0 24px" onclick="applySpeed(' + i + ');">Apply</button>';
|
var button = '<button type="button" style="margin: 0 0 0 24px" onclick="applySpeed(' + i + ');">' + t('port_apply') + '</button>';
|
||||||
td = tr.insertCell();
|
td = tr.insertCell();
|
||||||
td.innerHTML = button;
|
td.innerHTML = button;
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ function createPortTable() {
|
|||||||
tr = tbl.insertRow();
|
tr = tbl.insertRow();
|
||||||
for (let i = 1; i <= numPorts; i++) {
|
for (let i = 1; i <= numPorts; i++) {
|
||||||
let td = tr.insertCell();
|
let td = tr.insertCell();
|
||||||
td.innerHTML = '<button type="button" style="margin: 0 0 0 24px" onclick="applyMTU(' + i + ');">Apply</button>';
|
td.innerHTML = '<button type="button" style="margin: 0 0 0 24px" onclick="applyMTU(' + i + ');">' + t('port_apply') + '</button>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ function updatePortTable() {
|
|||||||
for (let i = 1; i <= numPorts ; i++) {
|
for (let i = 1; i <= numPorts ; i++) {
|
||||||
if (pIsSFP[i-1])
|
if (pIsSFP[i-1])
|
||||||
continue;
|
continue;
|
||||||
tbl.rows[i].cells[2].innerHTML = `${linkS[pState[i-1]+1]}`;
|
tbl.rows[i].cells[2].innerHTML = linkText(pState[i-1]+1);
|
||||||
if (!clicked[i] && pState[i - 1] < 0) {
|
if (!clicked[i] && pState[i - 1] < 0) {
|
||||||
document.getElementById('speed_sel_' + i).disabled = true;
|
document.getElementById('speed_sel_' + i).disabled = true;
|
||||||
document.getElementById('disable_port_' + i).checked = true;
|
document.getElementById('disable_port_' + i).checked = true;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>FreeSwitchOS Port Statistics</title>
|
<title data-i18n="stat_title">FreeSwitchOS Port Statistics</title>
|
||||||
<style>
|
<style>
|
||||||
.popup {
|
.popup {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -31,14 +32,14 @@
|
|||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
<div id="popup" class="popup">
|
<div id="popup" class="popup">
|
||||||
<div class="popup-content">
|
<div class="popup-content">
|
||||||
<h2>Detailed Port Statistics</h2>
|
<h2 data-i18n="stat_detailed">Detailed Port Statistics</h2>
|
||||||
<div id="popup_text"></div>
|
<div id="popup_text"></div>
|
||||||
<button id="closePopup" class="action">Close</button>
|
<button id="closePopup" class="action" data-i18n="stat_close">Close</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h1>Port Statistics</h1>
|
<h1 data-i18n="stat_heading">Port Statistics</h1>
|
||||||
<table id="statstable">
|
<table id="statstable">
|
||||||
<tr> <th>Port</th> <th>Name</th> <th>link</th> <th>TX Good</th> <th>TX Bad</th> <th>RX Good</th> <th>RX Bad</th> <th> All Counters </th></tr>
|
<tr> <th data-i18n="stat_col_port">Port</th> <th data-i18n="stat_col_name">Name</th> <th data-i18n="stat_col_link">link</th> <th data-i18n="stat_col_tx_good">TX Good</th> <th data-i18n="stat_col_tx_bad">TX Bad</th> <th data-i18n="stat_col_rx_good">RX Good</th> <th data-i18n="stat_col_rx_bad">RX Bad</th> <th data-i18n="stat_col_all"> All Counters </th></tr>
|
||||||
<script src="/stat.js"></script>
|
<script src="/stat.js"></script>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -109,44 +109,44 @@ const mib_counters = [
|
|||||||
function getCounters(port) {
|
function getCounters(port) {
|
||||||
var xhttp = new XMLHttpRequest();
|
var xhttp = new XMLHttpRequest();
|
||||||
const popup = document.getElementById('popup');
|
const popup = document.getElementById('popup');
|
||||||
xhttp.onreadystatechange = function() {
|
xhttp.onreadystatechange = function () {
|
||||||
if (this.readyState == 4 && this.status == 200) {
|
if (this.readyState == 4 && this.status == 200) {
|
||||||
const s = JSON.parse(xhttp.responseText);
|
const s = JSON.parse(xhttp.responseText);
|
||||||
console.log("Counters: ", JSON.stringify(s));
|
console.log("Counters: ", JSON.stringify(s));
|
||||||
const ptext = document.getElementById('popup_text');
|
const ptext = document.getElementById('popup_text');
|
||||||
var t = "<table style='width:100%'> <tr> <th>Counter</th> <th>Value</th> <th>Counter</th> <th>Value</th></tr> <tr>";
|
var tableHtml = "<table style='width:100%'> <tr> <th>" + t('stat_counter') + "</th> <th>" + t('stat_value') + "</th> <th>" + t('stat_counter') + "</th> <th>" + t('stat_value') + "</th></tr> <tr>";
|
||||||
console.log("Counter 0: ", BigInt(s[0]).toString(), " length: ", s.length);
|
console.log("Counter 0: ", BigInt(s[0]).toString(), " length: ", s.length);
|
||||||
var c = 0;
|
var c = 0;
|
||||||
for (i = 0; i < mib_counters.length; i += 4) {
|
for (i = 0; i < mib_counters.length; i += 4) {
|
||||||
console.log(i, " ", mib_counters[i], ": ", mib_counters[i+1]);
|
console.log(i, " ", mib_counters[i], ": ", mib_counters[i + 1]);
|
||||||
if (mib_counters[i] == "" && mib_counters[i + 1] == 8) {
|
if (mib_counters[i] == "" && mib_counters[i + 1] == 8) {
|
||||||
console.log("c " + i + ": continue");
|
console.log("c " + i + ": continue");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var count = BigInt(s[i/4]);
|
var count = BigInt(s[i / 4]);
|
||||||
if (mib_counters[i+1] == 8) {
|
if (mib_counters[i + 1] == 8) {
|
||||||
t += "<td>" + mib_counters[i] + "</td><td>" + count.toString() + "</td>";
|
tableHtml += "<td>" + mib_counters[i] + "</td><td>" + count.toString() + "</td>";
|
||||||
c += 1;
|
c += 1;
|
||||||
} else if (mib_counters[i+1] == 4) {
|
} else if (mib_counters[i + 1] == 4) {
|
||||||
if (mib_counters[i] != "") {
|
if (mib_counters[i] != "") {
|
||||||
t += "<td>" + mib_counters[i] + "</td><td>" + (count >> 32n).toString() + "</td>";
|
tableHtml += "<td>" + mib_counters[i] + "</td><td>" + (count >> 32n).toString() + "</td>";
|
||||||
c += 1;
|
c += 1;
|
||||||
}
|
}
|
||||||
if (c == 2) {
|
if (c == 2) {
|
||||||
t += "</tr> <tr>";
|
tableHtml += "</tr> <tr>";
|
||||||
c = 0;
|
c = 0;
|
||||||
}
|
}
|
||||||
if (mib_counters[i+2] != "") {
|
if (mib_counters[i + 2] != "") {
|
||||||
t += "<td>" + mib_counters[i+2] + "</td><td>" + (count & 4294967295n).toString() + "</td>";
|
tableHtml += "<td>" + mib_counters[i + 2] + "</td><td>" + (count & 4294967295n).toString() + "</td>";
|
||||||
c += 1;
|
c += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == 2) {
|
if (c == 2) {
|
||||||
t += "</tr> <tr>";
|
tableHtml += "</tr> <tr>";
|
||||||
c = 0;
|
c = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptext.innerHTML = t + "</tr></table>";
|
ptext.innerHTML = tableHtml + "</tr></table>";
|
||||||
popup.style.display = 'flex';
|
popup.style.display = 'flex';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -161,26 +161,26 @@ function fillStats() {
|
|||||||
return;
|
return;
|
||||||
if (tbl.rows.length > 1) {
|
if (tbl.rows.length > 1) {
|
||||||
for (let i = 0; i < numPorts; i++) {
|
for (let i = 0; i < numPorts; i++) {
|
||||||
console.log("Table Update row: " + i + " state " + pState[i] + " is " + linkS[pState[i] +1]);
|
console.log("Table Update row: " + i + " state " + pState[i] + " is " + linkS[pState[i] + 1]);
|
||||||
tbl.rows[i+1].cells[2].innerHTML = `${linkS[pState[i]+1]}`;
|
tbl.rows[i + 1].cells[2].innerHTML = linkText(pState[i] + 1);
|
||||||
tbl.rows[i+1].cells[3].innerHTML = `${txG[i]} pkts`;
|
tbl.rows[i + 1].cells[3].innerHTML = `${txG[i]}` + t('common_pkts');
|
||||||
tbl.rows[i+1].cells[4].innerHTML = `${txB[i]} pkts`;
|
tbl.rows[i + 1].cells[4].innerHTML = `${txB[i]}` + t('common_pkts');
|
||||||
tbl.rows[i+1].cells[5].innerHTML = `${rxG[i]} pkts`;
|
tbl.rows[i + 1].cells[5].innerHTML = `${rxG[i]}` + t('common_pkts');
|
||||||
tbl.rows[i+1].cells[6].innerHTML = `${rxB[i]} pkts`;
|
tbl.rows[i + 1].cells[6].innerHTML = `${rxB[i]}` + t('common_pkts');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < numPorts; i++) {
|
for (let i = 0; i < numPorts; i++) {
|
||||||
console.log("Table row: " + i);
|
console.log("Table row: " + i);
|
||||||
const tr = tbl.insertRow();
|
const tr = tbl.insertRow();
|
||||||
let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i+1}`));
|
let td = tr.insertCell(); td.appendChild(document.createTextNode(t('common_port') + (i + 1)));
|
||||||
let portName = portNames[physToLogPort[i]] || '';
|
let portName = portNames[physToLogPort[i]] || '';
|
||||||
td = tr.insertCell(); td.appendChild(document.createTextNode(portName));
|
td = tr.insertCell(); td.appendChild(document.createTextNode(portName));
|
||||||
td = tr.insertCell(); td.appendChild(document.createTextNode(`${linkS[pState[i]+1]}`));
|
td = tr.insertCell(); td.appendChild(document.createTextNode(linkText(pState[i] + 1)));
|
||||||
td = tr.insertCell(); td.appendChild(document.createTextNode(`${txG[i]} pkts`));
|
td = tr.insertCell(); td.appendChild(document.createTextNode(`${txG[i]}` + t('common_pkts')));
|
||||||
td = tr.insertCell();td.appendChild(document.createTextNode(`${txB[i]} pkts`));
|
td = tr.insertCell(); td.appendChild(document.createTextNode(`${txB[i]}` + t('common_pkts')));
|
||||||
td = tr.insertCell();td.appendChild(document.createTextNode(`${rxG[i]} pkts`));
|
td = tr.insertCell(); td.appendChild(document.createTextNode(`${rxG[i]}` + t('common_pkts')));
|
||||||
td = tr.insertCell();td.appendChild(document.createTextNode(`${rxB[i]} pkts`));
|
td = tr.insertCell(); td.appendChild(document.createTextNode(`${rxB[i]}` + t('common_pkts')));
|
||||||
var button = '<button type="button" style="margin: 0 0 0 24px" onclick="getCounters(' + i + ');">Show</button>';
|
var button = '<button type="button" style="margin: 0 0 0 24px" onclick="getCounters(' + (i + 1) + ');">' + t('stat_show') + '</button>';
|
||||||
td = tr.insertCell(); td.innerHTML = button;
|
td = tr.insertCell(); td.innerHTML = button;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,8 +197,8 @@ window.addEventListener('click', (event) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
window.addEventListener("load", function () {
|
||||||
update( () => {
|
update(() => {
|
||||||
update();
|
update();
|
||||||
fillStats();
|
fillStats();
|
||||||
const stat = setInterval(fillStats, 1000);
|
const stat = setInterval(fillStats, 1000);
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ object, img {
|
|||||||
.isNOK{ color: #900;}
|
.isNOK{ color: #900;}
|
||||||
.isOK{ color: #090;}
|
.isOK{ color: #090;}
|
||||||
.ip{padding:8px 16px;margin-bottom: 1em;margin-left: 1em}
|
.ip{padding:8px 16px;margin-bottom: 1em;margin-left: 1em}
|
||||||
|
.rotext{display:inline-block;padding:8px 16px;margin-bottom: 1em;margin-left: 1em}
|
||||||
.row {display: flex;}
|
.row {display: flex;}
|
||||||
.rcol {flex: 90%;}
|
.rcol {flex: 90%;}
|
||||||
.lcol {flex: 10%;}
|
.lcol {flex: 10%;}
|
||||||
@@ -164,3 +165,8 @@ margin: 30px 0;
|
|||||||
select { text-align-last: right; font-family: monospace}
|
select { text-align-last: right; font-family: monospace}
|
||||||
option { direction: rtl; font-family: sans-serif}
|
option { direction: rtl; font-family: sans-serif}
|
||||||
#vlanTable td { text-align: left; }
|
#vlanTable td { text-align: left; }
|
||||||
|
|
||||||
|
.l2sort{cursor:pointer;user-select:none}
|
||||||
|
.l2sort:hover{text-decoration:underline}
|
||||||
|
.l2arrow{opacity:0.55;font-size:0.85em}
|
||||||
|
.l2filter{width:100%;box-sizing:border-box;font-weight:normal;font-size:0.9em}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>System Settings</title>
|
<title data-i18n="sys_title">System Settings</title>
|
||||||
<style>
|
<style>
|
||||||
.tab-bar { display: flex; border-bottom: 2px solid #226; margin-bottom: 0; margin-left: 16%; padding: 1px 16px; padding-bottom: 0; }
|
.tab-bar { display: flex; border-bottom: 2px solid #226; margin-bottom: 0; margin-left: 16%; padding: 1px 16px; padding-bottom: 0; }
|
||||||
.tab-btn { padding: 10px 20px; background-color: #ddf; border: none; cursor: pointer; font-size: 1em; border-radius: 8px 8px 0 0; margin-right: 4px; }
|
.tab-btn { padding: 10px 20px; background-color: #ddf; border: none; cursor: pointer; font-size: 1em; border-radius: 8px 8px 0 0; margin-right: 4px; }
|
||||||
@@ -14,57 +15,79 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="tab-bar">
|
<div class="tab-bar">
|
||||||
<button class="tab-btn active" onclick="openTab(event, 'system-tab')">System</button>
|
<button class="tab-btn active" onclick="openTab(event, 'system-tab')" data-i18n="sys_tab_system">System</button>
|
||||||
<button class="tab-btn" onclick="openTab(event, 'advanced-tab')">Advanced</button>
|
<button class="tab-btn" onclick="openTab(event, 'advanced-tab')" data-i18n="sys_tab_advanced">Advanced</button>
|
||||||
<button class="tab-btn" onclick="openTab(event, 'console-tab')">Console</button>
|
<button class="tab-btn" onclick="openTab(event, 'console-tab')" data-i18n="sys_tab_console">Console</button>
|
||||||
</div>
|
</div>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
|
|
||||||
<div id="system-tab" class="tab-content active">
|
<div id="system-tab" class="tab-content active">
|
||||||
<h1>System Settings</h1>
|
<h1 data-i18n="sys_heading">System Settings</h1>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="lcol"> <label for="ip">IP address:</label></div>
|
<div class="lcol"> <label for="hostname" data-i18n="sys_hostname">Hostname:</label></div>
|
||||||
|
<div class="rcol"> <input id="hostname" type="text" maxlength="23" size="20"/>
|
||||||
|
<button onclick="hostSub()" data-i18n="sys_apply">Apply</button></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label data-i18n="sys_model">Model:</label></div>
|
||||||
|
<div class="rcol"><span id="model" class="rotext"></span></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="ip" data-i18n="sys_ip">IP address:</label></div>
|
||||||
<div class="rcol"> <input id="ip" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
<div class="rcol"> <input id="ip" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="lcol"> <label for="netmask">Netmask:</label></div>
|
<div class="lcol"> <label for="netmask" data-i18n="sys_netmask">Netmask:</label></div>
|
||||||
<div class="rcol"><input id="netmask" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
<div class="rcol"><input id="netmask" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="lcol"> <label for="gw">Gateway:</label></div>
|
<div class="lcol"> <label for="gw" data-i18n="sys_gateway">Gateway:</label></div>
|
||||||
<div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
<div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="mgmtvlan" data-i18n="sys_mgmt_vlan">Management VLAN:</label></div>
|
||||||
|
<div class="rcol"><select id="mgmtvlan" class="ip" onchange="mgmtVlanChanged()"></select></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label data-i18n="sys_language">Language:</label></div>
|
||||||
|
<div class="rcol">
|
||||||
|
<select id="lang-select" onchange="changeLang()">
|
||||||
|
<option value="en">English</option>
|
||||||
|
<option value="ja">日本語</option>
|
||||||
|
<option value="zh">中文</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
When updating the above settings, remember to point your browser to the new IP afterwards:<br/>
|
<span data-i18n="sys_ip_note">When updating the above settings, remember to point your browser to the new IP afterwards:</span><br/>
|
||||||
<input style="width:40%;" class="action" id="ip_sub" onclick="ipSub();" type="button" value="Update Settings"><br/>
|
<input style="width:40%;" class="action" id="ip_sub" onclick="ipSub();" type="button" data-i18n="sys_update" value="Update Settings"><br/>
|
||||||
<br/>
|
<br/>
|
||||||
Save all current settings to Flash:<br/>
|
<span data-i18n="sys_save_label">Save all current settings to Flash:</span><br/>
|
||||||
<input style="width:40%;" class="action" id="flash_sub" onclick="flashSave();" type="button" value="Save Settings to Flash">
|
<input style="width:40%;" class="action" id="flash_sub" onclick="flashSave();" type="button" data-i18n="sys_save" value="Save Settings to Flash">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="advanced-tab" class="tab-content">
|
<div id="advanced-tab" class="tab-content">
|
||||||
<h1>Advanced Settings</h1>
|
<h1 data-i18n="sys_advanced">Advanced Settings</h1>
|
||||||
<div class="lcol"> <label for="config_display">Startup configuration:</label></div>
|
<div class="lcol"> <label for="config_display" data-i18n="sys_startup_config">Startup configuration:</label></div>
|
||||||
<textarea id="config_display" rows="8" cols="60"></textarea>
|
<textarea id="config_display" rows="8" cols="60"></textarea>
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
Be careful when saving the directly edited startup configuration, you can lock yourself out:<br/>
|
<span data-i18n="sys_startup_warn">Be careful when saving the directly edited startup configuration, you can lock yourself out:</span><br/>
|
||||||
<input style="width:40%;" class="action" id="clear_config" onclick="clearConfig();" type="button" value="Clear Startup Config">
|
<input style="width:40%;" class="action" id="clear_config" onclick="clearConfig();" type="button" data-i18n="sys_clear_config" value="Clear Startup Config">
|
||||||
<br/>
|
<br/>
|
||||||
<input style="width:40%;" class="action" id="flash_startup_sub" onclick="flashStartupSave();" type="button" value="Save Startup Settings to Flash">
|
<input style="width:40%;" class="action" id="flash_startup_sub" onclick="flashStartupSave();" type="button" data-i18n="sys_save_startup" value="Save Startup Settings to Flash">
|
||||||
<br/>
|
<br/>
|
||||||
<input style="width:40%;" class="action" id="switch_reset" onclick="resetSwitch();" type="button" value="Reset Switch">
|
<input style="width:40%;" class="action" id="switch_reset" onclick="resetSwitch();" type="button" data-i18n="sys_reset" value="Reset Switch">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="console-tab" class="tab-content">
|
<div id="console-tab" class="tab-content">
|
||||||
<h1>Console Command</h1>
|
<h1 data-i18n="sys_console">Console Command</h1>
|
||||||
<label for="console_command">Enter command:</label>
|
<label for="console_command" data-i18n="sys_enter_cmd">Enter command:</label>
|
||||||
<input type="text" id="console_cmd" name="console_cmd" style="width:40%;">
|
<input type="text" id="console_cmd" name="console_cmd" style="width:40%;">
|
||||||
<input style="width:20%;" class="action" id="cmd_sub" onclick="cmdSub();" type="button" value="Send Command"><br/>
|
<input style="width:20%;" class="action" id="cmd_sub" onclick="cmdSub();" type="button" data-i18n="sys_send_cmd" value="Send Command"><br/>
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
Be careful when entering console commands, you can lock yourself out!<br/>
|
<span data-i18n="sys_console_warn">Be careful when entering console commands, you can lock yourself out!</span><br/>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,14 @@ var systemInterval = Number();
|
|||||||
var isSaving = false;
|
var isSaving = false;
|
||||||
const ips = ["ip", "netmask", "gw"];
|
const ips = ["ip", "netmask", "gw"];
|
||||||
|
|
||||||
|
function changeLang() {
|
||||||
|
var lang = document.getElementById('lang-select').value;
|
||||||
|
setLang(lang);
|
||||||
|
}
|
||||||
|
|
||||||
function checkIp(ip) {
|
function checkIp(ip) {
|
||||||
const ipv4 = /^(\d{1,3}\.){3}\d{1,3}$/;
|
const ipv4 = /^(\d{1,3}\.){3}\d{1,3}$/;
|
||||||
if (!ipv4.test(ip)) {alert(`Invalid ip:${ip}`); return false };
|
if (!ipv4.test(ip)) {alert(t('sys_invalid_ip') + ip); return false };
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +48,14 @@ async function cmdSub() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function hostSub() {
|
||||||
|
const h = document.getElementById("hostname").value;
|
||||||
|
try { await fetch('/cmd', { method: 'POST', body: "hostname " + h }); }
|
||||||
|
catch(err) { console.error(`Error: ${err}`); }
|
||||||
|
fetchIP();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async function sendConfig(c) {
|
async function sendConfig(c) {
|
||||||
if (isSaving) return;
|
if (isSaving) return;
|
||||||
isSaving = true;
|
isSaving = true;
|
||||||
@@ -118,6 +131,9 @@ function fetchIP() {
|
|||||||
document.getElementById("ip").value=s.ip_address;
|
document.getElementById("ip").value=s.ip_address;
|
||||||
document.getElementById("netmask").value=s.ip_netmask;
|
document.getElementById("netmask").value=s.ip_netmask;
|
||||||
document.getElementById("gw").value=s.ip_gateway;
|
document.getElementById("gw").value=s.ip_gateway;
|
||||||
|
document.getElementById("hostname").value=s.hostname;
|
||||||
|
document.getElementById("model").textContent=s.hw_ver;
|
||||||
|
loadMgmtVlan();
|
||||||
clearInterval(systemInterval);
|
clearInterval(systemInterval);
|
||||||
// Fetch and populate the config textbox
|
// Fetch and populate the config textbox
|
||||||
fetchConfig().then((configText) => {
|
fetchConfig().then((configText) => {
|
||||||
@@ -136,15 +152,57 @@ function fetchIP() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resetSwitch() {
|
function resetSwitch() {
|
||||||
if (!confirm('Are you sure you want to reset the switch?')) {
|
if (!confirm(t('sys_reset_confirm'))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fetch('/reset', { method: 'GET' }).catch(() => {});
|
fetch('/reset', { method: 'GET' }).catch(() => {});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
alert('Switch is resetting. Please wait and refresh the page.');
|
alert(t('sys_resetting'));
|
||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
window.addEventListener("load", function() {
|
||||||
|
var langSel = document.getElementById('lang-select');
|
||||||
|
if (langSel) langSel.value = rtlLang;
|
||||||
systemInterval = setInterval(fetchIP, 1000);
|
systemInterval = setInterval(fetchIP, 1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var mgmtVlanCurrent = 0;
|
||||||
|
|
||||||
|
function loadMgmtVlan() {
|
||||||
|
var sel = document.getElementById('mgmtvlan');
|
||||||
|
if (!sel) return;
|
||||||
|
fetch('/vlanlist').then(function(r) { return r.json(); }).then(function(d) {
|
||||||
|
var cur = d.mgmt || 0;
|
||||||
|
var list = d.vlan || [];
|
||||||
|
mgmtVlanCurrent = cur;
|
||||||
|
sel.innerHTML = '';
|
||||||
|
if (!cur) {
|
||||||
|
var none = document.createElement('option');
|
||||||
|
none.value = 0; none.disabled = true;
|
||||||
|
none.textContent = t('sys_mgmt_untagged');
|
||||||
|
sel.appendChild(none);
|
||||||
|
}
|
||||||
|
for (var i = 0; i < list.length; i++) {
|
||||||
|
var o = document.createElement('option');
|
||||||
|
o.value = list[i].id;
|
||||||
|
o.textContent = list[i].name ? (list[i].id + ' (' + list[i].name + ')') : list[i].id;
|
||||||
|
sel.appendChild(o);
|
||||||
|
}
|
||||||
|
sel.value = cur;
|
||||||
|
}).catch(function(err) { console.error('VLAN list failed:', err); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function mgmtVlanChanged() {
|
||||||
|
var sel = document.getElementById('mgmtvlan');
|
||||||
|
var id = parseInt(sel.value, 10);
|
||||||
|
if (!id || id === mgmtVlanCurrent) return;
|
||||||
|
if (!confirm(t('sys_mgmt_confirm') + id + '.\n\n' + t('sys_mgmt_warn'))) {
|
||||||
|
sel.value = mgmtVlanCurrent;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fetch('/cmd', { method: 'POST', body: 'vlan ' + id + ' mgmt' })
|
||||||
|
.then(function() { mgmtVlanCurrent = id; })
|
||||||
|
.catch(function(err) { console.error('Set management VLAN failed:', err); sel.value = mgmtVlanCurrent; });
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>Firmware update</title>
|
<title data-i18n="update_title">Firmware update</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;width:40%;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;width:40%;">
|
||||||
<h1>Firmware Update</h1>
|
<h1 data-i18n="update_heading">Firmware Update</h1>
|
||||||
<form enctype="multipart/form-data" action="/upload" method="POST">
|
<form enctype="multipart/form-data" action="/upload" method="POST">
|
||||||
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
|
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
|
||||||
Choose a firmware update file to upload: <br/> <br/>
|
<span data-i18n="update_instruction">Choose a firmware update file to upload:</span> <br/> <br/>
|
||||||
<input name="uploadedfile" type="file" accept=".bin" /><br />
|
<input name="uploadedfile" type="file" accept=".bin" /><br />
|
||||||
<input style="margin-top:3em" type="submit" value="Upload File" />
|
<input style="margin-top:3em" type="submit" data-i18n="update_upload" value="Upload File" />
|
||||||
</form>
|
</form>
|
||||||
<script src="/navigation.js"></script>
|
<script src="/navigation.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,52 +1,53 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
|
<script src="/i18n.js"></script>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>FreeSwitchOS VLAN Configuration</title>
|
<title data-i18n="vlan_title">FreeSwitchOS VLAN Configuration</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
<h1>VLAN Configuration</h1>
|
<h1 data-i18n="vlan_heading">VLAN Configuration</h1>
|
||||||
<form id="vform" action="/vlan.html">
|
<form id="vform" action="/vlan.html">
|
||||||
<div>
|
<div>
|
||||||
<label for="vlanSelect">VLAN auswählen:</label>
|
<label for="vlanSelect" data-i18n="vlan_select">VLAN Select:</label>
|
||||||
<select id="vlanSelect" style="margin: 0 0 0 8px">
|
<select id="vlanSelect" style="margin: 0 0 0 8px">
|
||||||
<option value="" disabled selected>— VLAN wählen —</option>
|
<option value="" disabled selected data-i18n="vlan_choose">— VLAN Choose —</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
<div>
|
<div>
|
||||||
<label for="vid">VLAN ID:</label>
|
<label for="vid" data-i18n="vlan_id">VLAN ID:</label>
|
||||||
<input type="number" min="1" max="4094" id="vid" name="vid">
|
<input type="number" min="1" max="4094" id="vid" name="vid">
|
||||||
<button type="button" style="margin: 0 0 0 24px" onclick="fetchVLAN();">Get Configuration</button>
|
<button type="button" style="margin: 0 0 0 24px" onclick="fetchVLAN();" data-i18n="vlan_get_config">Get Configuration</button>
|
||||||
</div>
|
</div>
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
<label for="vname">VLAN Name:</label>
|
<label for="vname" data-i18n="vlan_name">VLAN Name:</label>
|
||||||
<input type="text" id="vname" name="vname"><br><br>
|
<input type="text" id="vname" name="vname"><br><br>
|
||||||
<br/>
|
<br/>
|
||||||
<h2>Tagged Ports</h2>
|
<h2 data-i18n="vlan_tagged">Tagged Ports</h2>
|
||||||
<div id="tPorts"><button type="button" style="transform: translateY(-100%);margin: 0 50px 0 0" onclick="utClicked(true);">Select all</button></div>
|
<div id="tPorts"><button type="button" style="transform: translateY(-100%);margin: 0 50px 0 0" onclick="utClicked(true);" data-i18n="vlan_select_all">Select all</button></div>
|
||||||
<h2>Untagged Ports</h2>
|
<h2 data-i18n="vlan_untagged">Untagged Ports</h2>
|
||||||
<div id="uPorts"><button type="button" style="transform: translateY(-100%); margin: 0 50px 0 0" onclick="utClicked(false);">Select all</button> </div>
|
<div id="uPorts"><button type="button" style="transform: translateY(-100%); margin: 0 50px 0 0" onclick="utClicked(false);" data-i18n="vlan_select_all">Select all</button> </div>
|
||||||
<h2>Use as default VLAN for incoming traffic (PVID)</h2>
|
<h2 data-i18n="vlan_pvid">Use as default VLAN for incoming traffic (PVID)</h2>
|
||||||
<div id="pPorts"><button type="button" style="transform: translateY(-100%); margin: 0 50px 0 0" onclick="pvClicked(true);">Select all</button> </div>
|
<div id="pPorts"><button type="button" style="transform: translateY(-100%); margin: 0 50px 0 0" onclick="pvClicked(true);" data-i18n="vlan_select_all">Select all</button> </div>
|
||||||
<script src="/vlan.js"></script>
|
<script src="/vlan.js"></script>
|
||||||
<br/> <input style="width:40%;" class="action" id="vlan_sub" onclick="vlanSub();" type="button" value="Update / Create">
|
<br/> <input style="width:40%;" class="action" id="vlan_sub" onclick="vlanSub();" type="button" data-i18n="vlan_update" value="Update / Create">
|
||||||
<script src="/vlan_sub.js"></script>
|
<script src="/vlan_sub.js"></script>
|
||||||
</form>
|
</form>
|
||||||
<h2>Configured VLANs</h2>
|
<h2 data-i18n="vlan_configured">Configured VLANs</h2>
|
||||||
<table id="vlanTable" style="width:90%">
|
<table id="vlanTable" style="width:90%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>VLAN</th>
|
<th>VLAN</th>
|
||||||
<th>Name</th>
|
<th data-i18n="vlan_col_name">Name</th>
|
||||||
<th>Member Ports</th>
|
<th data-i18n="vlan_col_member">Member Ports</th>
|
||||||
<th>Tagged Ports</th>
|
<th data-i18n="vlan_col_tagged">Tagged Ports</th>
|
||||||
<th>Untagged Ports</th>
|
<th data-i18n="vlan_col_untagged">Untagged Ports</th>
|
||||||
<th>PVID Ports</th>
|
<th data-i18n="vlan_col_pvid">PVID Ports</th>
|
||||||
<th>Delete</th>
|
<th data-i18n="vlan_col_delete">Delete</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="vlanTableBody">
|
<tbody id="vlanTableBody">
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ function fetchVLAN() {
|
|||||||
};
|
};
|
||||||
var v=document.getElementById('vid').value
|
var v=document.getElementById('vid').value
|
||||||
if (!v) {
|
if (!v) {
|
||||||
alert("Set VLAN ID first");
|
alert(t('vlan_set_id_first'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xhttp.open("GET", `/vlan.json?vid=${v}`, true);
|
xhttp.open("GET", `/vlan.json?vid=${v}`, true);
|
||||||
@@ -110,7 +110,7 @@ async function loadVlanTable() {
|
|||||||
var resp;
|
var resp;
|
||||||
try { resp = await fetch('/vlanlist'); } catch(e) { return; }
|
try { resp = await fetch('/vlanlist'); } catch(e) { return; }
|
||||||
if (!resp.ok) return;
|
if (!resp.ok) return;
|
||||||
var vlans = await resp.json();
|
var vlans = (await resp.json()).vlan || [];
|
||||||
for (var i = 0; i < vlans.length; i++) {
|
for (var i = 0; i < vlans.length; i++) {
|
||||||
var v = vlans[i];
|
var v = vlans[i];
|
||||||
var vresp;
|
var vresp;
|
||||||
@@ -161,7 +161,7 @@ async function loadVlanTable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function deleteVlan(id) {
|
function deleteVlan(id) {
|
||||||
if (!confirm('Delete VLAN ' + id + '?')) return;
|
if (!confirm(t('vlan_delete_confirm') + id + '?')) return;
|
||||||
fetch('/cmd', { method: 'POST', body: 'vlan ' + id + ' d' })
|
fetch('/cmd', { method: 'POST', body: 'vlan ' + id + ' d' })
|
||||||
.then(function() { refreshVlanViews(); })
|
.then(function() { refreshVlanViews(); })
|
||||||
.catch(function(err) { console.error('Delete failed:', err); });
|
.catch(function(err) { console.error('Delete failed:', err); });
|
||||||
@@ -181,7 +181,7 @@ function loadVlanList() {
|
|||||||
sel.style.display = 'none';
|
sel.style.display = 'none';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var vlans = JSON.parse(this.responseText);
|
var vlans = JSON.parse(this.responseText).vlan || [];
|
||||||
if (!vlans.length) {
|
if (!vlans.length) {
|
||||||
sel.style.display = 'none';
|
sel.style.display = 'none';
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ async function vlanSub() {
|
|||||||
var cmd = "vlan ";
|
var cmd = "vlan ";
|
||||||
var v=document.getElementById('vid').value
|
var v=document.getElementById('vid').value
|
||||||
if (!v) {
|
if (!v) {
|
||||||
alert("Set VLAN ID first");
|
alert(t('vlan_set_id_first'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cmd = cmd + v;
|
cmd = cmd + v;
|
||||||
|
|||||||
@@ -41,8 +41,17 @@ __xdata uint32_t cont_addr;
|
|||||||
|
|
||||||
// HTTP header properties
|
// HTTP header properties
|
||||||
__xdata uint8_t boundary[72];
|
__xdata uint8_t boundary[72];
|
||||||
__xdata uint8_t *content_type = 0;
|
|
||||||
__xdata uint8_t *session = 0;
|
// a client may split the request anywhere, including inside a boundary or a
|
||||||
|
// part header, so a configuration upload is parsed only once it is complete;
|
||||||
|
// sized for a full config sector plus the multipart framing around it
|
||||||
|
#define CONFIG_UPLOAD_BUF (CONFIG_LEN + 384)
|
||||||
|
__xdata uint8_t config_upload;
|
||||||
|
__xdata uint8_t config_buf[CONFIG_UPLOAD_BUF];
|
||||||
|
__xdata uint16_t cfg_pos, cfg_hdr, cfg_body, cfg_end, cfg_last;
|
||||||
|
__xdata uint8_t cfg_bl;
|
||||||
|
__xdata uint8_t * __xdata content_type = 0;
|
||||||
|
__xdata uint8_t * __xdata session = 0;
|
||||||
|
|
||||||
// Global variables holding POST state
|
// Global variables holding POST state
|
||||||
__xdata uint16_t bindex; // Current index into the boundary
|
__xdata uint16_t bindex; // Current index into the boundary
|
||||||
@@ -54,7 +63,7 @@ __xdata char passwd[21];
|
|||||||
__xdata char session_id[SESSION_ID_LENGTH + 1];
|
__xdata char session_id[SESSION_ID_LENGTH + 1];
|
||||||
__xdata uint8_t authenticated;
|
__xdata uint8_t authenticated;
|
||||||
__xdata uint32_t now;
|
__xdata uint32_t now;
|
||||||
__xdata uint8_t *timeptr;
|
__xdata uint8_t * __xdata timeptr;
|
||||||
__xdata uint32_t last_session_use;
|
__xdata uint32_t last_session_use;
|
||||||
|
|
||||||
#define TSTATE_NONE 0
|
#define TSTATE_NONE 0
|
||||||
@@ -77,6 +86,7 @@ inline uint8_t is_separator(uint8_t c)
|
|||||||
|
|
||||||
void httpd_init(void) __banked
|
void httpd_init(void) __banked
|
||||||
{
|
{
|
||||||
|
config_upload = 0; // xdata is not zeroed by the startup code
|
||||||
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
|
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
|
||||||
// Start listening to port 80
|
// Start listening to port 80
|
||||||
uip_listen(HTONS(80));
|
uip_listen(HTONS(80));
|
||||||
@@ -101,21 +111,6 @@ uint8_t find_entry(__xdata uint8_t *e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char strcmp(__xdata uint8_t *c, __code uint8_t * __xdata d)
|
|
||||||
{
|
|
||||||
uint8_t i = 0;
|
|
||||||
|
|
||||||
while (d[i] && (d[i] == c[i]))
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if (c[i] < d[i])
|
|
||||||
return -1;
|
|
||||||
else if (c[i] > d[i])
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool is_word(__xdata uint8_t *xdata_str_p, __code uint8_t * __xdata code_str_p)
|
bool is_word(__xdata uint8_t *xdata_str_p, __code uint8_t * __xdata code_str_p)
|
||||||
{
|
{
|
||||||
uint8_t u, c;
|
uint8_t u, c;
|
||||||
@@ -124,8 +119,8 @@ bool is_word(__xdata uint8_t *xdata_str_p, __code uint8_t * __xdata code_str_p)
|
|||||||
u = *xdata_str_p++;
|
u = *xdata_str_p++;
|
||||||
c = *code_str_p++;
|
c = *code_str_p++;
|
||||||
|
|
||||||
if (c == '\0') {
|
if (c == NUL) {
|
||||||
if (u != '\0' && u != ' ' && u != '\t' && u != ':' && u != '?' && u != '=' && u != '\n' && u != '\r')
|
if (u != NUL && u != ' ' && u != '\t' && u != ':' && u != '?' && u != '=' && u != '\n' && u != '\r')
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -145,8 +140,8 @@ bool is_url_word_x(__xdata uint8_t *uri_str_p, __xdata uint8_t *src_str_p)
|
|||||||
u = *uri_str_p++;
|
u = *uri_str_p++;
|
||||||
s = *src_str_p++;
|
s = *src_str_p++;
|
||||||
|
|
||||||
if (s == '\0') {
|
if (s == NUL) {
|
||||||
if (u != '\0' && u != ' ' && u != '\t' && u != ':' && u != '?' && u != '=' && u != '\n' && u != '\r')
|
if (u != NUL && u != ' ' && u != '\t' && u != ':' && u != '?' && u != '=' && u != '\n' && u != '\r')
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -180,7 +175,7 @@ bool is_url_word_x(__xdata uint8_t *uri_str_p, __xdata uint8_t *src_str_p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool is_word_x(__xdata uint8_t *lhs_str_p, __xdata uint8_t *rhs_str_p)
|
bool is_word_x(__xdata uint8_t * lhs_str_p, __xdata uint8_t * rhs_str_p)
|
||||||
{
|
{
|
||||||
uint8_t u, c;
|
uint8_t u, c;
|
||||||
|
|
||||||
@@ -188,8 +183,9 @@ bool is_word_x(__xdata uint8_t *lhs_str_p, __xdata uint8_t *rhs_str_p)
|
|||||||
u = *lhs_str_p++;
|
u = *lhs_str_p++;
|
||||||
c = *rhs_str_p++;
|
c = *rhs_str_p++;
|
||||||
|
|
||||||
if (c == '\0') {
|
if (c == NUL) {
|
||||||
if (u != '\0' && u != ' ' && u != '\t' && u != ':' && u != '?' && u != '=' && u != '\n' && u != '\r')
|
/* ';' separates cookies in a Cookie header, so it ends a value too. */
|
||||||
|
if (u != NUL && u != ' ' && u != '\t' && u != ':' && u != '?' && u != '=' && u != '\n' && u != '\r' && u != ';')
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -219,28 +215,28 @@ uint8_t parse_short(__xdata uint8_t *p)
|
|||||||
|
|
||||||
void send_not_found(void)
|
void send_not_found(void)
|
||||||
{
|
{
|
||||||
slen = strtox(outbuf, "HTTP/1.1 404 Not found\r\nContent-Type: text/html\r\n\r\n" \
|
slen = strtox(outbuf, "HTTP/1.1 404 Not found\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n" \
|
||||||
"<!DOCTYPE HTML PUBLIC>\n<title>404 Not Found</title>\n<h1>Not Found</h1>\n");
|
"<!DOCTYPE HTML PUBLIC>\n<title>404 Not Found</title>\n<h1>Not Found</h1>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void send_bad_request(void)
|
void send_bad_request(void)
|
||||||
{
|
{
|
||||||
slen = strtox(outbuf, "HTTP/1.1 400 Bad Request\r\nContent-Type: text/html\r\n\r\n" \
|
slen = strtox(outbuf, "HTTP/1.1 400 Bad Request\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n" \
|
||||||
"<!DOCTYPE HTML PUBLIC>\n<title>400 Bad Request</title>\n<h1>Bad Request</h1>\n");
|
"<!DOCTYPE HTML PUBLIC>\n<title>400 Bad Request</title>\n<h1>Bad Request</h1>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void send_to_login(void)
|
void send_to_login(void)
|
||||||
{
|
{
|
||||||
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\n" \
|
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\nConnection: close\r\n" \
|
||||||
"Location: login.html\r\n\r\n");
|
"Location: login.html\r\n\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void send_unauthorized(void)
|
void send_unauthorized(void)
|
||||||
{
|
{
|
||||||
slen = strtox(outbuf, "HTTP/1.1 401 Unauthorized\r\n\r\n");
|
slen = strtox(outbuf, "HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -255,7 +251,7 @@ __xdata uint8_t *skip_boundary(__xdata uint8_t *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
__xdata uint8_t *scan_header(__xdata uint8_t *p)
|
__xdata uint8_t *scan_header(__xdata uint8_t * __xdata p)
|
||||||
{
|
{
|
||||||
content_type = 0;
|
content_type = 0;
|
||||||
session = 0;
|
session = 0;
|
||||||
@@ -267,14 +263,27 @@ __xdata uint8_t *scan_header(__xdata uint8_t *p)
|
|||||||
break;
|
break;
|
||||||
if (is_word(p, "\nContent-Type:"))
|
if (is_word(p, "\nContent-Type:"))
|
||||||
content_type = p + 15;
|
content_type = p + 15;
|
||||||
else if (is_word(p, "\nCookie:"))
|
else if (is_word(p, "\nCookie:")) {
|
||||||
session = p + 17;
|
/* Scan for the "session" key: the header may hold several
|
||||||
|
* cookies in any order. Match "session" not "session=" -
|
||||||
|
* is_word() requires a separator after the match and '=' is
|
||||||
|
* one, so this also rejects a longer key like "sessionx". */
|
||||||
|
__xdata uint8_t *c = p + 8; /* past "\nCookie:" */
|
||||||
|
while (*c && *c != '\r' && *c != '\n') {
|
||||||
|
if (is_word(c, "session")) {
|
||||||
|
session = c + 8; /* past "session=" */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (content_type && is_word(content_type, "multipart/form-data; boundary")) {
|
if (content_type && is_word(content_type, "multipart/form-data; boundary")) {
|
||||||
dbg_string("\nFound multipart\n");
|
dbg_string("\nFound multipart\n");
|
||||||
content_type += 30;
|
content_type += 30;
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
while (content_type[i] != '\r' && content_type[i] != '\n') {
|
while (i < (sizeof(boundary) - 5) &&
|
||||||
|
content_type[i] != '\r' && content_type[i] != '\n') {
|
||||||
boundary[i + 4] = content_type[i];
|
boundary[i + 4] = content_type[i];
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -301,10 +310,12 @@ __xdata uint8_t *scan_header(__xdata uint8_t *p)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void gen_random_bytes(__xdata uint8_t *b, uint8_t bytes)
|
* Generate random HEX-chars at the buffer location.
|
||||||
|
*/
|
||||||
|
void gen_random_hex_chars(__xdata uint8_t * b, __xdata uint8_t bytes)
|
||||||
{
|
{
|
||||||
__xdata uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
while (bytes) {
|
while (bytes) {
|
||||||
if (!i)
|
if (!i)
|
||||||
get_random_32();
|
get_random_32();
|
||||||
@@ -316,6 +327,65 @@ void gen_random_bytes(__xdata uint8_t *b, uint8_t bytes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 0: body incomplete, 1: configuration stored, 2: malformed */
|
||||||
|
static uint8_t config_take(void)
|
||||||
|
{
|
||||||
|
cfg_bl = strlen_x(boundary);
|
||||||
|
|
||||||
|
// the body is complete once the closing boundary has arrived
|
||||||
|
cfg_last = 0;
|
||||||
|
while (1) {
|
||||||
|
if (cfg_last + cfg_bl + 1 >= write_len)
|
||||||
|
return 0;
|
||||||
|
if (strstart_x(&config_buf[cfg_last], boundary)
|
||||||
|
&& strstart(&config_buf[cfg_last + cfg_bl], "--"))
|
||||||
|
break;
|
||||||
|
cfg_last++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// every part lies ahead of the closing boundary, so it bounds the walk
|
||||||
|
cfg_pos = 0;
|
||||||
|
while (cfg_pos < cfg_last) {
|
||||||
|
if (!strstart_x(&config_buf[cfg_pos], boundary)) {
|
||||||
|
cfg_pos++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cfg_hdr = cfg_pos + cfg_bl;
|
||||||
|
cfg_body = cfg_hdr;
|
||||||
|
while (1) {
|
||||||
|
if (cfg_body + 3 >= cfg_last)
|
||||||
|
return 2;
|
||||||
|
if (strstart(&config_buf[cfg_body], "\r\n\r\n"))
|
||||||
|
break;
|
||||||
|
cfg_body++;
|
||||||
|
}
|
||||||
|
cfg_end = cfg_body;
|
||||||
|
cfg_body += 4;
|
||||||
|
// reaching cfg_last is a match: the last part ends at the closing boundary
|
||||||
|
while (cfg_end < cfg_last && !strstart_x(&config_buf[cfg_end], boundary))
|
||||||
|
cfg_end++;
|
||||||
|
while (cfg_hdr + 8 < cfg_body) {
|
||||||
|
// the part carrying a filename holds the configuration
|
||||||
|
if (strstart(&config_buf[cfg_hdr], "filename")) {
|
||||||
|
// the payload plus its terminator must fit the sector
|
||||||
|
if (cfg_end - cfg_body + 1 > CONFIG_LEN)
|
||||||
|
return 2;
|
||||||
|
config_buf[cfg_end] = 0;
|
||||||
|
flash_region.addr = CONFIG_START;
|
||||||
|
flash_sector_erase();
|
||||||
|
flash_region.addr = CONFIG_START;
|
||||||
|
flash_region.len = cfg_end - cfg_body + 1;
|
||||||
|
flash_write_bytes(config_buf + cfg_body);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
cfg_hdr++;
|
||||||
|
}
|
||||||
|
cfg_pos = cfg_end;
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads post data from the http stream and writes it into flash memory
|
* Reads post data from the http stream and writes it into flash memory
|
||||||
* Input: the current position in the TCP buffer (uip_appdata)
|
* Input: the current position in the TCP buffer (uip_appdata)
|
||||||
@@ -419,10 +489,10 @@ void handle_post(void)
|
|||||||
// Find end of request path
|
// Find end of request path
|
||||||
while (*p && !is_separator(*p))
|
while (*p && !is_separator(*p))
|
||||||
p++;
|
p++;
|
||||||
*p++ = '\0';
|
*p++ = NUL;
|
||||||
|
|
||||||
// Find end of request header
|
// Find end of request header
|
||||||
boundary[0] ='\0';
|
boundary[0] =NUL;
|
||||||
p = scan_header(p);
|
p = scan_header(p);
|
||||||
dbg_string("Boundary: >"); dbg_string_x(boundary); dbg_string("<\n");
|
dbg_string("Boundary: >"); dbg_string_x(boundary); dbg_string("<\n");
|
||||||
if (!*p || !content_type) {
|
if (!*p || !content_type) {
|
||||||
@@ -438,6 +508,7 @@ void handle_post(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
print_string("Firmware upload started.");
|
print_string("Firmware upload started.");
|
||||||
|
config_upload = 0;
|
||||||
uptr = FIRMWARE_UPLOAD_START;
|
uptr = FIRMWARE_UPLOAD_START;
|
||||||
verify_crc = 1;
|
verify_crc = 1;
|
||||||
max_upload = 1024576;
|
max_upload = 1024576;
|
||||||
@@ -446,12 +517,10 @@ void handle_post(void)
|
|||||||
send_unauthorized();
|
send_unauthorized();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dbg_string("Configuration upload, erasing config mem!\n");
|
dbg_string("Configuration upload\n");
|
||||||
uptr = CONFIG_START;
|
|
||||||
verify_crc = 0;
|
verify_crc = 0;
|
||||||
max_upload = 2048;
|
config_upload = 1;
|
||||||
flash_region.addr = CONFIG_START;
|
write_len = 0;
|
||||||
flash_sector_erase();
|
|
||||||
}
|
}
|
||||||
// Check for other POST requests, which are not multipart, below
|
// Check for other POST requests, which are not multipart, below
|
||||||
} else {
|
} else {
|
||||||
@@ -482,16 +551,16 @@ void handle_post(void)
|
|||||||
if (is_url_word_x(p, passwd)) {
|
if (is_url_word_x(p, passwd)) {
|
||||||
dbg_string("Password accepted!\n");
|
dbg_string("Password accepted!\n");
|
||||||
read_reg_timer(&last_session_use);
|
read_reg_timer(&last_session_use);
|
||||||
gen_random_bytes(session_id, SESSION_ID_LENGTH);
|
gen_random_hex_chars(session_id, SESSION_ID_LENGTH);
|
||||||
session_id[SESSION_ID_LENGTH] = '\0';
|
session_id[SESSION_ID_LENGTH] = NUL;
|
||||||
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\nLocation: index.html\r\n" \
|
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\nConnection: close\r\nLocation: index.html\r\n" \
|
||||||
"Set-Cookie: session=");
|
"Set-Cookie: session=");
|
||||||
for (register uint8_t i = 0; i < SESSION_ID_LENGTH; i++)
|
for (uint8_t i = 0; i < SESSION_ID_LENGTH; i++)
|
||||||
outbuf[slen++] = session_id[i];
|
outbuf[slen++] = session_id[i];
|
||||||
slen += strtox(outbuf + slen, "; SameSite=Strict\r\n\r\n");
|
slen += strtox(outbuf + slen, "; SameSite=Strict\r\n\r\n");
|
||||||
} else {
|
} else {
|
||||||
dbg_string("Password invalid!\n");
|
dbg_string("Password invalid!\n");
|
||||||
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\nLocation: login.html\r\n\r\n");
|
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\nConnection: close\r\nLocation: login.html\r\n\r\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (s->tstate == TSTATE_MULTIPART || is_word(request_path, "upload") || is_word(request_path, "config")) {
|
} else if (s->tstate == TSTATE_MULTIPART || is_word(request_path, "upload") || is_word(request_path, "config")) {
|
||||||
@@ -505,6 +574,32 @@ void handle_post(void)
|
|||||||
send_bad_request();
|
send_bad_request();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (config_upload) {
|
||||||
|
cfg_pos = uip_len - (p - uip_appdata);
|
||||||
|
if (write_len + cfg_pos >= CONFIG_UPLOAD_BUF) {
|
||||||
|
print_string("Configuration too large, aborting.\n");
|
||||||
|
config_upload = 0;
|
||||||
|
s->tstate = TSTATE_NONE;
|
||||||
|
send_bad_request();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(config_buf + write_len, p, cfg_pos);
|
||||||
|
write_len += cfg_pos;
|
||||||
|
uint8_t taken = config_take();
|
||||||
|
|
||||||
|
if (!taken) {
|
||||||
|
s->tstate = TSTATE_MULTIPART;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
config_upload = 0;
|
||||||
|
s->tstate = TSTATE_NONE;
|
||||||
|
if (taken == 2) {
|
||||||
|
send_bad_request();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
// We skip the intial parts as part of the header
|
// We skip the intial parts as part of the header
|
||||||
do {
|
do {
|
||||||
p = skip_boundary(p);
|
p = skip_boundary(p);
|
||||||
@@ -536,7 +631,7 @@ void handle_post(void)
|
|||||||
send_not_found();
|
send_not_found();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
slen = strtox(outbuf, "HTTP/1.1 200 OK\r\n\r\n");
|
slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n");
|
||||||
return;
|
return;
|
||||||
bad_request:
|
bad_request:
|
||||||
send_bad_request();
|
send_bad_request();
|
||||||
@@ -641,9 +736,9 @@ void httpd_appcall(void)
|
|||||||
p += 4;
|
p += 4;
|
||||||
scan_header(p);
|
scan_header(p);
|
||||||
__xdata uint8_t *q = p;
|
__xdata uint8_t *q = p;
|
||||||
while (!is_separator(*p))
|
while (*p && !is_separator(*p))
|
||||||
p++;
|
p++;
|
||||||
*p = '\0';
|
*p = NUL;
|
||||||
dbg_string_x(q);
|
dbg_string_x(q);
|
||||||
dbg_char('\n');
|
dbg_char('\n');
|
||||||
|
|
||||||
@@ -665,7 +760,9 @@ void httpd_appcall(void)
|
|||||||
parse_short(q + 15);
|
parse_short(q + 15);
|
||||||
send_vlan(short_parsed);
|
send_vlan(short_parsed);
|
||||||
} else if (is_word(q, "/counters.json")) {
|
} else if (is_word(q, "/counters.json")) {
|
||||||
send_counters(q[20]-'0');
|
uint8_t cport = q[20] - '0';
|
||||||
|
if (send_counters(cport))
|
||||||
|
send_bad_request();
|
||||||
} else if (is_word(q, "/eee.json")) {
|
} else if (is_word(q, "/eee.json")) {
|
||||||
send_eee();
|
send_eee();
|
||||||
} else if (is_word(q, "/bandwidth.json")) {
|
} else if (is_word(q, "/bandwidth.json")) {
|
||||||
@@ -714,7 +811,13 @@ void httpd_appcall(void)
|
|||||||
|
|
||||||
slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: ");
|
slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: ");
|
||||||
slen += strtox(outbuf + slen, mime_strings[f_data[entry].mime]);
|
slen += strtox(outbuf + slen, mime_strings[f_data[entry].mime]);
|
||||||
slen += strtox(outbuf + slen, "; charset=UTF-8\r\nCache-Control: max-age=60, must-revalidate\r\nAccess-Control-Allow-Origin: *\r\nContent-Security-Policy: style-src 'self' 'unsafe-inline'\r\n\r\n");
|
/* 'unsafe-inline' is needed for the inline onclick handlers
|
||||||
|
* and the inline <script> on login.html. Connection: close is
|
||||||
|
* required because this httpd closes the connection after every
|
||||||
|
* response; without advertising it a browser reuses the socket
|
||||||
|
* from its keep-alive pool and the next request hits the already
|
||||||
|
* closed connection (a POST is then dropped without a retry). */
|
||||||
|
slen += strtox(outbuf + slen, "; charset=UTF-8\r\nCache-Control: max-age=60, must-revalidate\r\nConnection: close\r\nAccess-Control-Allow-Origin: *\r\nContent-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; form-action 'self'\r\n\r\n");
|
||||||
|
|
||||||
len_left = f_data[entry].len;
|
len_left = f_data[entry].len;
|
||||||
if (len_left > (TCP_OUTBUF_SIZE - slen)) {
|
if (len_left > (TCP_OUTBUF_SIZE - slen)) {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
extern __code const struct machine machine;
|
extern __code const struct machine machine;
|
||||||
extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE];
|
extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE];
|
||||||
extern __xdata uint16_t slen;
|
extern __xdata uint16_t slen;
|
||||||
|
extern __xdata uint16_t management_vlan;
|
||||||
extern __xdata uint16_t cont_len;
|
extern __xdata uint16_t cont_len;
|
||||||
extern __xdata uint32_t cont_addr;
|
extern __xdata uint32_t cont_addr;
|
||||||
extern __code uint8_t * __code hex;
|
extern __code uint8_t * __code hex;
|
||||||
@@ -45,7 +46,7 @@ extern __xdata char sfp_module_model[2][17];
|
|||||||
extern __xdata char sfp_module_serial[2][17];
|
extern __xdata char sfp_module_serial[2][17];
|
||||||
extern __xdata uint8_t sfp_options[2];
|
extern __xdata uint8_t sfp_options[2];
|
||||||
|
|
||||||
__code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
|
__code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n";
|
||||||
__code uint8_t * __code HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
|
__code uint8_t * __code HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
|
||||||
|
|
||||||
// Convert uint8_t to ascii HEX char push on html-buffer.
|
// Convert uint8_t to ascii HEX char push on html-buffer.
|
||||||
@@ -156,14 +157,14 @@ void sfr_data_to_html(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void reg_to_html(register uint16_t reg)
|
void reg_to_html(uint16_t reg)
|
||||||
{
|
{
|
||||||
reg_read_m(reg);
|
reg_read_m(reg);
|
||||||
sfr_data_to_html();
|
sfr_data_to_html();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void reg_to_html_long(register uint16_t reg)
|
void reg_to_html_long(uint16_t reg)
|
||||||
{
|
{
|
||||||
reg_read_m(reg);
|
reg_read_m(reg);
|
||||||
byte_to_html(sfr_data[0]);
|
byte_to_html(sfr_data[0]);
|
||||||
@@ -176,10 +177,12 @@ void reg_to_html_long(register uint16_t reg)
|
|||||||
void send_sfp_info(uint8_t sfp)
|
void send_sfp_info(uint8_t sfp)
|
||||||
{
|
{
|
||||||
// This loops over the Vendor-name, Vendor OUI, Vendor PN and Vendor rev ASCII fields
|
// This loops over the Vendor-name, Vendor OUI, Vendor PN and Vendor rev ASCII fields
|
||||||
for (uint8_t i = 20; i < 60; i++) {
|
for (uint8_t i = 16; i < 64; i++) {
|
||||||
if (i >= 36 && i < 40) // Skip Non-ASCII codes
|
if (!(i & 0xf))
|
||||||
|
sfp_read_block(sfp, i, 16);
|
||||||
|
if (i < 20 || i >= 60 || (i >= 36 && i < 40)) // Skip Non-ASCII codes
|
||||||
continue;
|
continue;
|
||||||
uint8_t c = sfp_read_reg(sfp, i);
|
uint8_t c = sfp_buf[i & 0xf];
|
||||||
if (c && c != 0xa0) // a0 is the byte read from a non-existant I2C EEPROM
|
if (c && c != 0xa0) // a0 is the byte read from a non-existant I2C EEPROM
|
||||||
char_to_html(c);
|
char_to_html(c);
|
||||||
}
|
}
|
||||||
@@ -192,32 +195,10 @@ void sfp_send_data(uint8_t slot, uint8_t reg, uint8_t len)
|
|||||||
if (len > 16)
|
if (len > 16)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (reg & 0x80) { // Configure SFP readings address (0x51) as I2C device address
|
sfp_read_block(slot, reg, len);
|
||||||
reg &= 0x7f;
|
|
||||||
REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16) | (len - 1) & 0xf, 0x51 >> 5, (0x51 << 3) & 0xff);
|
|
||||||
} else {
|
|
||||||
REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16) | (len - 1) & 0xf, 0x50 >> 5, (0x50 << 3) & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_read_m(RTL837X_REG_I2C_CTRL);
|
for (uint8_t i = 0; i < len; i++)
|
||||||
sfr_mask_data(1, 0xfc, i2c_bus_from_scl_pin(machine.sfp_port[slot].i2c.scl) << 5 | i2c_bus_from_sda_pin(machine.sfp_port[slot].i2c.sda) << 2);
|
byte_to_html(sfp_buf[i]);
|
||||||
reg_write_m(RTL837X_REG_I2C_CTRL);
|
|
||||||
|
|
||||||
REG_WRITE(RTL837X_REG_I2C_IN, 0, 0, 0, reg);
|
|
||||||
|
|
||||||
// Execute I2C Read
|
|
||||||
reg_bit_set(RTL837X_REG_I2C_CTRL, 0);
|
|
||||||
|
|
||||||
// Wait for execution to finish
|
|
||||||
do {
|
|
||||||
reg_read_m(RTL837X_REG_I2C_CTRL);
|
|
||||||
} while (sfr_data[3] & 0x1);
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < len; i++) {
|
|
||||||
if (!(i & 0x3))
|
|
||||||
reg_read_m(RTL837X_REG_I2C_OUT + i);
|
|
||||||
byte_to_html(sfr_data[3 - (i & 0x3)]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -252,6 +233,12 @@ void send_basic_info(void)
|
|||||||
byte_to_html(uip_ethaddr.addr[3]); char_to_html(':');
|
byte_to_html(uip_ethaddr.addr[3]); char_to_html(':');
|
||||||
byte_to_html(uip_ethaddr.addr[4]); char_to_html(':');
|
byte_to_html(uip_ethaddr.addr[4]); char_to_html(':');
|
||||||
byte_to_html(uip_ethaddr.addr[5]);
|
byte_to_html(uip_ethaddr.addr[5]);
|
||||||
|
slen += strtox(outbuf + slen, "\",\"hostname\":\"");
|
||||||
|
{
|
||||||
|
__xdata char *hp = hostname; /* sanitized on ingest, emit verbatim */
|
||||||
|
while (*hp)
|
||||||
|
char_to_html(*hp++);
|
||||||
|
}
|
||||||
slen += strtox(outbuf + slen, "\",\"sw_ver\":\"");
|
slen += strtox(outbuf + slen, "\",\"sw_ver\":\"");
|
||||||
slen += strtox(outbuf + slen, VERSION_SW);
|
slen += strtox(outbuf + slen, VERSION_SW);
|
||||||
slen += strtox(outbuf + slen, "\",\"build_date\":\"");
|
slen += strtox(outbuf + slen, "\",\"build_date\":\"");
|
||||||
@@ -302,17 +289,26 @@ void send_vlan(uint16_t vlan)
|
|||||||
slen += strtox(outbuf + slen, "\"}");
|
slen += strtox(outbuf + slen, "\"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Send counters
|
||||||
void send_counters(char port)
|
* Only accepts physical port 1..9.
|
||||||
|
* Returns an error if the port physical don't exists.
|
||||||
|
*/
|
||||||
|
bool send_counters(uint8_t phys_port)
|
||||||
{
|
{
|
||||||
dbg_string("send_counters called: "); dbg_byte(port); dbg_char('\n');
|
uint8_t phys_port_idx = phys_port - 1;
|
||||||
|
if (phys_port_idx > 8)
|
||||||
|
goto err;
|
||||||
|
uint8_t log_port = machine.phys_to_log_port[phys_port_idx];
|
||||||
|
if (log_port == 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
dbg_string("send_counters called: "); dbg_byte(phys_port_idx); dbg_char('\n');
|
||||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||||
dbg_string("sending counters\n");
|
dbg_string("sending counters\n"); dbg_byte(phys_port_idx);
|
||||||
dbg_byte(port);
|
|
||||||
uint8_t i = machine.phys_to_log_port[port];
|
char_to_html('[');
|
||||||
slen += strtox(outbuf + slen, "[");
|
|
||||||
for (uint8_t counter = 0; counter < 0x37; counter++) {
|
for (uint8_t counter = 0; counter < 0x37; counter++) {
|
||||||
STAT_GET(counter, i);
|
STAT_GET(counter, log_port);
|
||||||
slen += strtox(outbuf + slen, "\"0x");
|
slen += strtox(outbuf + slen, "\"0x");
|
||||||
reg_to_html(RTL837X_STAT_V_HIGH);
|
reg_to_html(RTL837X_STAT_V_HIGH);
|
||||||
reg_to_html_long(RTL837X_STAT_V_LOW);
|
reg_to_html_long(RTL837X_STAT_V_LOW);
|
||||||
@@ -321,6 +317,12 @@ void send_counters(char port)
|
|||||||
char_to_html(',');
|
char_to_html(',');
|
||||||
}
|
}
|
||||||
char_to_html(']');
|
char_to_html(']');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
err:
|
||||||
|
dbg_string("Error: counters: phy_port_idx don't exists\n");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -349,6 +351,7 @@ void send_l2(uint16_t idx)
|
|||||||
*/
|
*/
|
||||||
__xdata uint16_t entry = idx & 0xfff;
|
__xdata uint16_t entry = idx & 0xfff;
|
||||||
__xdata uint16_t first_entry = 0xffff; // An illegal entry index
|
__xdata uint16_t first_entry = 0xffff; // An illegal entry index
|
||||||
|
__bit first = true;
|
||||||
char_to_html('[');
|
char_to_html('[');
|
||||||
while (1) {
|
while (1) {
|
||||||
entries_left--;
|
entries_left--;
|
||||||
@@ -362,9 +365,22 @@ void send_l2(uint16_t idx)
|
|||||||
} while (sfr_data[3] & TBL_EXECUTE);
|
} while (sfr_data[3] & TBL_EXECUTE);
|
||||||
|
|
||||||
reg_read_m(RTL837x_L2_DATA_OUT_B);
|
reg_read_m(RTL837x_L2_DATA_OUT_B);
|
||||||
if ((sfr_data[0] & 0x20)) { // Check entry is valid
|
__bit valid = (sfr_data[0] & 0x20) != 0;
|
||||||
|
if (valid) {
|
||||||
|
/* separator + 74-byte worst-case entry + closing "]" */
|
||||||
|
if (slen + 76 > TCP_OUTBUF_SIZE)
|
||||||
|
break;
|
||||||
|
if (!first)
|
||||||
|
char_to_html(',');
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
// VLAN, taken from the read above instead of reading the register twice
|
||||||
|
slen += strtox(outbuf + slen, "{\"vlan\":\"");
|
||||||
|
charhex_to_html(sfr_data[0] & 0x0f);
|
||||||
|
byte_to_html(sfr_data[1]);
|
||||||
|
|
||||||
// MAC
|
// MAC
|
||||||
slen += strtox(outbuf + slen, "{\"mac\":\"");
|
slen += strtox(outbuf + slen, "\",\"mac\":\"");
|
||||||
byte_to_html(sfr_data[2]); char_to_html(':');
|
byte_to_html(sfr_data[2]); char_to_html(':');
|
||||||
byte_to_html(sfr_data[3]); char_to_html(':');
|
byte_to_html(sfr_data[3]); char_to_html(':');
|
||||||
port = (sfr_data[0] >> 6) & 0x3;
|
port = (sfr_data[0] >> 6) & 0x3;
|
||||||
@@ -374,47 +390,35 @@ void send_l2(uint16_t idx)
|
|||||||
byte_to_html(sfr_data[2]); char_to_html(':');
|
byte_to_html(sfr_data[2]); char_to_html(':');
|
||||||
byte_to_html(sfr_data[3]);
|
byte_to_html(sfr_data[3]);
|
||||||
|
|
||||||
// VLAN
|
|
||||||
slen += strtox(outbuf + slen, "\",\"vlan\":\"");
|
|
||||||
reg_read_m(RTL837x_L2_DATA_OUT_B);
|
|
||||||
charhex_to_html(sfr_data[0] & 0x0f);
|
|
||||||
byte_to_html(sfr_data[1]);
|
|
||||||
|
|
||||||
// type
|
// type
|
||||||
reg_read_m(RTL837x_L2_DATA_OUT_C);
|
reg_read_m(RTL837x_L2_DATA_OUT_C);
|
||||||
if (sfr_data[2] & 0x1)
|
if (sfr_data[1] & 0x1)
|
||||||
slen += strtox(outbuf + slen, "\",\"type\":\"s\",\"port\":");
|
slen += strtox(outbuf + slen, "\",\"type\":\"s\",\"port\":");
|
||||||
else
|
else
|
||||||
slen += strtox(outbuf + slen, "\",\"type\":\"l\",\"port\":");
|
slen += strtox(outbuf + slen, "\",\"type\":\"l\",\"port\":");
|
||||||
|
|
||||||
port |= (sfr_data[3] & 0x3) << 2;
|
port |= (sfr_data[3] & 0x3) << 2;
|
||||||
itoa_html(port);
|
itoa_html(port);
|
||||||
|
}
|
||||||
|
|
||||||
// Index
|
// Index
|
||||||
reg_read_m(RTL837x_TBL_DATA_0);
|
reg_read_m(RTL837x_TBL_DATA_0);
|
||||||
entry = (((uint16_t)sfr_data[2] & 0x0f) << 8) | sfr_data[3];
|
entry = (((uint16_t)sfr_data[2] & 0x0f) << 8) | sfr_data[3];
|
||||||
|
if (valid) {
|
||||||
slen += strtox(outbuf + slen, ",\"idx\":\"");
|
slen += strtox(outbuf + slen, ",\"idx\":\"");
|
||||||
byte_to_html(entry >> 8);
|
byte_to_html(entry >> 8);
|
||||||
byte_to_html(entry);
|
byte_to_html(entry);
|
||||||
char_to_html('"');
|
char_to_html('"');
|
||||||
char_to_html('}');
|
char_to_html('}');
|
||||||
entry += 1; // We want the next entry following after the current entry
|
|
||||||
} else {
|
|
||||||
reg_read_m(RTL837x_TBL_DATA_0);
|
|
||||||
entry = (((uint16_t)sfr_data[2] & 0x0f) << 8) | sfr_data[3] + 1;
|
|
||||||
}
|
}
|
||||||
if (first_entry == 0xffff) {
|
entry += 1; // We want the next entry following after the current entry
|
||||||
char_to_html(',');
|
|
||||||
|
if (first_entry == 0xffff)
|
||||||
first_entry = entry;
|
first_entry = entry;
|
||||||
} else {
|
else if (first_entry == entry || !entries_left)
|
||||||
if (first_entry == entry || !entries_left) {
|
break;
|
||||||
char_to_html(']');
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
char_to_html(',');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
char_to_html(']');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -511,8 +515,7 @@ void send_lag(void)
|
|||||||
slen += strtox(outbuf + slen, "{\"lagNum\":");
|
slen += strtox(outbuf + slen, "{\"lagNum\":");
|
||||||
itoa_html(l);
|
itoa_html(l);
|
||||||
slen += strtox(outbuf + slen, ",\"members\":\"");
|
slen += strtox(outbuf + slen, ",\"members\":\"");
|
||||||
reg_read_m(RTL837X_TRK_MBR_CTRL_BASE + (l << 2));
|
uint16_t ports = port_lag_members_get(l);
|
||||||
uint16_t ports = ((uint16_t)sfr_data[2] << 8) | sfr_data[3];
|
|
||||||
for (uint8_t i = 0; i < 16; i++) {
|
for (uint8_t i = 0; i < 16; i++) {
|
||||||
bool_to_html(!!(ports & 0x8000));
|
bool_to_html(!!(ports & 0x8000));
|
||||||
ports <<= 1;
|
ports <<= 1;
|
||||||
@@ -660,52 +663,53 @@ void send_status(void)
|
|||||||
slen += strtox(outbuf + slen, "\"");
|
slen += strtox(outbuf + slen, "\"");
|
||||||
|
|
||||||
if (machine.is_sfp[i]) {
|
if (machine.is_sfp[i]) {
|
||||||
|
uint8_t sfp = machine.is_sfp[i] - 1;
|
||||||
slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":");
|
slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":");
|
||||||
if (!(sfp_pins_last & (0x1 << ((machine.is_sfp[i] - 1) << 2)))) {
|
if (!(sfp_pins_last & (0x1 << (sfp << 2)))) {
|
||||||
bool_to_html(1);
|
bool_to_html(1);
|
||||||
slen += strtox(outbuf + slen,",\"sfp_options\":\"0x");
|
slen += strtox(outbuf + slen,",\"sfp_options\":\"0x");
|
||||||
byte_to_html(sfp_options[machine.is_sfp[i]-1]);
|
byte_to_html(sfp_options[sfp]);
|
||||||
if (sfp_options[machine.is_sfp[i]-1] & 0x40) {
|
if (sfp_options[sfp] & 0x40) {
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_temp\":\"0x");
|
slen += strtox(outbuf + slen,"\",\"sfp_temp\":\"0x");
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 224, 2);
|
sfp_send_data(sfp, 224, 2);
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_vcc\":\"0x");
|
slen += strtox(outbuf + slen,"\",\"sfp_vcc\":\"0x");
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 226, 2);
|
sfp_send_data(sfp, 226, 2);
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_txbias\":\"0x");
|
slen += strtox(outbuf + slen,"\",\"sfp_txbias\":\"0x");
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 228, 2);
|
sfp_send_data(sfp, 228, 2);
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_txpower\":\"0x");
|
slen += strtox(outbuf + slen,"\",\"sfp_txpower\":\"0x");
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 230, 2);
|
sfp_send_data(sfp, 230, 2);
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_rxpower\":\"0x");
|
slen += strtox(outbuf + slen,"\",\"sfp_rxpower\":\"0x");
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 232, 2);
|
sfp_send_data(sfp, 232, 2);
|
||||||
if (sfp_options[machine.is_sfp[i]-1] & 0x10) {
|
if (sfp_options[sfp] & 0x10) {
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_temp_cal\":\"0x");
|
slen += strtox(outbuf + slen,"\",\"sfp_temp_cal\":\"0x");
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 212, 4);
|
sfp_send_data(sfp, 212, 4);
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_vcc_cal\":\"0x");
|
slen += strtox(outbuf + slen,"\",\"sfp_vcc_cal\":\"0x");
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 216, 4);
|
sfp_send_data(sfp, 216, 4);
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_txbias_cal\":\"0x");
|
slen += strtox(outbuf + slen,"\",\"sfp_txbias_cal\":\"0x");
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 204, 4);
|
sfp_send_data(sfp, 204, 4);
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_txpower_cal\":\"0x");
|
slen += strtox(outbuf + slen,"\",\"sfp_txpower_cal\":\"0x");
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 208, 4);
|
sfp_send_data(sfp, 208, 4);
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_rxpower_cal\":\"0x");
|
slen += strtox(outbuf + slen,"\",\"sfp_rxpower_cal\":\"0x");
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 184, 16);
|
sfp_send_data(sfp, 184, 16);
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 200, 4);
|
sfp_send_data(sfp, 200, 4);
|
||||||
}
|
}
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_state\":\"0x");
|
slen += strtox(outbuf + slen,"\",\"sfp_state\":\"0x");
|
||||||
sfp_send_data(machine.is_sfp[i] - 1, 238, 1);
|
sfp_send_data(sfp, 238, 1);
|
||||||
}
|
}
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_vendor\":\"");
|
slen += strtox(outbuf + slen,"\",\"sfp_vendor\":\"");
|
||||||
for (register uint8_t s = 0; s < 16; s++)
|
for (uint8_t s = 0; s < 16 && sfp_module_vendor[sfp][s]; s++)
|
||||||
outbuf[slen++] = sfp_module_vendor[machine.is_sfp[i]-1][s];
|
outbuf[slen++] = sfp_module_vendor[sfp][s];
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_model\":\"");
|
slen += strtox(outbuf + slen,"\",\"sfp_model\":\"");
|
||||||
for (register uint8_t s = 0; s < 16; s++)
|
for (uint8_t s = 0; s < 16 && sfp_module_model[sfp][s]; s++)
|
||||||
outbuf[slen++] = sfp_module_model[machine.is_sfp[i]-1][s];
|
outbuf[slen++] = sfp_module_model[sfp][s];
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_serial\":\"");
|
slen += strtox(outbuf + slen,"\",\"sfp_serial\":\"");
|
||||||
for (register uint8_t s = 0; s < 16; s++)
|
for (uint8_t s = 0; s < 16 && sfp_module_serial[sfp][s]; s++)
|
||||||
outbuf[slen++] = sfp_module_serial[machine.is_sfp[i]-1][s];
|
outbuf[slen++] = sfp_module_serial[sfp][s];
|
||||||
slen += strtox(outbuf + slen,"\",\"sfp_los\":");
|
slen += strtox(outbuf + slen,"\",\"sfp_los\":");
|
||||||
if (machine.sfp_port[machine.is_sfp[i]-1].pin_los == GPIO_NA) {
|
if (machine.sfp_port[sfp].pin_los == GPIO_NA) {
|
||||||
slen += strtox(outbuf + slen,"null");
|
slen += strtox(outbuf + slen,"null");
|
||||||
} else {
|
} else {
|
||||||
bool_to_html(sfp_pins_last & (0x2 << (((machine.is_sfp[i]-1) << 2))));
|
bool_to_html(sfp_pins_last & (0x2 << (sfp << 2)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bool_to_html(0);
|
bool_to_html(0);
|
||||||
@@ -813,7 +817,7 @@ found_end:
|
|||||||
if (valid_len > (TCP_OUTBUF_SIZE - slen)) {
|
if (valid_len > (TCP_OUTBUF_SIZE - slen)) {
|
||||||
cont_len = valid_len - (TCP_OUTBUF_SIZE - slen);
|
cont_len = valid_len - (TCP_OUTBUF_SIZE - slen);
|
||||||
valid_len = TCP_OUTBUF_SIZE - slen;
|
valid_len = TCP_OUTBUF_SIZE - slen;
|
||||||
cont_addr = valid_len;
|
cont_addr = CONFIG_START + valid_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
flash_region.addr = CONFIG_START;
|
flash_region.addr = CONFIG_START;
|
||||||
@@ -850,7 +854,9 @@ void send_vlanlist(void)
|
|||||||
uint8_t first = 1;
|
uint8_t first = 1;
|
||||||
|
|
||||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||||
char_to_html('[');
|
slen += strtox(outbuf + slen, "{\"mgmt\":");
|
||||||
|
itoa16_html(management_vlan);
|
||||||
|
slen += strtox(outbuf + slen, ",\"vlan\":[");
|
||||||
|
|
||||||
for (i = 1; i < 4095; i++) {
|
for (i = 1; i < 4095; i++) {
|
||||||
if (vlan_get(i) < 0)
|
if (vlan_get(i) < 0)
|
||||||
@@ -858,7 +864,7 @@ void send_vlanlist(void)
|
|||||||
if (!(sfr_data[0] & 0x02)) /* bit 1: VLAN table entry valid */
|
if (!(sfr_data[0] & 0x02)) /* bit 1: VLAN table entry valid */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (slen + 139 > TCP_OUTBUF_SIZE) /* 138 bytes worst-case entry + 1 byte for closing ']' */
|
if (slen + 141 > TCP_OUTBUF_SIZE) /* comma + 138-byte worst-case entry + closing "]}" */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!first)
|
if (!first)
|
||||||
@@ -880,4 +886,5 @@ void send_vlanlist(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char_to_html(']');
|
char_to_html(']');
|
||||||
|
char_to_html('}');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#ifndef __PAGE_IMPL_H__
|
#ifndef __PAGE_IMPL_H__
|
||||||
#define __PAGE_IMPL_H__
|
#define __PAGE_IMPL_H__
|
||||||
|
|
||||||
void send_counters(char port);
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
bool send_counters(uint8_t phys_port);
|
||||||
void send_status(void);
|
void send_status(void);
|
||||||
void send_vlan(uint16_t vlan);
|
void send_vlan(uint16_t vlan);
|
||||||
void send_basic_info(void);
|
void send_basic_info(void);
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ uint8_t flash_read_status(void)
|
|||||||
* Reads bulk data of length len from the flash memory starging at address src
|
* Reads bulk data of length len from the flash memory starging at address src
|
||||||
* and writes the data into a buffer pointed to by dst in XMEM
|
* and writes the data into a buffer pointed to by dst in XMEM
|
||||||
*/
|
*/
|
||||||
void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, register uint16_t len)
|
void flash_read_bulk(__xdata uint8_t *dst, __xdata uint32_t src, uint16_t len)
|
||||||
{
|
{
|
||||||
short status;
|
short status;
|
||||||
do {
|
do {
|
||||||
|
|||||||
@@ -5,9 +5,23 @@
|
|||||||
#include "rtl837x_regs.h"
|
#include "rtl837x_regs.h"
|
||||||
#include "rtl837x_common.h"
|
#include "rtl837x_common.h"
|
||||||
|
|
||||||
#ifdef MACHINE_KP_9000_6XHML_X2
|
#if defined(MACHINE_KP_9000_6XHML_X2) || \
|
||||||
|
defined(MACHINE_KP_9000_6XH_X2_V1_1) || \
|
||||||
|
defined(MACHINE_KP_9000_6XHML_X2_V1_1) || \
|
||||||
|
defined(MACHINE_KP_9000_6XH_X2_V1_2) || \
|
||||||
|
defined(MACHINE_KP_9000_6XHML_X2_V1_2)
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
|
#if defined(MACHINE_KP_9000_6XH_X2_V1_1)
|
||||||
|
.machine_name = "keepLink KP-9000-6XH V1.1",
|
||||||
|
#elif defined(MACHINE_KP_9000_6XHML_X2_V1_1)
|
||||||
|
.machine_name = "keepLink KP-9000-6XHML V1.1",
|
||||||
|
#elif defined(MACHINE_KP_9000_6XH_X2_V1_2)
|
||||||
|
.machine_name = "keepLink KP-9000-6XH V1.2",
|
||||||
|
#elif defined(MACHINE_KP_9000_6XHML_X2_V1_2)
|
||||||
|
.machine_name = "keepLink KP-9000-6XHML V1.2",
|
||||||
|
#else
|
||||||
.machine_name = "keepLink KP-9000-6XHML-X2",
|
.machine_name = "keepLink KP-9000-6XHML-X2",
|
||||||
|
#endif
|
||||||
.isRTL8373 = 0,
|
.isRTL8373 = 0,
|
||||||
.min_port = 3,
|
.min_port = 3,
|
||||||
.max_port = 8,
|
.max_port = 8,
|
||||||
@@ -42,8 +56,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_KP_9000_6XH_X
|
#elif defined MACHINE_KP_9000_6XH_X
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "keepLink KP-9000-6XH-X",
|
.machine_name = "keepLink KP-9000-6XH-X",
|
||||||
@@ -72,11 +84,15 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
#elif defined(MACHINE_KP_9000_6XH_X2) || defined(MACHINE_KP_9000_6XH_X2_V2_1) || defined(MACHINE_KP_9000_6XHML_X2_V2_1)
|
||||||
|
|
||||||
#elif defined MACHINE_KP_9000_6XH_X2
|
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
|
#if defined(MACHINE_KP_9000_6XHML_X2_V2_1)
|
||||||
|
.machine_name = "keepLink KP-9000-6XHML V2.1",
|
||||||
|
#elif defined(MACHINE_KP_9000_6XH_X2_V2_1)
|
||||||
|
.machine_name = "keepLink KP-9000-6XH-X2 V2.1",
|
||||||
|
#else
|
||||||
.machine_name = "keepLink KP-9000-6XH-X2",
|
.machine_name = "keepLink KP-9000-6XH-X2",
|
||||||
|
#endif
|
||||||
.isRTL8373 = 0,
|
.isRTL8373 = 0,
|
||||||
.min_port = 3,
|
.min_port = 3,
|
||||||
.max_port = 8,
|
.max_port = 8,
|
||||||
@@ -122,10 +138,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) {
|
|
||||||
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined MACHINE_KP_9000_9XH_X_EU
|
#elif defined MACHINE_KP_9000_9XH_X_EU
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "keepLink KP-9000-9XH-X-EU",
|
.machine_name = "keepLink KP-9000-9XH-X-EU",
|
||||||
@@ -151,8 +163,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_KP_9000_9XHML_X_V2_2
|
#elif defined MACHINE_KP_9000_9XHML_X_V2_2
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "keepLink KP-9000-9XHML-X V2.2",
|
.machine_name = "keepLink KP-9000-9XHML-X V2.2",
|
||||||
@@ -204,8 +214,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_KP_9000_9XHML_X_V3_1
|
#elif defined MACHINE_KP_9000_9XHML_X_V3_1
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "keepLink KP-9000-9XHML-X V3.1",
|
.machine_name = "keepLink KP-9000-9XHML-X V3.1",
|
||||||
@@ -241,8 +249,6 @@ __code const struct machine machine = {
|
|||||||
0x1a, 0x19, 0x1d, 0x1e, 0x1c, 0x1d, 0x20, 0x21},
|
0x1a, 0x19, 0x1d, 0x1e, 0x1c, 0x1d, 0x20, 0x21},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_SWGT024_V2_0_MANAGED
|
#elif defined MACHINE_SWGT024_V2_0_MANAGED
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "SWGT024 V2.0 Managed",
|
.machine_name = "SWGT024 V2.0 Managed",
|
||||||
@@ -284,8 +290,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_SWGT024_V2_0_UNMANAGED
|
#elif defined MACHINE_SWGT024_V2_0_UNMANAGED
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "SWGT024 V2.0 Unmanaged",
|
.machine_name = "SWGT024 V2.0 Unmanaged",
|
||||||
@@ -327,8 +331,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_SWTG018AS_A_V_2_0
|
#elif defined MACHINE_SWTG018AS_A_V_2_0
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "SWTG018AS-A V2.0",
|
.machine_name = "SWTG018AS-A V2.0",
|
||||||
@@ -344,7 +346,7 @@ __code const struct machine machine = {
|
|||||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||||
.sfp_port[0].sds = 1,
|
.sfp_port[0].sds = 1,
|
||||||
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
.reset_pin = GPIO_NA,
|
.reset_pin = GPIO48_I2C_SCL1,
|
||||||
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
|
.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},
|
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
.led_sets = {
|
.led_sets = {
|
||||||
@@ -368,8 +370,6 @@ __code const struct machine machine = {
|
|||||||
0x1d, 0x20, 0x21 },
|
0x1d, 0x20, 0x21 },
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_HG0402XG_V1_1
|
#elif defined MACHINE_HG0402XG_V1_1
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "HG0402XG V1.1",
|
.machine_name = "HG0402XG V1.1",
|
||||||
@@ -408,13 +408,12 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_SWTGW218AS
|
#elif defined MACHINE_SWTGW218AS
|
||||||
|
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "SWTGW218AS 8+1 Managed Switch",
|
.machine_name = "SWTGW218AS 8+1 Managed Switch",
|
||||||
.isRTL8373 = 1,
|
.isRTL8373 = 1,
|
||||||
|
.mac_flash_offset = 0x1FC000,
|
||||||
.min_port = 0,
|
.min_port = 0,
|
||||||
.max_port = 8,
|
.max_port = 8,
|
||||||
.n_sfp = 1,
|
.n_sfp = 1,
|
||||||
@@ -442,7 +441,48 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
#elif defined MACHINE_PCB_SWTG018AS_V2_1_0 // Sold as Sodola SL902 / Horaco "SWTGW218AS"; the SWTGW218AS label also covers other PCBs with different SFP and LED wiring (see MACHINE_SWTGW218AS)
|
||||||
|
|
||||||
|
__code const struct machine machine = {
|
||||||
|
.machine_name = "SWTGW218AS (SWTG018AS-V2.1.0)",
|
||||||
|
.isRTL8373 = 1,
|
||||||
|
.mac_flash_offset = 0x1FC000,
|
||||||
|
.min_port = 0,
|
||||||
|
.max_port = 8,
|
||||||
|
.n_sfp = 1,
|
||||||
|
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||||
|
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
|
||||||
|
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
.sfp_port[0].pin_detect = GPIO38, // pulled low on module insert
|
||||||
|
.sfp_port[0].pin_los = GPIO_NA, // no LOS pin wired
|
||||||
|
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||||
|
.sfp_port[0].sds = 1,
|
||||||
|
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
|
.reset_pin = GPIO54_ACL_BIT2_EN,
|
||||||
|
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
|
||||||
|
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
// LED wiring matches the SWTG018AS-A V2.0 (same PCB family)
|
||||||
|
.led_sets = {
|
||||||
|
{ /* RJ45: First LED, yellow, second LED: green */
|
||||||
|
LEDS_2G5 | LEDS_LINK,
|
||||||
|
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
}, { /* SFP set (superseded by the raw register override in machine_custom_init) */
|
||||||
|
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
}},
|
||||||
|
.led_mux_custom = 1,
|
||||||
|
.led_mux = { 0x00, 0x01, 0x04, 0x05, 0x08, // 65e0
|
||||||
|
0x09, 0x0c, 0x09, 0x0d, 0x10, // 65e4
|
||||||
|
0x11, 0x0e, 0x14, 0x11, 0x12, // 65e8
|
||||||
|
0x15, 0x15, 0x16, 0x18, 0x19, // 65ec
|
||||||
|
0x1a, 0x19, 0x1d, 0x1e, 0x1c, // 65f0
|
||||||
|
0x1d, 0x20, 0x21 },
|
||||||
|
};
|
||||||
|
|
||||||
#elif defined MACHINE_LIANGUO_ZX_SWTGW215AS // Has PCB branded PCB-SWTG115AS-V2.0 but is labeled and reports as a ZX-SWTGW215AS, seems to be identical to the "real" ZX-SWTGW215AS except for the LEDs
|
#elif defined MACHINE_LIANGUO_ZX_SWTGW215AS // Has PCB branded PCB-SWTG115AS-V2.0 but is labeled and reports as a ZX-SWTGW215AS, seems to be identical to the "real" ZX-SWTGW215AS except for the LEDs
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "Lianguo ZX-SWTGW215AS",
|
.machine_name = "Lianguo ZX-SWTGW215AS",
|
||||||
@@ -475,8 +515,6 @@ __code const struct machine machine = {
|
|||||||
.led_mux_custom = 0,
|
.led_mux_custom = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_DEFAULT_8C_1SFP
|
#elif defined MACHINE_DEFAULT_8C_1SFP
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "8+1 SFP Port Switch",
|
.machine_name = "8+1 SFP Port Switch",
|
||||||
@@ -502,8 +540,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_TRENDNET_TEG_S562
|
#elif defined MACHINE_TRENDNET_TEG_S562
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "Trendnet TEG-S562",
|
.machine_name = "Trendnet TEG-S562",
|
||||||
@@ -543,8 +579,6 @@ __code const struct machine machine = {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined(MACHINE_PCB_K0402WS_V3) || defined(MACHINE_HI_K0402WS) // Sold as a variety of devices, see doc/
|
#elif defined(MACHINE_PCB_K0402WS_V3) || defined(MACHINE_HI_K0402WS) // Sold as a variety of devices, see doc/
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "PCB-K0402WS-V3.0",
|
.machine_name = "PCB-K0402WS-V3.0",
|
||||||
@@ -591,10 +625,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) {
|
|
||||||
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined MACHINE_K0501W_V2_0
|
#elif defined MACHINE_K0501W_V2_0
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "K0501W V2.0",
|
.machine_name = "K0501W V2.0",
|
||||||
@@ -629,8 +659,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_ZX310S_4T2XH
|
#elif defined MACHINE_ZX310S_4T2XH
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "ZX310S-4T2XH",
|
.machine_name = "ZX310S-4T2XH",
|
||||||
@@ -674,8 +702,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_STEAMEMO_IG204_V1
|
#elif defined MACHINE_STEAMEMO_IG204_V1
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "Steamemo IG204 V1",
|
.machine_name = "Steamemo IG204 V1",
|
||||||
@@ -726,8 +752,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_HI_K0801WS
|
#elif defined MACHINE_HI_K0801WS
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "Hi-Source HI-k0801WS",
|
.machine_name = "Hi-Source HI-k0801WS",
|
||||||
@@ -777,8 +801,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) { }
|
|
||||||
|
|
||||||
#elif defined MACHINE_FNS1200P
|
#elif defined MACHINE_FNS1200P
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "FNS-1200P",
|
.machine_name = "FNS-1200P",
|
||||||
@@ -834,11 +856,6 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void)
|
|
||||||
{
|
|
||||||
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#elif defined MACHINE_PCB_SWTG024AS_A_2_0_1
|
#elif defined MACHINE_PCB_SWTG024AS_A_2_0_1
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
@@ -888,13 +905,91 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void)
|
#elif defined MACHINE_SWTG024AS_A_2_0_1_5C_1SFP
|
||||||
{
|
__code const struct machine machine = {
|
||||||
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
.machine_name = "SWTG024AS-A-V2.0.1-5C-1SFP",
|
||||||
reg_bit_set(RTL837X_REG_LED_MODE, 17);
|
.isRTL8373 = 0,
|
||||||
reg_bit_clear(RTL837X_REG_LED_MODE, 9);
|
.min_port = 3,
|
||||||
reg_bit_clear(RTL837X_REG_LED_MODE, 7);
|
.max_port = 8,
|
||||||
}
|
.n_sfp = 1,
|
||||||
|
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
|
||||||
|
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
|
||||||
|
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
.sfp_port[0].pin_detect = GPIO38,
|
||||||
|
.sfp_port[0].pin_los = GPIO_NA,
|
||||||
|
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||||
|
.sfp_port[0].sds = 1,
|
||||||
|
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
|
|
||||||
|
.reset_pin = GPIO_NA,
|
||||||
|
.high_leds = { .mux = LED_28_SYS | LED_29, .enable = LED_27 | LED_28_SYS | LED_29 },
|
||||||
|
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
/* Ports 1-5 RJ45 use set 0, port 9 SFP uses set 1
|
||||||
|
* Ports 1-5: Green: 2.5GBit, Amber: 10/100/1000MBit
|
||||||
|
* SFP-port: Blue: 10GBit, Green: 100MBit-2.5GBit
|
||||||
|
*/
|
||||||
|
.led_sets = {
|
||||||
|
{
|
||||||
|
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_DUPLEX,
|
||||||
|
LEDS_2G5 | LEDS_LINK | LEDS_ACT
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_10G | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_2G5 | LEDS_LINK,
|
||||||
|
LEDS_COL | LEDS_DUPLEX
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.led_mux_custom = 1,
|
||||||
|
.led_mux = {
|
||||||
|
0x00,0x01,0x04,0x05,0x08,0x09,0x0c,0x3f,0x0d,0x10,0x11,0x0e,0x14,0x11,0x12,0x15,0x15,0x16,0x18,0x19,0x1a,0x19,0x1d,0x1e,0x1c,0x1d,0x20,0x21
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif defined MACHINE_SWTG024AS_V2_0
|
||||||
|
__code const struct machine machine = {
|
||||||
|
.machine_name = "SWTG024AS-V2.0",
|
||||||
|
.isRTL8373 = 0,
|
||||||
|
.min_port = 3,
|
||||||
|
.max_port = 8,
|
||||||
|
.n_sfp = 1,
|
||||||
|
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
|
||||||
|
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
|
||||||
|
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
|
||||||
|
.sfp_port[0].pin_los = GPIO37,
|
||||||
|
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||||
|
.sfp_port[0].sds = 1,
|
||||||
|
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
|
|
||||||
|
.reset_pin = GPIO_NA,
|
||||||
|
.high_leds = { .mux = LED_28_SYS | LED_29, .enable = LED_27 | LED_28_SYS | LED_29 },
|
||||||
|
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
/* Ports 1-5 RJ45 use set 0, port 9 SFP uses set 1
|
||||||
|
* Ports 1-5: Green: 2.5GBit, Amber: 10/100/1000MBit
|
||||||
|
* SFP-port: Blue: 10GBit, Amber: 100MBit-2.5GBit
|
||||||
|
*/
|
||||||
|
.led_sets = {
|
||||||
|
{
|
||||||
|
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_DUPLEX,
|
||||||
|
LEDS_2G5 | LEDS_LINK | LEDS_ACT
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_10G | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_2G5 | LEDS_LINK,
|
||||||
|
LEDS_COL | LEDS_DUPLEX
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.led_mux_custom = 1,
|
||||||
|
.led_mux = {
|
||||||
|
0x00,0x01,0x04,0x05,0x08,0x09,0x0c,0x3f,0x0d,0x10,0x11,0x0e,0x14,0x11,0x12,0x15,0x15,0x16,0x18,0x19,0x1a,0x19,0x1d,0x1e,0x1c,0x1d,0x20,0x21
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
#elif defined MACHINE_ZX310S_4T2XT
|
#elif defined MACHINE_ZX310S_4T2XT
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
@@ -933,11 +1028,71 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void) {
|
#elif defined MACHINE_FG_4GT_2SX_V2_0
|
||||||
// For this device, the reset value of RTL837X_PIN_MUX_0 is 0x30000000,
|
__code const struct machine machine = {
|
||||||
// which would disables all LEDS, enable them manually:
|
.machine_name = "FG-4GT-2SX_V2.0",
|
||||||
REG_SET(RTL837X_PIN_MUX_0, 0x30db68bf);
|
.isRTL8373 = 0,
|
||||||
}
|
.min_port = 3,
|
||||||
|
.max_port = 8,
|
||||||
|
.n_sfp = 2,
|
||||||
|
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
|
||||||
|
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
|
||||||
|
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
|
||||||
|
|
||||||
|
// Left SFP port
|
||||||
|
.sfp_port[0].pin_detect = GPIO38,
|
||||||
|
.sfp_port[0].pin_los = GPIO_NA,
|
||||||
|
.sfp_port[0].sds = 1,
|
||||||
|
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
|
|
||||||
|
// Right SFP port
|
||||||
|
.sfp_port[1].pin_detect = GPIO37,
|
||||||
|
.sfp_port[1].pin_los = GPIO_NA,
|
||||||
|
.sfp_port[1].sds = 0,
|
||||||
|
.sfp_port[1].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
|
|
||||||
|
.reset_pin = GPIO_NA,
|
||||||
|
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
|
||||||
|
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
|
||||||
|
/* Ports 1-4 RJ45 use set 0, port 5-6 SFP uses set 1
|
||||||
|
* Ports 1-4: Green: 2.5GBit, Amber: 10/100/1000MBit
|
||||||
|
* Ports 5-6: Green: 100MBit-10GBit
|
||||||
|
*/
|
||||||
|
.led_sets = {
|
||||||
|
{
|
||||||
|
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||||
|
0,
|
||||||
|
LEDS_2G5 | LEDS_LINK | LEDS_ACT
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_10G | LEDS_LINK,
|
||||||
|
0,
|
||||||
|
LEDS_COL | LEDS_DUPLEX
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_2G5 | LEDS_1G | LEDS_LINK,
|
||||||
|
LEDS_5G | LEDS_2G5 | LEDS_LINK | LEDS_ACT,
|
||||||
|
LEDS_10G | LEDS_LINK | LEDS_ACT
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEDS_TX,
|
||||||
|
LEDS_RX,
|
||||||
|
LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5 |
|
||||||
|
LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_ACT,
|
||||||
|
LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5 |
|
||||||
|
LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.led_mux_custom = 1,
|
||||||
|
.led_mux = {
|
||||||
|
0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x3f, 0x15, 0x16,
|
||||||
|
0x18, 0x0e, 0x19, 0x11, 0x12, 0x1a, 0x15, 0x16, 0x1c, 0x19,
|
||||||
|
0x1a, 0x1d, 0x1d, 0x1e, 0x1e, 0x20, 0x21, 0x22
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "Please select a machine type in machine.h"
|
#error "Please select a machine type in machine.h"
|
||||||
|
|||||||
@@ -6,9 +6,19 @@
|
|||||||
/*
|
/*
|
||||||
* Select your machine type below
|
* Select your machine type below
|
||||||
*/
|
*/
|
||||||
|
// Legacy KP-9000 4+2 targets. Prefer the PCB-revision-specific targets below.
|
||||||
// #define MACHINE_KP_9000_6XHML_X2
|
// #define MACHINE_KP_9000_6XHML_X2
|
||||||
// #define MACHINE_KP_9000_6XH_X
|
|
||||||
// #define MACHINE_KP_9000_6XH_X2
|
// #define MACHINE_KP_9000_6XH_X2
|
||||||
|
|
||||||
|
// KP-9000 4+2 targets by PCB silkscreen revision.
|
||||||
|
// #define MACHINE_KP_9000_6XH_X2_V1_1
|
||||||
|
// #define MACHINE_KP_9000_6XHML_X2_V1_1
|
||||||
|
// #define MACHINE_KP_9000_6XH_X2_V1_2
|
||||||
|
// #define MACHINE_KP_9000_6XHML_X2_V1_2
|
||||||
|
// #define MACHINE_KP_9000_6XH_X2_V2_1
|
||||||
|
// #define MACHINE_KP_9000_6XHML_X2_V2_1
|
||||||
|
|
||||||
|
// #define MACHINE_KP_9000_6XH_X
|
||||||
// #define MACHINE_KP_9000_9XH_X_EU
|
// #define MACHINE_KP_9000_9XH_X_EU
|
||||||
// #define MACHINE_KP_9000_9XHML_X_V2_2
|
// #define MACHINE_KP_9000_9XHML_X_V2_2
|
||||||
// #define MACHINE_KP_9000_9XHML_X_V3_1
|
// #define MACHINE_KP_9000_9XHML_X_V3_1
|
||||||
@@ -18,6 +28,7 @@
|
|||||||
// #define MACHINE_HG0402XG_V1_1
|
// #define MACHINE_HG0402XG_V1_1
|
||||||
// #define MACHINE_SWTG018AS_A_V_2_0
|
// #define MACHINE_SWTG018AS_A_V_2_0
|
||||||
// #define MACHINE_SWTGW218AS
|
// #define MACHINE_SWTGW218AS
|
||||||
|
// #define MACHINE_PCB_SWTG018AS_V2_1_0
|
||||||
// #define MACHINE_PCB_K0402WS_V3
|
// #define MACHINE_PCB_K0402WS_V3
|
||||||
// #define MACHINE_K0501W_V2_0
|
// #define MACHINE_K0501W_V2_0
|
||||||
// #define MACHINE_LIANGUO_ZX_SWTGW215AS
|
// #define MACHINE_LIANGUO_ZX_SWTGW215AS
|
||||||
@@ -28,6 +39,9 @@
|
|||||||
// #define MACHINE_HI_K0801WS
|
// #define MACHINE_HI_K0801WS
|
||||||
// #define MACHINE_FNS1200P
|
// #define MACHINE_FNS1200P
|
||||||
// #define MACHINE_PCB_SWTG024AS_A_2_0_1
|
// #define MACHINE_PCB_SWTG024AS_A_2_0_1
|
||||||
|
// #define MACHINE_SWTG024AS_A_2_0_1_5C_1SFP
|
||||||
|
// #define MACHINE_SWTG024AS_V2_0
|
||||||
|
// #define MACHINE_FG_4GT_2SX_V2_0
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// GPIO pins for SDA/SCL
|
// GPIO pins for SDA/SCL
|
||||||
@@ -82,6 +96,7 @@ typedef struct machine {
|
|||||||
uint32_t led_sets[4][4];
|
uint32_t led_sets[4][4];
|
||||||
uint8_t led_mux_custom;
|
uint8_t led_mux_custom;
|
||||||
uint8_t led_mux[28];
|
uint8_t led_mux[28];
|
||||||
|
uint32_t mac_flash_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct machine_runtime
|
typedef struct machine_runtime
|
||||||
@@ -90,6 +105,6 @@ typedef struct machine_runtime
|
|||||||
uint8_t isN : 1;
|
uint8_t isN : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
void machine_custom_init(void);
|
void machine_custom_init(void) __banked;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Per-machine one-shot boot hooks, hosted in BANK2 so board-specific
|
||||||
|
* tables and code do not consume the common bank.
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "machine.h"
|
||||||
|
#include "rtl837x_pins.h"
|
||||||
|
#include "rtl837x_leds.h"
|
||||||
|
#include "rtl837x_sfr.h"
|
||||||
|
#include "rtl837x_regs.h"
|
||||||
|
#include "rtl837x_common.h"
|
||||||
|
|
||||||
|
#pragma codeseg BANK2
|
||||||
|
#pragma constseg BANK2
|
||||||
|
|
||||||
|
#if defined(MACHINE_KP_9000_6XH_X2) || \
|
||||||
|
defined(MACHINE_KP_9000_6XH_X2_V2_1) || \
|
||||||
|
defined(MACHINE_KP_9000_6XHML_X2_V2_1)
|
||||||
|
void machine_custom_init(void) __banked
|
||||||
|
{
|
||||||
|
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined MACHINE_PCB_SWTG018AS_V2_1_0
|
||||||
|
// Stock-firmware values for what the LED-set encoding cannot express: the
|
||||||
|
// bi-color SFP LED (blue pin at 10G) and the PIN_MUX_0 routing of that pin
|
||||||
|
// to the LED controller. Runs after leds_setup(), which covers the rest.
|
||||||
|
static __code const struct { uint16_t reg; uint32_t val; } custom_init_regs[] = {
|
||||||
|
{ RTL837X_REG_LED3_0_SET1, 0x00100000UL },
|
||||||
|
{ RTL837X_REG_LED1_0_SET1, 0x01400155UL },
|
||||||
|
{ RTL837X_REG_LED1_0_SET0, 0x01740141UL },
|
||||||
|
{ RTL837X_REG_LED_GLB_IO_EN, 0x7f24977fUL },
|
||||||
|
{ RTL837X_PIN_MUX_0, 0x20db6880UL },
|
||||||
|
};
|
||||||
|
|
||||||
|
void machine_custom_init(void) __banked
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
// REG_SET is a multi-statement macro without a do-while wrapper: braces required
|
||||||
|
for (i = 0; i < sizeof(custom_init_regs) / sizeof(custom_init_regs[0]); i++) {
|
||||||
|
REG_SET(custom_init_regs[i].reg, custom_init_regs[i].val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(MACHINE_PCB_K0402WS_V3) || defined(MACHINE_HI_K0402WS)
|
||||||
|
void machine_custom_init(void) __banked
|
||||||
|
{
|
||||||
|
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined MACHINE_FNS1200P
|
||||||
|
void machine_custom_init(void) __banked
|
||||||
|
{
|
||||||
|
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined MACHINE_PCB_SWTG024AS_A_2_0_1
|
||||||
|
void machine_custom_init(void) __banked
|
||||||
|
{
|
||||||
|
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
||||||
|
reg_bit_set(RTL837X_REG_LED_MODE, 17);
|
||||||
|
reg_bit_clear(RTL837X_REG_LED_MODE, 9);
|
||||||
|
reg_bit_clear(RTL837X_REG_LED_MODE, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined MACHINE_SWTG024AS_A_2_0_1_5C_1SFP
|
||||||
|
void machine_custom_init(void) __banked
|
||||||
|
{
|
||||||
|
uint16_t pval;
|
||||||
|
|
||||||
|
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
||||||
|
reg_bit_set(RTL837X_REG_LED_MODE, 17);
|
||||||
|
reg_bit_clear(RTL837X_REG_LED_MODE, 9);
|
||||||
|
reg_bit_clear(RTL837X_REG_LED_MODE, 7);
|
||||||
|
|
||||||
|
// OEM firmware sets these companion SDS0 polarity bits for the RTL8221B.
|
||||||
|
sds_read(0, 0, 0);
|
||||||
|
pval = SFR_DATA_U16;
|
||||||
|
sds_write_v(0, 0, 0, pval | 0x100);
|
||||||
|
|
||||||
|
sds_read(0, 6, 2);
|
||||||
|
pval = SFR_DATA_U16;
|
||||||
|
sds_write_v(0, 6, 2, pval | 0x4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined MACHINE_SWTG024AS_V2_0
|
||||||
|
void machine_custom_init(void) __banked
|
||||||
|
{
|
||||||
|
uint16_t pval;
|
||||||
|
|
||||||
|
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
||||||
|
reg_bit_set(RTL837X_REG_LED_MODE, 17);
|
||||||
|
reg_bit_clear(RTL837X_REG_LED_MODE, 9);
|
||||||
|
reg_bit_clear(RTL837X_REG_LED_MODE, 7);
|
||||||
|
|
||||||
|
// OEM firmware sets these companion SDS0 polarity bits for the RTL8221B.
|
||||||
|
sds_read(0, 0, 0);
|
||||||
|
pval = SFR_DATA_U16;
|
||||||
|
sds_write_v(0, 0, 0, pval | 0x100);
|
||||||
|
|
||||||
|
sds_read(0, 6, 2);
|
||||||
|
pval = SFR_DATA_U16;
|
||||||
|
sds_write_v(0, 6, 2, pval | 0x4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined MACHINE_ZX310S_4T2XT
|
||||||
|
void machine_custom_init(void) __banked
|
||||||
|
{
|
||||||
|
// For this device, the reset value of RTL837X_PIN_MUX_0 is 0x30000000,
|
||||||
|
// which would disables all LEDS, enable them manually:
|
||||||
|
REG_SET(RTL837X_PIN_MUX_0, 0x30db68bf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined MACHINE_FG_4GT_2SX_V2_0
|
||||||
|
void machine_custom_init(void) __banked
|
||||||
|
{
|
||||||
|
REG_SET(RTL837X_REG_LED_GLB_IO_EN, 0x7624155b);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
void machine_custom_init(void) __banked { }
|
||||||
|
#endif
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#define SYS_TICK_HZ 200
|
#define SYS_TICK_HZ 200
|
||||||
|
|
||||||
#define CPU_PORT 9
|
#define CPU_PORT 9
|
||||||
|
#define NUL '\0'
|
||||||
|
|
||||||
// Define Port-masks for 9-port devices and 6-port devices
|
// Define Port-masks for 9-port devices and 6-port devices
|
||||||
#define PMASK_9 0x1ff
|
#define PMASK_9 0x1ff
|
||||||
@@ -115,11 +116,17 @@ struct flash_region_t {
|
|||||||
|
|
||||||
extern __xdata char port_names[9][PORT_NAME_SIZE];
|
extern __xdata char port_names[9][PORT_NAME_SIZE];
|
||||||
|
|
||||||
|
/* System hostname (device identity). Set via `hostname <text>` and the System
|
||||||
|
* Settings page, reported in /information.json. Other modules (e.g. LLDP, which
|
||||||
|
* advertises it as the System Name TLV) read it from here. */
|
||||||
|
extern __xdata char hostname[24];
|
||||||
|
|
||||||
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
|
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
|
||||||
extern __xdata struct uip_eth_addr uip_ethaddr;
|
extern __xdata struct uip_eth_addr uip_ethaddr;
|
||||||
|
|
||||||
// Headers for calls in the common code area (HOME/BANK0)
|
// Headers for calls in the common code area (HOME/BANK0)
|
||||||
void print_string_no_syslog(__code char *p);
|
void print_string_no_syslog(__code char *p);
|
||||||
|
void print_string_newline_no_syslog(__code char *p);
|
||||||
void print_string(__code char *p);
|
void print_string(__code char *p);
|
||||||
void print_string_x(__xdata char *p);
|
void print_string_x(__xdata char *p);
|
||||||
void print_long(uint32_t a);
|
void print_long(uint32_t a);
|
||||||
@@ -129,6 +136,7 @@ void itoa(uint8_t v);
|
|||||||
void print_sfr_data(void);
|
void print_sfr_data(void);
|
||||||
void print_phy_data(void);
|
void print_phy_data(void);
|
||||||
void print_cmd_prompt(void);
|
void print_cmd_prompt(void);
|
||||||
|
void print_phys_port(uint8_t port);
|
||||||
void phy_write_mask(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v);
|
void phy_write_mask(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v);
|
||||||
void phy_write(uint8_t phy_id, uint8_t dev_id, uint16_t reg, uint16_t v);
|
void phy_write(uint8_t phy_id, uint8_t dev_id, uint16_t reg, uint16_t v);
|
||||||
void phy_read(uint8_t phy_id, uint8_t dev_id, uint16_t reg);
|
void phy_read(uint8_t phy_id, uint8_t dev_id, uint16_t reg);
|
||||||
@@ -144,7 +152,8 @@ void sleep(uint16_t t);
|
|||||||
void write_char_no_syslog(char c);
|
void write_char_no_syslog(char c);
|
||||||
void write_char(char c);
|
void write_char(char c);
|
||||||
void print_reg(uint16_t reg);
|
void print_reg(uint16_t reg);
|
||||||
uint8_t sfp_read_reg(uint8_t slot, uint8_t reg);
|
bool sfp_read_block(uint8_t slot, uint8_t reg, uint8_t len) __banked __reentrant;
|
||||||
|
extern __xdata uint8_t sfp_buf[16];
|
||||||
void reg_bit_set(uint16_t reg_addr, char bit);
|
void reg_bit_set(uint16_t reg_addr, char bit);
|
||||||
void reg_bit_clear(uint16_t reg_addr, char bit);
|
void reg_bit_clear(uint16_t reg_addr, char bit);
|
||||||
uint8_t reg_bit_test(uint16_t reg_addr, char bit);
|
uint8_t reg_bit_test(uint16_t reg_addr, char bit);
|
||||||
@@ -152,17 +161,20 @@ void sfr_mask_data(uint8_t n, uint8_t mask, uint8_t set);
|
|||||||
void sfr_set_zero(void);
|
void sfr_set_zero(void);
|
||||||
void reset_chip(void);
|
void reset_chip(void);
|
||||||
void memcpy(__xdata void * __xdata dst, __xdata const void * __xdata src, uint16_t len);
|
void memcpy(__xdata void * __xdata dst, __xdata const void * __xdata src, uint16_t len);
|
||||||
void memcpyc(register __xdata uint8_t *dst, register __code uint8_t *src, register uint16_t len);
|
void memcpyc(__xdata uint8_t *dst, __code uint8_t *src, uint16_t len);
|
||||||
void memset(register __xdata uint8_t *dst, register __xdata uint8_t v, register uint8_t len);
|
void memset(__xdata uint8_t *dst, __xdata uint8_t v, uint8_t len);
|
||||||
uint16_t strlen(register __code const char *s);
|
uint16_t strlen(__code const char *s);
|
||||||
uint16_t strlen_x(register __xdata const char *s);
|
uint16_t strlen_x(__xdata const char *s);
|
||||||
uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s);
|
uint16_t strtox(__xdata uint8_t *dst, __code const char *s);
|
||||||
uint16_t strcpy(register __xdata uint8_t *dst, register const char *s);
|
uint16_t strcpy(__xdata uint8_t *dst, const char *s);
|
||||||
|
char strcmp(__xdata const uint8_t *a, __code const uint8_t *b);
|
||||||
|
bool strstart(__xdata const uint8_t *a, __code const uint8_t *b);
|
||||||
|
bool strstart_x(__xdata const uint8_t *a, __xdata const uint8_t *b);
|
||||||
void tcpip_output(void);
|
void tcpip_output(void);
|
||||||
uint8_t read_flash(uint8_t bank, __code uint8_t *addr);
|
uint8_t read_flash(uint8_t bank, __code uint8_t *addr);
|
||||||
void get_random_32(void);
|
void get_random_32(void);
|
||||||
void read_reg_timer(__xdata uint32_t * tmr);
|
void read_reg_timer(__xdata uint32_t * tmr);
|
||||||
void sfp_print_info(uint8_t sfp);
|
bool sfp_print_info(uint8_t sfp);
|
||||||
bool gpio_pin_test(uint8_t pin);
|
bool gpio_pin_test(uint8_t pin);
|
||||||
void set_sys_led_state(uint8_t state);
|
void set_sys_led_state(uint8_t state);
|
||||||
void sds_read(uint8_t sds_id, uint8_t page, uint8_t reg);
|
void sds_read(uint8_t sds_id, uint8_t page, uint8_t reg);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
|
|
||||||
extern __code struct machine machine;
|
extern __code struct machine machine;
|
||||||
|
extern __xdata uint8_t igmpEnabled;
|
||||||
|
|
||||||
#include "uip.h"
|
#include "uip.h"
|
||||||
|
|
||||||
@@ -85,6 +86,7 @@ void igmp_setup(void) __banked
|
|||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
print_string("igmp_setup called\n");
|
print_string("igmp_setup called\n");
|
||||||
|
igmpEnabled = 0;
|
||||||
// For now, forward all unkown IP-MC pkts (2 bits per port. 00: flood via floodmask, 01: drop, 10: trap, 11: to rport)
|
// For now, forward all unkown IP-MC pkts (2 bits per port. 00: flood via floodmask, 01: drop, 10: trap, 11: to rport)
|
||||||
REG_SET(RTL837X_IPV4_PORT_MC_LM_ACT, LOOKUP_MISS_FLOOD);
|
REG_SET(RTL837X_IPV4_PORT_MC_LM_ACT, LOOKUP_MISS_FLOOD);
|
||||||
REG_SET(RTL837X_IPV6_PORT_MC_LM_ACT, LOOKUP_MISS_FLOOD);
|
REG_SET(RTL837X_IPV6_PORT_MC_LM_ACT, LOOKUP_MISS_FLOOD);
|
||||||
@@ -96,11 +98,6 @@ void igmp_setup(void) __banked
|
|||||||
// Enable lookup of IPv4 MC addresses in table
|
// Enable lookup of IPv4 MC addresses in table
|
||||||
reg_bit_set(RTL837X_L2_CTRL, L2_CTRL_LUT_IPMC_HASH);
|
reg_bit_set(RTL837X_L2_CTRL, L2_CTRL_LUT_IPMC_HASH);
|
||||||
|
|
||||||
// Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping,
|
|
||||||
// bits 16-24 configure max MC group used by that port. For now all protocols are flooded (01)
|
|
||||||
for (i = machine.min_port; i <= machine.max_port; i++)
|
|
||||||
REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), 0x00ff7c15);
|
|
||||||
|
|
||||||
/* Configure per-port IGMP operations when protocol messages are received
|
/* Configure per-port IGMP operations when protocol messages are received
|
||||||
* bits 0-9 enable MC protocol snooping
|
* bits 0-9 enable MC protocol snooping
|
||||||
* bit 10: Enable dynamic router port learning
|
* bit 10: Enable dynamic router port learning
|
||||||
@@ -135,6 +132,7 @@ void igmp_setup(void) __banked
|
|||||||
void igmp_enable(void) __banked
|
void igmp_enable(void) __banked
|
||||||
{
|
{
|
||||||
print_string("igmp_enable called\n");
|
print_string("igmp_enable called\n");
|
||||||
|
igmpEnabled = 1;
|
||||||
// Configure trapping of unhandled IGMP protocol packets to CPU
|
// Configure trapping of unhandled IGMP protocol packets to CPU
|
||||||
REG_SET(RTL837X_IGMP_TRAP_CFG, IGMP_CPU_PORT | IGMP_TRAP_PRIORITY);
|
REG_SET(RTL837X_IGMP_TRAP_CFG, IGMP_CPU_PORT | IGMP_TRAP_PRIORITY);
|
||||||
|
|
||||||
@@ -223,7 +221,7 @@ void igmp_packet_handler(void) __banked
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IPMC_USES_L3MC
|
#ifdef IPMC_USES_L3MC
|
||||||
memset(&entry, 0, sizeof(struct ipmc_table_entry));
|
memset((__xdata uint8_t *)&entry, 0, sizeof(struct ipmc_table_entry));
|
||||||
// For IPv4 MC, the Source-IP is 0.0.0.0
|
// For IPv4 MC, the Source-IP is 0.0.0.0
|
||||||
entry.sip[0] = 0x00; entry.sip[1] = 0x00; entry.sip[2] = 0x00; entry.sip[3] = 0x00;
|
entry.sip[0] = 0x00; entry.sip[1] = 0x00; entry.sip[2] = 0x00; entry.sip[3] = 0x00;
|
||||||
// For IPv4 MC, the Destination-IP is the IPv4 MC address
|
// For IPv4 MC, the Destination-IP is the IPv4 MC address
|
||||||
@@ -235,7 +233,7 @@ void igmp_packet_handler(void) __banked
|
|||||||
* yy = MC_IP[2]
|
* yy = MC_IP[2]
|
||||||
* zz = MC_IP[3]
|
* zz = MC_IP[3]
|
||||||
*/
|
*/
|
||||||
memset(&entry, 0, sizeof(struct l2mc_table_entry));
|
memset((__xdata uint8_t *)&entry, 0, sizeof(struct l2mc_table_entry));
|
||||||
entry.mac[0] = 0x01; entry.mac[1] = 0x00; entry.mac[2] = 0x5e;
|
entry.mac[0] = 0x01; entry.mac[1] = 0x00; entry.mac[2] = 0x5e;
|
||||||
entry.mac[3] = IGMP_I->mc_ip[1] & 0x7f; entry.mac[4] = IGMP_I->mc_ip[2]; entry.mac[5] = IGMP_I->mc_ip[3];
|
entry.mac[3] = IGMP_I->mc_ip[1] & 0x7f; entry.mac[4] = IGMP_I->mc_ip[2]; entry.mac[5] = IGMP_I->mc_ip[3];
|
||||||
entry.vlan = 1; //TODO: Get this out of the packet and compare with VLAN table!
|
entry.vlan = 1; //TODO: Get this out of the packet and compare with VLAN table!
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ void phy_set_speed(void) __banked
|
|||||||
{
|
{
|
||||||
uint16_t v;
|
uint16_t v;
|
||||||
|
|
||||||
print_string("Setting port "); write_char(machine.log_to_phys_port[phy_settings.port] + '0');
|
print_string("Setting port "); print_phys_port(phy_settings.port);
|
||||||
if (machine.n_10g && phy_settings.port == 3)
|
if (machine.n_10g && phy_settings.port == 3)
|
||||||
phy_settings.is10g_port = 1;
|
phy_settings.is10g_port = 1;
|
||||||
if (machine.n_10g == 2 && phy_settings.port == 8)
|
if (machine.n_10g == 2 && phy_settings.port == 8)
|
||||||
@@ -381,7 +381,7 @@ void phy_set_duplex(void) __banked
|
|||||||
{
|
{
|
||||||
uint16_t v;
|
uint16_t v;
|
||||||
|
|
||||||
print_string("Setting port "); write_char(machine.log_to_phys_port[phy_settings.port] + '0');
|
print_string("Setting port "); print_phys_port(phy_settings.port);
|
||||||
if (phy_settings.duplex)
|
if (phy_settings.duplex)
|
||||||
print_string(" to full duplex");
|
print_string(" to full duplex");
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
#include "rtl837x_pins.h"
|
#include "rtl837x_pins.h"
|
||||||
#include "rtl837x_common.h"
|
#include "rtl837x_common.h"
|
||||||
|
#include "rtl837x_sfr.h"
|
||||||
#include "rtl837x_regs.h"
|
#include "rtl837x_regs.h"
|
||||||
|
#include "machine.h"
|
||||||
|
|
||||||
|
extern __code const struct machine machine;
|
||||||
|
extern __xdata uint8_t sfr_data[4];
|
||||||
|
|
||||||
#pragma codeseg BANK2
|
#pragma codeseg BANK2
|
||||||
#pragma constseg BANK2
|
#pragma constseg BANK2
|
||||||
@@ -121,3 +126,56 @@ void gpio_output_setup(uint8_t pin, __xdata uint8_t initial_val) __banked{
|
|||||||
|
|
||||||
reg_bit_set(gpio_direction_reg(pin), (pin % 32));
|
reg_bit_set(gpio_direction_reg(pin), (pin % 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read up to 16 consecutive registers of the EEPROM via I2C into sfp_buf
|
||||||
|
*/
|
||||||
|
bool sfp_read_block(uint8_t slot, uint8_t reg, uint8_t len) __banked __reentrant
|
||||||
|
{
|
||||||
|
uint8_t dev;
|
||||||
|
uint8_t val;
|
||||||
|
|
||||||
|
len--;
|
||||||
|
if (len > 15)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dev = (reg & 0x80) ? 0x51 : 0x50; // 0x51 holds the diagnostics, 0x50 the module data
|
||||||
|
reg &= 0x7f;
|
||||||
|
|
||||||
|
REG_WRITE(RTL837X_REG_I2C_IN, 0, 0, 0, reg);
|
||||||
|
|
||||||
|
REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00,
|
||||||
|
0x1 << (I2C_MEM_ADDR_WIDTH - 16) | len,
|
||||||
|
(dev >> 5) | i2c_bus_from_scl_pin(machine.sfp_port[slot].i2c.scl) << 5
|
||||||
|
| i2c_bus_from_sda_pin(machine.sfp_port[slot].i2c.sda) << 2,
|
||||||
|
((dev << 3) & 0xff) | 0x1);
|
||||||
|
|
||||||
|
do {
|
||||||
|
reg_read(RTL837X_REG_I2C_CTRL);
|
||||||
|
} while (SFR_DATA_0 & 0x1);
|
||||||
|
|
||||||
|
if (SFR_DATA_0 & 0x2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i <= len; i++) {
|
||||||
|
switch (i & 0x3) {
|
||||||
|
case 0:
|
||||||
|
reg_read(RTL837X_REG_I2C_OUT + i);
|
||||||
|
val = SFR_DATA_0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
val = SFR_DATA_8;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
val = SFR_DATA_16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
val = SFR_DATA_24;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sfp_buf[i] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ __xdata uint32_t l2_head;
|
|||||||
|
|
||||||
__xdata struct vlan_settings vlan_settings;
|
__xdata struct vlan_settings vlan_settings;
|
||||||
|
|
||||||
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked
|
void port_mirror_set(uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked
|
||||||
{
|
{
|
||||||
print_string("\nport_mirror_set called \n");
|
print_string("\nport_mirror_set called \n");
|
||||||
print_string("Mirroring port: "); print_byte(port); print_string(" with rx-mask: ");
|
print_string("Mirroring port: "); print_byte(port); print_string(" with rx-mask: ");
|
||||||
@@ -115,6 +115,9 @@ uint16_t port_pvid_get(uint8_t port) __banked
|
|||||||
|
|
||||||
void vlan_delete(uint16_t vlan) __banked
|
void vlan_delete(uint16_t vlan) __banked
|
||||||
{
|
{
|
||||||
|
if (!vlan || vlan >= 0xfff)
|
||||||
|
return;
|
||||||
|
|
||||||
print_string("\nvlan_delete called \n"); print_short(vlan);
|
print_string("\nvlan_delete called \n"); print_short(vlan);
|
||||||
vlan_name_remove(vlan);
|
vlan_name_remove(vlan);
|
||||||
REG_WRITE(RTL837x_TBL_DATA_IN_A, 0, 0, 0, 0);
|
REG_WRITE(RTL837x_TBL_DATA_IN_A, 0, 0, 0, 0);
|
||||||
@@ -159,7 +162,7 @@ void vlan_name_remove(uint16_t vlan) __banked
|
|||||||
* Reads VLAN information from VLAN table
|
* Reads VLAN information from VLAN table
|
||||||
* Returns data in sfr_data
|
* Returns data in sfr_data
|
||||||
*/
|
*/
|
||||||
int8_t vlan_get(register uint16_t vlan) __banked
|
int8_t vlan_get(uint16_t vlan) __banked
|
||||||
{
|
{
|
||||||
if (vlan >= 0xfff) // VLAN 4095 is special
|
if (vlan >= 0xfff) // VLAN 4095 is special
|
||||||
return -1;
|
return -1;
|
||||||
@@ -174,7 +177,7 @@ int8_t vlan_get(register uint16_t vlan) __banked
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
__xdata uint16_t vlan_name(register uint16_t vlan) __banked
|
__xdata uint16_t vlan_name(uint16_t vlan) __banked
|
||||||
{
|
{
|
||||||
__xdata int16_t i = 0;
|
__xdata int16_t i = 0;
|
||||||
__xdata uint8_t begin = 1;
|
__xdata uint8_t begin = 1;
|
||||||
@@ -197,6 +200,11 @@ __xdata uint16_t vlan_name(register uint16_t vlan) __banked
|
|||||||
*/
|
*/
|
||||||
void vlan_create(void) __banked
|
void vlan_create(void) __banked
|
||||||
{
|
{
|
||||||
|
if (!vlan_settings.vlan || vlan_settings.vlan >= 0xfff) {
|
||||||
|
print_string("\nInvalid VLAN: "); print_short(vlan_settings.vlan); write_char('\n');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// For now, the CPU-port is always a tagged member:
|
// For now, the CPU-port is always a tagged member:
|
||||||
vlan_settings.members |= 0x0200; // Set 10th bit
|
vlan_settings.members |= 0x0200; // Set 10th bit
|
||||||
vlan_settings.tagged |= 0x0200;
|
vlan_settings.tagged |= 0x0200;
|
||||||
@@ -382,10 +390,7 @@ void port_l2_learned(void) __banked
|
|||||||
print_string("\tlearned\t");
|
print_string("\tlearned\t");
|
||||||
|
|
||||||
port |= (sfr_data[3] & 0x3) << 2;
|
port |= (sfr_data[3] & 0x3) << 2;
|
||||||
if (port < 9)
|
print_phys_port(port);
|
||||||
write_char(machine.log_to_phys_port[port] + '0');
|
|
||||||
else
|
|
||||||
print_string("CPU");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entry++;
|
entry++;
|
||||||
@@ -423,7 +428,7 @@ void port_stats_print(void) __banked
|
|||||||
{
|
{
|
||||||
print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n");
|
print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n");
|
||||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||||
write_char('0' + machine.log_to_phys_port[i]); write_char('\t');
|
print_phys_port(i); write_char('\t');
|
||||||
|
|
||||||
if (!machine.is_sfp[i]) {
|
if (!machine.is_sfp[i]) {
|
||||||
phy_read(i, PHY_MMD31, 0xa610);
|
phy_read(i, PHY_MMD31, 0xa610);
|
||||||
@@ -500,14 +505,14 @@ void port_stats_print(void) __banked
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void port_isolate(register uint8_t port, __xdata uint16_t pmask) __banked
|
void port_isolate(uint8_t port, __xdata uint16_t pmask) __banked
|
||||||
{
|
{
|
||||||
if (port <= machine.max_port)
|
if (port <= machine.max_port)
|
||||||
REG_SET(RTL837X_PORT_ISOLATION_BASE + (port << 2), pmask);
|
REG_SET(RTL837X_PORT_ISOLATION_BASE + (port << 2), pmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t port_isolation_get(register uint8_t port) __banked
|
uint16_t port_isolation_get(uint8_t port) __banked
|
||||||
{
|
{
|
||||||
if (port > machine.max_port)
|
if (port > machine.max_port)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -598,7 +603,7 @@ void port_eee_disable(uint8_t port) __banked
|
|||||||
|
|
||||||
void port_eee_status(uint8_t port) __banked
|
void port_eee_status(uint8_t port) __banked
|
||||||
{
|
{
|
||||||
print_string("Port: "); write_char('0' + machine.log_to_phys_port[port]);
|
print_string("Port: "); print_phys_port(port);
|
||||||
print_string(": ");
|
print_string(": ");
|
||||||
if (machine.is_sfp[port]) {
|
if (machine.is_sfp[port]) {
|
||||||
print_string("SFP\n");
|
print_string("SFP\n");
|
||||||
@@ -725,6 +730,19 @@ void port_rldp_on(__xdata uint16_t p_ms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reads the member port bitmask of a Link Aggregation Group.
|
||||||
|
* The groups have numbers 0-3; bit n is set when logical port n is a member.
|
||||||
|
* The bitmask reflects what the hardware holds, so it covers groups set up
|
||||||
|
* statically and groups a protocol brought up, without either having to say so.
|
||||||
|
*/
|
||||||
|
uint16_t port_lag_members_get(uint8_t lag) __banked
|
||||||
|
{
|
||||||
|
reg_read(RTL837X_TRK_MBR_CTRL_BASE + (lag << 2));
|
||||||
|
return ((uint16_t)SFR_DATA_8 << 8) | SFR_DATA_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure LAGs
|
* Configure LAGs
|
||||||
* Sets the members via port bitmask of a given Link Aggregation Group
|
* Sets the members via port bitmask of a given Link Aggregation Group
|
||||||
@@ -736,11 +754,14 @@ void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banke
|
|||||||
{
|
{
|
||||||
print_string("port_lag_members_set, lag: "); print_byte(lag); print_string(", members: "); print_short(members);
|
print_string("port_lag_members_set, lag: "); print_byte(lag); print_string(", members: "); print_short(members);
|
||||||
write_char('\n');
|
write_char('\n');
|
||||||
if (lag > 3)
|
if (lag > 3) {
|
||||||
print_string("Link aggregation group must be 0-3!\n");
|
print_string("Link aggregation group out of range\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
reg_read_m(RTL837X_TRK_HASH_CTRL_BASE + (lag << 2));
|
reg_read_m(RTL837X_TRK_HASH_CTRL_BASE + (lag << 2));
|
||||||
if (!(sfr_data[0] | sfr_data [1] | sfr_data [2] | sfr_data [3]))
|
if (!(sfr_data[0] | sfr_data[1] | sfr_data[2])
|
||||||
REG_SET(RTL837X_TRK_HASH_CTRL_BASE, LAG_HASH_DEFAULT);
|
&& (sfr_data[3] == LAG_HASH_RESET || sfr_data[3] == 0))
|
||||||
|
REG_SET(RTL837X_TRK_HASH_CTRL_BASE + (lag << 2), LAG_HASH_DEFAULT);
|
||||||
REG_WRITE(RTL837X_TRK_MBR_CTRL_BASE + (lag << 2), 0, 0, members >> 8, members & 0xff);
|
REG_WRITE(RTL837X_TRK_MBR_CTRL_BASE + (lag << 2), 0, 0, members >> 8, members & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,8 +774,10 @@ void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash_bits) __banked
|
|||||||
{
|
{
|
||||||
print_string("port_lag_hash_set, lag: "); print_byte(lag); print_string(", hash: "); print_byte(hash_bits);
|
print_string("port_lag_hash_set, lag: "); print_byte(lag); print_string(", hash: "); print_byte(hash_bits);
|
||||||
write_char('\n');
|
write_char('\n');
|
||||||
if (lag > 3)
|
if (lag > 3) {
|
||||||
print_string("Link aggregation group must be 0-3!\n");
|
print_string("Link aggregation group out of range\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
REG_WRITE(RTL837X_TRK_HASH_CTRL_BASE + (lag << 2), 0, 0, 0, hash_bits);
|
REG_WRITE(RTL837X_TRK_HASH_CTRL_BASE + (lag << 2), 0, 0, 0, hash_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -775,16 +798,6 @@ void print_port_ingress_filter_mode(vlan_ingress_mode_t mode) __banked
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_phys_port(uint8_t port) __banked
|
|
||||||
{
|
|
||||||
if (port >= machine.min_port && port <= machine.max_port)
|
|
||||||
write_char(machine.log_to_phys_port[port] + '0');
|
|
||||||
else if (port == 9)
|
|
||||||
write_char('9');
|
|
||||||
else
|
|
||||||
write_char('?');
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_vlan_ingress_port(uint8_t log_port) __banked
|
void print_vlan_ingress_port(uint8_t log_port) __banked
|
||||||
{
|
{
|
||||||
print_phys_port(log_port);write_char('\t');
|
print_phys_port(log_port);write_char('\t');
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ extern __xdata struct vlan_settings vlan_settings;
|
|||||||
uint8_t port_l2_forget(void) __banked;
|
uint8_t port_l2_forget(void) __banked;
|
||||||
void port_l2_learned(void) __banked;
|
void port_l2_learned(void) __banked;
|
||||||
void port_stats_print(void) __banked;
|
void port_stats_print(void) __banked;
|
||||||
int8_t vlan_get(register uint16_t vlan) __banked;
|
int8_t vlan_get(uint16_t vlan) __banked;
|
||||||
__xdata uint16_t vlan_name(register uint16_t vlan) __banked;
|
__xdata uint16_t vlan_name(uint16_t vlan) __banked;
|
||||||
void vlan_name_remove(uint16_t vlan) __banked;
|
void vlan_name_remove(uint16_t vlan) __banked;
|
||||||
void vlan_setup(void) __banked;
|
void vlan_setup(void) __banked;
|
||||||
void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked;
|
void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked;
|
||||||
@@ -57,10 +57,11 @@ uint16_t port_pvid_get(uint8_t port) __banked;
|
|||||||
void vlan_create(void) __banked;
|
void vlan_create(void) __banked;
|
||||||
void vlan_delete(uint16_t vlan) __banked;
|
void vlan_delete(uint16_t vlan) __banked;
|
||||||
void vlan_dump(void) __banked;
|
void vlan_dump(void) __banked;
|
||||||
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked;
|
void port_mirror_set(uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked;
|
||||||
void port_mirror_del(void) __banked;
|
void port_mirror_del(void) __banked;
|
||||||
bool port_ingress_filter(__xdata uint8_t port, __xdata vlan_ingress_mode_t type) __banked;
|
bool port_ingress_filter(__xdata uint8_t port, __xdata vlan_ingress_mode_t type) __banked;
|
||||||
void port_l2_setup(void) __banked;
|
void port_l2_setup(void) __banked;
|
||||||
|
uint16_t port_lag_members_get(uint8_t lag) __banked;
|
||||||
void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked;
|
void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked;
|
||||||
void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash) __banked;
|
void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash) __banked;
|
||||||
void port_eee_enable_all(__xdata uint8_t speed) __banked;
|
void port_eee_enable_all(__xdata uint8_t speed) __banked;
|
||||||
@@ -72,7 +73,7 @@ void port_eee_status(uint8_t port) __banked;
|
|||||||
void print_port_ingress_filter_mode(vlan_ingress_mode_t mode) __banked;
|
void print_port_ingress_filter_mode(vlan_ingress_mode_t mode) __banked;
|
||||||
bool port_ingress_vlan_filter_set(__xdata uint8_t port, __xdata bool enabled) __banked;
|
bool port_ingress_vlan_filter_set(__xdata uint8_t port, __xdata bool enabled) __banked;
|
||||||
bool port_ingress_vlan_filter_get(__xdata uint8_t port) __banked;
|
bool port_ingress_vlan_filter_get(__xdata uint8_t port) __banked;
|
||||||
void port_isolate(register uint8_t port, __xdata uint16_t pmask) __banked;
|
void port_isolate(uint8_t port, __xdata uint16_t pmask) __banked;
|
||||||
uint16_t port_isolation_get(register uint8_t port) __banked;
|
uint16_t port_isolation_get(uint8_t port) __banked;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -232,6 +232,8 @@
|
|||||||
#define LAG_HASH_L4_SPORT 0x20
|
#define LAG_HASH_L4_SPORT 0x20
|
||||||
#define LAG_HASH_L4_DPORT 0x40
|
#define LAG_HASH_L4_DPORT 0x40
|
||||||
#define LAG_HASH_DEFAULT (LAG_HASH_L2_SMAC | LAG_HASH_L2_DMAC | LAG_HASH_L3_SIP | LAG_HASH_L3_DIP | LAG_HASH_L4_SPORT | LAG_HASH_L4_DPORT)
|
#define LAG_HASH_DEFAULT (LAG_HASH_L2_SMAC | LAG_HASH_L2_DMAC | LAG_HASH_L3_SIP | LAG_HASH_L3_DIP | LAG_HASH_L4_SPORT | LAG_HASH_L4_DPORT)
|
||||||
|
#define LAG_HASH_RESET (LAG_HASH_SOURCE_PORT_NUMBER | LAG_HASH_L2_SMAC | LAG_HASH_L2_DMAC \
|
||||||
|
| LAG_HASH_L3_SIP | LAG_HASH_L3_DIP | LAG_HASH_L4_SPORT)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Port isolation
|
* Port isolation
|
||||||
@@ -305,32 +307,40 @@
|
|||||||
|
|
||||||
#ifdef REGDBG
|
#ifdef REGDBG
|
||||||
|
|
||||||
#define REG_SET(r, v) SFR_DATA_24 = (((uint32_t)v) >> 24) & 0xff; \
|
#define REG_SET(r, v) do { \
|
||||||
|
SFR_DATA_24 = (((uint32_t)v) >> 24) & 0xff; \
|
||||||
SFR_DATA_16 = (((uint32_t)v) >> 16) & 0xff; \
|
SFR_DATA_16 = (((uint32_t)v) >> 16) & 0xff; \
|
||||||
SFR_DATA_8 = (((uint16_t)v) >> 8 & 0xff); \
|
SFR_DATA_8 = (((uint16_t)v) >> 8 & 0xff); \
|
||||||
SFR_DATA_0 = (v) & 0xff; \
|
SFR_DATA_0 = (v) & 0xff; \
|
||||||
reg_write(r); \
|
reg_write(r); \
|
||||||
write_char('R'); print_byte(r >> 8); print_byte(r); write_char('-'); \
|
write_char('R'); print_byte(r >> 8); print_byte(r); write_char('-'); \
|
||||||
print_byte(((v) >> 24) & 0xff); print_byte((v) >> 16 & 0xff); print_byte((v) >> 8 & 0xff); print_byte( (v) & 0xff); write_char(' ');
|
print_byte(((v) >> 24) & 0xff); print_byte((v) >> 16 & 0xff); print_byte((v) >> 8 & 0xff); print_byte( (v) & 0xff); write_char(' '); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define REG_WRITE(r, v24, v16, v8, v0) SFR_DATA_24 = (v24); \
|
#define REG_WRITE(r, v24, v16, v8, v0) do { \
|
||||||
|
SFR_DATA_24 = (v24); \
|
||||||
SFR_DATA_16 = (v16); \
|
SFR_DATA_16 = (v16); \
|
||||||
SFR_DATA_8 = (v8); \
|
SFR_DATA_8 = (v8); \
|
||||||
SFR_DATA_0 = (v0); \
|
SFR_DATA_0 = (v0); \
|
||||||
reg_write(r); \
|
reg_write(r); \
|
||||||
write_char('R'); print_byte(r>>8); print_byte(r); write_char('-'); print_byte(v24); print_byte(v16); print_byte(v8); print_byte(v0); write_char(' ');
|
write_char('R'); print_byte(r>>8); print_byte(r); write_char('-'); print_byte(v24); print_byte(v16); print_byte(v8); print_byte(v0); write_char(' '); \
|
||||||
|
} while (0)
|
||||||
#else
|
#else
|
||||||
#define REG_SET(r, v) SFR_DATA_24 = (((uint32_t)v) >> 24) & 0xff; \
|
#define REG_SET(r, v) do { \
|
||||||
|
SFR_DATA_24 = (((uint32_t)v) >> 24) & 0xff; \
|
||||||
SFR_DATA_16 = (((uint32_t)v) >> 16) & 0xff; \
|
SFR_DATA_16 = (((uint32_t)v) >> 16) & 0xff; \
|
||||||
SFR_DATA_8 = (((uint16_t)v) >> 8 & 0xff); \
|
SFR_DATA_8 = (((uint16_t)v) >> 8 & 0xff); \
|
||||||
SFR_DATA_0 = (v) & 0xff; \
|
SFR_DATA_0 = (v) & 0xff; \
|
||||||
reg_write(r);
|
reg_write(r); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define REG_WRITE(r, v24, v16, v8, v0) SFR_DATA_24 = (v24); \
|
#define REG_WRITE(r, v24, v16, v8, v0) do { \
|
||||||
|
SFR_DATA_24 = (v24); \
|
||||||
SFR_DATA_16 = (v16); \
|
SFR_DATA_16 = (v16); \
|
||||||
SFR_DATA_8 = (v8); \
|
SFR_DATA_8 = (v8); \
|
||||||
SFR_DATA_0 = (v0); \
|
SFR_DATA_0 = (v0); \
|
||||||
reg_write(r);
|
reg_write(r); \
|
||||||
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,6 +14,11 @@
|
|||||||
#include "uip.h"
|
#include "uip.h"
|
||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
|
|
||||||
|
// All entry points are __banked and nothing here runs from an interrupt,
|
||||||
|
// so the module does not need to stay in the resident bank
|
||||||
|
#pragma codeseg BANK2
|
||||||
|
#pragma constseg BANK2
|
||||||
|
|
||||||
extern __code struct machine machine;
|
extern __code struct machine machine;
|
||||||
extern __xdata uint8_t sfr_data[4];
|
extern __xdata uint8_t sfr_data[4];
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "phy.h"
|
#include "phy.h"
|
||||||
#include "syslog.h"
|
#include "syslog.h"
|
||||||
|
#include "httpd/page_impl.h"
|
||||||
|
|
||||||
extern __code const struct machine machine;
|
extern __code const struct machine machine;
|
||||||
extern __xdata uint32_t flash_size;
|
extern __xdata uint32_t flash_size;
|
||||||
@@ -120,6 +121,8 @@ __xdata uint16_t management_vlan;
|
|||||||
__xdata uint8_t tx_seq;
|
__xdata uint8_t tx_seq;
|
||||||
|
|
||||||
__xdata uint8_t stpEnabled;
|
__xdata uint8_t stpEnabled;
|
||||||
|
__xdata uint8_t igmpEnabled;
|
||||||
|
__xdata char hostname[24]; /* device hostname, default set at boot, see rtl837x_common.h */
|
||||||
|
|
||||||
__code uint16_t bit_mask[16] = {
|
__code uint16_t bit_mask[16] = {
|
||||||
0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
|
0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
|
||||||
@@ -137,11 +140,27 @@ __xdata char sfp_module_vendor[2][17];
|
|||||||
__xdata char sfp_module_model[2][17];
|
__xdata char sfp_module_model[2][17];
|
||||||
__xdata char sfp_module_serial[2][17];
|
__xdata char sfp_module_serial[2][17];
|
||||||
__xdata uint8_t sfp_options[2];
|
__xdata uint8_t sfp_options[2];
|
||||||
|
__xdata uint8_t sfp_buf[16]; /* scratch for one I2C transaction, the controller reads at most 16 bytes */
|
||||||
__xdata uint8_t sfp_speed[2];
|
__xdata uint8_t sfp_speed[2];
|
||||||
|
__xdata uint8_t sfp_quirks[2];
|
||||||
__xdata bool button_last;
|
__xdata bool button_last;
|
||||||
__xdata uint8_t button_sec_counter_last;
|
__xdata uint8_t button_sec_counter_last;
|
||||||
volatile __bit tx_buf_empty;
|
volatile __bit tx_buf_empty;
|
||||||
|
|
||||||
|
__code enum sfp_quirk {
|
||||||
|
SFP_QUIRK_DDM = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sfp_quirk_entry {
|
||||||
|
__code char *vendor; // Set vendor or model to 0 to act as wildcard
|
||||||
|
__code char *model;
|
||||||
|
uint8_t quirks;
|
||||||
|
};
|
||||||
|
|
||||||
|
static __code struct sfp_quirk_entry sfp_quirk_table[] = {
|
||||||
|
{ "QSFPTEK", "QT-SFP+-T", SFP_QUIRK_DDM },
|
||||||
|
};
|
||||||
|
|
||||||
struct eth_in {
|
struct eth_in {
|
||||||
struct uip_eth_addr dst;
|
struct uip_eth_addr dst;
|
||||||
struct uip_eth_addr src;
|
struct uip_eth_addr src;
|
||||||
@@ -271,6 +290,12 @@ void print_string_no_syslog(__code char *p)
|
|||||||
write_char_no_syslog(*p++);
|
write_char_no_syslog(*p++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_string_newline_no_syslog(__code char *p)
|
||||||
|
{
|
||||||
|
write_char_no_syslog('\n');
|
||||||
|
print_string_no_syslog(p);
|
||||||
|
}
|
||||||
|
|
||||||
void print_string_x(__xdata char *p)
|
void print_string_x(__xdata char *p)
|
||||||
{
|
{
|
||||||
while (*p)
|
while (*p)
|
||||||
@@ -286,20 +311,20 @@ void memcpy(__xdata void * __xdata dst, __xdata const void * __xdata src, uint16
|
|||||||
*d++ = *s++;
|
*d++ = *s++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void memcpyc(register __xdata uint8_t *dst, register __code uint8_t *src, register uint16_t len)
|
void memcpyc(__xdata uint8_t *dst, __code uint8_t *src, uint16_t len)
|
||||||
{
|
{
|
||||||
while (len--)
|
while (len--)
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void memset(register __xdata uint8_t *dst, register __xdata uint8_t v, register uint8_t len)
|
void memset(__xdata uint8_t *dst, __xdata uint8_t v, uint8_t len)
|
||||||
{
|
{
|
||||||
while (len--)
|
while (len--)
|
||||||
*dst++ = v;
|
*dst++ = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s)
|
uint16_t strtox(__xdata uint8_t *dst, __code const char *s)
|
||||||
{
|
{
|
||||||
__xdata uint8_t *b = dst;
|
__xdata uint8_t *b = dst;
|
||||||
while (*s)
|
while (*s)
|
||||||
@@ -309,7 +334,7 @@ uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t strlen(register __code const char *s)
|
uint16_t strlen(__code const char *s)
|
||||||
{
|
{
|
||||||
uint16_t l = 0;
|
uint16_t l = 0;
|
||||||
while (s[l])
|
while (s[l])
|
||||||
@@ -318,7 +343,7 @@ uint16_t strlen(register __code const char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t strlen_x(register __xdata const char *s)
|
uint16_t strlen_x(__xdata const char *s)
|
||||||
{
|
{
|
||||||
uint16_t l = 0;
|
uint16_t l = 0;
|
||||||
while (s[l])
|
while (s[l])
|
||||||
@@ -327,6 +352,47 @@ uint16_t strlen_x(register __xdata const char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char strcmp(__xdata const uint8_t *a, __code const uint8_t *b)
|
||||||
|
{
|
||||||
|
uint8_t i = 0;
|
||||||
|
|
||||||
|
while (b[i] && (b[i] == a[i]))
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (a[i] < b[i])
|
||||||
|
return -1;
|
||||||
|
else if (a[i] > b[i])
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* True when b is a prefix of a. Unlike strcmp() the byte after the match is not
|
||||||
|
* compared, and unlike is_word_x() it need not be a separator.
|
||||||
|
*/
|
||||||
|
bool strstart(__xdata const uint8_t *a, __code const uint8_t *b)
|
||||||
|
{
|
||||||
|
uint8_t i = 0;
|
||||||
|
|
||||||
|
while (b[i] && (b[i] == a[i]))
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return !b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool strstart_x(__xdata const uint8_t *a, __xdata const uint8_t *b)
|
||||||
|
{
|
||||||
|
uint8_t i = 0;
|
||||||
|
|
||||||
|
while (b[i] && (b[i] == a[i]))
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return !b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void print_short(uint16_t a)
|
void print_short(uint16_t a)
|
||||||
{
|
{
|
||||||
// allocating the registers first improves the sdcc code here
|
// allocating the registers first improves the sdcc code here
|
||||||
@@ -601,7 +667,7 @@ void nic_rx_header(uint16_t ring_ptr)
|
|||||||
* data will be returned in the xmem buffer points to
|
* data will be returned in the xmem buffer points to
|
||||||
* ring_ptr is the current position of the RX Ring on the ASIC side
|
* ring_ptr is the current position of the RX Ring on the ASIC side
|
||||||
*/
|
*/
|
||||||
void nic_rx_packet(register uint16_t buffer, register uint16_t ring_ptr)
|
void nic_rx_packet(uint16_t buffer, uint16_t ring_ptr)
|
||||||
{
|
{
|
||||||
SFR_NIC_DATA_U16LE = buffer;
|
SFR_NIC_DATA_U16LE = buffer;
|
||||||
SFR_NIC_RING_U16LE = ring_ptr;
|
SFR_NIC_RING_U16LE = ring_ptr;
|
||||||
@@ -747,6 +813,19 @@ void print_reg(uint16_t reg)
|
|||||||
print_sfr_data();
|
print_sfr_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print the physical port of a logical port number.
|
||||||
|
void print_phys_port(uint8_t port)
|
||||||
|
{
|
||||||
|
if (port < CPU_PORT)
|
||||||
|
write_char(machine.log_to_phys_port[port] + '0');
|
||||||
|
else if (port == CPU_PORT)
|
||||||
|
print_string("CPU");
|
||||||
|
else {
|
||||||
|
print_string("UNKNOWN ");
|
||||||
|
write_char(port + '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TODO: This uses 2 DSEG bytes and is not used!
|
// TODO: This uses 2 DSEG bytes and is not used!
|
||||||
@@ -1003,37 +1082,6 @@ void sds_config(uint8_t sds, uint8_t mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read a register of the EEPROM via I2C
|
|
||||||
*/
|
|
||||||
uint8_t sfp_read_reg(uint8_t slot, uint8_t reg)
|
|
||||||
{
|
|
||||||
if (reg & 0x80) { // Configure SFP readings address (0x51) as I2C device address
|
|
||||||
reg &= 0x7f;
|
|
||||||
REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16) | 0, 0x51 >> 5, (0x51 << 3) & 0xff);
|
|
||||||
} else {
|
|
||||||
REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16) | 0, 0x50 >> 5, (0x50 << 3) & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_read_m(RTL837X_REG_I2C_CTRL);
|
|
||||||
sfr_mask_data(1, 0xfc, i2c_bus_from_scl_pin(machine.sfp_port[slot].i2c.scl) << 5 | i2c_bus_from_sda_pin(machine.sfp_port[slot].i2c.sda) << 2);
|
|
||||||
reg_write_m(RTL837X_REG_I2C_CTRL);
|
|
||||||
|
|
||||||
REG_WRITE(RTL837X_REG_I2C_IN, 0, 0, 0, reg);
|
|
||||||
|
|
||||||
// Execute I2C Read
|
|
||||||
reg_bit_set(RTL837X_REG_I2C_CTRL, 0);
|
|
||||||
|
|
||||||
// Wait for execution to finish
|
|
||||||
do {
|
|
||||||
reg_read_m(RTL837X_REG_I2C_CTRL);
|
|
||||||
} while (sfr_data[3] & 0x1);
|
|
||||||
|
|
||||||
reg_read_m(RTL837X_REG_I2C_OUT);
|
|
||||||
return sfr_data[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adds TX Header to uip_buf and calls nic_tx_packet to send the packet
|
* Adds TX Header to uip_buf and calls nic_tx_packet to send the packet
|
||||||
* over the wire
|
* over the wire
|
||||||
@@ -1120,7 +1168,7 @@ void handle_rx(void)
|
|||||||
print_string("STP TX\n");
|
print_string("STP TX\n");
|
||||||
tcpip_output();
|
tcpip_output();
|
||||||
}
|
}
|
||||||
} else if (uip_buf[0] == 0x01 && uip_buf[1] == 0x00 && uip_buf[2] == 0x5e // IPv4-MC packet?
|
} else if (igmpEnabled && uip_buf[0] == 0x01 && uip_buf[1] == 0x00 && uip_buf[2] == 0x5e // IPv4-MC packet?
|
||||||
&& uip_buf[3] == 0x00 && uip_buf[4] == 0x00 && uip_buf[5] == 0x16) {
|
&& uip_buf[3] == 0x00 && uip_buf[4] == 0x00 && uip_buf[5] == 0x16) {
|
||||||
igmp_packet_handler();
|
igmp_packet_handler();
|
||||||
if (uip_len) {
|
if (uip_len) {
|
||||||
@@ -1172,7 +1220,7 @@ void handle_tx(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline uint8_t sfp_rate_to_sds_config(register uint8_t rate)
|
static inline uint8_t sfp_rate_to_sds_config(uint8_t rate)
|
||||||
{
|
{
|
||||||
if (rate == 0x1 || rate == 0x2)
|
if (rate == 0x1 || rate == 0x2)
|
||||||
return SDS_100FX;
|
return SDS_100FX;
|
||||||
@@ -1180,37 +1228,75 @@ static inline uint8_t sfp_rate_to_sds_config(register uint8_t rate)
|
|||||||
return SDS_1000BX_FIBER;
|
return SDS_1000BX_FIBER;
|
||||||
if (rate >= 0x19 && rate <= 0x20) // Ethernet 2.5 GBit
|
if (rate >= 0x19 && rate <= 0x20) // Ethernet 2.5 GBit
|
||||||
return SDS_HSG;
|
return SDS_HSG;
|
||||||
if (rate >= 0x63 && rate < 0x70)
|
if (rate >= 0x62 && rate < 0x70)
|
||||||
return SDS_10GR;
|
return SDS_10GR;
|
||||||
return 0xff;
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sfp_print_info(uint8_t sfp)
|
bool sfp_print_info(uint8_t sfp)
|
||||||
{
|
{
|
||||||
// This loops over the Vendor-name, Vendor OUI, Vendor PN and Vendor rev ASCII fields
|
// This loops over the Vendor-name, Vendor OUI, Vendor PN and Vendor rev ASCII fields
|
||||||
for (uint8_t i = 20; i < 60; i++) {
|
for (uint8_t i = 16; i < 64; i++) {
|
||||||
if (i >= 36 && i < 40) // Skip Non-ASCII codes
|
if (!(i & 0xf) && !sfp_read_block(sfp, i, 16))
|
||||||
|
return false;
|
||||||
|
if (i < 20 || i >= 60 || (i >= 36 && i < 40)) // Skip Non-ASCII codes
|
||||||
continue;
|
continue;
|
||||||
uint8_t c = sfp_read_reg(sfp, i);
|
uint8_t c = sfp_buf[i & 0xf];
|
||||||
if (c)
|
if (c)
|
||||||
write_char(c);
|
write_char(c);
|
||||||
}
|
}
|
||||||
print_string("\n");
|
print_string("\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normalize strings from EEPROM by removing any trailing spaces; this allows simpler comparisons
|
||||||
void sfp_get_info(uint8_t sfp)
|
bool sfp_read_field(__xdata char *dst, uint8_t sfp, uint8_t start, uint8_t length) __reentrant
|
||||||
{
|
{
|
||||||
for (uint8_t i = 20; i < 36; i++)
|
if (!sfp_read_block(sfp, start, length))
|
||||||
sfp_module_vendor[sfp][i-20] = sfp_read_reg(sfp, i);
|
return false;
|
||||||
sfp_module_vendor[sfp][16] = '\0';
|
|
||||||
for (uint8_t i = 40; i < 56; i++)
|
dst[length] = NUL;
|
||||||
sfp_module_model[sfp][i-40] = sfp_read_reg(sfp, i);
|
memcpy(dst, sfp_buf, length);
|
||||||
sfp_module_model[sfp][16] = '\0';
|
|
||||||
for (uint8_t i = 68; i < 84; i++)
|
while (length > 0 && dst[--length] == ' ')
|
||||||
sfp_module_serial[sfp][i-68] = sfp_read_reg(sfp, i);
|
dst[length] = NUL;
|
||||||
sfp_module_serial[sfp][16] = '\0';
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sfp_get_info(uint8_t sfp)
|
||||||
|
{
|
||||||
|
if (!sfp_read_field(sfp_module_vendor[sfp], sfp, 20, 16))
|
||||||
|
return false;
|
||||||
|
if (!sfp_read_field(sfp_module_model[sfp], sfp, 40, 16))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return sfp_read_field(sfp_module_serial[sfp], sfp, 68, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sfp_apply_quirks(uint8_t sfp) __reentrant
|
||||||
|
{
|
||||||
|
sfp_quirks[sfp] = 0;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < sizeof(sfp_quirk_table) / sizeof(*sfp_quirk_table); i++) {
|
||||||
|
if (!sfp_quirk_table[i].vendor || !strcmp(sfp_module_vendor[sfp], sfp_quirk_table[i].vendor)) {
|
||||||
|
if (!sfp_quirk_table[i].model || !strcmp(sfp_module_model[sfp], sfp_quirk_table[i].model)) {
|
||||||
|
sfp_quirks[sfp] |= sfp_quirk_table[i].quirks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sfp_quirks[sfp] & SFP_QUIRK_DDM) {
|
||||||
|
if (!(sfp_options[sfp] & 0x40)) {
|
||||||
|
// The module reports that DDM is not implemented, but try a dummy read to confirm
|
||||||
|
// 0xff would mean a failed I2C read or an impossible (per spec) voltage greater than 6.5V
|
||||||
|
if (sfp_read_block(sfp, 226, 1) && sfp_buf[0] != 0xff) {
|
||||||
|
sfp_options[sfp] |= 0x40;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1230,6 +1316,45 @@ void setup_sfp_gpio(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool sfp_module_read(uint8_t sfp)
|
||||||
|
{
|
||||||
|
uint8_t rate;
|
||||||
|
|
||||||
|
// Read Reg 11: Encoding, see SFF-8472 and SFF-8024
|
||||||
|
// Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit
|
||||||
|
delay(100); // Delay, because some modules need time to wake up
|
||||||
|
if (!sfp_read_block(sfp, 11, 2))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rate = sfp_buf[1];
|
||||||
|
if (sfp_speed[sfp] == SFP_SPEED_100M)
|
||||||
|
rate = 0x1;
|
||||||
|
else if (sfp_speed[sfp] == SFP_SPEED_1G)
|
||||||
|
rate = 0xc;
|
||||||
|
else if (sfp_speed[sfp] == SFP_SPEED_2G5)
|
||||||
|
rate = 0x19;
|
||||||
|
else if (sfp_speed[sfp] == SFP_SPEED_10G)
|
||||||
|
rate = 0x69;
|
||||||
|
print_string(" Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored?
|
||||||
|
print_string(" Encoding: "); print_byte(sfp_buf[0]);
|
||||||
|
print_string(" Module: ");
|
||||||
|
if (!sfp_print_info(sfp))
|
||||||
|
return false;
|
||||||
|
print_string("\n");
|
||||||
|
|
||||||
|
if (!sfp_read_block(sfp, 92, 1))
|
||||||
|
return false;
|
||||||
|
sfp_options[sfp] = sfp_buf[0];
|
||||||
|
if (!sfp_get_info(sfp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sfp_apply_quirks(sfp);
|
||||||
|
sds_config(machine.sfp_port[sfp].sds, sfp_rate_to_sds_config(rate));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void handle_sfp(void)
|
void handle_sfp(void)
|
||||||
{
|
{
|
||||||
for (uint8_t sfp = 0; sfp < machine.n_sfp; sfp++) {
|
for (uint8_t sfp = 0; sfp < machine.n_sfp; sfp++) {
|
||||||
@@ -1237,25 +1362,10 @@ void handle_sfp(void)
|
|||||||
if (sfp_pins_last & (0x1 << (sfp << 2))) {
|
if (sfp_pins_last & (0x1 << (sfp << 2))) {
|
||||||
sfp_pins_last &= ~(0x01 << (sfp << 2));
|
sfp_pins_last &= ~(0x01 << (sfp << 2));
|
||||||
print_string("\n<MODULE INSERTED> Slot: "); write_char('1' + sfp);
|
print_string("\n<MODULE INSERTED> Slot: "); write_char('1' + sfp);
|
||||||
// Read Reg 11: Encoding, see SFF-8472 and SFF-8024
|
if (!sfp_module_read(sfp)) {
|
||||||
// Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit
|
print_string("SFP: an I2C read failed, retrying on the next poll\n");
|
||||||
delay(100); // Delay, because some modules need time to wake up
|
sfp_pins_last |= 0x01 << (sfp << 2);
|
||||||
uint8_t rate = sfp_read_reg(sfp, 12);
|
}
|
||||||
if (sfp_speed[sfp] == SFP_SPEED_100M)
|
|
||||||
rate = 0x1;
|
|
||||||
else if (sfp_speed[sfp] == SFP_SPEED_1G)
|
|
||||||
rate = 0xc;
|
|
||||||
else if (sfp_speed[sfp] == SFP_SPEED_2G5)
|
|
||||||
rate = 0x19;
|
|
||||||
else if (sfp_speed[sfp] == SFP_SPEED_10G)
|
|
||||||
rate = 0x69;
|
|
||||||
print_string(" Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored?
|
|
||||||
print_string(" Encoding: "); print_byte(sfp_read_reg(sfp, 11));
|
|
||||||
print_string(" Module: "); sfp_print_info(sfp);
|
|
||||||
print_string("\n");
|
|
||||||
sfp_options[sfp] = sfp_read_reg(sfp, 92);
|
|
||||||
sfp_get_info(sfp);
|
|
||||||
sds_config(machine.sfp_port[sfp].sds, sfp_rate_to_sds_config(rate));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!(sfp_pins_last & (0x1 << (sfp << 2)))) {
|
if (!(sfp_pins_last & (0x1 << (sfp << 2)))) {
|
||||||
@@ -1945,6 +2055,34 @@ void check_and_flash_update_image(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Give the switch a name carrying the tail of its MAC, so several of them on
|
||||||
|
* one network are distinguishable out of the box. Called after the startup
|
||||||
|
* config has been replayed and returns at once if that config already set a
|
||||||
|
* name, so a configured switch does no work for it (suggested in review).
|
||||||
|
*
|
||||||
|
* Written without a loop on purpose. Locals - counters and pointers alike -
|
||||||
|
* land in the 8051's internal-RAM overlay, and on an image with LACP and STP
|
||||||
|
* both enabled that overlay is exhausted: a loop here makes the linker fail
|
||||||
|
* with "Could not get 8 consecutive bytes in internal RAM for area OSEG".
|
||||||
|
* Moving the code into its own function does not help; the overlay is shared
|
||||||
|
* across the whole image. Hoisting the locals to xdata does not help either,
|
||||||
|
* because itohex() is inline and brings its own frame. */
|
||||||
|
void set_hostname_default(void)
|
||||||
|
{
|
||||||
|
if (hostname[0] != NUL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
strcpy((__xdata uint8_t *)hostname, "RTLPlayground-");
|
||||||
|
hostname[14] = hex[uip_ethaddr.addr[3] >> 4];
|
||||||
|
hostname[15] = hex[uip_ethaddr.addr[3] & 0xf];
|
||||||
|
hostname[16] = hex[uip_ethaddr.addr[4] >> 4];
|
||||||
|
hostname[17] = hex[uip_ethaddr.addr[4] & 0xf];
|
||||||
|
hostname[18] = hex[uip_ethaddr.addr[5] >> 4];
|
||||||
|
hostname[19] = hex[uip_ethaddr.addr[5] & 0xf];
|
||||||
|
hostname[20] = NUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
ticks = 0;
|
ticks = 0;
|
||||||
@@ -2023,20 +2161,28 @@ void main(void)
|
|||||||
uip_ipaddr(&uip_hostaddr, ownIP[0], ownIP[1], ownIP[2], ownIP[3]);
|
uip_ipaddr(&uip_hostaddr, ownIP[0], ownIP[1], ownIP[2], ownIP[3]);
|
||||||
uip_ipaddr(&uip_draddr, gatewayIP[0], gatewayIP[1], gatewayIP[2], gatewayIP[3]);
|
uip_ipaddr(&uip_draddr, gatewayIP[0], gatewayIP[1], gatewayIP[2], gatewayIP[3]);
|
||||||
uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]);
|
uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]);
|
||||||
reg_read_m(RTL837X_REG_CHIP_UUID);
|
uip_ethaddr.addr[0] = 0xff;
|
||||||
#ifdef DEBUG
|
if (machine.mac_flash_offset) {
|
||||||
print_string("SoC UUID: "); print_sfr_data();
|
flash_region.addr = machine.mac_flash_offset;
|
||||||
#endif
|
flash_region.len = FLASH_BUF_SIZE;
|
||||||
uip_ethaddr.addr[0] = 0x06; // LAA prefix
|
flash_read_bulk(flash_buf);
|
||||||
uip_ethaddr.addr[3] = sfr_data[0] ^ sfr_data[3];
|
// accept only a real unicast, globally-administered address (reject blank/LAA/multicast/all-zero OUI)
|
||||||
uip_ethaddr.addr[4] = sfr_data[1] ^ sfr_data[3];
|
if (flash_buf[0] != 0xff && !(flash_buf[0] & 0x03) && (flash_buf[0] | flash_buf[1] | flash_buf[2])) {
|
||||||
uip_ethaddr.addr[5] = sfr_data[2] ^ sfr_data[3];
|
uip_ethaddr.addr[0] = flash_buf[0]; uip_ethaddr.addr[1] = flash_buf[1];
|
||||||
reg_read_m(RTL837X_REG_CHIP_LOT_NO);
|
uip_ethaddr.addr[2] = flash_buf[2]; uip_ethaddr.addr[3] = flash_buf[3];
|
||||||
#ifdef DEBUG
|
uip_ethaddr.addr[4] = flash_buf[4]; uip_ethaddr.addr[5] = flash_buf[5];
|
||||||
print_string(", LOT: "); print_sfr_data(); write_char(' ');
|
}
|
||||||
#endif
|
}
|
||||||
uip_ethaddr.addr[1] = sfr_data[0] ^ sfr_data[2];
|
if (uip_ethaddr.addr[0] == 0xff) { // no valid flash MAC -> generate locally-administered
|
||||||
uip_ethaddr.addr[2] = sfr_data[1] ^ sfr_data[3];
|
reg_read_m(RTL837X_REG_CHIP_UUID);
|
||||||
|
uip_ethaddr.addr[0] = 0x06; // LAA prefix
|
||||||
|
uip_ethaddr.addr[3] = sfr_data[0] ^ sfr_data[3];
|
||||||
|
uip_ethaddr.addr[4] = sfr_data[1] ^ sfr_data[3];
|
||||||
|
uip_ethaddr.addr[5] = sfr_data[2] ^ sfr_data[3];
|
||||||
|
reg_read_m(RTL837X_REG_CHIP_LOT_NO);
|
||||||
|
uip_ethaddr.addr[1] = sfr_data[0] ^ sfr_data[2];
|
||||||
|
uip_ethaddr.addr[2] = sfr_data[1] ^ sfr_data[3];
|
||||||
|
}
|
||||||
print_string("Setting MAC to: ");
|
print_string("Setting MAC to: ");
|
||||||
print_byte(uip_ethaddr.addr[0]); write_char(':'); print_byte(uip_ethaddr.addr[1]); write_char(':');
|
print_byte(uip_ethaddr.addr[0]); write_char(':'); print_byte(uip_ethaddr.addr[1]); write_char(':');
|
||||||
print_byte(uip_ethaddr.addr[2]); write_char(':'); print_byte(uip_ethaddr.addr[3]); write_char(':');
|
print_byte(uip_ethaddr.addr[2]); write_char(':'); print_byte(uip_ethaddr.addr[3]); write_char(':');
|
||||||
@@ -2109,6 +2255,8 @@ void main(void)
|
|||||||
early_boot_handle_button();
|
early_boot_handle_button();
|
||||||
|
|
||||||
execute_config();
|
execute_config();
|
||||||
|
/* After the config: a name from it wins, otherwise derive one. */
|
||||||
|
set_hostname_default();
|
||||||
print_cmd_prompt();
|
print_cmd_prompt();
|
||||||
idle_ready = 1;
|
idle_ready = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -30,16 +30,16 @@ void syslog_start(void) __banked
|
|||||||
uip_ipaddr(server_ip, state.server_ip[0], state.server_ip[1], state.server_ip[2], state.server_ip[3]);
|
uip_ipaddr(server_ip, state.server_ip[0], state.server_ip[1], state.server_ip[2], state.server_ip[3]);
|
||||||
state.syslog_conn = uip_udp_new(&server_ip, HTONS(514));
|
state.syslog_conn = uip_udp_new(&server_ip, HTONS(514));
|
||||||
if (state.syslog_conn == 0) {
|
if (state.syslog_conn == 0) {
|
||||||
print_string_no_syslog("Failed to create a new UDP client\n");
|
print_string_newline_no_syslog("Failed to create a new UDP client");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
print_string_no_syslog("Started syslog to IP ");
|
print_string_newline_no_syslog("Started syslog to IP ");
|
||||||
itoa(state.server_ip[0]); write_char('.'); itoa(state.server_ip[1]); write_char('.');
|
itoa(state.server_ip[0]); write_char('.'); itoa(state.server_ip[1]); write_char('.');
|
||||||
itoa(state.server_ip[2]); write_char('.'); itoa(state.server_ip[3]); write_char('\n');
|
itoa(state.server_ip[2]); write_char('.'); itoa(state.server_ip[3]); write_char('\n');
|
||||||
state.enabled = 1;
|
state.enabled = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print_string_no_syslog("Syslog is already running\n");
|
print_string_newline_no_syslog("Syslog is already running");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,9 +49,9 @@ void syslog_stop(void) __banked
|
|||||||
if (state.syslog_conn != 0) {
|
if (state.syslog_conn != 0) {
|
||||||
uip_udp_remove(state.syslog_conn);
|
uip_udp_remove(state.syslog_conn);
|
||||||
state.syslog_conn = 0;
|
state.syslog_conn = 0;
|
||||||
print_string_no_syslog("Stopped syslog\n");
|
print_string_newline_no_syslog("Stopped syslog");
|
||||||
} else {
|
} else {
|
||||||
print_string_no_syslog("Syslog is not running\n");
|
print_string_newline_no_syslog("Syslog is not running");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,19 +62,19 @@ void syslog_callback(uint16_t lport) __banked
|
|||||||
|
|
||||||
if ((state.readptr != state.writeptr) && state.line_available)
|
if ((state.readptr != state.writeptr) && state.line_available)
|
||||||
{
|
{
|
||||||
int16_t log_size = state.writeptr - state.readptr;
|
__xdata int16_t log_size = state.writeptr - state.readptr;
|
||||||
if (log_size < 0)
|
if (log_size < 0)
|
||||||
log_size += LOGBUF_SIZE;
|
log_size += LOGBUF_SIZE;
|
||||||
|
|
||||||
// Skipping linefeeds at the start of the log line
|
// Skipping linefeeds at the start of the log line
|
||||||
uint16_t log_start = state.readptr;
|
__xdata uint16_t log_start = state.readptr;
|
||||||
while (log_size > 0 && logbuf[log_start] == '\n') {
|
while (log_size > 0 && logbuf[log_start] == '\n') {
|
||||||
log_start = (log_start + 1) & (LOGBUF_SIZE - 1);
|
log_start = (log_start + 1) & (LOGBUF_SIZE - 1);
|
||||||
log_size--;
|
log_size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skipping linefeeds and whitespaces at the end of the log line
|
// Skipping linefeeds and whitespaces at the end of the log line
|
||||||
uint16_t log_end = state.writeptr;
|
__xdata uint16_t log_end = state.writeptr;
|
||||||
while ( (log_size > 0) &&
|
while ( (log_size > 0) &&
|
||||||
((logbuf[(log_end-1) & (LOGBUF_SIZE - 1)] == '\n') ||
|
((logbuf[(log_end-1) & (LOGBUF_SIZE - 1)] == '\n') ||
|
||||||
(logbuf[(log_end-1) & (LOGBUF_SIZE - 1)] == ' ')))
|
(logbuf[(log_end-1) & (LOGBUF_SIZE - 1)] == ' ')))
|
||||||
@@ -95,7 +95,7 @@ void syslog_callback(uint16_t lport) __banked
|
|||||||
memcpy(SYSLOG_P + 4, logbuf + log_start, LOGBUF_SIZE - log_start);
|
memcpy(SYSLOG_P + 4, logbuf + log_start, LOGBUF_SIZE - log_start);
|
||||||
memcpy(SYSLOG_P + 4 + LOGBUF_SIZE - log_start, logbuf, log_end);
|
memcpy(SYSLOG_P + 4 + LOGBUF_SIZE - log_start, logbuf, log_end);
|
||||||
} else {
|
} else {
|
||||||
memcpy(SYSLOG_P + 4, logbuf + log_start, log_end - log_start);
|
memcpy(SYSLOG_P + 4, logbuf + log_start, log_end - log_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
uip_udp_send(log_size+4);
|
uip_udp_send(log_size+4);
|
||||||
|
|||||||
@@ -500,6 +500,10 @@ struct Server serverConstructor(int port, void (*launch)(struct Server *server))
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int reuse = 1;
|
||||||
|
if (setsockopt(server.socket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
|
||||||
|
perror("setsockopt(SO_REUSEADDR) failed");
|
||||||
|
|
||||||
if (bind(server.socket, (struct sockaddr*)&server.address, sizeof(server.address)) < 0) {
|
if (bind(server.socket, (struct sockaddr*)&server.address, sizeof(server.address)) < 0) {
|
||||||
perror("Failed to bind socket...\n");
|
perror("Failed to bind socket...\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@@ -554,8 +558,12 @@ char *scan_header(char *p)
|
|||||||
break;
|
break;
|
||||||
if (is_word(p, "\nContent-Type:"))
|
if (is_word(p, "\nContent-Type:"))
|
||||||
content_type = p + 15;
|
content_type = p + 15;
|
||||||
else if (is_word(p, "\nCookie:"))
|
else if (is_word(p, "\nCookie:")) {
|
||||||
session = p + 17;
|
session = p + 9;
|
||||||
|
while (*session == ' ') session++;
|
||||||
|
const char *s = strstr(session, "session=");
|
||||||
|
if (s) session = s + 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (content_type && is_word(content_type, "multipart/form-data; boundary")) {
|
if (content_type && is_word(content_type, "multipart/form-data; boundary")) {
|
||||||
printf("Found multiplart\n");
|
printf("Found multiplart\n");
|
||||||
@@ -799,7 +807,8 @@ void launch(struct Server *server)
|
|||||||
printf("Password accepted!\n");
|
printf("Password accepted!\n");
|
||||||
response = "HTTP/1.1 302 Found\r\n"
|
response = "HTTP/1.1 302 Found\r\n"
|
||||||
"Location: index.html\r\n"
|
"Location: index.html\r\n"
|
||||||
"Set-Cookie: session=" SESSION_ID "; SameSite=Strict\r\n";
|
"Set-Cookie: session=" SESSION_ID "; Path=/; SameSite=Strict\r\n"
|
||||||
|
"\r\n";
|
||||||
} else {
|
} else {
|
||||||
response = "HTTP/1.1 302 Found\r\n"
|
response = "HTTP/1.1 302 Found\r\n"
|
||||||
"Location: login.html\r\n\r\n";
|
"Location: login.html\r\n\r\n";
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
# LED GPIO Utilities
|
||||||
|
|
||||||
|
This directory contains utility talking to RTL837x switch IC via I2C bus.
|
||||||
|
These scripts are designed to help with monitoring, debugging GPIO, and identifying LED configurations.
|
||||||
|
(Only tested in Linux)
|
||||||
|
|
||||||
|
## Hardware requirements
|
||||||
|
|
||||||
|
To use these utilities, you need:
|
||||||
|
|
||||||
|
- A hardware dongle that can communicate with I2C devices. One example is the [I2C-Pico-USB](https://github.com/dquadros/I2C-Pico-USB) which provides USB-to-I2C connectivity.
|
||||||
|
- Connection between the hardware dongle and the RTL837x's I2C communication port.
|
||||||
|
|
||||||
|
## Scripts
|
||||||
|
|
||||||
|
### 1. `i2c_read_rtl_gpio.py`
|
||||||
|
|
||||||
|
This script reads RTL GPIO register values via I2C and displays changes in GPIO states.
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
|
||||||
|
- Reads live RTL GPIO register values via I2C (default address 0x5C)
|
||||||
|
- Monitors GPIO changes with delta detection
|
||||||
|
- Allows specification of I2C bus, sleep interval, and ignored GPIO pins
|
||||||
|
- Shows changes in real-time with GPIO index display
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
# Basic usage (defaults to I2C bus 1, 2s sleep interval)
|
||||||
|
python3 i2c_read_rtl_gpio.py
|
||||||
|
|
||||||
|
# Specify I2C bus
|
||||||
|
python3 i2c_read_rtl_gpio.py --i2c-bus 0
|
||||||
|
|
||||||
|
# Specify sleep interval in seconds
|
||||||
|
python3 i2c_read_rtl_gpio.py --sleep-interval 5
|
||||||
|
|
||||||
|
# Ignore specific GPIO pins
|
||||||
|
python3 i2c_read_rtl_gpio.py --ignored-ios 28 31 34 44
|
||||||
|
|
||||||
|
# Combine options
|
||||||
|
python3 i2c_read_rtl_gpio.py --i2c-bus 2 --sleep-interval 1 --ignored-ios 28 31
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output Format:**
|
||||||
|
|
||||||
|
- Displays register address and data in hex format
|
||||||
|
- Shows GPIO pins that have changed since last read
|
||||||
|
- Example: `0044: 00 00 00 00 00 00 00 00`
|
||||||
|
|
||||||
|
### 2. `i2c_dump_rtl_regs.py`
|
||||||
|
|
||||||
|
This script dumps all register values from an RTL device via I2C.
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
|
||||||
|
- Dumps registers sequentially from address 0x0000 to 0xFFFF
|
||||||
|
- Reads 16 bytes at a time for efficiency
|
||||||
|
- Configurable I2C bus number
|
||||||
|
- Provides complete register dump in hex format
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
# Basic usage (defaults to I2C bus 1)
|
||||||
|
python3 i2c_dump_rtl_regs.py >reg_dump.txt
|
||||||
|
|
||||||
|
# Specify I2C bus
|
||||||
|
python3 i2c_dump_rtl_regs.py --bus 0 >reg_dump.txt
|
||||||
|
|
||||||
|
# Or using short option
|
||||||
|
python3 i2c_dump_rtl_regs.py -b 2 >reg_dump.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output Format:**
|
||||||
|
|
||||||
|
- Displays address and 16 bytes of data in hex format
|
||||||
|
- Example: `0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00`
|
||||||
|
|
||||||
|
### 3. `dec_leds_from_dump.py`
|
||||||
|
|
||||||
|
This script decodes LED configuration from a register dump file ( the output from `i2c_dump_rtl_regs.py`).
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
|
||||||
|
- Parses register dump files (reg_dump.txt format)
|
||||||
|
- Decodes LED pad configurations and LED sets
|
||||||
|
- Maps LED types to bit positions based on configuration
|
||||||
|
- Outputs LED mux configuration and set mappings
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
# Must be run in same directory as reg_dump.txt
|
||||||
|
python3 dec_leds_from_dump.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output Format:**
|
||||||
|
|
||||||
|
- LED pad configuration (hex values for each pad)
|
||||||
|
- LED set configurations with descriptions of LED types
|
||||||
|
- Port selection mappings
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
|
||||||
|
- Requires a `reg_dump.txt` file containing the register dump output
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
All scripts require:
|
||||||
|
|
||||||
|
- Python 3
|
||||||
|
- `smbus2` Python package
|
||||||
|
|
||||||
|
(Depend upon Linux distribution) Install with:
|
||||||
|
```bash
|
||||||
|
apt install python3-smbus2
|
||||||
|
```
|
||||||
|
OR
|
||||||
|
```bash
|
||||||
|
pip3 install smbus2
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Common Use Cases
|
||||||
|
|
||||||
|
Both `i2c_read_rtl_gpio.py` and `i2c_dump_rtl_regs.py` shall run with the **original** firmware, not RTLPlayground firmware.
|
||||||
|
|
||||||
|
|
||||||
|
### Monitoring GPIO Changes
|
||||||
|
```bash
|
||||||
|
# Monitor GPIO changes on bus 1 with 1-second intervals
|
||||||
|
python3 i2c_read_rtl_gpio.py --i2c-bus 1 --sleep-interval 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Register Analysis
|
||||||
|
```bash
|
||||||
|
# Dump all device registers
|
||||||
|
python3 i2c_dump_rtl_regs.py --bus 2 > reg_dump.txt
|
||||||
|
|
||||||
|
# Analyze the register dump to understand LED configuration
|
||||||
|
python3 dec_leds_from_dump.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
All scripts support command-line arguments for flexible configuration:
|
||||||
|
|
||||||
|
- `--i2c-bus` or `-b`: Specify I2C bus (default: 1)
|
||||||
|
- `--sleep-interval` or `-s`: Sleep between reads in seconds (default: 2)
|
||||||
|
- `--ignored-ios` or `-i`: GPIO pins to ignore (default: [28, 31, 34, 44])
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
regs = list(range(65536))
|
||||||
|
|
||||||
|
glb_mux = 0x65E0
|
||||||
|
|
||||||
|
led3_0_set1 = 0x6528
|
||||||
|
led1_0_set0 = 0x6548
|
||||||
|
led_port_sel = 0x654C
|
||||||
|
|
||||||
|
|
||||||
|
def get_word(i):
|
||||||
|
val = (regs[i + 3] << 24) + (regs[i + 2] << 16) + (regs[i + 1] << 8) + regs[i]
|
||||||
|
# print(f"READING {i:04x} : {val:08x}")
|
||||||
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
with open("reg_dump.txt", "r") as file:
|
||||||
|
for line in file:
|
||||||
|
addr, data = line.split(":")
|
||||||
|
data = [int(x, 16) for x in data.strip().split(" ")]
|
||||||
|
addr = int(addr, 16)
|
||||||
|
for x in range(len(data)):
|
||||||
|
regs[addr + x] = data[x]
|
||||||
|
|
||||||
|
ledstr = []
|
||||||
|
ledfmt = []
|
||||||
|
print("LED pad Configuration:")
|
||||||
|
for i in range(28):
|
||||||
|
j = i % 5
|
||||||
|
if j == 0:
|
||||||
|
idx = glb_mux + (i // 5) * 4
|
||||||
|
val = get_word(idx)
|
||||||
|
ledval = (val >> (6 * j)) & 0x3F
|
||||||
|
ledstr.append(f"{ledval:02x}")
|
||||||
|
ledfmt.append(f"{i:02x}")
|
||||||
|
print(f"{' '.join(ledfmt)}")
|
||||||
|
print(f"{' '.join(ledstr)}")
|
||||||
|
print(f".led_mux = {{ 0x{', 0x'.join(ledstr)} }},")
|
||||||
|
|
||||||
|
LED_TYPES = [
|
||||||
|
" 10G",
|
||||||
|
16,
|
||||||
|
" TWO_5G",
|
||||||
|
17,
|
||||||
|
" 5G",
|
||||||
|
18,
|
||||||
|
" TWO_2G5",
|
||||||
|
19,
|
||||||
|
" 2G5",
|
||||||
|
0,
|
||||||
|
" TWO_1G",
|
||||||
|
1,
|
||||||
|
" 1G",
|
||||||
|
2,
|
||||||
|
" 500M",
|
||||||
|
3,
|
||||||
|
" 100M",
|
||||||
|
4,
|
||||||
|
" 10M",
|
||||||
|
5,
|
||||||
|
" LINK",
|
||||||
|
6,
|
||||||
|
" LINK_FLASH",
|
||||||
|
7,
|
||||||
|
" ACT",
|
||||||
|
8,
|
||||||
|
" RX",
|
||||||
|
9,
|
||||||
|
" TX",
|
||||||
|
10,
|
||||||
|
" COL",
|
||||||
|
11,
|
||||||
|
" DUPLEX",
|
||||||
|
12,
|
||||||
|
" TRAINING",
|
||||||
|
13,
|
||||||
|
" MASTER",
|
||||||
|
14,
|
||||||
|
"",
|
||||||
|
15,
|
||||||
|
]
|
||||||
|
|
||||||
|
led_set = []
|
||||||
|
led_set_str = []
|
||||||
|
print("\nLED-set Configuration:")
|
||||||
|
print("LED-ID 0 1 2 3")
|
||||||
|
for i in range(4):
|
||||||
|
idval = []
|
||||||
|
idvalstr = []
|
||||||
|
for id in range(4):
|
||||||
|
val = 0xFFFF & (
|
||||||
|
get_word(led1_0_set0 - 8 * i - ((id >> 1) << 2)) >> (16 * (id & 1))
|
||||||
|
)
|
||||||
|
valhi = (
|
||||||
|
0xF & (get_word(led3_0_set1 - 4 * (i >> 1)) >> (16 * (i & 1) + 4 * id))
|
||||||
|
) << 16
|
||||||
|
val += valhi
|
||||||
|
idval.append(val)
|
||||||
|
valstr = "("
|
||||||
|
for bit in range(0, len(LED_TYPES), 2):
|
||||||
|
if val & (1 << (LED_TYPES[bit + 1])):
|
||||||
|
valstr += LED_TYPES[bit]
|
||||||
|
valstr += ")"
|
||||||
|
idvalstr.append(valstr)
|
||||||
|
led_set.append(idval)
|
||||||
|
led_set_str.append(idvalstr)
|
||||||
|
idstr = " ".join([f"{d:05x}" for d in idval])
|
||||||
|
print(f"SET {i}: {idstr}")
|
||||||
|
# print(f"{idvalstr}")
|
||||||
|
|
||||||
|
portsel = get_word(led_port_sel)
|
||||||
|
for i in range(3, 9):
|
||||||
|
sel = (portsel >> (i << 1)) & 3
|
||||||
|
print(f"Port {i}: SET {sel}: {', '.join(led_set_str[sel])}")
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
from smbus2 import SMBus, i2c_msg
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
DEVICE_ADDR = 0x5C # Replace with your device address
|
||||||
|
NUM_BYTES = 16 # Bytes to read
|
||||||
|
|
||||||
|
# Parse command line arguments
|
||||||
|
parser = argparse.ArgumentParser(description="Dump RTL registers via I2C")
|
||||||
|
parser.add_argument(
|
||||||
|
"-b",
|
||||||
|
"--i2c-bus",
|
||||||
|
type=int,
|
||||||
|
required=True,
|
||||||
|
help="I2C bus number (use i2cdetect -l to find out the bus number of the dongle)",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Open I2C bus
|
||||||
|
with SMBus(args.i2c_bus) as bus:
|
||||||
|
|
||||||
|
for addr in range(0, 65536, NUM_BYTES):
|
||||||
|
# Create write message (send register address)
|
||||||
|
write = i2c_msg.write(DEVICE_ADDR, [addr >> 8, addr & 0xFF])
|
||||||
|
|
||||||
|
# Create read message (read 2 bytes)
|
||||||
|
read = i2c_msg.read(DEVICE_ADDR, NUM_BYTES)
|
||||||
|
|
||||||
|
# Perform combined transaction
|
||||||
|
bus.i2c_rdwr(write, read)
|
||||||
|
|
||||||
|
new_data = list(read)
|
||||||
|
|
||||||
|
# Convert read message to string
|
||||||
|
datastr = " ".join([f"{x:02x}" for x in new_data])
|
||||||
|
print(f"{addr:04x}: {datastr}")
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import time
|
||||||
|
import argparse
|
||||||
|
from smbus2 import SMBus, i2c_msg
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
I2C_BUS = 1
|
||||||
|
DEVICE_ADDR = 0x5C # Replace with your device address
|
||||||
|
NUM_BYTES = 8 # Bytes to read
|
||||||
|
SLEEP_INTERVAL = 1
|
||||||
|
|
||||||
|
# Handle command line arguments for ignored IOs
|
||||||
|
# default to ignore IOs related to SYS_LED, UART, SMI, SPI
|
||||||
|
IGNORED_IOS = [28, 31, 32, 34, 35, 42, 43, 44, 45]
|
||||||
|
|
||||||
|
# Setup argument parser
|
||||||
|
parser = argparse.ArgumentParser(description="Read I2C data from RTL GPIO expander")
|
||||||
|
parser.add_argument(
|
||||||
|
"-b",
|
||||||
|
"--i2c-bus",
|
||||||
|
type=int,
|
||||||
|
required=True,
|
||||||
|
help="I2C bus number (use i2cdetect -l to find out the bus number of the dongle)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-s",
|
||||||
|
"--sleep-interval",
|
||||||
|
type=int,
|
||||||
|
default=SLEEP_INTERVAL,
|
||||||
|
help=f"Sleep interval in seconds (default: {SLEEP_INTERVAL})",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-i",
|
||||||
|
"--ignored-ios",
|
||||||
|
nargs="*",
|
||||||
|
type=int,
|
||||||
|
default=IGNORED_IOS,
|
||||||
|
help=f"List of GPIO pins to ignore (default: {IGNORED_IOS})",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
I2C_BUS = args.i2c_bus
|
||||||
|
|
||||||
|
first_read = True
|
||||||
|
last_data = [0 for x in range(NUM_BYTES)]
|
||||||
|
|
||||||
|
# Open I2C bus
|
||||||
|
with SMBus(I2C_BUS) as bus:
|
||||||
|
addr = 0x44
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# Create write message (send register address)
|
||||||
|
write = i2c_msg.write(DEVICE_ADDR, [addr >> 8, addr & 0xFF])
|
||||||
|
|
||||||
|
# Create read message (read NUM_BYTES bytes)
|
||||||
|
read = i2c_msg.read(DEVICE_ADDR, NUM_BYTES)
|
||||||
|
|
||||||
|
# Perform combined transaction
|
||||||
|
bus.i2c_rdwr(write, read)
|
||||||
|
|
||||||
|
new_data = list(read)
|
||||||
|
if first_read:
|
||||||
|
delta_data = last_data
|
||||||
|
first_read = False
|
||||||
|
else:
|
||||||
|
delta_data = [new_data[x] ^ last_data[x] for x in range(NUM_BYTES)]
|
||||||
|
last_data = new_data
|
||||||
|
|
||||||
|
# Convert read message to list
|
||||||
|
datastr = " ".join([f"{x:02x}" for x in new_data])
|
||||||
|
deltastr = ""
|
||||||
|
chg_list = []
|
||||||
|
for x in range(NUM_BYTES):
|
||||||
|
if delta_data[x] == 0:
|
||||||
|
continue
|
||||||
|
for y in range(8):
|
||||||
|
if delta_data[x] & (1 << y):
|
||||||
|
idx = x * 8 + y
|
||||||
|
if idx not in args.ignored_ios:
|
||||||
|
deltastr += f"\n{' ':8s}GPIO{idx}"
|
||||||
|
# deltastr = " ".join([ f"{x:02x}" for x in delta_data])
|
||||||
|
print(f"{addr:04x}: {datastr}{deltastr}")
|
||||||
|
time.sleep(args.sleep_interval)
|
||||||
@@ -75,8 +75,7 @@
|
|||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
buf_setup(register __xdata struct psock_buf *buf,
|
buf_setup(__xdata struct psock_buf *buf, __xdata u8_t *bufptr, u16_t bufsize)
|
||||||
register __xdata u8_t *bufptr, register u16_t bufsize)
|
|
||||||
{
|
{
|
||||||
buf->ptr = bufptr;
|
buf->ptr = bufptr;
|
||||||
buf->left = bufsize;
|
buf->left = bufsize;
|
||||||
@@ -84,7 +83,7 @@ buf_setup(register __xdata struct psock_buf *buf,
|
|||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
inline u8_t
|
inline u8_t
|
||||||
buf_bufdata(register __xdata struct psock_buf *buf, register __xdata u8_t **dataptr, register __xdata u16_t *datalen)
|
buf_bufdata(__xdata struct psock_buf *buf, __xdata u8_t **dataptr, __xdata u16_t *datalen)
|
||||||
{
|
{
|
||||||
if(*datalen < buf->left) {
|
if(*datalen < buf->left) {
|
||||||
memcpy(buf->ptr, *dataptr, *datalen);
|
memcpy(buf->ptr, *dataptr, *datalen);
|
||||||
@@ -145,7 +144,7 @@ buf_bufto(__xdata struct psock_buf *buf, u8_t endmarker,
|
|||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static char
|
static char
|
||||||
send_data(register __xdata struct psock *s)
|
send_data(__xdata struct psock *s)
|
||||||
{
|
{
|
||||||
if(s->state != STATE_DATA_SENT || uip_rexmit()) {
|
if(s->state != STATE_DATA_SENT || uip_rexmit()) {
|
||||||
if(s->sendlen > uip_mss()) {
|
if(s->sendlen > uip_mss()) {
|
||||||
@@ -160,7 +159,7 @@ send_data(register __xdata struct psock *s)
|
|||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static char
|
static char
|
||||||
data_acked(register __xdata struct psock *s)
|
data_acked(__xdata struct psock *s)
|
||||||
{
|
{
|
||||||
if(s->state == STATE_DATA_SENT && uip_acked()) {
|
if(s->state == STATE_DATA_SENT && uip_acked()) {
|
||||||
if(s->sendlen > uip_mss()) {
|
if(s->sendlen > uip_mss()) {
|
||||||
@@ -176,8 +175,7 @@ data_acked(register __xdata struct psock *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
PT_THREAD(psock_send(register __xdata struct psock *s, register __xdata const char *buf,
|
PT_THREAD(psock_send(__xdata struct psock *s, __xdata const char *buf, uint16_t len))
|
||||||
register uint16_t len))
|
|
||||||
{
|
{
|
||||||
PT_BEGIN(&s->psockpt);
|
PT_BEGIN(&s->psockpt);
|
||||||
|
|
||||||
@@ -218,7 +216,7 @@ PT_THREAD(psock_send(register __xdata struct psock *s, register __xdata const ch
|
|||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
// PT_THREAD(psock_generator_send(register __xdata struct psock *s,
|
// PT_THREAD(psock_generator_send(__xdata struct psock *s,
|
||||||
// unsigned short (*generate)(void *), void *arg))
|
// unsigned short (*generate)(void *), void *arg))
|
||||||
// {
|
// {
|
||||||
// PT_BEGIN(&s->psockpt);
|
// PT_BEGIN(&s->psockpt);
|
||||||
@@ -275,7 +273,7 @@ psock_newdata(__xdata struct psock *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
PT_THREAD(psock_readto(register __xdata struct psock *psock, unsigned char c))
|
PT_THREAD(psock_readto(__xdata struct psock *psock, unsigned char c))
|
||||||
{
|
{
|
||||||
PT_BEGIN(&psock->psockpt);
|
PT_BEGIN(&psock->psockpt);
|
||||||
|
|
||||||
@@ -304,7 +302,7 @@ PT_THREAD(psock_readto(register __xdata struct psock *psock, unsigned char c))
|
|||||||
PT_END(&psock->psockpt);
|
PT_END(&psock->psockpt);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
PT_THREAD(psock_readbuf(register __xdata struct psock *psock))
|
PT_THREAD(psock_readbuf(__xdata struct psock *psock))
|
||||||
{
|
{
|
||||||
PT_BEGIN(&psock->psockpt);
|
PT_BEGIN(&psock->psockpt);
|
||||||
|
|
||||||
@@ -334,7 +332,7 @@ PT_THREAD(psock_readbuf(register __xdata struct psock *psock))
|
|||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
psock_init(register __xdata struct psock *psock, register __xdata char *buffer, register uint16_t buffersize)
|
psock_init(__xdata struct psock *psock, __xdata char *buffer, uint16_t buffersize)
|
||||||
{
|
{
|
||||||
psock->state = STATE_NONE;
|
psock->state = STATE_NONE;
|
||||||
psock->readlen = 0;
|
psock->readlen = 0;
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ struct psock {
|
|||||||
u8_t state; /* The state of the protosocket. */
|
u8_t state; /* The state of the protosocket. */
|
||||||
};
|
};
|
||||||
|
|
||||||
void psock_init(__xdata struct psock *psock, register __xdata char *buffer, register uint16_t buffersize);
|
void psock_init(__xdata struct psock *psock, __xdata char *buffer, uint16_t buffersize);
|
||||||
/**
|
/**
|
||||||
* Initialize a protosocket.
|
* Initialize a protosocket.
|
||||||
*
|
*
|
||||||
@@ -158,7 +158,7 @@ void psock_init(__xdata struct psock *psock, register __xdata char *buffer, regi
|
|||||||
*/
|
*/
|
||||||
#define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt))
|
#define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt))
|
||||||
|
|
||||||
PT_THREAD(psock_send(register __xdata struct psock *psock, register __xdata const char *buf, register uint16_t len));
|
PT_THREAD(psock_send(__xdata struct psock *psock, __xdata const char *buf, uint16_t len));
|
||||||
/**
|
/**
|
||||||
* Send data.
|
* Send data.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -106,9 +106,23 @@ typedef unsigned short uip_stats_t;
|
|||||||
/**
|
/**
|
||||||
* uIP buffer size.
|
* uIP buffer size.
|
||||||
*
|
*
|
||||||
|
* Sized to the largest frame the CPU port accepts on ingress: anything above
|
||||||
|
* that the NIC drops in hardware, so a larger buffer only costs XDATA. Measured
|
||||||
|
* with ICMP, which bypasses MSS and so probes the hardware directly: a 1502-byte
|
||||||
|
* payload is answered and 1503 is not, which puts the frame at 1556 bytes of
|
||||||
|
* uip_buf. The limit is the NIC's rather than a port's, so how the frame was
|
||||||
|
* tagged on the wire does not change it.
|
||||||
|
*
|
||||||
* \hideinitializer
|
* \hideinitializer
|
||||||
*/
|
*/
|
||||||
#define UIP_CONF_BUFFER_SIZE 2200
|
#define UIP_CONF_BUFFER_SIZE 1556
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytes of the buffer kept out of the advertised MSS.
|
||||||
|
*
|
||||||
|
* \hideinitializer
|
||||||
|
*/
|
||||||
|
#define UIP_CONF_BUFFER_EXTRA 30
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CPU byte order.
|
* CPU byte order.
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ __xdata u16_t uip_len, uip_slen;
|
|||||||
__xdata u8_t uip_flags; /* The uip_flags variable is used for
|
__xdata u8_t uip_flags; /* The uip_flags variable is used for
|
||||||
communication between the TCP/IP stack
|
communication between the TCP/IP stack
|
||||||
and the application program. */
|
and the application program. */
|
||||||
__xdata struct uip_conn *uip_conn; /* uip_conn always points to the current
|
__xdata struct uip_conn * __xdata uip_conn; /* uip_conn always points to the current
|
||||||
connection. */
|
connection. */
|
||||||
|
|
||||||
__xdata struct uip_conn uip_conns[UIP_CONNS];
|
__xdata struct uip_conn uip_conns[UIP_CONNS];
|
||||||
@@ -167,7 +167,7 @@ __xdata u16_t uip_listenports[UIP_LISTENPORTS];
|
|||||||
/* The uip_listenports list all currently
|
/* The uip_listenports list all currently
|
||||||
listning ports. */
|
listning ports. */
|
||||||
#if UIP_UDP
|
#if UIP_UDP
|
||||||
__xdata struct uip_udp_conn *uip_udp_conn;
|
__xdata struct uip_udp_conn * __xdata uip_udp_conn;
|
||||||
__xdata struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
|
__xdata struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
|
||||||
#endif /* UIP_UDP */
|
#endif /* UIP_UDP */
|
||||||
|
|
||||||
@@ -234,7 +234,7 @@ __xdata struct uip_stats uip_stat;
|
|||||||
#endif /* UIP_STATISTICS == 1 */
|
#endif /* UIP_STATISTICS == 1 */
|
||||||
|
|
||||||
#if UIP_LOGGING == 1
|
#if UIP_LOGGING == 1
|
||||||
#define UIP_LOG(m) print_string_no_syslog(m);
|
#define UIP_LOG(m) print_string_newline_no_syslog(m);
|
||||||
#else
|
#else
|
||||||
#define UIP_LOG(m)
|
#define UIP_LOG(m)
|
||||||
#endif /* UIP_LOGGING == 1 */
|
#endif /* UIP_LOGGING == 1 */
|
||||||
@@ -400,7 +400,7 @@ uip_init(void) __banked
|
|||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#if UIP_ACTIVE_OPEN
|
#if UIP_ACTIVE_OPEN
|
||||||
__xdata struct uip_conn *
|
__xdata struct uip_conn *
|
||||||
uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport) __banked
|
uip_connect(__xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport) __banked
|
||||||
{
|
{
|
||||||
__xdata struct uip_conn *conn, *cconn;
|
__xdata struct uip_conn *conn, *cconn;
|
||||||
|
|
||||||
@@ -466,7 +466,7 @@ uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport) __banke
|
|||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#if UIP_UDP
|
#if UIP_UDP
|
||||||
__xdata struct uip_udp_conn *
|
__xdata struct uip_udp_conn *
|
||||||
uip_udp_new(__xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport) __banked
|
uip_udp_new(__xdata uip_ipaddr_t * __xdata ripaddr, __xdata u16_t rport) __banked
|
||||||
{
|
{
|
||||||
__xdata struct uip_udp_conn *conn;
|
__xdata struct uip_udp_conn *conn;
|
||||||
|
|
||||||
@@ -677,7 +677,7 @@ uip_add_rcv_nxt(u16_t n)
|
|||||||
void
|
void
|
||||||
uip_process(u8_t flag) __banked
|
uip_process(u8_t flag) __banked
|
||||||
{
|
{
|
||||||
register __xdata struct uip_conn *uip_connr = uip_conn;
|
__xdata struct uip_conn *uip_connr = uip_conn;
|
||||||
|
|
||||||
#if UIP_UDP
|
#if UIP_UDP
|
||||||
if(flag == UIP_UDP_SEND_CONN) {
|
if(flag == UIP_UDP_SEND_CONN) {
|
||||||
|
|||||||
@@ -763,7 +763,7 @@ void uip_send(__xdata const void *data, __xdata uint16_t len) __banked;
|
|||||||
* \return The uip_udp_conn structure for the new connection or NULL
|
* \return The uip_udp_conn structure for the new connection or NULL
|
||||||
* if no connection could be allocated.
|
* if no connection could be allocated.
|
||||||
*/
|
*/
|
||||||
__xdata struct uip_udp_conn *uip_udp_new(__xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport) __banked;
|
__xdata struct uip_udp_conn *uip_udp_new(__xdata uip_ipaddr_t * __xdata ripaddr, __xdata u16_t rport) __banked;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removed a UDP connection.
|
* Removed a UDP connection.
|
||||||
@@ -1193,7 +1193,7 @@ struct uip_conn {
|
|||||||
* The uip_conn pointer can be used to access the current TCP
|
* The uip_conn pointer can be used to access the current TCP
|
||||||
* connection.
|
* connection.
|
||||||
*/
|
*/
|
||||||
extern __xdata struct uip_conn *uip_conn;
|
extern __xdata struct uip_conn * __xdata uip_conn;
|
||||||
/* The array containing all uIP connections. */
|
/* The array containing all uIP connections. */
|
||||||
extern __xdata struct uip_conn uip_conns[UIP_CONNS];
|
extern __xdata struct uip_conn uip_conns[UIP_CONNS];
|
||||||
/**
|
/**
|
||||||
@@ -1226,7 +1226,7 @@ struct uip_udp_conn {
|
|||||||
/**
|
/**
|
||||||
* The current UDP connection.
|
* The current UDP connection.
|
||||||
*/
|
*/
|
||||||
extern __xdata struct uip_udp_conn *uip_udp_conn;
|
extern __xdata struct uip_udp_conn * __xdata uip_udp_conn;
|
||||||
extern __xdata struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
|
extern __xdata struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
|
||||||
#endif /* UIP_UDP */
|
#endif /* UIP_UDP */
|
||||||
|
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ uip_arp_timer(void) __banked
|
|||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
uip_arp_update(__xdata u16_t *ipaddr, __xdata struct uip_eth_addr *ethaddr)
|
uip_arp_update(__xdata u16_t * __xdata ipaddr, __xdata struct uip_eth_addr * __xdata ethaddr)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
/* Walk through the ARP mapping table and try to find an entry to
|
/* Walk through the ARP mapping table and try to find an entry to
|
||||||
|
|||||||
@@ -298,11 +298,8 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The TCP maximum segment size.
|
* The TCP maximum segment size.
|
||||||
*
|
|
||||||
* This is should not be to set to more than
|
|
||||||
* UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
|
|
||||||
*/
|
*/
|
||||||
#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
|
#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN - UIP_BUFFER_EXTRA)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size of the advertised receiver's window.
|
* The size of the advertised receiver's window.
|
||||||
@@ -381,6 +378,17 @@
|
|||||||
#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE
|
#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE
|
||||||
#endif /* UIP_CONF_BUFFER_SIZE */
|
#endif /* UIP_CONF_BUFFER_SIZE */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytes of uip_buf kept out of the advertised MSS.
|
||||||
|
*
|
||||||
|
* \hideinitializer
|
||||||
|
*/
|
||||||
|
#ifndef UIP_CONF_BUFFER_EXTRA
|
||||||
|
#define UIP_BUFFER_EXTRA 0
|
||||||
|
#else /* UIP_CONF_BUFFER_EXTRA */
|
||||||
|
#define UIP_BUFFER_EXTRA UIP_CONF_BUFFER_EXTRA
|
||||||
|
#endif /* UIP_CONF_BUFFER_EXTRA */
|
||||||
|
|
||||||
|
|
||||||
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
|
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
|
||||||
|
|
||||||
@@ -447,7 +455,7 @@ void uip_log(char *msg);
|
|||||||
#ifdef UIP_CONF_LLH_LEN
|
#ifdef UIP_CONF_LLH_LEN
|
||||||
#define UIP_LLH_LEN UIP_CONF_LLH_LEN
|
#define UIP_LLH_LEN UIP_CONF_LLH_LEN
|
||||||
#else /* UIP_CONF_LLH_LEN */
|
#else /* UIP_CONF_LLH_LEN */
|
||||||
#define UIP_LLH_LEN ETHER_HEADER_SIZE + RTL_FRAME_DESC_SIZE
|
#define UIP_LLH_LEN (ETHER_HEADER_SIZE + RTL_FRAME_DESC_SIZE)
|
||||||
#endif /* UIP_CONF_LLH_LEN */
|
#endif /* UIP_CONF_LLH_LEN */
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||