1 Commits
Author SHA1 Message Date
logicog 984831620c Use multiple concurrent TCP connections
This uses multiple concurrent TCP connections by making the state
of the connection including the output buffer a part of the application
data. This leads to the buffer, to be sent length of data and the already
sent data to be part of that state and must be handed over to functions
that generate data. At this point this leads to an overuse of OSEG and DSEG
memory space so further work needs to be done on tuning the code.
Putting it into a branch for now.
2025-08-06 17:00:14 +02:00
251 changed files with 2742 additions and 26521 deletions

No files matched your search

-19
View File
@@ -1,19 +0,0 @@
.git/
.gitignore
.gitattributes
.github/
output/
installer/output/
*.bin
html_data.c
html_data.h
*.o
*.rel
*.lst
*.sym
*.asm
*.ihx
*.img
*.map
*.mem
*.lk
-30
View File
@@ -1,30 +0,0 @@
name: Build firmware
on:
push:
branches: ['**']
pull_request:
jobs:
build:
runs-on: ubuntu-latest
container:
image: debian:trixie
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: |
apt update
apt install make gcc sdcc xxd python-is-python3 libjson-c-dev zlib1g-dev -y
- name: Run the host-side unit tests
run: make -C test
- name: Check if machine.c can be compiled for all machines
run: make machine_check
- name: Make project (4x2/RTL8372)
run: make CI=1 MACHINE="KP_9000_6XHML_X2"
- name: Make project (8x1/RTL8373)
run: make CI=1 MACHINE="KP_9000_9XHML_X_V3_1"
- name: Make project with the health instrumentation
run: make clean && make CI=1 MACHINE="KP_9000_6XHML_X2" HEALTH=1
-13
View File
@@ -1,13 +0,0 @@
.gitignore
.idea/
output/
html_data.c
html_data.h
version.h
tools/httpd_sim
tools/injector
tools/fileadder
# host-test stand-ins for the two generated headers
!test/stub/html_data.h
!test/stub/version.h
-37
View File
@@ -1,37 +0,0 @@
# Change Log
## [0.x] - 2026-xx-XX
## Added
- Web UI
- Compress the embedded assets (minify + gzip) and switch to a single-page layout. #315
- Replace the multi-page UI with a themed single-page app: light, dark and Selenized themes following the browser by default,
English, Japanese and Chinese, save to flash merges the command log into the startup config and verifies the write,
firmware images are checked in the browser before upload. #429
## Changed
## Fixed
- Config
- A startup configuration line longer than the command buffer no longer stops the replay:
the offending line is skipped and the following lines are still applied.
- The web UI and the configuration upload now refuse a line the replay cannot take,
instead of writing it to flash.
## Breaking changes
- Config
- VLAN don't accept port `u`-suffix anymore.
So `vlan 1 4u` is not valid anymore.
Replace it with `vlan 1 4`.
- Commands
- port zero/`0` is treated as the `CPU_PORT`. #326
- Many commands don't accept the CPU_PORT anymore. See #334.
When the CPU_PORT is needed, the command/service will add the CPU_PORT automaticly.
Only `isolate` accept the CPU_PORT as destination port.
## [v0.1_aplha] - 2025-11-03
First release.
-19
View File
@@ -1,19 +0,0 @@
FROM debian:13-slim
RUN apt-get update && apt-get install -y \
make \
gcc \
sdcc \
xxd \
python3 \
libjson-c-dev \
git \
zlib1g-dev \
&& 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"]
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2025 The RTLPlayground Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+33 -165
View File
@@ -1,189 +1,57 @@
VERSION=0.1.0 BOOTLOADER_ADDRESS=0x100
IMAGESIZE = 524288
DEFAULT_CONFIG_LOCATION = 454656
CONFIG_LOCATION = 458752
HTML_LOCATION = 262144
ifeq ($(origin CC),default)
CC = sdcc CC = sdcc
endif CC_FLAGS = -mmcs51 -Ihttpd -Iuip
CC_FLAGS = -mmcs51 -I. -Ihttpd -Iuip ASM = sdas8051
ASM ?= sdas8051
AFLAGS= -plosgff AFLAGS= -plosgff
SUBDIRS := tools SUBDIRS := tools uip httpd
SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS)) SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS))
ifeq ($(MACHINE),) all: $(SUBDIRS) rtlplayground.bin
MACHINE:= $(shell grep "^\s*#define MACHINE_" machine.h | sed "s/^\s*#define MACHINE_//")
else
CC_FLAGS += -DMACHINE_$(MACHINE)
endif
# Health instrumentation and the "health" console command: HEALTH=1 gmake ...
ifneq ($(HEALTH),)
CC_FLAGS += -DHEALTH
endif
ifeq ($(CI),1) SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c
CC_FLAGS += --Werror OBJS = ${SRCS:.c=.rel}
endif OBJS += uip/timer.rel uip/uip-fw.rel uip/uip-neighbor.rel uip/uip-split.rel uip/uip.rel uip/uip_arp.rel uip/uiplib.rel httpd/httpd.rel httpd/page_impl.rel
BUILDDIR = output/$(MACHINE) html_data.c html_data.h: html tools
VERSION_HEADER := version.h tools/fileadder -a -s -b BANK1 -d html -p html_data
GIT_VERSION := $(shell git rev-parse --short HEAD)
ifeq ($(shell git status --porcelain --untracked-files=no),)
else
GIT_VERSION := $(GIT_VERSION)-dirty
endif
VERSION_EXTENSION = v$(VERSION)-$(GIT_VERSION)
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
create_build_dir:
mkdir -p "$(BUILDDIR)"
mkdir -p "$(BUILDDIR)/uip"
mkdir -p "$(BUILDDIR)/httpd"
mkdir -p "$(BUILDDIR)/crypto"
# 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 \
boot.c \
sfp.c \
syslog.c \
udp_apps.c \
crypto/chacha20.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 \
rtl837x_storm.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
OBJS = ${SRCS:%.c=$(BUILDDIR)/%.rel}
DEPS := ${SRCS:%.c=$(BUILDDIR)/%.d}
HTML := $(shell find html -name '*.js' -or -name '*.html' -or -name '*.svg' -or -name '*.css' -or -name '*.ico')
# Minified copy of the web UI sources, used as the fileadder input.
# The raw html/ sources stay untouched for development; the minified
# copy is a build artifact under output/.
HTML_MIN := output/html_min
.PHONY: html_min
html_min: $(HTML)
rm -rf $(HTML_MIN)
mkdir -p $(HTML_MIN)
@for f in $(HTML); do python3 tools/minify.py $$f $(HTML_MIN)/$$(basename $$f) || exit 1; done
html_data.c html_data.h &: $(HTML) | tools html_min
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -z -d $(HTML_MIN) -p html_data
$(VERSION_HEADER): FORCE
@printf '%s\n' "#ifndef VERSION_H" "#define VERSION_H" \
"#define VERSION_SW \"$(VERSION_EXTENSION)\"" \
"#define BUILD_DATE \"$(BUILD_DATE)\"" \
"#endif" > $(VERSION_HEADER).tmp
@cmp -s $(VERSION_HEADER).tmp $(VERSION_HEADER) \
&& rm -f $(VERSION_HEADER).tmp \
|| mv $(VERSION_HEADER).tmp $(VERSION_HEADER)
httpd: html_data.h httpd: html_data.h
$(SUBDIRS): $(SUBDIRS):
$(MAKE) -C $@ $(MAKE) -C $@
clean: $(SUBDIRSCLEAN) clean:
-rm -f html_data.c html_data.h $(VERSION_HEADER) -make -C uip clean
-if [ -d $(BUILDDIR) ]; then find $(BUILDDIR) -type f ! -name "*.bin" -delete; fi -make -C httpd clean
-rm html_data.c html_data.c
if [ -e rtlplayground.bin ]; then rm rtlplayground.bin; fi
if [ -e rtlplayground.asm ]; then rm rtlplayground.asm; fi
-rm *.ihx *.lk *.lst *.map *.mem *.rel *.rst *.sym *.bin
distclean: $(SUBDIRSCLEAN)
-rm -f html_data.c html_data.h $(VERSION_HEADER)
-rm -rf $(BUILDDIR)
$(SUBDIRSCLEAN): %.rel: %.c
$(MAKE) -C $(@:clean=) clean $(CC) $(CC_FLAGS) -c $<
# Objects depend on the flags they were built with, through a stamp file that %.rel: %.asm
# is rewritten only when CC_FLAGS actually changes. ${ASM} ${AFLAGS} $^
CCFLAGS_STAMP := $(BUILDDIR)/.ccflags
.PHONY: FORCE
FORCE:
$(CCFLAGS_STAMP): FORCE | create_build_dir
@echo '$(CC_FLAGS)' | cmp -s - $@ 2>/dev/null || echo '$(CC_FLAGS)' > $@
$(BUILDDIR)/%.rel: %.c $(CCFLAGS_STAMP) | create_build_dir html_data.h
$(CC) -MMD $(CC_FLAGS) -o $@ -c $<
$(BUILDDIR)/%.rel: %.asm $(CCFLAGS_STAMP) | create_build_dir
${ASM} ${AFLAGS} -o $@ $<
# mv -f $(addprefix $(basename $^), .lst .rel .sym) . # mv -f $(addprefix $(basename $^), .lst .rel .sym) .
$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtbank.rel $(BUILDDIR)/crc16.rel $(BUILDDIR)/crypto/chacha_8051.rel rtlplayground.ihx: crtstart.rel $(OBJS)
$(CC) $(CC_FLAGS) --xram-size 48896 -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-bBANK3=0x34000 -Wl-r -o $@ $^ $(CC) $(CC_FLAGS) -Wl-bHOME=${BOOTLOADER_ADDRESS} -Wl-bBANK1=0x14000 -Wl-r -o $@ $^
$(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx %.img: %.ihx
objcopy --input-target=ihex -O binary $< $@ objcopy --input-target=ihex -O binary $< $@
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img | tools %.bin: %.img
if [ -e $@ ]; then rm $@; fi if [ -e $@ ]; then rm $@; fi
tools/output/imagebuilder -i $^ $@ echo "0000000: 00 40" | xxd -r - $@
tools/output/fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@ cat $< >> $@
tools/output/fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@ truncate --size=16K $@
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -z -d $(HTML_MIN) -b BANK1 $@ dd if=$< skip=80 bs=1024 >>$@
tools/output/crc_calculator -u $@ tools/fileadder -s -d config.txt $@
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin output/rtlplayground.bin tools/fileadder -a -s -d html -p html_data $@
.PHONY: clean distclean all $(SUBDIRS) $(SUBDIRSCLEAN) create_build_dir .PHONY: clean all $(SUBDIRS)
.PRECIOUS: %.rel %.ihx .img
.PHONY:
machine_check:
@mkdir -p $(BUILDDIR)/tmp
@set -eo pipefail; \
for MACHINE in `grep -E '^[[:space:]]*(//[[:space:]]*)?#define MACHINE_' machine.h | sed -E 's%^[[:space:]]*(//[[:space:]]*)?#define MACHINE_%%' | awk '{print $$1}' | sort -u`; \
do \
echo "Checking $${MACHINE}"; \
$(CC) $(CC_FLAGS) -DMACHINE_$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine.c; \
$(CC) $(CC_FLAGS) -DMACHINE_$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine_init.c; \
done
@rm -rf $(BUILDDIR)/tmp
-include $(DEPS)
+196 -245
View File
@@ -1,245 +1,223 @@
# RTLPlayground # RTLPlayground
A Playground for Firmware development for advanced user of RTL8372/RTL8373 based 2.5GBit Switches. A Playground for Firmware development for RTL8372/RTL8373 based 2.5GBit Switches.
For each hardware configuration of these devices, there is usually a managed and an For each hardware configuration of these devices, there is usually a managed and an
unmanaged version sold, with mostly identical hardware. The aim is to provide management umanaged version sold, with mostly identical hardware. The aim is to provide management
features also for unmanaged devices with additional features such as Management VLAN, features also for unmanaged devices with additional features such as Management VLAN,
DHCP servers, multi-language support, IPv6 and TLS-encrypted web-pages. At present, however dhcp servers, multi-language support, IPv6 and TLS-encrypted web-pages.
only the following features are provided:
- A modern web-interface with mouse-over to display further information
- A serial console interface to configure all features
- IGMP to configure Multicast streaming
- Port configuration showing detailed information about own and Link-partner advertised
Speed settings and configuration of these settings on the local side
- Per-port configuration of frame sizes (MTUs) for Jumbo-Frame support or limiting MTUs
for particular devices
- EEE (Energy Efficient Ethernet) can be configured per-port. Detailed information is
provided for support offered by the link partner and the EEE status of a port.
- VLAN configuration
- SFP information is displayed on the inserted modules, the current sensor values such as
temperatures, RX and TX power are displayed in the CLI and as mouse-over on the web
- Mirror configuration
- Link Aggregation Groups can be set up
- Detailed information on port packet statistics
- Configuration saved to flash via the web-interface
- Firmware updates via the web
- Installation as a firmware upgrade from the original web-interface
<img width="1673" height="977" alt="GUI" src="doc/images/gui.png" /> The playground currently provides a minimal alternative firmware for both the managed and unmanaged switches.
When used with unmanaged switches, it will provide some management features such as
setting up VLANs, mirroring ports and provide a Web-Server (currently no functions,
really), but will need to be configured via a serial connection. Installation on
managed devices only makes sense for developers, as plenty of features of the managed
switches are not supported, yet.
While the firmware provides already considerable improvements over the original managed firmware, At this point, the firmware can be installed on the hardware as given below,
the firmware still lacks support for the proprietary loop prevention all of the ports and SFP-slots will be supported. The following has been tested:
protocols as well as DHCP. Spanning Tree is available (see doc/stp.md), but is On the keepLINK kp-9000-6hx-x (RTL8372 + RTL8221B 2.5GBit PHY: 5 x 2.5GBit + 1x 10GBit SFP+),
a simplified implementation - read that document before enabling it on a at present the system will provide the same featurs as a dumb switch plus a tiny
switch you administer over the network. If you need these features, do not install the playground on your managed TCP stack that will allow to reply to ARP and ping messages, thus enabling pinging the device.
devices. In any case, installation is strongly discouraged unless you can at least make VLAN and mirroring can be configured (but not saved to flash).
a backup of the original flash content via a SOIC clamp such as also used for BIOS The ports served by the RTL8372 will be 100M/1G/2.5G auto-detect. Port 5 to RTL8221B PHY
backups and can re-install that firmware in case something is wrong. For this no soldering SerDes configuration works and supports 1GBit and 2.5GBit Ethernet (SGMII/HISGMII).
skills are necessary. SFP module insert/removal identification and reading of the SFP EEProm works. SFP
module configuration works, too, tested for 1G, 2.5G and 10G Ethernet and Fiber modules.
The firmware supports all hardware features of devices with The 4-Port Ethernet + 2 Port SFP+ devices (e.g. KP-9000-6HX-x2) are fully supported, too
- 4 2.5GBit ports + 2 SFP+ ports (e.g. KP-9000-6hx-x2) with the same features as above. In particular all fiber/Ethernet
- 5 2.5GBIT + 1 SFP+ port modules work in both SFP+ ports.
- 8 2.5GBit + 1 SFP+ port
Devices sold usually have a fairly common design, however there may be differences in the LED On the 9-port devices with RTL8273 + RTL8224 (for example kp-9000-9xh-x) all ports will
configuration (switches have LEDs with different colours and use types of LEDs). The list work for switching and CPU-access, the SFP+ port will work normally and TCP connectivity
of tested devices can be found in [Supported devices](doc/supported_devices.md). will work as above. Not all features of the RTL8224-ports (the first 4) have been tested.
To do meaningful development you will need to use a serial console, so soldering skills To do meaningful development you will need to use a serial console, so soldering skills
are required. Flashing must be done via a SOIC-8 PatchClamp or by soldering a socket are required. Flashing must be done via a SOIC-8 PatchClamp or by soldering a socket
for the flash chip. for the flash chip.
UPDATE: The Code comes with a port of the [uIP](https://github.com/adamdunkels/uip)
TCP/IP stack and includes a minimal web-server that can be used to work with the switch,
so if you use a patch-clamp for updating the firmware (~3 USD/EUR), you can try this
out without the need to solder anything. See the instructions below.
Note that updating the firmware of a managed switch with the images created in this
project via the OEM web-interface will not work, because it is currently unknown how
to generate the require checksum, see this
[issue](https://github.com/up-n-atom/SWTG118AS/issues/4).
However, if you use the patch-clamp to flash, this is not a problem.
If you don't want to open your device, you can use the project's code to learn about the If you don't want to open your device, you can use the project's code to learn about the
devices by looking at the image using e.g. Ghidra. If you want to contribute to the devices by looking at the image using e.g. Ghidra.
design of the web-interface or get a feeling for the interface first, a standalone
device simulator is provided, which runs entirely under Linux as a local webserver.
## (0) Compiling Requirements ## Compiling
Install the following particular build requisites (Debian 12, should work on Ubuntu)
Install the following particular build requisites (Debian 12/13), note that Ubuntu 24.04
still has an older version of sdcc, but you will need sdcc version 4.5 for the code to compile:
``` ```
sudo apt install make gcc sdcc xxd python-is-python3 libjson-c-dev zlib1g-dev sudo apt install sdcc xxd
``` ```
<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
Edit machine.h with an editor like vi or nano. Select the correct machine the firmware should build for.
> [!TIP]
> You can write configuration parameters in config.txt (see below) in order your switch to get
> straight at the first boot, a correct IP configuration.
Now, building the firmware image should work: Now, building the firmware image should work:
``` ```
make $ make
sdas8051 -plosgff crtstart.asm
sdcc -mmcs51 -c rtlplayground.c
sdcc -mmcs51 -c rtl837x_flash.c
sdcc -mmcs51 -Wl-bHOME=0x100 -o rtlplayground.ihx crtstart.rel rtlplayground.rel rtl837x_flash.rel
objcopy --input-target=ihex -O binary rtlplayground.ihx rtlplayground.img
if [ -e rtlplayground.bin ]; then rm rtlplayground.bin; fi
echo "0000000: 00 40" | xxd -r - rtlplayground.bin
cat rtlplayground.img >> rtlplayground.bin
``` ```
Note, that the image generated ends in .bin, not .img, in order to make IMSProg happy. Note, that the image generated ends in .bin, not .img, in order to make
IMSProg happy.
image location is stored in `RTLPlayground/output/rtlplayground_version_machine.bin` ## Installation
for example You can play with the image using ghidra or flash real Switch Hardware
### Supported Hardware
If you do not have an RTL837x-based switch device such as the ones
mentionned here: [Up-N-Atoms 2.5 GBit RTL Switch hacking guide]
(https://github.com/up-n-atom/SWTG118AS) or one of the other that
deployment was tested on, including:
- 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
### Understanding the image using ghidra
Start ghidra, load file starting from offset 0x0002 into
memory starting at 0x0000. The lengthe is 0x10000. Select generic 8051, big
endian.
After loading, the boot vector is at 0x0000, which will jump to 0x0100 for
the boot routine.
The firmware uses only bank 1 of the RTL837x since it is quite short.
Otherwise the firmware would be organized as follows
``` ```
rtlplayground-v0.1.0-12c98ba-dirty-LIANGUO_ZX_SWTGW215AS.bin --------------------------- 0x0000 ---------------------------------
Boot-Vector
ISRs
Common Code
Trampoline for inter-bank calls
Inter-bank calls, calling trampoline, one for each callable function
----- Bank 1 0x4000 ------ ---- Bank 2 0x4000 ----- -------- .....
Overlay 1 Overlay 2 Overlay n
--------- 0xffff --------- -------- 0xffff -------- -------- 0xffff
``` ```
The RTL837x firmware images are organized as follows:
The first 2 bytes of the image give the size of the prefetched data at the
start of the CPU power up. The default is 0x4000 (bytes: 0x00 0x40), which
means that the entire shared area of the code memory in all banks,
0x4000 bytes is read immediately into the code RAM.
Common code starts at
0x0002 in the image and has length 0x3ffd, the first bank starts at 0x4000
in the image, is mapped to 0x4000 and has length 0xc000. The second bank
starts at 0x10000, is mapped to 0x4000 and has length 0xc000. The third
bank would start at 0x1c000 and would again be mapped to 0x4000.
There are about 30 banks in use for managed switches, unmanaged ones use
2-3, while the hardware would allow to use 0x3f banks, i.e. up to 4 MB of
flash.
The current image uses Common BANK0 and the first BANK1 via sdccs __banked
function keyword and custom banking trampoline code for the RTL837x in
assembler.
### Hardware supported by the code so far
-The following hardware is supported:
- Clock generation, including different divider settings
- Interrupt control for timer, serial, external irqs 0, 1
- Serial console via SFRs
- Flash operations via SFRs
- Bank switching via SFRs
- Access to Switch registers via SFRs
- LED setup
- Reset
- Some switch settings such as MAC configuration
- GPIO to detect SFP module insert/removal/RX-LOS
- I2C to read SFP EEPROM on 1 and 2 SFP slot devices
- NIC setup
- L2 learning table access, L2 table flushing
- VLAN setup/configuration
- Port mirroring
- Access to PHYs via MDIO (clause 45 via SFR):
- Internal PHYs of RTL8372 and RTL8373
- RTL8221 (1x2.5GBit port on devices with 5 ports)
- RTL8224 (4x2.5GBit ports on devices with 8 ports)
- SerDes settings of SoC via SFR:
- Configure SFPs with 10Gbit/2.5Gbit/1Gbit (Ethernet and Fiber SFP(+) tested)
- RTL8221, RTL8224
- NIC TX and RX of packets via SFRs
- send and receive Ethernet frames via SFRs and Switch registers
- RTL-tags and VLAN ingress-tag decoding for CPU-port
Ethernet frame RX IRQ via IRQ1 is conceptually understood, but not activated. RX is
currently done via polling, which allows ping-times of <10ms.
The RTL8372/3 have 256 bytes of internal RAM (INTMEM) accessible through MOV
instructions, which are used for the stack and important globals. Some of
these are bit-adressable, e.g. for storing global flags.
Additionally, 64kB of extended RAM (XMEM) is built in, which is accessed
through the MOVX instruction. It is used for global variables, for most
of the function argument passing that is not done using the 8 registers
R0-R7 or registers A/B, and for local variables (which requires extremely
careful planning). The flash memory is transparently accessible for code
being executed and can be used to store configuration. Access is done through
the MOVC instruction, possibly setting the bank register before and
resetting it to access the entire 4MB space. Code is prefetched from flash
and cached in a small RAM automatically by the HW.
The peripherial functions are accessed through 2 different mechanisms:
- Special Function Registers (SFRs, 0x80-0xff) for banking, timers, UART, access to
switch registers, MDIO, SPI (flash) and NIC transfers. Some SFRs are not
used for HW purposes and can be used as RAM. Some SFRs are bit-adressable,
allowing for very tight event wait loops (a single 2-byte instruction).
- 0x10000 switch registers, which appear to be very similar to the registers
of the RTL838x, for which source code and datasheets are available. This
controls clock dividers, GPIO/LEDs and general switch functionality.
The playground image shows access to the different types of memory using the
SDCC compiler. Any support of Linux or e.g. Zephyr would require porting gcc.
There are FreeRTOS ports to 8051 processors using sdcc, however.
### Installation on an actual switch
> [!CAUTION] > [!CAUTION]
> This image can be flashed directly to the chip OR through the firmware update/upgrade > NOTE THAT WHILE THIS PROCEDURE HAS BEEN SUCCESSFULLY TESTED ON ALL DEVICES ABOVE,
> interface of RTLPlayground interface > ABSOLUTELY NO GUARANTY CAN BE GIVEN THAT YOU WILL NOT DESTROY YOUR SWITCH,
> ANY OTHER EQUIPMENT INVOLVED OR HARM YOURSELF BY OPENING THE ELECTRONIC
> DEVICE. OPENING THE SWITCH WILL VOID ITS WARRANTY.
## (2) Compiling for OEM running device with management options (web upgrade) There is no support for uploading the firmware via ethernet. Instead you
need to open the switch and flash the image directly onto the flash chip,
which is done easiest using a SOIC-8 clip (alternatively you de-solder the
flash chip and install a SOIC adapter):
- Disconnect power from switch
- Attach the clip onto the flash chip
- Connect USB of flash programmer, the power LED on the switch will light
up, check cabling if not. Don't panic, mixing up GND and 3.3V does not
seem to destroy the switch (at leasts the on I did this to).
- Use IMSProg (flashrom should work, too) to detect the clip
- MAKE A BACKUP OF THE EXISTING FIRMWARE!
- then load the firmware into IMSProg
- and program flash
Managed switches can be updated from the existing original firmware using a SPECIFIC upgrade image. Now you can connect a serial cable to the UART port found on all the
You first need to build the firmware for direct chip flashing : See below (1) devices, set 8N1 @ 115200 baud and power up the switch.
Then The device will perform some examples and provide a minimal console, the
documentation of which can be found in the source code rtlplayground.c`.
```
cd installer
make
```
image location is stored in `RTLPlayground/installer/output/rtlplayground_oem_upgrade.bin`
> [!CAUTION]
> This image must ONLY be used for original OEM firmware web interface firmware upgrade.
> You do not need this image if you are already on RTLplayground firmware.
> Unless you go back to the original OEM firmware, you would only flash this specific firmware
> only once. Future upgrades of RTLPlayground will only need to follow (1)
example of compilation console output
```
RTLPlayground/installer$ make
mkdir -p output
gcc updatebuilder.c -o output/updatebuilder
sdas8051 -plosgff -o output/crtstart.rel crtstart.asm
sdcc -mmcs51 --code-loc 0x1000 -o output/installer.rel -c installer.c
sdcc -mmcs51 -Wl-bHOME=0x1100 -Wl-r -o output/rtlinstaller.ihx output/crtstart.rel output/installer.rel
./output/updatebuilder -i output/rtlinstaller.ihx -o output/rtlplayground_oem_upgrade.bin ../output/rtlplayground.bin
Input file size: 524288
Bytes read: 524288
EOF
Payload sum 1 is: 0x25100
Payload sum 2 is: 0x25100
Payload sum with header is: 0x264ec
Payload sum is: 0xf8fe94
Header checksum is: 0x5a1
```
## (3) Sandbox Usage with Ghidra (optional)
You can play with the image using ghidra or flash real Switch Hardware. For
ghidra see this information about [Ghidra images](doc/ghidra.md).
## (4) Installation through the Web interface (software way)
Managed switches (OEM firmware of RTLplayground firmware) can be upgraded via the web interface.
Unmanaged switch cannot be flashed this way (see 5).
Go to "Firmware update" tab, select the correct file.
> [!IMPORTANT]
> If your device already runs RTLPlayground, you must upload the binary file /RTLPlayground/output/rtlplayground_Version_Machine.bin
> If your device is OEM, you must upload the binary file /RTLPlayground/installer/outputrtlplayground_oem_upgrade.bin
> [!CAUTION]
> Check one more time that your device matches the machine type before flashing.
> Be sure you have a backup of the original firmware before diving in RTLPlayground.
Finally, push the Upload File Button and you're done !
## (5) Flashing the ROM directly (hardware way, but also only way to rescue)
This procedure is the only way to flash unmanaged switches, if the ROM chip is large enough.
This is also the only way to unbrick your device if something went wrong.
> [!IMPORTANT]
> You need a SOIC-8 clip to flash the ROM chip directly onboard.
> Alternatively you can de-solder the flash chip and install a SOIC adapter).
> For flashing the chip directly, you must use the binary file /RTLPlayground/output/rtlplayground_Version_Machine.bin
> [!CAUTION]
> As you need to open your switch case, consider that the warranty is gone.
- Disconnect power from switch.
- Open the switch.
- Attach the clip onto the flash chip (Red line on Pin 1, Pin 1 has a point marker).
- Connect USB of flash programmer, the power LED on the switch will light up, check cabling if not.
- Don't panic, mixing up GND and 3.3V usually does not destroy the switch.
- Use IMSProg, Flashrom, or whatever Programmer to detect the chip.
- MAKE A BACKUP (DUMP) OF THE EXISTING FIRMWARE !
- ERASE THE ROM (BLANK) !
- Load the firmware into IMSProg.
- Flash is to the ROM chip.
- Disconnect the clip from the ROM chip.
- You're done, ready for the first boot.
## (6) Connecting a serial interface (optional)
You can connect a serial cable to the UART port found on all the devices, set 8N1 @ 115200 baud.
## (7) Power Up
When you power up the switch, the device will perform some examples and provide a minimal console
(if wired to a serial interface), the documentation of which can be found in the source code rtlplayground.c`.
## (8) The web-interface
The web-interface can be reached under the [default 192.168.10.247](http://192.168.10.247) unless you
specified an IP address in the config.txt before compilation.
> [!TIP]
> The default password is `1234`.
## (9) The command line
## The command line
The command line is very rudimentary and mostly for testing purposes. The command line is very rudimentary and mostly for testing purposes.
The following is a boot-log with some examples: The following is a boot-log with some examples:
``` ```
@@ -304,6 +282,7 @@ PORT 04 1G
<MODULE INSERTED> Rate: 67 Encoding: 01 <MODULE INSERTED> Rate: 67 Encoding: 01
Lightron Inc. WSPXG-ES3LC-IHA 0000 Lightron Inc. WSPXG-ES3LC-IHA 0000
> stat > stat
CMD: stat CMD: stat
Port State Link TxGood TxBad RxGood RxBad Port State Link TxGood TxBad RxGood RxBad
@@ -321,44 +300,16 @@ Lightron Inc. WSPXG-ES3LC-IHA 0000
CMD: sfp CMD: sfp
Rate: 67 Encoding: 01 Rate: 67 Encoding: 01
Lightron Inc. WSPXG-ES3LC-IHA 0000 Lightron Inc. WSPXG-ES3LC-IHA 0000
```
## (10) Advanced configuration
You can configure more deeply the switch without the need of the console mode.
While in compilation part, you might write directly to config.txt file before making the binary firmware
``` ```
nano config.txt
```
If you want to modify settings after the flash is done, go to the System tab and find the Startup Configuration.
<img width="1673" height="978" alt="ADVANCED SETTINGS" src="doc/images/advanced_settings.png" />
```
ip xxx.xxx.xxx.xxx = IP address of the switch
gw yyy.yyy.yyy.yyy = IP address of the gateway
netmask zzz.zzz.zzz.zzz = Network mask of the switch
port x name xxx = Name xxx the port number x
port z 1g = Set 1g speed for port z
igmp on/off = Turn IGMP on or off
session xxxx = Web session timeout in seconds (default 200)
```
[To be continue]
Enjoy playing! Enjoy playing!
## (11) Other documents ## Other documents
The following documents give further documentation on specific features of
The following documents give further documentation on specific features of the RTL837x SoCs: the RTL837x SoCs:
- [RTL8372/3 Feature support](doc/hardware.md)
- [CPU Port](doc/CpuPort.md) - [CPU Port](doc/CpuPort.md)
- [L2 learning](doc/l2.md) - [L2 learning](doc/l2.md)
- [IGMP (IP-MC streaming)](doc/igmp.md) - [Mirroring](doc/mirroring.md)
- [SFP+ ports](doc/sfp.md) - [SFP+ ports](doc/sfp.md)
- [Trunking aka. port aggregation](doc/trunking.md) - [Trunking aka. port aggregation](doc/trunking.md)
- [VLAN](doc/vlan.md) - [VLAN](doc/vlan.md)
- [Storm control](doc/storm_control.md)
- [Modifications and Flash replacement](doc/mods.md)
-479
View File
@@ -1,479 +0,0 @@
#pragma codeseg BANK3
#pragma constseg BANK3
#include <8051.h>
#include <stdint.h>
#include <stdbool.h>
#include "rtl837x_sfr.h"
#include "rtl837x_regs.h"
#include "rtl837x_common.h"
#include "rtl837x_flash.h"
#include "rtl837x_pins.h"
#include "rtl837x_phy.h"
#include "rtl837x_port.h"
#include "rtl837x_init.h"
#include "machine.h"
#include "phy.h"
#include "boot.h"
extern __code const struct machine machine;
extern __xdata struct machine_runtime machine_detected;
extern __xdata uint8_t sfr_data[4];
extern volatile __xdata uint32_t ticks;
__xdata uint32_t rtl8224_release_tick;
extern __xdata uint8_t tx_seq;
extern __code const uint8_t * __code const hex;
void sds_config_mac(uint8_t sds, uint8_t mode) __banked
{
reg_read_m(RTL837X_REG_SDS_MODES);
sfr_data[0] = 0;
sfr_data[1] = 0;
switch (sds) {
case 0:
sfr_mask_data(0, 0x1f, mode);
break;
case 1:
sfr_mask_data(0, 0xe0, mode << 5);
sfr_mask_data(1, 0x03, mode >> 3);
break;
case 2:
sfr_mask_data(1, 0xfc, 0x02 << 2);
}
if (machine_detected.isRTL8373) // Set 3rd SERDES Mode to 0x2 for RTL8224
sfr_mask_data(1, 0xfc, 0x02 << 2);
else
sfr_data[2] &= 0x03;
reg_write_m(RTL837X_REG_SDS_MODES);
print_string("\nRTL837X_REG_SDS_MODES: ");
print_reg(RTL837X_REG_SDS_MODES);
print_string("\n");
}
void early_boot_handle_button(void) __banked
{
if (machine.reset_pin == GPIO_NA)
return;
gpio_input_setup(machine.reset_pin);
// Debounce after init
delay(100);
// If the button is not already held at boot, continue normally.
if (gpio_pin_test(machine.reset_pin))
return;
set_sys_led_state(SYS_LED_FAST);
print_string("\n[Reset button held at boot]\n");
if (gpio_pin_test(machine.reset_pin))
return;
const __xdata uint32_t min_hold_ticks = 10UL * SYS_TICK_HZ;
const __xdata uint32_t max_hold_ticks = 30UL * SYS_TICK_HZ;
const __xdata uint32_t blink_ticks = SYS_TICK_HZ / 10; // 100 ms
const __xdata uint32_t pause_ticks = SYS_TICK_HZ / 2; // 500 ms
__xdata uint32_t start_ticks = ticks;
__xdata uint32_t last_blink_step = start_ticks;
__xdata uint8_t blink_step = 0;
set_sys_led_state(SYS_LED_ON);
while (!gpio_pin_test(machine.reset_pin)) {
__xdata uint32_t held_ticks = ticks - start_ticks;
if (held_ticks > max_hold_ticks) {
print_string("[Button held >30s at boot; continuing normal boot]\n");
return;
}
// Double blink pattern while button is held:
// ON (100ms), OFF (100ms), ON (100ms), OFF (500ms)
__xdata uint32_t step_ticks = (blink_step == 3) ? pause_ticks : blink_ticks;
if ((ticks - last_blink_step) >= step_ticks) {
blink_step = (blink_step + 1) & 0x3;
set_sys_led_state((blink_step == 0 || blink_step == 2) ? SYS_LED_ON : SYS_LED_OFF);
last_blink_step = ticks;
}
PCON |= 1;
}
set_sys_led_state(SYS_LED_ON);
if ((ticks - start_ticks) >= min_hold_ticks) {
print_string("[Button held 10s-30s at boot; restoring default config]\n");
set_sys_led_state(SYS_LED_FAST);
flash_default_config();
delay(3UL * SYS_TICK_HZ);
}
}
/*
* Configure the SerDes of the SoC for a particular mode
* to connect to an SFP module or a PHY
* Valid modes are SDS_10GR, SDS_QXGMII, SDS_HISGMII, SDS_HSG, SDS_SGMII and SDS_1000BX_FIBER
* The SerDes ID may be 0 or 1 for RTL8272 and 0-2 for RTL8373
* SDS_QXGMII is used for 10G Fiber, RTL8224 and RTL8261BE
*/
void sds_config(uint8_t sds, uint8_t mode) __banked
{
print_string("sds_config sds: "); print_byte(sds); print_string(", mode: "); print_byte(mode); write_char('\n');
sds_config_mac(sds, mode);
if (mode == SDS_10GR || mode == SDS_QXGMII)
sds_write_v(sds, 0x21, 0x10, 0x4480); // Q002110:6480
else
sds_write_v(sds, 0x21, 0x10, 0x6480); // Q002110:6480
sds_write_v(sds, 0x21, 0x13, 0x0400); // Q002113:0400
sds_write_v(sds, 0x21, 0x18, 0x6d02); // Q002118:6d02
sds_write_v(sds, 0x21, 0x1b, 0x424e); // Q00211b:424e
sds_write_v(sds, 0x21, 0x1d, 0x0002); // Q00211d:0002
sds_write_v(sds, 0x36, 0x1c, 0x1390); // Q00361c:1390
sds_write_v(sds, 0x36, 0x14, 0x003f); // Q003614:003f
uint8_t page = 0;
uint16_t v = 0;
switch (mode) {
case SDS_SGMII:
case SDS_1000BX_FIBER:
v = 0x0300;
page = 0x24;
break;
case SDS_HISGMII:
case SDS_HSG:
v = 0x0200;
page = 0x28;
break;
case SDS_10GR:
case SDS_QXGMII:
v = 0x0200;
page = 0x2e;
break;
case SDS_100FX:
v = 0x0200;
page = 0x26;
break;
default:
print_string("Error in SDS Mode\n");
return;
}
sds_write_v(sds, 0x36, 0x10, v); // Q003610:0200
if (page == 0x2e) { // 10G Fiber / SDS_QXGMII
sds_write_v(sds, page, 0x04, 0x0080); // Q012e04:0080
sds_write_v(sds, page, 0x06, 0x0408); // Q012e06:0408
sds_write_v(sds, page, 0x07, 0x020d); // Q012e07:020d
sds_write_v(sds, page, 0x09, 0x0601); // Q012e09:0601
sds_write_v(sds, page, 0x0b, 0x222c); // Q012e0b:222c
sds_write_v(sds, page, 0x0c, 0xa217); // Q012e0c:a217
sds_write_v(sds, page, 0x0d, 0xfe40); // Q012e0d:fe40
sds_write_v(sds, page, 0x15, 0xf5c1); // Q012e15:f5c1
} else {
sds_write_v(sds, page, 0x04, 0x0080); // Q002804:0080
sds_write_v(sds, page, 0x07, 0x1201); // Q002807:1201
sds_write_v(sds, page, 0x09, 0x0601); // Q002809:0601
sds_write_v(sds, page, 0x0b, 0x232c); // Q00280b:232c
sds_write_v(sds, page, 0x0c, 0x9217); // Q00280c:9217
sds_write_v(sds, page, 0x0f, 0x5b50); // Q00280f:5b50
sds_write_v(sds, page, 0x15, 0xe7c1); // Q002815:e7f1 BUG !
}
sds_write_v(sds, page, 0x16, 0x0443); // Q002816:0443 / Q012e16:0443
sds_write_v(sds, page, 0x1d, 0xabb0); // Q00281d:abb0 / Q012e1d:abb0
sds_write_v(sds, 0x06, 0x12, 0x5078); // Q000612:5078
sds_write_v(sds, 0x07, 0x06, 0x9401); // Q000706:9401
sds_write_v(sds, 0x07, 0x08, 0x9401); // Q000708:9401
sds_write_v(sds, 0x07, 0x0a, 0x9401); // Q00070a:9401
sds_write_v(sds, 0x07, 0x0c, 0x9401); // Q00070c:9401
sds_write_v(sds, 0x1f, 0x0b, 0x0003); // Q001f0b:0003
sds_write_v(sds, 0x06, 0x03, 0xc45c); // Q000603:c45c
// RTL8261BE
if (machine.n_10g && mode == SDS_QXGMII) {
sds_write_v(sds, 0x06, 0x1f, 0x2100); // Q00061f:2100
sds_write_v(sds, 0x07, 0x11, 0x054f); // Q000711:054f
sds_write_v(sds, 0x20, 0x00, 0x0030); // Q002000:0030
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
sds_write_v(sds, 0x20, 0x00, 0x0050); // Q002000:0050
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
sds_write_v(sds, 0x20, 0x00, 0x0cd0); // Q002000:0cd0
sds_write_v(sds, 0x20, 0x00, 0x04d0); // Q002000:04d0
sds_write_v(sds, 0x20, 0x00, 0x04d0); // Q002000:04d0
sds_write_v(sds, 0x20, 0x00, 0x0cd0); // Q002000:0cd0
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
sds_write_v(sds, 0x20, 0x00, 0x0050); // Q002000:0050
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
sds_write_v(sds, 0x20, 0x00, 0x0030); // Q002000:0030
sds_write_v(sds, 0x20, 0x00, 0x0000); // Q002000:0000
sds_write_v(sds, 0x1f, 0x00, 0x000b); // Q001f00:000b
sds_write_v(sds, 0x1f, 0x00, 0x0000); // Q001f00:0000
return;
}
if (mode != SDS_QXGMII)
sds_write_v(sds, 0x06, 0x1f, 0x2100); // Q00061f:2100
if (mode == SDS_1000BX_FIBER) {
sds_write_v(sds, 0x02, 0x04, 0x0020); // Q000204:0020
sds_write_v(sds, 0x00, 0x02, 0x73d0); // Q000002:73d0
sds_write_v(sds, 0x00, 0x04, 0x074d); // Q000004:074d
sds_write_v(sds, 0x20, 0x04, 0x0000); // Q002000:0000
sds_write_v(sds, 0x1f, 0x00, 0x0000); // Q001f00:0000
}
}
void rtl8224_enable(void) __banked
{
// Set Pin 4 low
reg_bit_clear(RTL837X_REG_GPIO_32_63_OUTPUT, 4);
// Configure Pin as output
reg_bit_set(RTL837X_REG_GPIO_32_63_DIRECTION, 4);
delay(4);
// Set pin 4 high
reg_bit_set(RTL837X_REG_GPIO_32_63_OUTPUT, 4);
rtl8224_release_tick = ticks;
}
void nic_setup(void) __banked
{
// Enable NIC
// r6040:00000100 R6040-00001100
reg_bit_set(RTL837X_REG_HW_CONF, 0xc);
// This sets the size of the RX buffer, the filling level is in 0x7874
// R7848-000004ff
REG_SET(RTL837X_REG_NIC_RXBUFF_RX, 0x4ff);
// R7844-000007fe
REG_SET(RTL837X_REG_NIC_BUFFSIZE_TX, 0x7fe);
// Configure NIC RX to receive various types of packets
// RTL837X_REG_RX_CTRL: Set bits 24-31 to 0x4, clear bits 16/17
reg_read_m(RTL837X_REG_RX_CTRL);
sfr_mask_data(3, 0xff, 0x04);
sfr_mask_data(2, 0x03, 0);
reg_write_m(RTL837X_REG_RX_CTRL);
// Enable NIC TX (set bit 0)
reg_bit_set(RTL837X_REG_TX_CTRL, 0);
// Enable NIC RX (set bit 0)
reg_bit_set(RTL837X_REG_RX_CTRL, 0);
// Drop packets with invalid CRC
reg_bit_clear(RTL837X_REG_RX_CTRL, 2);
// R603c-00000200
// CPU-port is CPU-Tag aware (bit 9)
REG_SET(RTL837X_REG_CPU_TAG_AWARE_PMASK, 0x200);
// Insert CPU-tag for internally received packets (bit 0), MODE is 0, i.e. ALL packets (bits 8-9)
reg_read_m(RTL837X_REG_CPU_TAG);
sfr_mask_data(0, 1, 1);
sfr_mask_data(1, 3, 0);
reg_write_m(RTL837X_REG_CPU_TAG);
// Force MAC mode of the CPU port (port 9)
// r6368:00000194 R6368-00000197
reg_read_m(RTL837X_REG_MAC_FORCE_MODE + 9 * 4);
sfr_mask_data(0, 0, 3); // Set bits 0, 1: Force link
reg_write_m(RTL837X_REG_MAC_FORCE_MODE+ 9 * 4);
// Sequence number of TX packets
tx_seq = 0;
}
void rtl8373_revision(void) __banked
{
reg_read_m(RTL837X_REG_CHIP_INFO);
sfr_mask_data(2, 0x0a, 0x0a); // Enable reading version
reg_write_m(RTL837X_REG_CHIP_INFO);
delay(50);
reg_read_m(RTL837X_REG_CHIP_INFO);
print_string("CPU revision: "); print_byte(sfr_data[2]); print_byte(sfr_data[2]); write_char('\n');
sfr_mask_data(2, 0x0a, 0x00); // Enable reading version
reg_write_m(RTL837X_REG_CHIP_INFO);
}
/*
* The SoC manages Link-State for steering the LEDs and can set PHY-settings
* automatically through Realtek's SMI (Simple Managagement) Interface, a
* proprietary version of MDIO which for example allows for more PHYs on the same
* bus.
* Configure polling via SMI and the interface setup during boot.
*/
void init_smi(void) __banked
{
print_string("\ninit_switch called\n");
/* Set the SMI(i.e.I2C) type for PHY polling, 0b01 is 2.5/10G PHY. Disable (0b00) for the SFP-ports
* which are at port 8 and additionally at port 3 for a dual SFP device
*/
// Default: 0x00005555
// Workaround for SDCC BUG 4070: SFR_DATA_U32 = 0x00005555;
SFR_DATA_U16_UPPER = 0x0000;
SFR_DATA_U16 = 0x5555;
if (machine.n_10g == 2) {
// 0x00015555, only change the bytes that differs from the default.
SFR_DATA_16 = 0x01;
} else if (machine.n_sfp == 2)
// 0x00005515
SFR_DATA_0 = 0x15;
reg_write(RTL837X_REG_SMI_MAC_TYPE);
// Configure polling of all PHYs by the MAC to detect link-state changes
// Default: 0x000000ff
// Workaround for SDCC BUG 4070: SFR_DATA_U32 = 0x000000ff;
SFR_DATA_U16_UPPER = 0x0000;
SFR_DATA_U16 = 0x00ff;
if (!machine_detected.isRTL8373) {
if (machine.n_sfp == 2) {
// 0x000000f0, only change the bytes that differs from the default.
SFR_DATA_0 = 0xf0;
} else {
// 0x000001f8, only change the bytes that differs from the default.
SFR_DATA_8 = 0x01;
SFR_DATA_0 = 0xf8;
}
}
reg_write(RTL837X_REG_SMI_PORT_POLLING);
// Enable MDC
reg_read_m(RTL837X_REG_SMI_CTRL);
sfr_mask_data(1, 0, 0x70); // Set bits 12-14 to enable MDC for SMI0-SMI2
reg_write_m(RTL837X_REG_SMI_CTRL);
delay(50);
if (!machine_detected.isRTL8373) {
// Change I2C addresses for SMI of the non-existent PHYs
// r6450:000020e6 R6450-000000e6
reg_read_m(RTL837X_REG_SMI_PORT6_9_ADDR);
sfr_mask_data(1, 0x7c, 0);
reg_write_m(RTL837X_REG_SMI_PORT6_9_ADDR);
// r644c:0a418820 R644c-0a400820
reg_read_m(RTL837X_REG_SMI_PORT0_5_ADDR);
sfr_mask_data(2, 0x0f, 0);
sfr_mask_data(1, 0x80, 0);
reg_write_m(RTL837X_REG_SMI_PORT0_5_ADDR);
}
if (machine.n_10g == 2) {
// Set address of second external PHY on port 8
REG_SET(RTL837X_REG_SMI_PORT6_9_ADDR, 0x000040e6);
}
}
void setup_i2c(void) __banked
{
REG_SET(RTL837X_REG_I2C_MST_IF_CTRL, 0);
// Configure SFP EEPROM address (0x50) as I2C device address
// Configure SFP readings address (0x51) as I2C device address
REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16), 0x50 >> 5, (0x50 << 3) & 0xff);
REG_SET(RTL837X_REG_I2C_CTRL2, 0);
// HW Control register, enable I2C depending on PIN configuration
reg_read_m(RTL837X_PIN_MUX_1);
for (uint8_t sfp = 0; sfp < machine.n_sfp; sfp++) {
uint8_t i2c = machine.sfp_port[sfp].i2c;
uint8_t scl_bus = (i2c >> RTL837X_REG_I2C_SCL_SHIFT) & RTL837X_REG_I2C_SCL_MASK;
uint8_t sda_bus = (i2c >> RTL837X_REG_I2C_SDA_SHIFT) & RTL837X_REG_I2C_SDA_MASK;
print_string("Configuring I2C for SFP idx="); print_byte(sfp); print_string(" SCL="); print_byte(scl_bus); print_string(", SDA="); print_byte(sda_bus); write_char('\n');
// `& RTL837X_REG_I2C_SCL_MASK` is needed to silens a compiler warning 110.
switch (scl_bus & RTL837X_REG_I2C_SCL_MASK) {
case 3:
// Bit 5-6 0b10 -> SCL (implies enabled SDA on bus 3)
sfr_mask_data(0, 0x60, 0x40);
break;
case 2:
// Bit 15-16 0b01 -> SCL
sfr_mask_data(1, 0x80, 0x80);
sfr_mask_data(2, 0x01, 0x00);
break;
case 1:
// Bit 11-12 0b01 -> SCL
sfr_mask_data(1, 0x18, 0x08);
break;
case 0:
// Bit 7-8 0b01 -> SCL
sfr_mask_data(0, 0x80, 0x80);
sfr_mask_data(1, 0x01, 0x00);
break;
}
switch (sda_bus) {
case 4:
// Bit 29 0b0 -> SDA
sfr_mask_data(3, 0x20, 0x00);
break;
case 3:
// Bit 5-6 0b10 -> SDA (implies enabled SCL on bus 3)
sfr_mask_data(0, 0x60, 0x40);
break;
case 2:
// Bit 17-18 0b01 -> SDA
sfr_mask_data(2, 0x06, 0x02);
break;
case 1:
// Bit 13-14 0b01 -> SDA
sfr_mask_data(1, 0x60, 0x20);
break;
case 0:
// Bit 9-10 0b01 -> SDA
sfr_mask_data(1, 0x06, 0x02);
break;
}
}
reg_write_m(RTL837X_PIN_MUX_1);
}
/* 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) __banked
{
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;
}
-14
View File
@@ -1,14 +0,0 @@
#ifndef BOOT_H
#define BOOT_H
void sds_config_mac(uint8_t sds, uint8_t mode) __banked;
void sds_config(uint8_t sds, uint8_t mode) __banked;
void early_boot_handle_button(void) __banked;
void rtl8224_enable(void) __banked;
void nic_setup(void) __banked;
void rtl8373_revision(void) __banked;
void init_smi(void) __banked;
void setup_i2c(void) __banked;
void set_hostname_default(void) __banked;
#endif
-211
View File
@@ -1,211 +0,0 @@
#include "cmd_parser.h"
#include "machine.h"
#pragma codeseg BANK2
#pragma constseg BANK2
// Position in the serial buffer
__xdata uint8_t l;
// Properties of currently edited command line in cmd_buffer[CMD_BUF_SIZE]
__xdata uint8_t cursor;
__xdata uint8_t cmd_line_len;
__xdata uint8_t current_cmdline[CMD_BUF_SIZE];
__xdata uint16_t history_editptr;
extern __xdata uint8_t cmd_history[CMD_HISTORY_SIZE];
extern __xdata uint16_t cmd_history_ptr;
void cmd_editor_init(void) __banked
{
l = sbuf_ptr; // We have printed out entered characters until l
cursor = 0;
cmd_line_len = 0;
cmd_available = 0;
history_editptr = 0xffff;
}
/*
* Allows editing the current command line held in cmd_buffer[CMD_BUF_SIZE] by
* identifying new characters typed or up to 4-byte escape sequences in the
* serial buffer ring sbuf[SBUF_SIZE].
* Upon detecting new characters or escape sequences, the cmd_buffer and the
* representation of the command line in the terminal are updated.
* To debug, the easist is to interpose a tty-interceptor between the physical
* serial device and a logical one created by interceptty:
* sudo interceptty -s 'ispeed 115200 ospeed 115200' /dev/ttyUSB0 /dev/tmpS
* picocom -b 115200 /dev/tmpS
*/
void cmd_edit(void) __banked
{
while (l != sbuf_ptr) {
if (sbuf[l] >= ' ' && sbuf[l] < 127) { // A printable character, copy to command line
// Reserve one byte for the terminating NUL written on Enter. When the
// line is full, drop the character but still fall through to advance the
// serial-ring read pointer below; a 'continue' here would spin forever.
if (cmd_line_len < CMD_BUF_SIZE - 1) {
write_char(sbuf[l]);
// Shift buffer to right
for (uint8_t i = cmd_line_len; i > cursor; i--)
cmd_buffer[i] = cmd_buffer[i-1];
// Insert char in comand buffer
cmd_buffer[cursor++] = sbuf[l];
cmd_line_len++;
// Print rest of line
for (uint8_t i = cursor; i < cmd_line_len; i++)
write_char(cmd_buffer[i]);
// 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
// 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)
continue;
if (((sbuf_ptr > l ? sbuf_ptr - l : SBUF_SIZE + sbuf_ptr - l) >= 4)
&& sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == '3' && sbuf[(l + 3) & SBUF_MASK] == '~') { // DEL
if (cursor < cmd_line_len) {
write_char('\033'); write_char('['); write_char('1'); write_char('P'); // Delete to end of line
cmd_line_len--;
for (uint8_t i = cursor; i < cmd_line_len; i++) {
cmd_buffer[i] = cmd_buffer[i+1];
write_char(cmd_buffer[i]);
}
for (uint8_t i = cursor; i < cmd_line_len; i++)
write_char('\010');
}
l += 4;
l &= SBUF_MASK;
continue;
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'D') { // <CURSOR-LEFT>
if (cursor) {
write_char('\010'); // BS works like cursor-left
cursor--;
}
l += 3;
l &= SBUF_MASK;
continue;
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'C') { // <CURSOR-RIGHT>
if (cursor < cmd_line_len) {
write_char('\033'); write_char('['); write_char('C');
cursor++;
}
l += 3;
l &= SBUF_MASK;
continue;
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'A') { // <CURSOR-UP>
for (uint8_t i = 0; i < cmd_line_len; i++)
current_cmdline[i] = cmd_buffer[i];
current_cmdline[cmd_line_len] = 0;
__xdata uint16_t p;
if (history_editptr == 0xffff)
p = (cmd_history_ptr - 2) & CMD_HISTORY_MASK;
else
p = history_editptr;
// Move cursor to beginning of line
write_char('\033'); write_char('['); itoa(cursor + 2); write_char('D');
cursor = 0;
while (cmd_history[p] && cmd_history[p] != '\n') {
cursor++;
p--;
p &= CMD_HISTORY_MASK;
}
history_editptr = (p - 1) & CMD_HISTORY_MASK;
p = (p + 1) & CMD_HISTORY_MASK;
if (cursor) {
print_string("\033[2K> "); // Clear entire line: ^[[2K and print new prompt
for (uint8_t i = 0; i < cursor; i++) {
cmd_buffer[i] = cmd_history[p];
write_char(cmd_buffer[i]);
p = (p+1) & CMD_HISTORY_MASK;
}
cmd_line_len = cursor;
} else {
print_string("\033[2C"); // Move 2 right to start of editing space
}
l += 3;
l &= SBUF_MASK;
continue;
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'B') { // <CURSOR-DOWN>
if (history_editptr != 0xffff) {
__xdata uint16_t p = (history_editptr + 2) & CMD_HISTORY_MASK;
// Move cursor to beginning of line
write_char('\033'); write_char('['); itoa(cursor + 2); write_char('D');
print_string("\033[2K> "); // Clear entire line: ^[[2K and print new prompt
uint8_t i = 0;
while (cmd_history[p] && cmd_history[p] != '\n') {
p = (p + 1) & CMD_HISTORY_MASK;
}
p = (p + 1) & CMD_HISTORY_MASK;
while (cmd_history[p] && cmd_history[p] != '\n') {
cmd_buffer[i] = cmd_history[p];
write_char(cmd_buffer[i++]);
p = (p + 1) & CMD_HISTORY_MASK;
}
history_editptr = (p - 1) & CMD_HISTORY_MASK;
if (!i) {
if (current_cmdline[i]) {
while (current_cmdline[i]) {
cmd_buffer[i] = current_cmdline[i];
write_char(cmd_buffer[i++]);
}
} else {
write_char('\033'); write_char('['); write_char('C');
}
history_editptr = 0xffff;
// Move cursor right
}
cmd_line_len = i;
cursor = 0;
// Move cursor again to beginning of line
write_char('\033'); write_char('['); itoa(i); write_char('D');
} else {
// If we are at the last entry of the history, just move the cursor to the end of the line
if (cursor < cmd_line_len) {
write_char('\033'); write_char('['); itoa(cmd_line_len - cursor); write_char('C');
}
cursor = cmd_line_len;
}
l += 3;
l &= SBUF_MASK;
continue;
} else { // An unknown or not yet complete Escape sequence: wait
continue;
}
} else if (sbuf[l] == 127 || sbuf[l] == 8) { // Backspace DEL or BS/^H
if (cursor > 0) {
write_char('\010');
for (uint8_t i = cursor; i < cmd_line_len; i++)
write_char(cmd_buffer[i]);
write_char(' '); // Overwrite end of line
// Move backwards n steps:
for (uint8_t i = cursor; i <= cmd_line_len; i++)
write_char('\010');
cursor--;
for (uint8_t i = cursor; i <= cmd_line_len; i++)
cmd_buffer[i] = cmd_buffer[i+1];
cmd_line_len--;
}
}
// If the command buffer is currently in use, we cannot copy to it
if (cmd_available)
break;
// Check whether return was pressed:
if (sbuf[l] == '\n' || sbuf[l] == '\r') {
write_char('\n');
cmd_buffer[cmd_line_len] = NUL;
// write_char('>'); print_string_x(cmd_buffer); write_char('<');
// If there is a command we print the prompt after execution
// otherwise immediately because there is nothing to execute
if (cmd_line_len)
cmd_available = 1;
else
print_cmd_prompt();
cursor = 0;
cmd_line_len = 0;
history_editptr = 0xffff;
}
l++;
l &= SBUF_MASK;
}
}
-9
View File
@@ -1,9 +0,0 @@
#ifndef _CMD_EDITOR_H_
#define _CMD_EDITOR_H_
#include <stdint.h>
void cmd_editor_init(void) __banked;
void cmd_edit(void) __banked;
#endif
+270 -2229
View File
File diff suppressed because it is too large. Load diff
+2 -42
View File
@@ -1,47 +1,7 @@
#ifndef _CMD_PARSER_H_ #ifndef _CMD_PARSER_H_
#define _CMD_PARSER_H_ #define _CMD_PARSER_H_
#include <stdint.h>
#include "rtl837x_common.h"
extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
extern __bit __at(0x03) cmd_available;
extern __xdata uint8_t err_status;
/* Health instrumentation, built with HEALTH=1. Without it the hooks below
* compile to nothing and the "health" command does not exist. */
#ifdef HEALTH
/* Phase ids, in main-loop order */
#define HEALTH_PH_LINK 0
#define HEALTH_PH_SFP 1
#define HEALTH_PH_RX 2
#define HEALTH_PH_TX 3
#define HEALTH_PH_STP 4
#define HEALTH_PH_CMD 5
#define HEALTH_PHASES 6
extern __xdata uint16_t health_rx_frames;
#define health_rx_frame() health_rx_frames++
void health_loop_start(void) __banked; /* once per idle() pass, resets the phase baseline */
void health_phase(uint8_t id) __banked; /* after each phase; accounts ticks since last checkpoint */
void health_stack_paint(void) __banked; /* paint the unused stack area once at boot */
void health_show(void) __banked; /* "health" CLI dump */
#else
#define health_rx_frame()
#define health_loop_start()
#define health_phase(id)
#define health_stack_paint()
#endif
void cmd_tokenize(void) __banked;
void cmd_parser(void) __banked; void cmd_parser(void) __banked;
void execute_config(void) __banked; void cmd_parser_setup(void) __banked;
void execute_commands(__xdata uint8_t *p) __banked; void execute_config() __banked;
void print_ip(__xdata uint8_t *ptr) __banked;
void print_mac(__xdata uint8_t *ptr) __banked;
void print_sw_version(void) __banked;
void clear_command_history(void) __banked;
#endif #endif
-3
View File
@@ -1,3 +0,0 @@
ip 192.168.10.247
gw 192.168.10.1
netmask 255.255.255.0
-127
View File
@@ -1,127 +0,0 @@
;
; CRC16 calculation module
;
.globl _crc_value
.globl _crc16
.globl _crc16_bank1
.globl __sdcc_banked_ret
.equ BANK, 0x96
; .equ DPS, 0x86
; Variable in XMEM holding current CRC16 value, being updated
.area XSEG (XDATA)
_crc_value::
.ds 2
;-------------------------------------------------------
; CRC16 subroutine
; - dptr points to byte to be CRCd in xmem
; - algorithm uses table lookup
;-------------------------------------------------------
.area HOME (CODE)
.area CSEG (CODE)
; .area BANK1 (CODE)
_crc16_bank1:
mov BANK, #1
push dph
push dpl
movx a, @dptr
; inc DPS
mov b, a
mov dptr, #_crc_value
movx a, @dptr
xrl a, b ; create index into tables
push a ; save index
mov dptr, #crc16_table_l ; low part of table address
movc a, @a+dptr ; get low byte
mov b, a
mov dptr, #_crc_value + 1
movx a, @dptr
xrl a, b
mov dptr, #_crc_value
movx @dptr, a ; save result low part
mov dptr, #crc16_table_h ; high part of table address
pop a ; restore index
movc a, @a+dptr
mov dptr, #_crc_value+1
movx @dptr, a ; save result high part
pop dpl
pop dph
; clr DPS
ret
.area BANK1 (CODE)
_crc16:
lcall _crc16_bank1
ljmp __sdcc_banked_ret
crc16_table_l:
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
crc16_table_h:
.byte #0x00, #0xc0, #0xc1, #0x01, #0xc3, #0x03, #0x02, #0xc2
.byte #0xc6, #0x06, #0x07, #0xc7, #0x05, #0xc5, #0xc4, #0x04
.byte #0xcc, #0x0c, #0x0d, #0xcd, #0x0f, #0xcf, #0xce, #0x0e
.byte #0x0a, #0xca, #0xcb, #0x0b, #0xc9, #0x09, #0x08, #0xc8
.byte #0xd8, #0x18, #0x19, #0xd9, #0x1b, #0xdb, #0xda, #0x1a
.byte #0x1e, #0xde, #0xdf, #0x1f, #0xdd, #0x1d, #0x1c, #0xdc
.byte #0x14, #0xd4, #0xd5, #0x15, #0xd7, #0x17, #0x16, #0xd6
.byte #0xd2, #0x12, #0x13, #0xd3, #0x11, #0xd1, #0xd0, #0x10
.byte #0xf0, #0x30, #0x31, #0xf1, #0x33, #0xf3, #0xf2, #0x32
.byte #0x36, #0xf6, #0xf7, #0x37, #0xf5, #0x35, #0x34, #0xf4
.byte #0x3c, #0xfc, #0xfd, #0x3d, #0xff, #0x3f, #0x3e, #0xfe
.byte #0xfa, #0x3a, #0x3b, #0xfb, #0x39, #0xf9, #0xf8, #0x38
.byte #0x28, #0xe8, #0xe9, #0x29, #0xeb, #0x2b, #0x2a, #0xea
.byte #0xee, #0x2e, #0x2f, #0xef, #0x2d, #0xed, #0xec, #0x2c
.byte #0xe4, #0x24, #0x25, #0xe5, #0x27, #0xe7, #0xe6, #0x26
.byte #0x22, #0xe2, #0xe3, #0x23, #0xe1, #0x21, #0x20, #0xe0
.byte #0xa0, #0x60, #0x61, #0xa1, #0x63, #0xa3, #0xa2, #0x62
.byte #0x66, #0xa6, #0xa7, #0x67, #0xa5, #0x65, #0x64, #0xa4
.byte #0x6c, #0xac, #0xad, #0x6d, #0xaf, #0x6f, #0x6e, #0xae
.byte #0xaa, #0x6a, #0x6b, #0xab, #0x69, #0xa9, #0xa8, #0x68
.byte #0x78, #0xb8, #0xb9, #0x79, #0xbb, #0x7b, #0x7a, #0xba
.byte #0xbe, #0x7e, #0x7f, #0xbf, #0x7d, #0xbd, #0xbc, #0x7c
.byte #0xb4, #0x74, #0x75, #0xb5, #0x77, #0xb7, #0xb6, #0x76
.byte #0x72, #0xb2, #0xb3, #0x73, #0xb1, #0x71, #0x70, #0xb0
.byte #0x50, #0x90, #0x91, #0x51, #0x93, #0x53, #0x52, #0x92
.byte #0x96, #0x56, #0x57, #0x97, #0x55, #0x95, #0x94, #0x54
.byte #0x9c, #0x5c, #0x5d, #0x9d, #0x5f, #0x9f, #0x9e, #0x5e
.byte #0x5a, #0x9a, #0x9b, #0x5b, #0x99, #0x59, #0x58, #0x98
.byte #0x88, #0x48, #0x49, #0x89, #0x4b, #0x8b, #0x8a, #0x4a
.byte #0x4e, #0x8e, #0x8f, #0x4f, #0x8d, #0x4d, #0x4c, #0x8c
.byte #0x44, #0x84, #0x85, #0x45, #0x87, #0x47, #0x46, #0x86
.byte #0x82, #0x42, #0x43, #0x83, #0x41, #0x81, #0x80, #0x40
-29
View File
@@ -1,29 +0,0 @@
.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
+57
View File
@@ -0,0 +1,57 @@
.globl __start__stack
;--------------------------------------------------------
; Stack segment in internal ram
;--------------------------------------------------------
.area SSEG (DATA)
__start__stack:
.ds 1
.area VECTOR (CODE)
.globl __interrupt_vect
__interrupt_vect:
ljmp __sdcc_gsinit_startup
ljmp _isr_ext0 ; 0x03
.ds 5
ljmp _isr_timer0 ; 0x0b
.ds 5
ljmp _isr_ext1 ; 0x13
.ds 5
reti
.ds 7
ljmp _isr_serial ; 0x23
.ds 5
reti ; 0x2b TIMER 2 IRQ
.ds 7
reti ; 0x33 NOT used by DW8051
.ds 7
reti ; 0x3b Serial port 1 RX/TX IRQ
.ds 7
ljmp _isr_ext2 ; 0x43
.ds 5
ljmp _isr_ext3 ; 0x4b
.globl __start__stack
.area GSINIT0 (CODE)
__sdcc_gsinit_startup::
mov sp,#__start__stack - 1
.area GSFINAL (CODE)
ljmp _bootloader
__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
-23
View File
@@ -1,23 +0,0 @@
#ifndef _CHACHA_H_
#define _CHACHA_H_
#include <stdint.h>
struct chacha20_t {
uint8_t wstate[64]; // 64 bytes written here
uint8_t constant[16]; // 128 bit constant
uint8_t key[32]; // 256-bit secret key
uint32_t cnt; // 32-bit block counter 1, 2.. Big Endian!
uint8_t nonce[12]; // 96-bit nonce
__xdata uint8_t *plaintext;
uint16_t length;
__xdata uint8_t *cyphertext;
};
// Encrypt a plaintext with ChaCha20 as per RFC7539
void chacha20_encrypt(void);
// Test ChaCha20 using the example from RFC7539
void chacha20_test(void);
#endif
-98
View File
@@ -1,98 +0,0 @@
#include "rtl837x_common.h"
#include "chacha.h"
void chacha_20(void);
void chacha_update(void);
void chacha_count(void);
// generate a block of ChaCha20 keystream as per RFC7539
__xdata struct chacha20_t __at(0xbf00) chacha20;
__xdata uint8_t plaintext[256];
__xdata uint8_t cyphertext[256];
void chacha20_print_block(void)
{
for (uint8_t i=0; i < 64; i++) {
print_byte(*(uint8_t * __xdata)(chacha20.wstate + i));
if (i%4 == 3)
write_char(' ');
}
}
void chacha20_encrypt(void)
{
__xdata uint8_t *p = chacha20.plaintext;
while (chacha20.length) {
register uint8_t i;
chacha_count();
memcpy(chacha20.wstate, chacha20.wstate + 64, 64);
#ifdef DEBUG
chacha20_print_block(); write_char('\n');
#endif
chacha_20();
chacha_update();
#ifdef DEBUG
chacha20_print_block(); write_char('\n');
#endif
for (i = 0; i < ((chacha20.length > 64) ? 64 : chacha20.length); i++)
*chacha20.cyphertext++ = *p++ ^ chacha20.wstate[i];
chacha20.length -= chacha20.length > 64 ? 64 : chacha20.length;
#ifdef DEBUG
print_string("\n round done\n");
#endif
};
}
// Test the example of RFC 7539 Section 2.4.2
void chacha20_test(void)
{
__code uint8_t chacha_c[16] =
{ 0x61, 0x70, 0x78, 0x65, 0x33, 0x20, 0x64, 0x6e,
0x79, 0x62, 0x2d, 0x32, 0x6b, 0x20, 0x65, 0x74 };
__code uint8_t key[32] =
{ 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04,
0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c,
0x13, 0x12, 0x11, 0x10, 0x17, 0x16, 0x15, 0x14,
0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c };
__code uint8_t nonce[12] = {
0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
__code uint8_t sunscreen[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for " \
"the future, sunscreen would be it.";
/*
Ciphertext Sunscreen (from RFC 7539 Section 2.4.2):
000 6e 2e 35 9a 25 68 f9 80 41 ba 07 28 dd 0d 69 81 n.5.%h..A..(..i.
016 e9 7e 7a ec 1d 43 60 c2 0a 27 af cc fd 9f ae 0b .~z..C`..'......
032 f9 1b 65 c5 52 47 33 ab 8f 59 3d ab cd 62 b3 57 ..e.RG3..Y=..b.W
048 16 39 d6 24 e6 51 52 ab 8f 53 0c 35 9f 08 61 d8 .9.$.QR..S.5..a.
064 07 ca 0d bf 50 0d 6a 61 56 a3 8e 08 8a 22 b6 5e ....P.jaV....".^
080 52 bc 51 4d 16 cc f8 06 81 8c e9 1a b7 79 37 36 R.QM.........y76
096 5a f9 0b bf 74 a3 5b e6 b4 0b 8e ed f2 78 5e 42 Z...t.[......x^B
112 87 4d
*/
strcpy(plaintext, sunscreen);
memcpyc(chacha20.constant, chacha_c, 16);
memcpyc(chacha20.key, key, 32);
chacha20.cnt = 0;
memcpyc(chacha20.nonce, nonce, 12);
chacha20.plaintext = plaintext;
chacha20.length = strlen_x(plaintext);
chacha20.cyphertext = cyphertext;
print_string("Encrypting...\n");
chacha20_encrypt();
print_string("Cypertext:\n");
uint16_t len = strlen_x(plaintext);
for (uint8_t i = 0; i < len; i++) {
print_byte(cyphertext[i]); write_char(' ');
}
}
-455
View File
@@ -1,455 +0,0 @@
; ChaCha Quater-Round implementation in Assembler
.module chacha_8051
; Global variables:
.globl _chacha_20
.globl _chacha_update
.globl _chacha_count
;#define CHACHA_QR(A, B, C, D) { \
; A += B; D ^= A; D = ROTL32(D, 16); \
; C += D; B ^= C; B = ROTL32(B, 12); \
; A += B; D ^= A; D = ROTL32(D, 8); \
; C += D; B ^= C; B = ROTL32(B, 7); \
;}
; r0 r1 r2 r3
; CHACHA_QR( v[ 0], v[ 4], v[ 8], v[12] );
.area HOME (CODE)
store_32:
ar7 = 0x07
ar6 = 0x06
ar5 = 0x05
ar4 = 0x04
ar3 = 0x03
ar2 = 0x02
ar1 = 0x01
ar0 = 0x00
mov a, r7
movx @dptr, a
dec dpl
mov a, r6
movx @dptr, a
dec dpl
mov a, r5
movx @dptr, a
dec dpl
mov a, r4
movx @dptr, a
ret
rol_b:
clr c
mov a, r7
rlc a
mov r7, a
mov a, r6
rlc a
mov r6, a
mov a, r5
rlc a
mov r5, a
mov a, r4
rlc a
mov r4, a
clr a
addc a, r7
mov r7, a
djnz dpl, rol_b
ret
chacha_plus_xor:
; Load A into registers r4-r7, A pointed to by r0
mov dptr, #_chacha20
mov dpl, r0
movx a, @dptr
mov r7, a
dec dpl
movx a, @dptr
mov r6, a
dec dpl
movx a, @dptr
mov r5, a
dec dpl
movx a, @dptr
mov r4, a
; A += B, B pointed to by r1
mov dpl, r1
movx a, @dptr
add a, r7
mov r7, a
dec dpl
movx a, @dptr
addc a, r6
mov r6, a
dec dpl
movx a, @dptr
addc a, r5
mov r5, a
dec dpl
movx a, @dptr
addc a, r4
mov r4, a
mov dpl, r0 ; Store A back
mov a, r7
movx @dptr, a
dec dpl
mov a, r6
movx @dptr, a
dec dpl
mov a, r5
movx @dptr, a
dec dpl
mov a, r4
movx @dptr, a
; D ^= A
mov dpl, r3
movx a, @dptr
xrl a, r7
mov r7, a
dec dpl
movx a, @dptr
xrl a, r6
mov r6, a
dec dpl
movx a, @dptr
xrl a, r5
mov r5, a
dec dpl
movx a, @dptr
xrl a, r4
mov r4, a
dec dpl
ret
chacha_qr:
; QR Part: A += B; D ^= A; D = ROTL32(D, 16);
acall chacha_plus_xor
; rotate left 16. D is r4, r5, r6, r7 -> r6, r7, r4, r5
mov a, r6
xch a, r4
mov r6, a
mov a, r7
xch a, r5
mov r7, a
mov dpl, r3 ; Store D
acall store_32
;QR Part: C += D; B ^= C; B = ROTL32(B, 12);
; Swap A <-> C and D <-> B
mov a, r0
xch a, r2
mov r0, a
mov a, r1
xch a, r3
mov r1, a
acall chacha_plus_xor
; rotate left 12. D is r4, r5, r6, r7 -> r5, r6, r7, r4
mov a, r4
xch a, r7
xch a, r6
xch a, r5
mov r4, a
mov dpl, #4
acall rol_b
mov dpl, r3 ; Store D (being B)
acall store_32
; Swap A <-> C and D <-> B
mov a, r0
xch a, r2
mov r0, a
mov a, r1
xch a, r3
mov r1, a
; QR Part A += B; D ^= A; D = ROTL32(D, 8);
acall chacha_plus_xor
mov a, r4
xch a, r7
xch a, r6
xch a, r5
mov r4, a
mov dpl, r3 ; Store D
acall store_32
; QR Part
; C += D; B ^= C; B = ROTL32(B, 7);
line4:
; Swap A <-> C and D <-> B
mov a, r0
xch a, r2
mov r0, a
mov a, r1
xch a, r3
mov r1, a
acall chacha_plus_xor
; Roll left 7 bits, start by rolling 8 bits left, then roll 1 to the right
mov a, r4
xch a, r7
xch a, r6
xch a, r5
mov r4, a
clr c
mov a, r4
rrc a
mov r4, a
mov a, r5
rrc a
mov r5, a
mov a, r6
rrc a
mov r6, a
mov a, r7
rrc a
mov r7, a
clr a
rrc a
add a, r4
mov r4, a
; Swap A <-> C and D <-> B
mov a, r0
xch a, r2
mov r0, a
mov a, r1
xch a, r3
mov r1, a
mov dpl, r1 ; Store B
acall store_32
ret
;
; Implementation of 20 ChaCha Rounds (10 Double Rounds)
;
_chacha_20:
push acc
push b
push dpl
push dph
push ar7
push ar6
push ar5
push ar4
push ar3
push ar2
push ar1
push ar0
push psw
mov b, #10 ; 10 Double rounds
chacha_20_loop:
; CHACHA_QR( v[ 0], v[ 4], v[ 8], v[12] );
mov r0, #3
mov r1, #19
mov r2, #35
mov r3, #51
acall chacha_qr
; CHACHA_QR( v[ 1], v[ 5], v[ 9], v[13] ); 7 23 39 55
mov r0, #7
mov r1, #23
mov r2, #39
mov r3, #55
acall chacha_qr
; CHACHA_QR( v[ 2], v[ 6], v[10], v[14] ); 11 27 43 59
mov r0, #11
mov r1, #27
mov r2, #43
mov r3, #59
acall chacha_qr
; CHACHA_QR( v[ 3], v[ 7], v[11], v[15] ); 15 31 47 63
mov r0, #15
mov r1, #31
mov r2, #47
mov r3, #63
acall chacha_qr
; CHACHA_QR( v[ 0], v[ 5], v[10], v[15] ); 3 23 43 63
mov r0, #3
mov r1, #23
mov r2, #43
mov r3, #63
acall chacha_qr
; CHACHA_QR( v[ 1], v[ 6], v[11], v[12] ); 7 27 47 51
mov r0, #7
mov r1, #27
mov r2, #47
mov r3, #51
acall chacha_qr
; CHACHA_QR( v[ 2], v[ 7], v[ 8], v[13] ); 11 31 35 55
mov r0, #11
mov r1, #31
mov r2, #35
mov r3, #55
acall chacha_qr
; CHACHA_QR( v[ 3], v[ 4], v[ 9], v[14] ); 15 19 39 59
mov r0, #15
mov r1, #19
mov r2, #39
mov r3, #59
acall chacha_qr
djnz b, chacha_20_loop
pop psw
pop ar0
pop ar1
pop ar2
pop ar3
pop ar4
pop ar5
pop ar6
pop ar7
pop dph
pop dpl
pop b
pop acc
ret
;
; Update ChaCHa state
;
_chacha_update:
push acc
push b
push dpl
push dph
push ar4
push ar3
push ar2
push ar1
push ar0
push psw
mov dptr, #_chacha20
mov b, #16 ; 16 uint32
update_loop:
mov a, b ; multiply by 4 and subtract 1
rl a
rl a
dec a
; Load Working State variable into registers r0-r3
mov dpl, a
orl a, #64 ; Save pointer to state
mov r4, a
movx a, @dptr
mov r3, a
dec dpl
movx a, @dptr
mov r2, a
dec dpl
movx a, @dptr
mov r1, a
dec dpl
movx a, @dptr
mov r0, a
; Add to State variable
mov a, r4
mov dpl, a
movx a, @dptr
add a, r3
mov r3, a
dec dpl
movx a, @dptr
addc a, r2
mov r2, a
dec dpl
movx a, @dptr
addc a, r1
mov r1, a
dec dpl
movx a, @dptr
addc a, r0
mov r0, a
; Store back state variable in LSB, first sequence (serialized)
mov a, r4
xrl a, #64 ; Save pointer to working state
mov dpl, a
mov a, r0
movx @dptr, a
dec dpl
mov a, r1
movx @dptr, a
dec dpl
mov a, r2
movx @dptr, a
dec dpl
mov a, r3
movx @dptr, a
djnz b, update_loop
pop psw
pop ar0
pop ar1
pop ar2
pop ar3
pop ar4
pop dph
pop dpl
pop b
pop acc
ret
;
; Increase counter in state
;
_chacha_count:
push acc
push dpl
push dph
mov dptr, #_chacha20
mov dpl, #112 + 3
movx a, @dptr
inc a
movx @dptr, a
jnz chacha_count_done
dec dpl
movx a, @dptr
inc a
movx @dptr, a
jnz chacha_count_done
dec dpl
movx a, @dptr
inc a
movx @dptr, a
jnz chacha_count_done
dec dpl
movx a, @dptr
inc a
movx @dptr, a
chacha_count_done:
pop dph
pop dpl
pop acc
ret
-18
View File
@@ -1,18 +0,0 @@
#ifndef __DEBUG_H__
#define __DEBUG_H__
#ifdef DEBUG
#define dbg_string(s) print_string(s)
#define dbg_string_x(s) print_string_x(s)
#define dbg_byte(s) print_byte(s)
#define dbg_short(s) print_short(s)
#define dbg_char(s) write_char(s)
#else
#define dbg_string(s)
#define dbg_string_x(s)
#define dbg_byte(s)
#define dbg_short(s)
#define dbg_char(s)
#endif
#endif
-425
View File
@@ -1,425 +0,0 @@
/*
* This is a DHCP client implementation for the RTL837x-based switches
*/
// #define REGDBG
// #define DEBUG
#include <stdint.h>
#include "rtl837x_sfr.h"
#include "rtl837x_common.h"
#include "dhcp.h"
#include "uip.h"
#include "uip/uip.h"
__xdata struct dhcp_state dhcp_state;
__xdata uip_ipaddr_t server;
#define DHCP_HW_TYPE_ETH 1
#define DHCP_SUBNET_MASK 1
#define DHCP_SUBNET_MASK_LEN 4
#define DHCP_ROUTER 3
#define DHCP_ROUTER_LEN 4
#define DHCP_DNS 6
#define DHCP_DNS_LEN 4
#define DHCP_BROADCAST 28
#define DHCP_BROADCAST_LEN 4
#define DHCP_SERVER_ID 54
#define DHCP_SERVER_ID_LEN 4
#define DHCP_MESSAGE_TYPE 53
#define DHCP_MESSAGE_TYPE_LEN 1
#define DHCP_MESSAGE_DISCOVER 1
#define DHCP_MESSAGE_OFFER 2
#define DHCP_MESSAGE_REQUEST 3
#define DHCP_MESSAGE_ACK 5
#define DHCP_LEASE 51
#define DHCP_LEASE_LEN 4
#define DHCP_RENEWAL 58
#define DHCP_RENEWAL_LEN 4
#define DHCP_REBIND 59
#define DHCP_REBIND_LEN 4
#define DHCP_CLIENT_ID 61
#define DHCP_CLIENT_ID_LEN 7
#define DHCP_HOSTNAME 12
#define DHCP_REQUEST_IP 50
#define DHCP_REQUEST_IP_LEN 4
#define DHCP_PARAMS 55
#define DHCP_PARAM_SUBNET 1
#define DHCP_PARAM_ROUTER 3
#define DHCP_PARAM_DNS 6
#define DHCP_END 255
#pragma codeseg BANK3
#pragma constseg BANK2
struct dhcp_pkt {
uint8_t type;
uint8_t hw;
uint8_t hw_len;
uint8_t hops;
uint32_t tid;
uint16_t delay;
uint16_t flags;
uint8_t client_ip[4];
uint8_t your_ip[4];
uint8_t next_server_ip[4];
uint8_t relay_ip[4];
uint8_t client_addr[6];
uint8_t client_pad[10];
uint8_t server_name[64];
uint8_t file[128];
uint8_t cookie[4];
};
#define DHCP_P ((__xdata struct dhcp_pkt *)uip_appdata)
#define DHCP_OPT ((__xdata uint8_t *)(uip_appdata) + sizeof (struct dhcp_pkt))
__xdata uint32_t long_value;
void dhcp_print_ip(__xdata uint8_t *a)
{
itoa(a[0]); write_char('.');
itoa(a[1]); write_char('.');
itoa(a[2]); write_char('.');
itoa(a[3]);
}
void dhcp_prepare_request(void)
{
DHCP_P->type = 1;
DHCP_P->hw = DHCP_HW_TYPE_ETH;
DHCP_P->hw_len = 6;
DHCP_P->hops = 0;
DHCP_P->tid = dhcp_state.transaction_id;
DHCP_P->delay = HTONS(0);
DHCP_P->flags = 0;
// Clear fields client_ip to bootp_file
memset(DHCP_P->client_ip, 0, 224);
memcpy(DHCP_P->client_addr, uip_ethaddr.addr, 6);
DHCP_P->cookie[0] = 0x63;
DHCP_P->cookie[1] = 0x82;
DHCP_P->cookie[2] = 0x53;
DHCP_P->cookie[3] = 0x63;
}
void dhcp_addopt_client_id(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_HW_TYPE_ETH;
memcpy(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 6);
dhcp_state.opt_ptr += 6;
}
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)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REQUEST_IP;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REQUEST_IP_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[0];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[1];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[2];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[3];
}
void dhcp_addopt_server_id(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_SERVER_ID;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_SERVER_ID_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[0];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[1];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[2];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[3];
}
void dhcp_send_discover(void)
{
dhcp_prepare_request();
dhcp_state.opt_ptr = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_DISCOVER;
dhcp_addopt_client_id();
dhcp_addopt_request_ip();
dhcp_addopt_hostname();
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_SUBNET;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_ROUTER;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_DNS;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_END;
// Padding to 300 bytes
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
uip_udp_send(sizeof(struct dhcp_pkt) + dhcp_state.opt_ptr);
dhcp_state.state = DHCP_DISCOVER_SENT;
dhcp_state.ticks = SYS_TICK_HZ;
dhcp_state.dhcp_timer = 30; // Timeout for discover
}
void dhcp_send_request(void)
{
dhcp_prepare_request();
dhcp_state.opt_ptr = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_REQUEST;
dhcp_addopt_client_id();
dhcp_addopt_request_ip();
dhcp_addopt_server_id();
dhcp_addopt_hostname();
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_SUBNET;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_ROUTER;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_DNS;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_END;
// Padding to 300 bytes
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
uip_udp_send(sizeof(struct dhcp_pkt) + dhcp_state.opt_ptr);
dhcp_state.state = DHCP_REQUEST_SENT;
dhcp_state.ticks = SYS_TICK_HZ;
dhcp_state.dhcp_timer = 30; // Timeout for request
}
void ip_opt(__xdata uint8_t * ip)
{
dhcp_state.opt_ptr++;
uint8_t len = DHCP_OPT[dhcp_state.opt_ptr++];
if (len >= 4)
memcpy(ip, &DHCP_OPT[dhcp_state.opt_ptr], 4);
// There may be more than one IP option, such as 2 DNS servers advertised
dhcp_state.opt_ptr += len;
}
uint8_t long_opt(void)
{
dhcp_state.opt_ptr++;
uint8_t len = DHCP_OPT[dhcp_state.opt_ptr++];
if (len < 4) {
dhcp_state.opt_ptr += len;
return 0;
}
long_value = DHCP_OPT[dhcp_state.opt_ptr++];
long_value <<= 8;
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
long_value <<= 8;
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
long_value <<= 8;
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
dhcp_state.opt_ptr += len - 4;
return 1;
}
void parse_opts(void)
{
while (DHCP_OPT[dhcp_state.opt_ptr] && DHCP_OPT[dhcp_state.opt_ptr] != DHCP_END) {
switch(DHCP_OPT[dhcp_state.opt_ptr]) {
case DHCP_SUBNET_MASK:
ip_opt(&dhcp_state.subnet[0]);
break;
case DHCP_ROUTER:
ip_opt(&dhcp_state.router[0]);
break;
case DHCP_DNS:
ip_opt(&dhcp_state.dns[0]);
break;
case DHCP_SERVER_ID:
ip_opt(&dhcp_state.server[0]);
break;
case DHCP_BROADCAST:
ip_opt(&dhcp_state.broadcast[0]);
break;
case DHCP_LEASE:
if (long_opt())
dhcp_state.lease = long_value;
break;
case DHCP_REBIND:
if (long_opt())
dhcp_state.rebind = long_value;
break;
case DHCP_RENEWAL:
if (long_opt())
dhcp_state.renewal = long_value;
break;
case DHCP_END:
break;
default:
print_string("Unknown DHCP option: "); print_byte(DHCP_OPT[dhcp_state.opt_ptr]); write_char('\n');
dhcp_state.opt_ptr++;
dhcp_state.opt_ptr += DHCP_OPT[dhcp_state.opt_ptr];
dhcp_state.opt_ptr++;
}
}
}
void parse_dhcp(void)
{
if (DHCP_P->tid != dhcp_state.transaction_id)
return;
if (DHCP_P->cookie[0] != 0x63 || DHCP_P->cookie[1] != 0x82 || DHCP_P->cookie[2] != 0x53 || DHCP_P->cookie[3] != 0x63)
return;
dhcp_state.opt_ptr = 0;
if (DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE || DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE_LEN)
return;
if (DHCP_OPT[dhcp_state.opt_ptr] == DHCP_MESSAGE_OFFER) {
dhcp_state.opt_ptr++;
dhcp_state.current_ip[0] = DHCP_P->your_ip[0];
dhcp_state.current_ip[1] = DHCP_P->your_ip[1];
dhcp_state.current_ip[2] = DHCP_P->your_ip[2];
dhcp_state.current_ip[3] = DHCP_P->your_ip[3];
parse_opts();
print_string("DHCP offer received for IP "); dhcp_print_ip(dhcp_state.current_ip);
write_char('\n');
dhcp_send_request();
} else if (DHCP_OPT[dhcp_state.opt_ptr++] == DHCP_MESSAGE_ACK) {
parse_opts();
print_string("DHCP ACK, our IP is "); dhcp_print_ip(dhcp_state.current_ip);
write_char('\n');
print_string("DHCP netmask "); dhcp_print_ip(dhcp_state.subnet);
write_char('\n');
print_string("DHCP gateway "); dhcp_print_ip(dhcp_state.router);
write_char('\n');
print_string("DHCP lease-time ");
print_long(dhcp_state.lease);
write_char('\n');
uip_ipaddr(&uip_hostaddr, dhcp_state.current_ip[0], dhcp_state.current_ip[1], dhcp_state.current_ip[2], dhcp_state.current_ip[3]);
uip_ipaddr(&uip_draddr, dhcp_state.router[0], dhcp_state.router[1], dhcp_state.router[2], dhcp_state.router[3]);
uip_ipaddr(&uip_netmask, dhcp_state.subnet[0], dhcp_state.subnet[1], dhcp_state.subnet[2], dhcp_state.subnet[3]);
/* T1 is optional. Without it the renewal time stays zero, which
* makes dhcp_timer zero, and the callback then sends a REQUEST on
* every pass through LEASING: client and server trade REQUEST and
* ACK as fast as the round trip allows. RFC 2131 has the client
* renew at half the lease when the server does not say, and if
* there is no lease either, pick something rather than zero. Only
* filled in when absent, so a server that asks for a short renewal
* still gets it. */
if (!dhcp_state.renewal)
dhcp_state.renewal = dhcp_state.lease / 2;
if (!dhcp_state.renewal)
dhcp_state.renewal = 60;
dhcp_state.state = DHCP_LEASING;
dhcp_state.ticks = SYS_TICK_HZ;
dhcp_state.dhcp_timer = dhcp_state.renewal > 0xffff ? 0xffff : dhcp_state.renewal;
}
}
void dhcp_start(void) __banked
{
/* Starting twice would leave the first socket bound: uip_udp_new() takes
* the next free slot while the old one keeps port 68, and dhcp_callback()
* matches on that port rather than on the connection, so every leftover
* runs the state machine too and the timers count down once per socket. */
if (dhcp_state.state != DHCP_OFF)
dhcp_stop();
uip_ipaddr(server, 255,255,255,255);
dhcp_state.conn = uip_udp_new(&server, HTONS(DHCPC_SERVER_PORT));
dhcp_state.current_ip[0] = dhcp_state.current_ip[1] = dhcp_state.current_ip[2] = dhcp_state.current_ip[3] = 0;
if(dhcp_state.conn) {
uip_udp_bind(dhcp_state.conn, HTONS(DHCPC_CLIENT_PORT));
} else {
print_string("dhcp_start failed to set up socket\n");
return;
}
get_random_32();
// Workaround SDCC bug 4070: dhcp_state.transaction_id = SFR_DATA_U32;
__xdata uint8_t * tid = &dhcp_state.transaction_id;
*tid++ = SFR_DATA_24;
*tid++ = SFR_DATA_16;
*tid++ = SFR_DATA_8;
*tid = SFR_DATA_0;
dhcp_state.state = DHCP_START;
}
void dhcp_stop(void) __banked
{
uip_udp_remove(dhcp_state.conn);
dhcp_state.state = DHCP_OFF;
}
void dhcp_callback(uint16_t lport) __banked
{
if (lport != HTONS(DHCPC_CLIENT_PORT)) // Is this call for us? If not, ignore it
return;
if (!dhcp_state.state)
return;
if (uip_closed()) {
print_string("Closed\n");
return;
} else if (uip_newdata()) {
parse_dhcp();
} else {
if (dhcp_state.state == DHCP_START) {
dhcp_send_discover();
} else if (!--dhcp_state.ticks) {
// print_string("Timer: "); print_short(dhcp_state.ticks); write_char(' '); print_short(dhcp_state.dhcp_timer);
dhcp_state.dhcp_timer--;
dhcp_state.ticks = SYS_TICK_HZ;
}
if (!dhcp_state.dhcp_timer) {
switch (dhcp_state.state) {
case DHCP_DISCOVER_SENT:
dhcp_send_discover();
break;
case DHCP_LEASING:
case DHCP_REQUEST_SENT:
dhcp_send_request();
break;
default:
print_string("UNKNOWN STATE\n");
}
}
}
// By default we do not send anything out
uip_len = 0;
}
-43
View File
@@ -1,43 +0,0 @@
#ifndef _DHCP_H_
#define _DHCP_H_
#include "uipopt.h"
#include <stdint.h>
#define DHCPC_SERVER_PORT 67
#define DHCPC_CLIENT_PORT 68
#define DHCP_OFF 0
#define DHCP_START 1
#define DHCP_DISCOVER_SENT 2
#define DHCP_REQUEST_SENT 3
#define DHCP_LEASING 4
void dhcp_start(void) __banked;
void dhcp_stop(void) __banked;
// void dhcp_periodic(void) __banked;
void dhcp_callback(uint16_t lport) __banked;
struct dhcp_state {
uint8_t state;
uint32_t transaction_id;
uint16_t dhcp_timer;
uint8_t ticks;
uint16_t opt_ptr;
uint8_t current_ip[4];
uint8_t server[4];
uint8_t router[4];
uint8_t subnet[4];
uint8_t dns[4];
uint8_t broadcast[4];
uint32_t lease;
uint32_t rebind;
uint32_t renewal;
__xdata struct uip_udp_conn *conn;
};
typedef struct dhcp_state uip_udp_appstate_t;
#endif
+1 -38
View File
@@ -3,12 +3,6 @@
The RTL827x provide a CPU Port for a NIC on the 8051 side of the SoC. The RTL827x provide a CPU Port for a NIC on the 8051 side of the SoC.
## Receiving packets ## Receiving packets
In order to receive packets on the ASIC side, bit 0 of RTL837X_REG_RX_CTRL
(0x785c) must be set. Further bits in the register enable reception of various
kinds of Ethernet frames. They should all be set in order for the firmware
to decide what to do with them. To drop packets with incorrect Ethernet frame CRC
already by the ASIC, clear bit 2 of this register.
Packets are received by either polling the RTL837X_REG_RX_AVAIL register Packets are received by either polling the RTL837X_REG_RX_AVAIL register
(0x7874), which will be > 0 if data is within a ring-buffer on the ASIC side (0x7874), which will be > 0 if data is within a ring-buffer on the ASIC side
of the SoC. Alternatively, an interrupt can be triggered (EX1). of the SoC. Alternatively, an interrupt can be triggered (EX1).
@@ -45,8 +39,7 @@ buffer on the ASIC side by writing 0x1 to RTL837X_REG_RX_DONE (0x784c).
## Transmissing packets ## Transmissing packets
Packets are transmitted by preparing a frame-header plus frame in xdata memory Packets are transmitted by preparing a frame-header plus frame in xdata memory
and transferring both to the ASIC side via the SFRs. The ASIC will transmit and transferring both to the ASIC side via the SFRs.
packets if bit 0 of RTL837X_REG_TX_CTRL (0x7860) is set.
``` ```
SS 07 00 00 LL LH 00 00 SS 07 00 00 LL LH 00 00
@@ -64,33 +57,3 @@ Writing 0x1 to register 0x7850 will transmit the frame. The Ethernet frame
checksum and the TCP checksum are automatically calculated (offloaded) by the checksum and the TCP checksum are automatically calculated (offloaded) by the
ASIC before transmitting on the wire. ASIC before transmitting on the wire.
## The RTL tag words
The frame header uses the Realtek Remote Control Protocol (RRCP) format or
the like.
The `flags` word:
```
bit15 EFID_EN | 14:12 EFID | 11 PRI_EN | 10:8 PRI |
bit7 KEEP | 6 VSEL | 5 LEARN_DIS | 4:0 VIDX
```
All fields are in network byte order.
* `EFID_EN`, `EFID`: look the destination up under this filtering ID
instead of the port's own
* `PRI_EN`, `PRI`: force the given priority on the frame
* `KEEP`: keep the 802.1Q tagging of the frame exactly as injected,
bypassing the egress tagging rules of the port
* `VSEL`, `VIDX`: classify the frame into the VLAN at this index of the
VLAN table
* `LEARN_DIS`: do not learn the source address from this frame
The `pmask` word: bit 15 is `ALLOW`, bits 14 to 0 are a port mask.
* `ALLOW` clear: the mask is the egress set, the frame goes to exactly
the ports given
* `ALLOW` set: the ASIC looks the destination up as usual and the mask
only limits which ports the result may use
-32
View File
@@ -1,32 +0,0 @@
# Automation
## Upload
You can automate upload of the firmware via WEB with curl:
1. Authorize with /login endpoint and save cookie:
```bash
curl -c cookies.txt http://${SWITCH_IP}/login -d pwd=${PASSWORD} -i
```
This will save session cookie in cookies.txt
2. Send the firmware via form:
```bash
curl -b cookies.txt http://${SWITCH_IP}/upload -F "uploadedfile=@${FIRMWARE_FILE_PATH}" -i
```
You can expect that server will close connection, without responding to request.
Wait for SWITCH_IP to be responding again.
## Port status
In similar way to upload, you can fetch the json status of the ports.
1. Get the session cookie as for upload.
2. Hit the `/status.json` with cookie:
```bash
curl -b cookies.txt http://${SWITCH_IP}/status.json
```
-238
View File
@@ -1,238 +0,0 @@
# Egress and Ingress Bandwidth Control
The RTL8372/3 allows to control the bandwidth of data transmitted (egress) and/or
admitted (ingress) at any given port. Once admitted, packets are internally switched
at wire-speed, since the backplane of the devices has a bandwidth of 60GBit/s.
The devices schedules transmission of packets by assigning packets to 8 queues
implemented in hardware per port, which share a total of 8Mbit of memory internal
to the switching part of the SoCs. Packets are assigned to the respective queues
based on the priority assigned to a packet, which can be based on various
properties of a packet such as IEEE 802.1P priority, DSCP value, physical port
number, destination or source MAC, Ether-Type-based, CVID, SVID, IPv4 source or
destination IP, IPv4/IPv6 TOS field, IPv6 Flow Label and even TCP/UDP
source/destination port. Once in a queue, packets are scheduled for egress
based on differnent configurable algorithms.
RTLPlayground currently allows only to control the bandwidth at ingress at a port
or just before packets leave a port. There is no control of the priority assignment
or queue scheduling mechanisms. The bandwidth can be controlled in steps of 16Kbit/s
from 16Kbit/s to 10Gbp/s.
The bandwidth control as currently implemented allows e.g. to assign a certain
share of bandwidth to an attached device (e.g. to share an uplink), or simulate
connections with low bandwidth and even bad connectivity with packet drops when
ingress is not controlled by Flow Control but by simply droping packets.
## Ingress/Egress control
The relevant registers for controlling Ingress and Egress at a port are:
```
#define RTL837X_IGBW_CTRL 0x4c10
#define IGBW_INC_BYPASS_PKT 0x100
#define IGBW_INC_IFG 0x80
#define IGBW_ADM_DHCP 0x20
#define IGBW_ADM_ARPREQ 0x10
#define IGBW_ADM_RMA 0x08
#define IGBW_ADM_BPDU 0x04
#define IGBW_ADM_RTKPKT 0x02
#define IGBW_ADM_IGMP 0x01
#define RTL837X_IGBW_PORT_CTRL 0x4C18
#define RTL837X_IGBW_PORT_FC_CTRL 0x4C8C
#define RTL837X_EGBW_PORT_CTRL 0x1c34
#define RTL837X_EGBW_CTRL 0x447c
#define EGBW_INC_IFG 0x02
#define EGBW_CPUMODE 0x01
```
`RTL837X_IGBW_CTRL/RTL837X_EGBW_CTRL` control the behaviour of the bandwidth control
at ingress and egress. The flags such as `IGBW_ADM_DHCP`control whether certain types
of packets such as DHCP are exempt from being ingress controlled. The
`IGBW_INC_IFG/EGBW_INC_IFG` flags control whether the Inter Frame Gaps are part of
the bandwidth being controlled. `EGBW_CPUMODE` controls whether packets generated
by the internal CPU are subject to egress control.
`RTL837X_IGBW_PORT_CTRL/RTL837X_EGBW_PORT_CTRL` configure the bandwidth for ingress
and egress at a port.
`RTL837X_IGBW_PORT_FC_CTRL` configures whether packets are bandwidth-controlled using
Flow Control (port-bit set), or simply dropped (port-bit clear).
## Ingress/Egress bandwidth API
The code currently provides the following functions:
```
void bandwidth_setup(void) __banked;
void bandwidth_ingress_set(uint8_t port, __xdata uint32_t bw) __banked;
void bandwidth_ingress_disable(uint8_t port) __banked;
void bandwidth_ingress_drop(uint8_t port) __banked;
void bandwidth_egress_set(uint8_t port, __xdata uint32_t bw) __banked;
void bandwidth_egress_disable(uint8_t port) __banked;
void bandwidth_status(uint8_t port) __banked;
```c
`bandwidth_setup()` is called at boot-time and configures excluding all special packets
that may be for the CPU and packets outgoing from the CPU to be excluded from bandwidth
control. IFG is not part of the bandwidth calculation.
`bandwidth_ingress_set()` enables ingress bandwidth control for a particular port given
the specified bandwidth. This also enabled Flow Control at a port.
`bandwidth_ingress_set()` enables egress bandwidth control for a particular port given
the specified bandwidth
`bandwidth_ingress_disable() / bandwidth_egress_disable()` disable ingress and egress
bandwidth control at a given port
`bandwidth_ingress_drop(port)` configures packets exceeding bandwidth limitations to
simply be dropped
`bandwidth_status(port)` shows the current bandwidth control status for a given port
## Bandwidth control configuration on the Serial Console
The following commands are provided on the serial console:
```
> bw [in|out|status] <port> [<hexvalue>|off|drop]
Configures or shows the status of bandwidth control
```
The bandwidth is given as the `<hexvalue>` in Kbit/s. Note that the control is only
possible at a granularity of 16 Kbit/s and the minimum value is also 16 Kbit/s. The
hexadecimal numbers must be given in full bytes, i.e. have an even number of digits.
To enable bandwidth control of ingress for physical port 2 to be set to 256 Kbit/s
do:
```
> bw in 2 0100
```
To drop packets when the bandwidth is exceeeded at port 2 do:
```
> bw in 2 drop
```
To disable bandwidth control for incoming packets on port 2 do:
```
> bw in 2 off
```
## Bandwidth configuration via the Web Interface
Not implemented, yet!
## A Test using iperf3
The following is and example how to test bandwidth control with a signle Linux device using
network namespaces to route packets between a client and a server on the same Linux device
through an external switch.
You will need 2 network intefaces on the linux device, say, 2 USB-Ethernet controllers called
eth0 and eth1:
```
$ sudo ip netns add client
$ sudo ip netns add server
$ sudo ip link set dev eth0 netns client
$ sudo ip link set dev eth1 netns server
$ sudo ip netns exec client ip link set dev eth0 up
$ sudo ip netns exec server ip link set dev eth1 up
$ sudo ip netns exec client ip addr add dev eth0 192.168.99.1/24
$ sudo ip netns exec server ip addr add dev eth1 192.168.99.2/24
$ sudo ip netns exec server iperf3 -s
```
This will start an iper3 server in the above shell.
In a different shell you can now run the iperf3 client against your server:
```
$ sudo ip netns exec client iperf -c 192.168.99.2
```
The LEDs on your switch where your network adapters are connected should start to flicker.
On a 1GBit connection, you should see:
```
$ sudo ip netns exec client iperf3 -c 192.168.99.2
Connecting to host 192.168.99.2, port 5201
[ 5] local 192.168.99.1 port 46776 connected to 192.168.99.2 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 114 MBytes 952 Mbits/sec 0 339 KBytes
[ 5] 1.00-2.00 sec 113 MBytes 946 Mbits/sec 0 356 KBytes
[ 5] 2.00-3.00 sec 112 MBytes 937 Mbits/sec 0 390 KBytes
[ 5] 3.00-4.00 sec 112 MBytes 942 Mbits/sec 0 390 KBytes
[ 5] 4.00-5.00 sec 112 MBytes 943 Mbits/sec 0 390 KBytes
[ 5] 5.00-6.00 sec 112 MBytes 944 Mbits/sec 0 390 KBytes
[ 5] 6.00-7.00 sec 112 MBytes 938 Mbits/sec 0 390 KBytes
[ 5] 7.00-8.00 sec 112 MBytes 942 Mbits/sec 0 410 KBytes
[ 5] 8.00-9.00 sec 113 MBytes 947 Mbits/sec 0 410 KBytes
[ 5] 9.00-10.00 sec 112 MBytes 940 Mbits/sec 0 410 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 1.10 GBytes 943 Mbits/sec 0 sender
[ 5] 0.00-10.00 sec 1.10 GBytes 941 Mbits/sec receiver
```
Now, we limit ingress on port 1 (connected to eth0) to 4 MBit/s:
```> bw in 1 1000
bandwidth_ingress_set called, port 04
RTL837X_IGBW_PORT_CTRL:0x00100100
RTL837X_IGBW_PORT_FC_CTRL:0x00000010
```
We now get:
```
$ sudo ip netns exec client iperf3 -c 192.168.99.2
[ 5] local 192.168.99.1 port 43324 connected to 192.168.99.2 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 1.12 MBytes 9.43 Mbits/sec 0 160 KBytes
[ 5] 1.00-2.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
[ 5] 2.00-3.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes
[ 5] 3.00-4.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes
[ 5] 4.00-5.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
[ 5] 5.00-6.00 sec 256 KBytes 2.10 Mbits/sec 0 160 KBytes
[ 5] 6.00-7.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
[ 5] 7.00-8.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes
[ 5] 8.00-9.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
[ 5] 9.00-10.00 sec 256 KBytes 2.10 Mbits/sec 0 160 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 5.25 MBytes 4.40 Mbits/sec 0 sender
[ 5] 0.00-10.16 sec 4.75 MBytes 3.92 Mbits/sec receiver
iperf Done.
```
Which is the 4Mbit/s we configured. There are no packet drops (retries) because
Flow Control is used to signal the Ethernet adapter on the incoming interface
(port 1 of the router) to slow down.
We can also configure a mere 256KBit/s and packet drop to simulate a bad connection:
```
> bw in 1 0100
bandwidth_ingress_set called, port 04
RTL837X_IGBW_PORT_CTRL:0x00100010
RTL837X_IGBW_PORT_FC_CTRL:0x00000010
> bw in 1 drop
RTL837X_IGBW_PORT_FC_CTRL:0x00000000
```
We now get:
```
$ sudo ip netns exec client iperf3 -c 192.168.99.2
Connecting to host 192.168.99.2, port 5201
[ 5] local 192.168.99.1 port 46060 connected to 192.168.99.2 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 384 KBytes 3.14 Mbits/sec 2 1.41 KBytes
[ 5] 1.00-2.00 sec 0.00 Bytes 0.00 bits/sec 54 1.41 KBytes
[ 5] 2.00-3.00 sec 0.00 Bytes 0.00 bits/sec 31 29.7 KBytes
[ 5] 3.00-4.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes
[ 5] 4.00-5.00 sec 0.00 Bytes 0.00 bits/sec 23 1.41 KBytes
[ 5] 5.00-6.00 sec 128 KBytes 1.05 Mbits/sec 16 14.1 KBytes
[ 5] 6.00-7.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes
[ 5] 7.00-8.00 sec 0.00 Bytes 0.00 bits/sec 11 1.41 KBytes
[ 5] 8.00-9.00 sec 128 KBytes 1.05 Mbits/sec 9 8.48 KBytes
[ 5] 9.00-10.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 640 KBytes 524 Kbits/sec 152 sender
[ 5] 0.00-10.00 sec 256 KBytes 210 Kbits/sec receiver
iperf Done.
```
Which shows a large number of retries due to dropped packets and an average number
of received packets (the client sends the packets to the server, and they are sent
back to the client by the server) of 210 KBit/s, the number is higher for the transmitted
packets, because they may include dropped packets.
-177
View File
@@ -1,177 +0,0 @@
### 2M-PCB23-V2.2
## Brands
| Brand | Type | Managed | PCB | Flash | Chip RTL |
|----------|-----------------|---------|---------------|-------|-------------|
| keepLINK | KP-9000-9XHML-X | Yes | 2M-PCB23-V2.2 | 2M | 8373 + 8224 |
## PCB
<img src="photos/2M-PCB23-V2.2-managed/2M-PCB23-V2.2-top.jpg" width="300" />
## Port overview
```
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ┌──────────┐ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ SFP(J13) │ │
│ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ PORT 9 │ │
│ │ PORT 1 │ │ PORT 2 │ │ PORT 3 │ │ PORT 4 │ │ PORT 5 │ │ PORT 6 │ │ PORT 7 │ │ PORT 8 │ │ MAC 8 │ O (PWR) │
│ O │ MAC 0 │ │ MAC 1 │ │ MAC 2 │ │ MAC 3 │ │ MAC 4 │ │ MAC 5 │ │ MAC 6 │ │ MAC 7 │ │ SerDes 1 │ O (SFP) │
│ RST └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
```
# Connectors
### J13, SFP connector
| SFP Pin | Signal | GPIO | Notes |
| ------- | ----------------- | ------ | ------------------------------ |
| 2 | TX_FAULT | ?? | |
| 3 | TX_DISABLE | ?? | |
| 4 | MODDEF2 – SDA | GPIO39 | |
| 5 | MODDEF1 – SCL | GPIO40 | |
| 6 | MODDEF0 – PRESENT | GPIO30 | "OE Exist" reported by `fiber` |
| 7 | RATE SEL | ?? | |
| 8 | LOS | GPIO37 | "OE LOS" reported by `fiber` |
| 9 | TO? | ?? | |
### T5, serial console
| pin | GPIO | Signal |
| --- | ------ | -------------- |
| 1 | GPIO32 | U0RXD (Input) |
| 2 | GND | Ground |
| 3 | GPIO31 | U0TXD (Output) |
### S1, unknown connector
| pin | GPIO | Signal |
| --- | -------- | -------------- |
| 1 | ??? | |
| x | | |
| 3 | ??? | |
| 4 | ??? | |
| 5 | ??? | |
Potentially slave interface or SMI.
### U7, flash memory
Flash chip is FM25Q16A.
### Reset button
GPIO54
## Register values
As probed with `regget` on stock firmware "V1.6".
### Model
| Name | Addr | Value |
| ------------------------- | ------ | ---------- |
| MODEL_NAME_INFO | 0x0004 | 0x83730000 |
| CHIP_MODE_INFO | 0x0008 | 0x00008000 |
| CHIP_INFO | 0x000C | 0x00300000 |
### GPIO
| Name | Addr | Value |
| ------------------------- | ------ | ---------- |
| GPIO_OUT0 | 0x003c | 0x10000000 |
| GPIO_OUT1 | 0x0040 | 0x00000010 |
| GPIO_OE0 | 0x004c | 0x10000000 |
| GPIO_OE1 | 0x0050 | 0x00000010 |
| BOND_INFO | 0x7f60 | 0x00000fff |
| STRAP_INFO | 0x7f64 | 0x0002f515 |
| IO_DRVING_0 | 0x7f68 | 0x00000000 |
| IO_DRVING_1 | 0x7f6c | 0x00000000 |
| IO_DRVING_2 | 0x7f70 | 0x00000000 |
| IO_SLEW_0 | 0x7f74 | 0x00000000 |
| IO_SLEW_1 | 0x7f78 | 0x00000000 |
| IO_SLEW_2 | 0x7f7c | 0x00000000 |
| IO_SMT_EN_0 | 0x7f80 | 0xffffffff |
| IO_SMT_EN_1 | 0x7f84 | 0xffffffff |
| IO_SMT_EN_2 | 0x7f88 | 0x0003ffff |
| IO_MUX_SEL_0 | 0x7f8c | 0x28000000 |
| IO_MUX_SEL_1 | 0x7f90 | 0x40000041 |
| IO_MUX_SEL_2 | 0x7f94 | 0x00000000 |
### LED
| Name | Addr | Value |
| ------------------------- | ------ | ---------- |
| LED_GLB_CTRL | 0x6520 | 0x0023e0f0 |
| LED3_0_SET3_2_CTRL1 | 0x6524 | 0xff001400 |
| LED3_0_SET1_0_CTRL1 | 0x6528 | 0x000f0000 |
| LED3_2_SET3_CTRL0 | 0x652c | 0x007f013f |
| LED1_0_SET3_CTRL0 | 0x6530 | 0x02000400 |
| LED3_2_SET2_CTRL0 | 0x6534 | 0x01400141 |
| LED1_0_SET2_CTRL0 | 0x6538 | 0x01440170 |
| LED3_2_SET1_CTRL0 | 0x653c | 0x18000041 |
| LED1_0_SET1_CTRL0 | 0x6540 | 0x0044017f |
| LED3_2_SET0_CTRL0 | 0x6544 | 0x00000044 |
| LED1_0_SET0_CTRL0 | 0x6548 | 0x00410175 |
| LED_PORT_SET_SEL_CTRL | 0x654c | 0x00010000 |
| SW_LED_LOAD | 0x6550 | 0x00000000 |
| LED_PORT_SW_EN_CTRL[0..7] | 0x6554 | 0x00000000 |
| LED_PORT_SW_EN_CTRL[8] | 0x6558 | 0x00000000 |
| LED_PORT_SW_CTRL[0] | 0x655c | 0x00000000 |
| LED_PORT_SW_CTRL[1] | 0x6560 | 0x00000000 |
| LED_PORT_SW_CTRL[2] | 0x6564 | 0x00000000 |
| LED_PORT_SW_CTRL[3] | 0x6568 | 0x00000000 |
| LED_PORT_SW_CTRL[4] | 0x656c | 0x00000000 |
| LED_PORT_SW_CTRL[5] | 0x6570 | 0x00000000 |
| LED_PORT_SW_CTRL[6] | 0x6574 | 0x00000000 |
| LED_PORT_SW_CTRL[7] | 0x6578 | 0x00000000 |
| LED_PORT_SW_CTRL[8] | 0x657c | 0x00000000 |
| LED_LOAD_LV1_10G | 0x6580 | 0x000fa000 |
| LED_LOAD_LV2_10G | 0x6584 | 0x00271000 |
| LED_LOAD_LV3_10G | 0x6588 | 0x004e2000 |
| LED_LOAD_LV1_5G | 0x658c | 0x000fa000 |
| LED_LOAD_LV2_5G | 0x6590 | 0x00271000 |
| LED_LOAD_LV3_5G | 0x6594 | 0x004e2000 |
| LED_LOAD_LV1_2P5G | 0x6598 | 0x000fa000 |
| LED_LOAD_LV2_2P5G | 0x659c | 0x00271000 |
| LED_LOAD_LV3_2P5G | 0x65a0 | 0x004e2000 |
| LED_LOAD_LV1_1G | 0x65a4 | 0x000fa000 |
| LED_LOAD_LV2_1G | 0x65a8 | 0x00271000 |
| LED_LOAD_LV3_1G | 0x65ac | 0x004e2000 |
| LED_LOAD_LV1_500M | 0x65b0 | 0x0007d000 |
| LED_LOAD_LV2_500M | 0x65b4 | 0x00138800 |
| LED_LOAD_LV3_500M | 0x65b8 | 0x00271000 |
| LED_LOAD_LV1_100M | 0x65bc | 0x00019000 |
| LED_LOAD_LV2_100M | 0x65c0 | 0x0003e800 |
| LED_LOAD_LV3_100M | 0x65c4 | 0x0007d000 |
| LED_LOAD_LV1_10M | 0x65c8 | 0x00002800 |
| LED_LOAD_LV2_10M | 0x65cc | 0x00006400 |
| LED_LOAD_LV3_10M | 0x65d0 | 0x0000c800 |
| LED_P_LOAD_CTRL | 0x65d4 | 0x00000000 |
| LED_GLB_ACTIVE | 0x65d8 | 0x3ffbedff |
| LED_GLB_IO_EN | 0x65dc | 0x77ffffff |
| LED_GLB_MUX_1 | 0c65e0 | 0x05102040 |
| LED_GLB_MUX_2 | 0x65e4 | 0x0c289206 |
| LED_GLB_MUX_3 | 0x65e8 | 0x1245038d |
| LED_GLB_MUX_4 | 0x65ec | 0x19616554 |
| LED_GLB_MUX_5 | 0x65f0 | 0x2079d71a |
| LED_GLB_MUX_6 | 0x65f4 | 0x000238a1 |
| LED_RLDP_CTRL_1 | 0x65f8 | 0x00000019 |
| LED_RLDP_CTRL_2 | 0x65fc | 0xffffffff |
| LED_RLDP_CTRL_3 | 0x6600 | 0x00006600 |
| LED_DUMY_0_ADDR | 0x6604 | 0x00000000 |
| LED_DUMY_1_ADDR | 0x6608 | 0x00000000 |
# LEDs
| Name | Components | Controlled by |
| ----------------------------- | --------------------------- | -------------------------- |
| RJ45 Right Green ("LINK/ACT") | | RJ45 LED0 |
| RJ45 Left Orange ("2.5G") | | RJ45 LED1 |
| RJ45 Left Green ("1G") | | RJ45 LED2 |
| "P" (PWR) | Top LED in "LED6" stack | probably pulled from Vcc |
| SFP Link ("9") | Bottom LED in "LED6" stack | SFP LED0 |
| ?? | D23 | SFP LED1 |
| ?? | D22 | SFP LED2 |
-161
View File
@@ -1,161 +0,0 @@
### 2M-PCB23-V3.1
## Brands
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|---|---|---|---|---|---|
| keepLINK | KP-9000-9XHML-X | Yes| 2M-PCB23-V3.1 | 2M| 8273N + 8224N |
## PCB
<img src="photos/2M-PCB23-V3.1-managed/2M-PCB23-V3.1-top.jpeg" width="300" />
## Port overview
```
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ┌──────────┐ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ SFP (J4) │ │
│ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ PORT 9 │ │
│ │ PORT 1 │ │ PORT 2 │ │ PORT 3 │ │ PORT 4 │ │ PORT 5 │ │ PORT 6 │ │ PORT 7 │ │ PORT 8 │ │ MAC 8 │ O (PWR) │
│ O │ MAC 0 │ │ MAC 1 │ │ MAC 2 │ │ MAC 3 │ │ MAC 4 │ │ MAC 5 │ │ MAC 6 │ │ MAC 7 │ │ SerDes 1 │ O (SFP) │
│ RST └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
```
# Connectors
|`J4` SFP PINs | Signal | Component | GPIO | Notes |
|---|---|---|---|---|
|2| TX_FAULT | | --- | |
|3| TX_DISABLE | | --- | Pull down - 0R |
|4| MODDEF2 – SDA | b-r273 | GPIO39-SDA4 | |
|5| MODDEF1 – SCL | b-r274 | GPIO40-SCL3 | |
|6| MODDEF0 – PRESENT | B-R275 | GPIO38 | |
|7| RATE SEL | | --- | |
|8| LOS | B-R276 | GPIO38 | |
|9| TO? | | --- | |
Note: component numbering `<L>-<REFDES>-<SIDE>`
* L: Layer, T=Top, B=Bottom
* REFDEES: full silkscreen like `R123`
* SIDE: Side of the component. when the rj45 are facing towards you are you can read the silkscreen normal.
L = Left, R=right, B=bottom, T=top or P with a pin number.
### T8, serial console
|`T9` pin|GPIO|Signal|
|---|---|---|
| 1 | GPIO31 | U0TXD (Output) |
| 2 | GND | PWR |
| 3 | GPIO32 | U0RXD (Input) |
| 4 | 3V3 | PWR |
### T7, Slave Interface
|`T7` pin|what|Signal|Components|
|---|---|---|---|
| 1 | Slave Interface | Slave SCK/SCL/MDC/EE_SCL | U7-6 |
| 2 | GND | | |
| 3 | Slave Interface | Slave SDI/SDA/MDIO/EE_SDA | U7-5 |
| 4 | 3V3 | | |
| 5 | GPIO? | | |
| 6 | GPIO? | | |
`U7` can be a standard I2C eeprom memory, like `24LC32`.
The Slave Interface allows an extenal host to controll the SOC even if the internal MCU is used.
Depending on the `IF_SEL` bootstrap resistors, this can me `I2C`, `SPI` or `SMI`.
On this device it is `I2C` on address `0b1011100` or `0x5c` (7-bit notation).
* I2c Read: must be a write_read opperation `<Dev-ADDR><RegAddr15:8><RegAddr7:0>` `<DevAddr><Data7:0><Data15:8><Data23:16><Data31:24>`.
* I2c Write: `<Dev-ADDR><RegAddr15:8><RegAddr7:0><DevAddr><Data7:0><Data15:8><Data23:16><Data31:24>`.
Example register `0x0004` return chip id `0x00, 0x00, 0x72, 0x83` = `0x83720000`.
### T9
|`T9` SMI | Signal | Component | GPIO | Notes |
|---|---|---|---|---|
|1| MDO | SMI-MDO | GPIO41 | |
|2| GND | PWR | | |
|3| MDC | SMI-MDC | GPio40 | |
### T10
|`T10` pin|what|Signal|
|---|---|---|
| 1 | GPIO49 | |
| 2 | GPIO47 | |
| 3 | 3V3 | |
| 4 | GPIO48 | |
| 5 | GND | |
| 6 | GPIO46 | |
# Reset ciruit
Reset-line found at `T-D6-L`, `T-R83`, `T-R97`, `T-R94`, `T-R93` active-low.
# GPIO
| HEX VAL. | GPIO | Component | What | | GPIO | Component | What |
| -------- | ------ | ---- | ---- | ---- | ---- | ---- | ---- |
| 00000001 | GPIO00 | T-R34-R, P1-LED-YL |? | | GPIO32 | B-r126-r | U0RXD |
| 00000002 | GPIO01 | T-R99-R, P1-LED-GR |? | | GPIO33 | | |
| 00000004 | GPIO02 | |? | | GPIO34 | B-R172, To RTL8224 | SMI-MDC0 |
| 00000008 | GPIO03 | T-R113-R, P2-LED-GR |? | | GPIO35 | B-R173, To RTL8224 | SMI-MDIO0 |
| 00000010 | GPIO04 | T-R115-R, P3-LED-YL |? | | GPIO36 | | | |
| 00000020 | GPIO05 | T-R117-R, P3-LED-GR |? | | GPIO37 | To RTL8224 ?? | Already driver low | |
| 00000040 | GPIO06 | |? | | GPIO38 | sfp-6 via B-R275, sfp-8 via B-R276 | SFP-PRESENT |
| 00000080 | GPIO07 | |? | | GPIO39 | sfp-4, b-r273, B-r143 | I2C4-SDA |
| 00000100 | GPIO08 | | | | GPIO40 | T9-2, sfp-5 b-r274, B-r146 | I2C3-SCL |
| 00000200 | GPIO09 | |LEDx[^1] | | GPIO41 | T9-1, B-r143 | | I2C3-SDA (Unused) |
| 00000400 | GPIO10 | | | | GPIO42 | U6?8?-P6, T-R | SPI-MEMORY, CLK |
| 00000800 | GPIO11 | |LEDx[^1] | | GPIO43 | U6?8?-P5, T-R | SPI-MEMORY, DI,IO0 |
| 00001000 | GPIO12 | |LEDx[^1] | | GPIO44 | U6?8?-P2, T-R | SPI-MEMORY, DO,IO1 |
| 00002000 | GPIO13 | |LEDx[^1] | | GPIO45 | U6?8?-P1, T-R | SPI-MEMORY, CS |
| 00004000 | GPIO14 | |LEDx[^1] | | GPIO46 | T10-6 | SPI0-SCK |
| 00008000 | GPIO15 | |LEDx[^1] | | GPIO47 | T10-2 | SPI0-SDA |
| 00010000 | GPIO16 | |LEDx[^1] | | GPIO48 | T10-4, J6 (BUTTON RESET) | SPI1-SCK |
| 00020000 | GPIO17 | |LEDx[^1] | | GPIO49 | T10-1 | SPI1-SDA |
| 00040000 | GPIO18 | |LEDx[^1] | | GPIO50 | | |
| 00080000 | GPIO19 | |LEDx[^1] | | GPIO51 | | |
| 00100000 | GPIO20 | |LEDx[^1] | | GPIO52 | | |
| 00200000 | GPIO21 | P7-LED-GR, B-R139 |LEDx[^1] | | GPIO53 | | |
| 00400000 | GPIO22 | |LEDx[^1] | | GPIO54 | | |
| 00800000 | GPIO23 | |LEDx[^1] | | GPIO55 | | |
| 01000000 | GPIO24 | P8-led-yellow,b-r154 |LEDx | | GPIO56 | | |
| 02000000 | GPIO25 | | | | GPIO57 | | |
| 04000000 | GPIO26 | |LEDx | | GPIO58 | | |
| 08000000 | GPIO27 | |? | | GPIO59 | | |
| 10000000 | GPIO28 | | | | GPIO60 | | |
| 20000000 | GPIO29 | | | | GPIO61 | | |
| 40000000 | GPIO30 | RTL8224N Reset |RTL8224 | | GPIO62 | To RTL8224 | Already driver | |
| 80000000 | GPIO31 | B-r129-r? |U0TXD | | GPIO63 | | |
## GPIO Register Input value
GPIO 1: 0a7ffbdd
GPIO 0: effb6dff
# LEDs
| NAME | COMPONENTS | GPIO |
| ---- | ---------- | ---- |
| SYSTEM | | ? |
| SFP | | ? |
# Power supply
Board has two supply rails.
`0.95` and `3.3` volt.
## `0.95` Core Voltage.
Voltage is crated by a `MP2225GJ` Buck converter.
0.95V must be within 3%.
## `3.3` Voltage
Voltage is crated by a `MP2225GJ` Buck converter.
3.3V must be within 4.5%.
Chip can deliver up to 5A and the sweetspot is at 2A.
So higher power SFP-modules should work.
[^1]: LEDs are found by just plugin a RJ45 connector and see with cmd `gpio` the status change. But the bit pattern for port 1,2 are diffrent from port 3,4.
-40
View File
@@ -1,40 +0,0 @@
### 2M-PCB23-V3.2
## Brands
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|---|---|---|---|---|---|
| keepLINK | KP-9000-9XHML-X | Yes| 2M-PCB23-V3.2 | 2M (Winbond 25Q) | |
The original web interface reports this board as hardware version V3.2
(original firmware V100.9.25, January 2026).
## PCB
<img src="photos/2M-PCB23-V3.2-managed/2M-PCB23-V3.2-top.jpeg" width="300" />
## Compared to V3.1
The component placement matches [2M-PCB23-V3.1](2M-PCB23-V3_1.md): same
positions for the flash (U8), the T7/T8/T9/T10 headers, the SFP cage and its
LED, and the unpopulated U7/U9 footprints. Build with
`MACHINE=KP_9000_9XHML_X_V3_2`, which uses the V3.1 machine definition and
only differs in the reported name.
## Tested
Installed from the original firmware through its web interface with
`installer/output/rtlplayground_oem_upgrade.bin`, then:
- RJ45 ports link at 2.5G; LEDs: orange at 2.5G, green below
- SFP port: module detected with vendor/model/serial and DOM readings
(temperature, Vcc, TX bias, TX/RX power), link up at 10G
- factory MAC read from flash (0x1FC000)
- reset button (GPIO48): held for more than 10 s it restores the default config
## Flash access
Reading the flash in-circuit with a SOIC-8 clip did not work: the chip ID
comes back as `EF FF FF` (only the manufacturer byte is right) and reads
return 0xff, the same as on a V3.1 board. The switch chip is powered through
the clip and keeps driving the SPI lines. Make sure a way back is acceptable
before installing, or hold the switch chip in reset while reading.
-55
View File
@@ -1,55 +0,0 @@
# 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.
-32
View File
@@ -1,32 +0,0 @@
# MokerLink POE-2G080110GS
The `POE-2G080110GS` is an unmanaged 8x2.5G RJ45 and 1xSFP+ PoE switch sold by Mokerlink. There is also a `POE-2G080110GSM` managed version of the switch which may be similar but this has not been verified on actual hardware.
## Brands
| Brand | Type |Managed| PCB | Flash | Chip RTL |
|--------|------------------|-------|------------------|-----------------|---------------|
| Mokerlink | POE-2G080110GS | No | 2M-PCB51-ML-V1.1 | 4MB (W25Q32JV) | 8373N + 8224N |
## Hardware overview
Front
<img src="photos/POE-2G080110GS/POE-2G080110GS-front.jpg" width="300" />
Label
<img src="photos/POE-2G080110GS/POE-2G080110GS-label.jpg" width="300" />
The stock firmware from a POE-2G080110GS device had a sha256sum of `4c280853465eaad80e1772075c0f2d29c11fb8c561547f06353d3a5443c388e9`.
### PCB
Top silkscreen is marked `2M-PCB51-ML-V1.1`. PoE is provided by RTL8238C. Flash chip is 4 MB Winbond 25Q32JV (U8).
<img src="photos/POE-2G080110GS/POE-2G080110GS-pcb.jpg" width="300" />
> [!CAUTION]
> This device operates on mains voltage, which can be a dangerous or potentially lethal hazard. Even after the device is unplugged, high-voltage capacitors can remain charged afterward and may still shock you. Do not attempt to open/disassemble a mains powered device unless you understand how to do so safely. Also, opening the device may void your warranty.
## Notes
The stock firmware blinks both the 2.5G and 1G LEDs on activity, despite the front of the device indicating that each LED should be independent. The `POE_2G080110GS` machine config behaves as the front of the device indicates (and what seems more logical) -- each port LED turns on and blinks independently.
-70
View File
@@ -1,70 +0,0 @@
# F7008-2.5
Documentation for the unmanaged 8 + 1 switch sold as `7018-2.5G` by Guangnianwei
(光年微), board marking `F7008-2.5`, PCB `F7008-2.5GPOE-V1.2`.
### Brands
| Brand | Type | Managed | PCB | Flash | Chip RTL |
|-------|------|---------|-----|-------|----------|
| Guangnianwei (光年微) | 7018-2.5G | No | F7008-2.5GPOE-V1.2 | W25Q64JVSSIQ | 8373N + 8224N |
### What works
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
- SFP+ port with 1G/2.5G/10G modules
- LEDs of the eight RJ45 ports
### Not verified
- The LED pads for the SFP+ cage are not mapped yet. The SFP+ lamps are left
undriven, so an inserted module lights nothing.
- The UART header footprint is present but unpopulated, and no boot log could be
captured from it, so the baud rate is unknown. There are most likely
unpopulated 0-Ohm resistors next to the header; bridging those should bring
the console to life.
### Build target
```
make MACHINE=F7008_2_5
```
### LED wiring
Measured pad to lamp map (`led_mux` index -> lamp):
| Port | green lamp | yellow lamp |
|------|-----------|-------------|
| 1 | pad 0 | pad 1 |
| 2 | pad 2 | pad 3 |
| 3 | pad 4 | pad 5 |
| 4 | pad 6 | pad 8 |
| 5 | pad 9 | pad 10 |
| 6 | pad 12 | pad 15 |
| 7 | pad 18 | pad 21 |
| 8 | pad 24 | pad 25 |
Pads 7, 11, 13, 14, 16, 17, 19, 20, 22, 23, 26 and 27 do not drive an RJ45 lamp.
The front panel is silkscreened `2.5G: Green / 10/100M: Yellow`, and the target
follows it: the green lamp is on while the port is linked at 2.5G, the yellow
lamp blinks while data is flowing.
### PCB overview
The board is marked `F7008-2.5GPOE-V1.2`.
Top side:
<img src="photos/F7008-2.5/PCB-top.jpg" width="600" />
Bottom side:
<img src="photos/F7008-2.5/PCB-bottom.jpg" width="600" />
### Hardware notes
- 4 x `RT4802SNE` magnetics
- Unpopulated UART header footprint, next to the magnetics
- Power input 12V 1A, 180 x 84 x 29 mm metal case
-39
View File
@@ -1,39 +0,0 @@
# 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.
-79
View File
@@ -1,79 +0,0 @@
# FG-8GT-1SX
Following is documentation for unmanaged switch marked as `FG-8GT-1SX`.
Original software is running UART on 9600 baud rate.
Using SPI clamp in-board is the only method for initial installation.
### Brands
| Brand | Type | Managed | PCB | Flash | Chip RTL |
|---------|------------|---------|------------|-------------|---------------|
| Ruiying | RY-8GT-1SX | No | FG-8GT-1SX | GD25Q80ESIG | 8373N + 8224N |
### What works
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
- SFP port with 1G/2.5G/10G modules
- LEDs
### PCB overview
**Board markings**
- Top silkscreen: FG-8GT-1SX
Top side:
<img src="photos/FG-8GT-1SX/PCB-top.jpg" width="600" />
Bottom:
<img src="photos/FG-8GT-1SX/PCB-bottom.jpg" width="600" />
### Serial console
The PCB has five unpopulated through-holes near the SoC, with a white rectangle surrouding them, labeled as `J18` and a triangle points to the square shaped first pin.
This is where the "expected" UART header should be soldered at, with redundant 3V3 VCC, but also with missing 0Ω resistors between TX/RX and SoC, so simply soldering a header would not work. One need also add the missing resistors or solder the pads together, while making sure not connecting unrelated pads.
Numbered from the triangle, the header pinout is:
| Position | Signal | GPIO | Status |
|----------|--------|--------|-------------|
| 1 | GND | GND | Internal |
| 2 | TX | GPIO31 | Unconnected |
| 3 | RX | GPIO32 | Unconnected |
| 4 | 3V3 | - | Internal |
| 5 | 3V3 | - | Internal |
There're four resistor pads near the header.
| Resistor ID | SoC Side | Header Side |
|-------------|-------------|-------------|
| R1240 | TX / GPIO31 | Pin 2 |
| R1243 | 3V3 | - |
| R1242 | 3V3 | Pin 3 |
| R1241 | RX / GPIO32 | - |
To get TX working, solder a 0Ω resistor between the pads for R1240 or solder them together.
For RX However, the designer certainly made a mistake, as the SoC-side lines to the resistor expected for Rx (R1242) and 3V3 (R1241) are swapped. For RX to work, the R1241 SoC side and R1242 header side shall be connected, so either:
- Solder: R1241 SoC side -> R1241 header side -> R1242 header side
- Jump wire: R1241 SoC side -> R1242 header side
Be sure not to bring R1242 SoC side to the connection as that would wire Rx to 3v3.
A complete working serial header should look like following on this PCB:
<img src="photos/FG-8GT-1SX/Serial.png" width="600" />
- **Settings**: 115200 baud / 8N1 / 3.3V TTL
- Connect a USB-TTL adapter: adapter GND → pin 1, RX → pin 2, TX → pin 3
### Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
-93
View File
@@ -1,93 +0,0 @@
# FOXNEO FNS-1200P
RTL8372-based 4×2.5G PoE+ + 2×SFP+ unmanaged switch.
Using SPI clamp in-board is the only method for initial installation.
### Label specifications
- **Manufacturer**: FOXNEO
- **Model**: FNS-1200P
- **Ports**:
- 4 × RJ45: 10/100/1000/2500 Mbps with PoE+
- 2 × SFP+: 1G / 2.5G / 10G
### What works
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps (PoE+ is not configurable via RTLPlayground)
- Both SFP+ ports supporting 1G, 2.5G and 10G modules
- LEDs: amber (2.5G) and green (1G/100M/10M) per copper port; combined link/act on SFP ports
### PCB overview
**Board markings**
- Top silkscreen: PCB-K0402W-U13-V2.0 / DIP-K0402WB-V2.0
**Key components**
- U3: SPI NOR flash, 2 MiB
- U7: unpopulated SOP8 footprint — I2C bus (RTL8372 slave at 0x5c) is accessible from its pads, useful for register dumps
- S1: unpopulated slide switch footprint (three through-holes used as serial console)
Front panel
<img src="photos/FNS-1200P/chassis-front.jpg" width="400" />
Top side (PCB)
<img src="photos/FNS-1200P/PCB-top.jpg" width="300" />
### Port layout
| Front panel position | Logical port | Physical port | Type |
|----------------------|--------------|---------------|---------|
| SFP left | 8 | 5 | SFP+ |
| RJ45 1 | 4 | 1 | Copper |
| RJ45 2 | 5 | 2 | Copper |
| RJ45 3 | 6 | 3 | Copper |
| RJ45 4 | 7 | 4 | Copper |
| SFP right | 3 | 6 | SFP+ |
### Serial console
The PCB has three unpopulated through-holes intended for a slide switch, directly connected to UART0.
Numbered from the left (SFP port side), the pinout is:
| Position (left→right) | Signal | GPIO |
|-----------------------|--------|--------------------------|
| 1 (leftmost) | RX | GPIO32\_UART0\_RX (32) |
| 2 (middle) | GND | GND |
| 3 (rightmost) | TX | GPIO31\_UART0\_TX (31) |
- **Settings**: 115200 baud / 8N1 / 3.3V TTL
- Connect a USB-TTL adapter: adapter TX → pin 1, GND → pin 2, adapter RX → pin 3
### LED configuration
Copper ports use LED SET0, SFP ports use LED SET1.
| SET | LED0 | LED2 |
|------|--------------------------------------------------|---------------------------------------------------|
| SET0 | Amber — lights on 2.5G link | Green — lights on 1G / 100M / 10M link |
| SET1 | All speeds — lights on any link with activity | — |
LED pad to physical port mapping:
| GPIO pads | Port |
|-----------|-------------------------|
| GPIO8–11 | Physical port 5 (left SFP) |
| GPIO12–14 | Physical port 1 (RJ45 1) |
| GPIO15–17 | Physical port 2 (RJ45 2) |
| GPIO18–20 | Physical port 3 (RJ45 3) |
| GPIO21–23 | Physical port 4 (RJ45 4) |
| GPIO24–27 | Physical port 6 (right SFP) |
### SFP GPIO assignments
| SFP | pin\_detect (ModAbs) | pin\_los | SerDes | I2C SDA | I2C SCL |
|------------------|-----------------------------|------------------------|--------|----------------------|--------------------------|
| Left (logical 8) | GPIO30\_ACL\_BIT3\_EN | GPIO37 | SDS1 | GPIO39\_I2C\_SDA4 | GPIO40\_I2C\_SCL3\_MDC1 |
| Right (logical 3)| GPIO50\_I2C\_SCL2\_UART1\_TX | GPIO51\_I2C\_SDA2\_UART1\_RX | SDS0 | GPIO41\_I2C\_SDA3\_MDIO1 | GPIO40\_I2C\_SCL3\_MDC1 |
GPIO assignments were verified by observing GPIO state changes during SFP module insertion/removal
and cross-checked against an original firmware register dump.
`pin_tx_disable` is GPIO\_NA on both ports (original firmware keeps all GPIOs as inputs).
-75
View File
@@ -1,75 +0,0 @@
# Hasivo S1100WP-8GT-1SX-SE
RTL8373-based 8×2.5G PoE + 1×SFP switch.
### Label specifications
- **Manufacturer**: Hasivo
- **Model**: S1100WP-8GT-1SX-SE
- **Ports**:
- 8 × RJ45: 10/100/1000/2500 Mbps with PoE
- 1 × SFP: 1G / 2.5G / 10G
- **Power input**: DC 52V 2.5A
- **Stock firmware defaults**: IP 192.168.0.1, user/password `admin`/`admin`
### What works
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps (PoE is not configurable via RTLPlayground)
- SFP port supporting 1G, 2.5G and 10G modules
- LEDs: green (2.5G) and amber (1G/100M/10M) per copper port; combined link/act on the SFP port
### Photos
Front panel:
<img src="photos/HASIVO_S1100WP-8GT-1SX-SE/front.jpg" width="600" />
Label:
<img src="photos/HASIVO_S1100WP-8GT-1SX-SE/label.jpg" width="600" />
### PCB overview
Top side:
<img src="photos/HASIVO_S1100WP-8GT-1SX-SE/pcb_top.jpg" width="600" />
Bottom side:
<img src="photos/HASIVO_S1100WP-8GT-1SX-SE/pcb_bottom.jpg" width="600" />
### Port layout
| Logical port | Physical port | Type |
|--------------|---------------|--------|
| 1-8 | 1-8 | Copper |
| 9 | 9 | SFP |
### LED configuration
Copper ports use LED SET0, the SFP port uses LED SET1.
| SET | LED0 | LED2 |
|------|-----------------------------------------------|------------------------------------------------------|
| SET0 | Green — lights on 2.5G link with activity | Amber — lights on 1G / 100M / 10M link with activity |
| SET1 | All speeds — lights on any link with activity | — |
### SFP GPIO assignments
| SFP (logical 9) | pin_detect (ModAbs) | pin_los | pin_tx_disable | SerDes | I2C SDA | I2C SCL |
|-----------------|---------------------|---------|----------------|--------|-----------------|---------------------|
| SFP | GPIO30_ACL_BIT3_EN | GPIO37 | GPIO_NA | SDS1 | GPIO39_I2C_SDA4 | GPIO40_I2C_SCL3_MDC1 |
### Machine configuration
- `reset_pin`: GPIO54_ACL_BIT2_EN
- High LEDs (pads 27-29): mux = `LED_27 | LED_28_SYS | LED_29`, enable = `LED_28_SYS | LED_29`
### PoE
The 8 copper ports support PoE powered by a DC 52V 2.5A input. Power management is handled by two HS104PTI chipsets over I2C (GPIO47_I2C_SDA0, GPIO46_I2C_SCL0):
* Chip 1 (I2C address 0x1A): 2.5G Ports 1–4
* Chip 2 (I2C address 0x2A): 2.5G Ports 5–8
Note: The current implementation does not yet support PoE management. Consequently, PoE currently operates in standalone mode without software control.
-36
View File
@@ -1,36 +0,0 @@
# Hisource Hi-K0801WS
Following is documentation for unmanaged switch marked as `Hi-K0801WS`.
Using SPI clamp in-board is the only method for initial installation.
### Label specifications
- **Name**: 2.5G Ethernet Switch
- **Model**: Hi-K0801WS
- **Ports**:
- 8 × RJ45: 10/100/1000/2500 Mbps
- 1 × SFP: 1000 / 2500 / 10000 Mbps
### What works (expected from label + similar devices)
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
- SFP port supporting 1G, 2.5G and 10G modules
- LEDs
### PCB overview
**Board markings**
- Top silkscreen: PCB-KO801W-V2.0 / DIP-KO801WS-V2.0
Top side
<img src="photos/K0801W-V2.0-unmanaged\PCB-top.jpg" width="300" />
Bottom
<img src="photos/K0801W-V2.0-unmanaged\PCB-bottom.jpg" width="300" />
## Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
-64
View File
@@ -1,64 +0,0 @@
# Lianguo HYWS-SGT0108S
Following is documentation for unmanaged switch marked as `HYWS-SGT0108S`.
Original software is running UART on 9600 baud rate. Output is very minimal.
Using SPI clamp in-board is the only method for initial installation and update.
Stock flash chip is 512KB in size. Consider replacing for update through Web UI.
- Header for uart is clearly identified.
- The red LED act as a powered-on LED.
- There is no SYS LED.
- There is a footprint for a Reset button. Unpopulated. Unclear if routed back to RTL8373.
### Label specifications
- **Name**: 2.5G Ethernet Switch 8+1
- **Model**: HYWS-SGT0108S
- **Ports**:
- 8 × RJ45: 10/100/1000/2500 Mbps
- 1 × SFP: 1000 / 2500 / 10000 Mbps
### What works
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
- SFP port supporting 1G, 2.5G and 10G modules
- RJ45 LEDs (Blue+White)
- SFP Single LED (Blue)
### Assembled unit
Top side
<img src="photos/HYWS-SGT0108S-unmanaged\Assembled-top.jpg" width="300" />
Front
<img src="photos/HYWS-SGT0108S-unmanaged\Assembled-front.jpg" width="300" />
Bottom
<img src="photos/HYWS-SGT0108S-unmanaged\Assembled-bottom.jpg" width="300" />
### PCB overview
**Board markings**
- Top silkscreen: 2G5F_20G_V1.01 / 2023-09-28
Top side
<img src="photos/HYWS-SGT0108S-unmanaged\PCB-top.jpg" width="300" />
Bottom
<img src="photos/HYWS-SGT0108S-unmanaged\PCB-bot.jpg" width="300" />
Original SPI Flash Chip
<img src="photos/HYWS-SGT0108S-unmanaged\og_spi_flash.jpg" width="300" />
## Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
-23
View File
@@ -1,23 +0,0 @@
# K0501W V2.0
This board appears for example in the Davuaz Da-K6501W switch.
The general design of the board is similar to Hi-K0402WS V3.0.
However, there are several differences:
- One SFP port is replaced by a RTL8221B 2.5G PHY
- Only one LED is populated for the SFP port
- No mode switch and only one flash chip
- Older design using RTL8372 instead of RTL8372N (which also means different GPIO and LED configuration)
- Like earlier versions of the K0402W(S) board, there is no UART
All ports and LEDs are supported.
Installation is possible using a flash programmer.
The BoyaMicro 25Q16BSSIG flash chip is supported by flashprog with chip name "B.25D16AS/BY25Q16BS/BY25Q16ES".
## PCB pictures
The board is marked `PCB-K0501W-V2.0 DIP-K0501WS-V2.0`.
<img src="photos/K0501W_V2_0/pcb-top.jpg" width="300" />
<img src="photos/K0501W_V2_0/pcb-bottom.jpg" width="300" />
-93
View File
@@ -1,93 +0,0 @@
# Keeplink KP-9000-6XH-X2 / KP-9000-6XHML-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.
### Label specifications
- **Name**: 4X 2.5G RJ45 Port + 2 X 10G SFP+ Port
- **Model**: KP-9000-6XH-X2 / KP-9000-6XHML-X2
- **Ports**:
- 4 × RJ45: 10/100/1000/2500 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
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
- SFP port with 10G modules
- LEDs
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
### Hardware overview: 2M-PCB43-V2.1
Front side:
<img src="photos/2M-PCB43-V2.1-unmanaged/KP-9000-6XH-X2-front.jpg" width="600" />
Label:
<img src="photos/2M-PCB43-V2.1-unmanaged/KP-9000-6XH-X2-label.jpg" width="600" />
### PCB overview
**Board markings**
- Top silkscreen: 2M-PCB43-V2.1
Top side
<img src="photos/2M-PCB43-V2.1-unmanaged/2M-PCB43-V2.1-top.jpg" width="600" />
Bottom
<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
There's an unpopulated Reset button on the front left side of the PCB.
It can easily be soldered, you'll need an 4.5mmx4.5mm 90° button switch with a 3-pin footprint.
I got mine here: https://de.aliexpress.com/item/1005007295346702.html
The front case has already the hole in the metal case, you just have to punch a hole through the foil.
## Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
-53
View File
@@ -1,53 +0,0 @@
# IG108
Following is documentation for unmanaged switch marked as `IG108`.
Original software is running UART on 9600 baud rate.
Using SPI clamp in-board is the only method for initial installation.
### Brands
| Brand | Type | Managed | PCB | Flash | Chip RTL |
|---------|------------|---------|------------|-------------|---------------|
| Goalake | IG108 | No | PB-2132 | cFeon Q32A | 8373N + 8224N |
| Netcore | GS9 | No | PB-2132 | cFeon Q32A | 8373N + 8224N |
### What works
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
- SFP port with 1G/2.5G/10G modules
- LEDs
### PCB overview
**Board markings**
- Top silkscreen: PB-2132
Front Goalake:
<img src="photos/PB-2132/case.jpg" width="600" />
Label Goalake:
<img src="photos/PB-2132/label.jpg" width="600" />
Top side:
<img src="photos/PB-2132/PCB-top.jpg" width="600" />
Bottom:
<img src="photos/PB-2132/PCB-bottom.jpg" width="600" />
### Serial console
The PCB has unpopulated through-holes near the SFP Port, with description of each pin, works out of the box.
- **Settings**: 115200 baud / 8N1 / 3.3V TTL
### Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
-97
View File
@@ -1,97 +0,0 @@
Hisource Hi-K0402WS V2
RTL8372-based 4×2.5G + 2×SFP+ unmanaged switch.
Using SPI clamp in-board is the only method for initial installation.
### Label specifications
- **Manufacturer**: HISOURCE
- **Model**: Hi-K0402WS V2
- **Ports**:
- 4 × RJ45: 10/100/1000/2500 Mbps
- 2 × SFP+: 1G / 2.5G / 10G
### 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: amber (2.5G) and green (1G/100M/10M) per copper port; combined link/act on SFP ports
### PCB overview
**Board markings**
- PCB-K0402WS-V2.0
- DIP-K0402WS-V2.0
**Key components**
- U1: SPI NOR flash, 2 MiB
- S1: unpopulated slide switch footprint (three through-holes used as serial console)
Front panel
<img src="photos/PCB-K0402WS-V2.0/chassis-front.jpg" width="400" />
Bottom label
<img src="photos/PCB-K0402WS-V2.0/chassis-bottom.jpg" width="400" />
Top side (PCB)
<img src="photos/PCB-K0402WS-V2.0/PCB-top.jpg" width="300" />
### Port layout
| Front panel position | Logical port | Physical port | Type |
|----------------------|--------------|---------------|---------|
| SFP left | 8 | 5 | SFP+ |
| RJ45 1 | 4 | 1 | Copper |
| RJ45 2 | 5 | 2 | Copper |
| RJ45 3 | 6 | 3 | Copper |
| RJ45 4 | 7 | 4 | Copper |
| SFP right | 3 | 6 | SFP+ |
### Serial console
The PCB has three unpopulated through-holes intended for a slide switch, directly connected to UART0.
Numbered from the left (SFP port side), the pinout is:
| Position (left→right) | Signal | GPIO |
|-----------------------|--------|--------------------------|
| 1 (leftmost) | RX | GPIO32\_UART0\_RX (32) |
| 2 (middle) | GND | GND |
| 3 (rightmost) | TX | GPIO31\_UART0\_TX (31) |
- **Settings**: 115200 baud / 8N1 / 3.3V TTL
- Connect a USB-TTL adapter: adapter TX → pin 1, GND → pin 2, adapter RX → pin 3
### LED configuration
Copper ports use LED SET0, SFP ports use LED SET1.
| SET | LED0 | LED2 |
|------|--------------------------------------------------|---------------------------------------------------|
| SET0 | Amber — lights on 2.5G link | Green — lights on 1G / 100M / 10M link |
| SET1 | All speeds — lights on any link with activity | — |
LED pad to physical port mapping:
| GPIO pads | Port |
|-----------|-------------------------|
| GPIO8–11 | Physical port 5 (left SFP) |
| GPIO12–14 | Physical port 1 (RJ45 1) |
| GPIO15–17 | Physical port 2 (RJ45 2) |
| GPIO18–20 | Physical port 3 (RJ45 3) |
| GPIO21–23 | Physical port 4 (RJ45 4) |
| GPIO24–27 | Physical port 6 (right SFP) |
### SFP GPIO assignments
| SFP | pin\_detect (ModAbs) | pin\_los | SerDes | I2C SDA | I2C SCL |
|------------------|-----------------------------|------------------------|--------|----------------------|--------------------------|
| Left (logical 8) | GPIO30\_ACL\_BIT3\_EN | GPIO37 | SDS1 | GPIO39\_I2C\_SDA4 | GPIO40\_I2C\_SCL3\_MDC1 |
| Right (logical 3)| GPIO50\_I2C\_SCL2\_UART1\_TX | GPIO51\_I2C\_SDA2\_UART1\_RX | SDS0 | GPIO41\_I2C\_SDA3\_MDIO1 | GPIO40\_I2C\_SCL3\_MDC1 |
GPIO assignments were verified by observing GPIO state changes during SFP module insertion/removal
and cross-checked against an original firmware register dump.
`pin_tx_disable` is GPIO\_NA on both ports (original firmware keeps all GPIOs as inputs).
-79
View File
@@ -1,79 +0,0 @@
# PCB-K0402WS-V3.0
Following is documentation for a variety of unmanaged switch internally marked as `PCB-K0402WS-V3.0`. They are sold under many brands.
Original software is running UART on 9600 baud rate.
Note during opening the device: there might be a hidden 5th screw on the back
of the device just above the big label, might be covered by a QC sticker.
### Brands
* Hisource Hi-K0402WS
<img src="photos/PCB-K0402WS-V3.0/HiSource_HI-K0402WS.jpg" width="300" />
* Ztyuav Z-QWYT0402
<img src="photos/PCB-K0402WS-V3.0/Ztyuav_Z-QWYT0402.jpg" width="300" />
<img src="photos/PCB-K0402WS-V3.0/Ztyuav_Z-QWYT0402_label.jpg" width="300" />
* Siscolink SL-G0402F
<img src="photos/PCB-K0402WS-V3.0/Siscolink SL-G0402F.jpg" width="300"/>
### Programming
Using SPI clamp in-board is the only method for initial installation.
The board has two flash chips `BY25Q16BS` with 16M-bit size. The front switch, switches between the two flash chips.
These can be programed independently by using said switch - so it is e.g. possible to run the original and new firmware in parallel.
The switch actually controls the HOLD line of each flash chip, and toggling the switch results in a reboot.
If the programming clip keeps HOLD not connected, the flashing will commence on whatever the switch selected, regardless on which chip was clipped.
For the initial flash (at least with flashrom), the bin file produced by the build is much smaller than the flash chip, it is suggested to pad the file to keep flashrom happy: `truncate -s 2097152 rtlplayground-*-PCB_K0402WS_V3.bin`. Note: do not then proceed to use this resulting padded file for the web flashing (as it bricks the device), use the original unpadded .bin.
### What works (expected from label + similar devices)
- 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: PCB-KO4022W-V3.0 / DIP-KO4022WS-V3.0
Top side
<img src="photos/PCB-K0402WS-V3.0/PCB-top.jpg" width="300" />
Bottom
<img src="photos/PCB-K0402WS-V3.0/PCB-bottom.jpg" width="300" />
### T2, serial console
| `J2` pin | Signal |
| -------- | ----------- |
| 1 | 3V3 |
| 2 | RX (Input) |
| 3 | TX (Output) |
| 4 | GND |
## Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
Board has two supply rails. `0.95` and `3.3` volt.
### `0.95` Core Voltage
Voltage is made by a `Techcode TD1720` .
### `3.3` Voltage
Voltage is created by chip marked as `Techcode TD1720`.
**There seems to have been a miscalculation when choosing the inductor and the device is ~25% more efficient with an 5V power supply.**
-43
View File
@@ -1,43 +0,0 @@
# Steamemo IG204-V1
Following is documentation for unmanaged switch marked as `IG204-V1`.
Using SPI clamp in-board is the only method for initial installation.
### Label specifications
- **Name**: 2.5G Ethernet Switch
- **Model**: IG204 V1
- **Ports**:
- 4 × RJ45: 10/100/1000/2500 Mbps
- 2 × SFP: 1000 / 2500 / 10000 Mbps
### What works (expected from label + similar devices)
- Four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
- Two SFP ports supporting 1G, 2.5G and 10G modules
- LEDs
### PCB overview
**Board markings**
- Top silkscreen: PB-2131
Top side
<img src="photos/STEAMEMO_IG204_V1/PCB-top.jpg" width="600" />
### Connectors
### T7, serial console
| `T7` pin | Signal |
| -------- | ----------- |
| 1 | TX (Output) |
| 2 | GND |
| 3 | RX (Input) |
| 4 | 3V3 |
### Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
-61
View File
@@ -1,61 +0,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 |
| GoodTop | GT-ST018M | Yes | SWTG018AS-A V2.0 | ? | 8273N + 8224N |
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.
The original software is running UART on 9600 baud rate.
Using a SOIC clamp in-board is the only method for initial installation.
The board has a single flash chips `BS` with 4M-bit size. The front switch, switches between the two flash chips.
These can be programed independently by using said switch - so it is e.g. possible to run the original and new firmware in parallel.
### Label specifications
- **Name**: 9-Ports 2.5G Ethernet Switch
- **Ports**:
- 8 × RJ45: 10/100/1000/2500 Mbps
- 1 × SFP+: 1000 / 2500 / 10000 Mbps
- **Power**: 12V DC, 1A barrel connector
<img src="photos/SWTG018AS_A_V_2_0/label.jpg" width="300" />
### What works
The device is fully supported:
- All 8 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: SWTG018AS-A-V2.0.1_19649
Top side
<img src="photos/SWTG018AS_A_V_2_0/pcb_top.jpg" width="300" />
Bottom
<img src="photos/SWTG018AS_A_V_2_0/pcb_bottom.jpg" width="300" />
### J1, serial console
| `J1` pin | Signal |
| -------- | ----------- |
| 1 | 3V3 |
| 2 | GND |
| 3 | RX (Input) |
| 4 | TX (Output) |
## Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
-43
View File
@@ -1,43 +0,0 @@
### 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) |
-44
View File
@@ -1,44 +0,0 @@
### 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) |
-49
View File
@@ -1,49 +0,0 @@
### 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.
-213
View File
@@ -1,213 +0,0 @@
### SWTG024AS
SWTG024AS has at least 4 variants that look the same.
Variants are `managed` and a `unmanaged` version.
But both have pcb version `v1.0` and `v2.0`.
Also the RJ45 connectors can be all plastic/non-shielded or with metal shielding.
## Brands
|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 |
| Horaco |ZX-SWTG124AS | Yes | SWTG024AS-v2.0 | ??? | ??? | 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 |
## PCB
<img src="photos/SWTG024AS-v2.0-unmanaged/SWTG024AS-v2.0-top-uman.png" width="300" />
# SWTG024AS-v2.0 managed vs unmanged
Changes I found with my board vs [Managed version](https://github.com/up-n-atom/SWTG118AS/tree/main/photos/SWGT024AS-v2.0) of the PCB.
### Bottom
* R105: Installed, goes to R10-PullDown SFP2 (J2) -> TX-DISABLE
* R85: Not Installed (Connected to K1 Reset Button)
* R90: Not installed (System Led)
* LED3: Not installed (System Led)
### Top
* K1: Not installed (Reset Button)
* R95: Installed (SFP2 (J2) signal RX-LOS), means that the managed-version can´t use the RX-LOS function.
* R270: Installed (SFP1 (J4) signal RX-LOS), same here as above.
* R268: Installed (SFP2 (J2) signal TX-DISABLE, but R262 200R pull-down is to high to drive by the SOC, needs mod!)
* U5: Flash is only 512 KiB instead of 2/4 MiB.
### Notes
* `TX-Disable`-SFP2 and Button `K1` share the same GPIO pin via `R105` and `R85`.
But via `R88`, `TX-Disable`-SFP2 can be mapped to `GPIO36`.
* `TX-Disable` pull-down resistos on both SFP are to low to drive by the SOC.
We need to make a `Best`-BOM variant so we can use all the featues.
# Connectors
## Port overview
```
┌────────────────────────────────────────────────────────────────────────────────────────┐
│ ┌──────────┐ ┌──────────┐ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ SFP (J4) │ │ SFP (J2) │ │
│ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ PORT 5 │ │ PORT 6 │ │
│ │ PORT 1 │ │ PORT 2 │ │ PORT 3 │ │ PORT 4 │ │ MAC 8 │ │ MAC 3 │ │
│ O │ MAC 4 │ │ MAC 5 │ │ MAC 6 │ │ MAC 7 │ │ SerDes 1 │ │ SerDes 0 │ │
│ RST └─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘ └──────────┘ │
└────────────────────────────────────────────────────────────────────────────────────────┘
```
## J4
* Location: Left SFP connector `J4`.
* Connected to: 10GMAC number 8, second SerDes.
|`J4` SFP1 PINs | Signal | Component | GPIO | Notes |
|---|---|---|---|---|
|2| TX_FAULT | B-R262 | --- | |
|3| TX_DISABLE | B-R263, T-R268 | GPIO38 | R262 = Pull-down 200R|
|4| MODDEF2 – SDA | B-R261, T-R266 | GPIO39 | |
|5| MODDEF1 – SCL | B-R260, T-R267 | GPIO40 | Shared with both SFP |
|6| MODDEF0 – PRESENT | B-R259, T-R296 | GPIO30 | |
|7| RATE SEL | B-R257 | --- | |
|8| LOS | B-R258, T-R270 | GPIO37 | |
|9| TO? | B-R256 | --- | |
## J2
* Location: Right SFP connector `J2`.
* Connected to: 10GMAC number 3, first SerDes.
|`J2` SFP2 PINs | Signal | Component | GPIO | Notes |
|---|---|---|---|---|
|2| TX_FAULT | B-R70 | --- | |
|3| TX_DISABLE | B-R10, B-R105-R, T-R88-L | GPIO54 | R10 = Pull-down 200R |
|4| MODDEF2 – SDA | B-R26, T-R85 | GPIO41 | |
|5| MODDEF1 – SCL | B-R15, T-R87 | GPIO40 | Shared with both SFP |
|6| MODDEF0 – PRESENT | B-R14, T-R89 | GPIO50 | |
|7| RATE SEL | B-R12 | --- | |
|8| LOS | B-R13, T-R95 | GPIO51 | |
|9| TO? | B-R11 | --- | |
Note: component numbering `<L>-<REFDES>-<SIDE>`
* L: Layer, T=Top, B=Bottom
* REFDEES: full silkscreen like `R123`
* SIDE: Side of the component. when the rj45 are facing towards you are you can read the silkscreen normal.
L = Left, R=right, B=bottom, T=top or P with a pin number.
### T3, Slave Interface
This connector goes to U4 `I2C EEPROM` and U10 `SPI FLASH`.
Signals are based on that `U4` is likely a I2C-EEPROM, `U10` is likely other SPI-chip.
|`T3` pin|what|Signal|
|---|---|---|
|1| U4-P6, 33R U10-P6 | I2C-SCL, SPI-CLK, Slave SCK/SCL/MDC/EE_SCL |
|2| GND | --- |
|3| U4-P5, U10-P5 | I2C-SDA, SPI-DI/DO, Slave SDI/SDA/MDIO/EE_SDA |
|4| VCC |
|5| 33R -> U10-P2 | SPI-DO/D1 |
|6| U10-P1 | SPI-CS |
Note: 1 pin is square shaped.
The Slave Interface allows an extenal host to controll the SOC even if the internal MCU is used.
Depending on the `IF_SEL` bootstrap resistors, this can me `I2C`, `SPI` or `SMI`.
On this device it is `I2C` on address `0b1011100` or `0x5c` (7-bit notation).
* I2c Read: must be a write_read opperation `<Dev-ADDR><RegAddr15:8><RegAddr7:0>` `<DevAddr><Data7:0><Data15:8><Data23:16><Data31:24>`.
* I2c Write: `<Dev-ADDR><RegAddr15:8><RegAddr7:0><DevAddr><Data7:0><Data15:8><Data23:16><Data31:24>`.
Example register `0x0004` return chip id `0x00, 0x00, 0x72, 0x83` = `0x83720000`.
### T5, serial console
|`T5` pin|GPIO|Signal|
|---|---|---|
| 1 | GPIO31 | U0TXD (Output) |
| 2 | GND | |
| 3 | GPIO32 | U0RXD (Input) |
| 4 | 3V3 | |
Note: 1 pin is square shaped.
### T8
|`T8` pin|what|Signal|
|---|---|---|
| 1 | GPIO46 | |
| 2 | GND | |
| 3 | GPIO48 | |
| 4 | 3V3 | |
| 5 | GPIO47 | |
| 6 | GPIO49 | |
Note: 1 pin is square shaped.
# Reset ciruit
| Cmp | Function |
|---|---|
| T-R78 | 33k PullUp |
| T-D3 | Discharge Diode |
| T-C187 | RC-Delay |
Reset-line found at `T-D3-D` active-low.
# GPIO
| HEX VAL. | GPIO | Component | What | | GPIO | Component | What |
| -------- | ------ | ---- | ---- | ---- | ---- | ---- | ---- |
| 00000001 | GPIO00 | T-C151-T, T-R28-T, T-R29-T |? | | GPIO32 | T-R143-R | U0RXD |
| 00000002 | GPIO01 | T-C152-T |? | | GPIO33 | | |
| 00000004 | GPIO02 | T-C153-T |? | | GPIO34 | | |
| 00000008 | GPIO03 | T-R33-T |? | | GPIO35 | | |
| 00000010 | GPIO04 | B-C155 |? | | GPIO36 | T-R88-L, T-R84-B | Optional SFP2 TX-DISABLE[^2], Reset |
| 00000020 | GPIO05 | B-C156 |? | | GPIO37 | SFP1-8, T-R270 | SFP-LOS |
| 00000040 | GPIO06 | T-C157-T |? | | GPIO38 | SFP1-3, T-R268 | SFP1 TX-DISABLE[^2] |
| 00000080 | GPIO07 | T-C158-T, R165 |? | | GPIO39 | SFP1-4, T-R266 | I2C-SDA4 |
| 00000100 | GPIO08 | | | | GPIO40 | SFP2-5, T-R87; SFP1-5, T-R267; | I2C-SCL |
| 00000200 | GPIO09 | SFP2-LED, T-R36-T |LED-SFP2 | | GPIO41 | SFP2-4, T-R85 | I2C-SDA |
| 00000400 | GPIO10 | | | | GPIO42 | U8-P6, T-R124 | SPI-MEMORY, CLK |
| 00000800 | GPIO11 | |LEDx[^1] | | GPIO43 | U8-P5, T-R127 | SPI-MEMORY, DI,IO0 |
| 00001000 | GPIO12 | |LEDx[^1] | | GPIO44 | U8-P2, T-R128 | SPI-MEMORY, DO,IO1 |
| 00002000 | GPIO13 | PORT1-LED-GREEN |LEDx[^1] | | GPIO45 | U8-P1, T-R123 | SPI-MEMORY, CS |
| 00004000 | GPIO14 | PORT1-LED-YELLOW |LEDx | | GPIO46 | T8-1, T-R188| ? |
| 00008000 | GPIO15 | |LEDx[^1] | | GPIO47 | T8-5, T-R190 | ? |
| 00010000 | GPIO16 | PORT2-LED-GREEN |LEDx[^1] | | GPIO48 | T8-3, T-R189 | ? |
| 00020000 | GPIO17 | PORT2-LED-YELLOW |LEDx | | GPIO49 | T8-6, T-R190 | ? |
| 00040000 | GPIO18 | |LEDx[^1] | | GPIO50 | SFP2-6, T-R89 | SFP-DETECT |
| 00080000 | GPIO19 | PORT3-LED-GREEN |LEDx[^1] | | GPIO51 | SFP2-8, T-R95 | SFP-LOS |
| 00100000 | GPIO20 | PORT3-LED-YELLOW |LEDx | | GPIO52 | | |
| 00200000 | GPIO21 | |LEDx[^1] | | GPIO53 | | |
| 00400000 | GPIO22 | PORT4-LED-GREEN |LEDx[^1] | | GPIO54 | SFP2-3, T-R105-L | SFP2 TX-DISABLE[^2] or via T-R85 to RESET[^3], T-R84-T |
| 00800000 | GPIO23 | PORT4-LED-YELLOW |LEDx | | GPIO55 | T-R78-B | |
| 01000000 | GPIO24 | SFP1-LED-J4, T-R35 |LED-SFP1 | | GPIO56 | | |
| 02000000 | GPIO25 | | | | GPIO57 | | |
| 04000000 | GPIO26 | ? |LEDx | | GPIO58 | | |
| 08000000 | GPIO27 | R44L |? | | GPIO59 | | |
| 10000000 | GPIO28 | LED-SYSTEM, T-R50-R |LED-SYSTEM | | GPIO60 | | |
| 20000000 | GPIO29 | T-R187-R | | | GPIO61 | | |
| 40000000 | GPIO30 | SFP1-6, T-R269 |SFP-DETECT | | GPIO62 | | |
| 80000000 | GPIO31 | T-R144-R |U0TXD| | GPIO63 | | |
# LEDs
| NAME | COMPONENTS | GPIO | Active |
| ---- | ---------- | ---- | ------ |
| SYSTEM | T-R50-R (PU-4k2), T-R49-L, T-C185-L, B-R90 | GPIO28 | Low |
| SFP1 | T-R35-L (PU-3k9), T-R34-L, T-C179-L | GPIO24 | Low |
| SFP2 | T-R36-T (PD-4k0) | GPIO09 | High |
| PORT1-LED-YELLOW | | GPIO14 | Low |
| PORT2-LED-YELLOW | | GPIO17 | Low |
| PORT3-LED-YELLOW | | GPIO20 | Low |
| PORT4-LED-YELLOW | | GPIO23 | Low |
# Power supply
Board has two supply rails.
`0.95` and `3.3` volt.
## `0.95` Core Voltage.
Voltage is made by a `Richtek RT8120A` Buck converter.
0.95V must be within 3%.
## `3.3` Voltage
Voltage is crated by a `TMI3244T` Buck converter.
3.3V must be within 4.5%.
Chip can deliver up to 4A and the sweetspot is at 1A.
So higher power SFP-modules should work.
[^1]: LEDs are found by just plugin a RJ45 connector and see with cmd `gpio` the status change. But the bit pattern for port 1,2 are diffrent from port 3,4.
[^2]: Only on the unmanaged verions are `R10` and `R268` placed. But the very low pull-down resistor `R10` and `R262` prevent to SOC to drive does pins. A mod is needed.
[^3]: GPIO54 is used for the reset-button. `T-R85` is placed.
-183
View File
@@ -1,183 +0,0 @@
# ZX-SWTGW215AS
## Brands
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|---|---|---|---|---|---|
| Lianguo | ZX-SWTGW215AS | Yes | PCB-SWTG115AS-V2.0 | FM25Q16A | 8372 |
| sold as Lianguo, actual device unbranded | ZX-SWTGW215AS | Yes | PCB-SWTG115AS-V2.1 | W25Q16JVSIQ (2MiB) | 8372 |
## RTLPlayground target
Use machine target `MACHINE_LIANGUO_ZX_SWTGW215AS` for this device.
Physical hardware verification: 5x RJ45 ports + 1x SFP port.
Port 5 RJ45 is interfaced through a RTL8221B IC.
## Label (V2.0)
<img src="photos/ZX-SWTGW215AS-V2.0/label.jpg" width="300" />
## PCB (V2.0)
<img src="photos/ZX-SWTGW215AS-V2.0/pcb_top.jpg" width="300" />
<img src="photos/ZX-SWTGW215AS-V2.0/pcb_bottom.jpg" width="300" />
## PCB (V2.1)
<img src="photos/ZX-SWTGW215AS-V2.1/pcb-top.jpg" width="300" />
<img src="photos/ZX-SWTGW215AS-V2.1/pcb-bottom.jpg" width="300" />
## Connectors
### Port overview
```
┌──────────────────────────────────────────────────────────────────────────────────┐
│ ┌──────────┐ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ SFP (J4) │ │
│ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ PORT 6 │ │
│ │ PORT 1 │ │ PORT 2 │ │ PORT 3 │ │ PORT 4 │ │ PORT 5 │ │ LOG 8 │ │
│ O │ LOG 4 │ │ LOG 5 │ │ LOG 6 │ │ LOG 7 │ │ LOG 3 │ │ SerDes 1 │ │
│ RST └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘ │
└──────────────────────────────────────────────────────────────────────────────────┘
```
| Type | RTLPlayground logical ports | Physical index |
|---|---|---|
| RJ45 | 3, 4, 5, 6, 7 | 1-5 |
| SFP | 8 | 6 |
### J4
* Location: SFP connector `J4`.
* Connected to: 10GMAC number 8, SerDes 1.
|`J4` SFP PINs | Signal | GPIO | Notes |
|---|---|---|---|
|3| TX_DISABLE | GPIO_NA | Not connected |
|4| MODDEF2 – SDA | GPIO39 | I2C SDA |
|5| MODDEF1 – SCL | GPIO40 | I2C SCL |
|6| MODDEF0 – PRESENT | GPIO30 | Detect |
|8| LOS | GPIO37 | RX Loss of Signal |
#### Notes
* Not all signals were mapped mechanically, hence they've been left out of documentation.
### T3, Slave Interface
This connector goes to U4 `I2C EEPROM` and U10 `SPI FLASH` (mappings identical to SWTG024AS).
For detailed Slave Interface functionality and protocol information, see [T3 documentation in SWTG024AS.md](SWTG024AS.md#t3-slave-interface).
|`T3` pin|what|Signal|
|---|---|---|
|1| U4-P6, 33R U10-P6 | I2C-SCL, SPI-CLK, Slave SCK/SCL/MDC/EE_SCL |
|2| GND | --- |
|3| U4-P5, U10-P5 | I2C-SDA, SPI-DI/DO, Slave SDI/SDA/MDIO/EE_SDA |
|4| VCC |
|5| 33R -> U10-P2 | SPI-DO/D1 |
|6| U10-P1 | SPI-CS |
#### Notes
* 1 pin is square shaped.
### T5, Serial Console
|`T5` pin|GPIO|Signal|
|---|---|---|
| 1 | GPIO31 | U0TXD (Output) |
| 2 | GND | |
| 3 | GPIO32 | U0RXD (Input) |
| 4 | 3V3 | |
#### Notes
* 1 pin is square shaped.
### T8
|`T8` pin|GPIO|Signal|
|---|---|---|
| 1 | GPIO46 | |
| 2 | GND | |
| 3 | GPIO48 | |
| 4 | 3V3 | |
| 5 | GPIO47 | |
| 6 | GPIO49 | |
#### Notes
* 1 pin is square shaped.
* Mapping unverified but assumed the same as [LIANGUO SWTG024AS](SWTG024AS.md#t8).
## Reset Circuit
| Function | GPIO |
|---|---|
| Reset button | GPIO54 |
### Notes
* Circuit is active-low
## GPIO
Note: T3/U4/U10-related signal annotations below are copied from [LIANGUO SWTG024AS T3 section](SWTG024AS.md#t3-slave-interface) as well as T8 port from [LIANGUO SWTG024AS T8 section](SWTG024AS.md#t8). They should be treated as assumed identical for ZX-SWTGW215AS as it has not been 100% confirmed true at the moment.
| HEX VAL. | GPIO | Component / Purpose | Notes | | GPIO | Component / Purpose | Notes |
| -------- | ------ | ---- | ---- | ---- | ---- | ---- | ---- |
| 00000001 | GPIO00 | | | | GPIO32 | T5-3 | U0RXD |
| 00000002 | GPIO01 | | | | GPIO33 | | |
| 00000004 | GPIO02 | | | | GPIO34 | | |
| 00000008 | GPIO03 | | | | GPIO35 | | |
| 00000010 | GPIO04 | | | | GPIO36 | | |
| 00000020 | GPIO05 | | | | GPIO37 | J4-8 | SFP LOS |
| 00000040 | GPIO06 | | | | GPIO38 | | |
| 00000080 | GPIO07 | | | | GPIO39 | J4-4 | SFP I2C SDA |
| 00000100 | GPIO08 | | | | GPIO40 | J4-5 | SFP I2C SCL |
| 00000200 | GPIO09 | | | | GPIO41 | | |
| 00000400 | GPIO10 | | | | GPIO42 | U10-P6, U4-P6, T3-1 | SPI FLASH CLK / I2C-SCL (from [LIANGUO SWTG024AS](SWTG024AS.md#gpio)) |
| 00000800 | GPIO11 | | | | GPIO43 | U10-P5, U4-P5, T3-3 | SPI FLASH DI/IO0 / I2C-SDA (from [LIANGUO SWTG024AS](SWTG024AS.md#gpio)) |
| 00001000 | GPIO12 | | | | GPIO44 | U10-P2, T3-5 | SPI FLASH DO/IO1 (from [LIANGUO SWTG024AS](SWTG024AS.md#gpio)) |
| 00002000 | GPIO13 | PORT1 LED GREEN | | | GPIO45 | U10-P1, T3-6 | SPI FLASH CS (from [LIANGUO SWTG024AS](SWTG024AS.md#gpio)) |
| 00004000 | GPIO14 | PORT1 LED ORANGE | | | GPIO46 | T8-1 | (from [LIANGUO SWTG024AS](SWTG024AS.md#gpio)) |
| 00008000 | GPIO15 | | | | GPIO47 | T8-5 | (from [LIANGUO SWTG024AS](SWTG024AS.md#gpio)) |
| 00010000 | GPIO16 | PORT2 LED GREEN | | | GPIO48 | T8-3 | (from [LIANGUO SWTG024AS](SWTG024AS.md#gpio)) |
| 00020000 | GPIO17 | PORT2 LED ORANGE | | | GPIO49 | T8-6 | (from [LIANGUO SWTG024AS](SWTG024AS.md#gpio)) |
| 00040000 | GPIO18 | PORT3 LED GREEN | | | GPIO50 | | |
| 00080000 | GPIO19 | PORT3 LED ORANGE | | | GPIO51 | | |
| 00100000 | GPIO20 | PORT4 LED GREEN | | | GPIO52 | | |
| 00200000 | GPIO21 | PORT4 LED ORANGE | | | GPIO53 | | |
| 00400000 | GPIO22 | PORT5 LED GREEN | | | GPIO54 | Reset Button | GPIO54_ACL_BIT2_EN |
| 00800000 | GPIO23 | PORT5 LED ORANGE | | | GPIO55 | | |
| 01000000 | GPIO24 | SFP LED GREEN | J4 | | GPIO56 | | |
| 02000000 | GPIO25 | | | | GPIO57 | | |
| 04000000 | GPIO26 | | | | GPIO58 | | |
| 08000000 | GPIO27 | | | | GPIO59 | | |
| 10000000 | GPIO28 | LED-SYSTEM | | | GPIO60 | | |
| 20000000 | GPIO29 | | | | GPIO61 | | |
| 40000000 | GPIO30 | J4-6 | SFP DETECT | | GPIO62 | | |
| 80000000 | GPIO31 | T5-1 | U0TXD | | GPIO63 | | |
## LEDs
| NAME | GPIO | Port(s) | Function | Notes |
| ---- | ---- | ---- | ---- | ---- |
| PORT1 LED GREEN | GPIO13 |5| Activity | LEDS_2G5, LEDS_LINK, LEDS_ACT |
| PORT1 LED ORANGE | GPIO14 | 5 | Speed | LEDS_1G, LEDS_100M, LEDS_10M, LEDS_LINK, LEDS_ACT |
| PORT2 LED GREEN | GPIO16 | 4 | Activity | LEDS_2G5, LEDS_LINK, LEDS_ACT |
| PORT2 LED ORANGE | GPIO17 | 4 | Speed | LEDS_1G, LEDS_100M, LEDS_10M, LEDS_LINK, LEDS_ACT |
| PORT3 LED GREEN | GPIO18 | 3 | Activity | LEDS_2G5, LEDS_LINK, LEDS_ACT |
| PORT3 LED ORANGE | GPIO19 | 3 | Speed | LEDS_1G, LEDS_100M, LEDS_10M, LEDS_LINK, LEDS_ACT |
| PORT4 LED GREEN | GPIO20 | 2 | Activity | LEDS_2G5, LEDS_LINK, LEDS_ACT |
| PORT4 LED ORANGE | GPIO21 | 2 | Speed | LEDS_1G, LEDS_100M, LEDS_10M, LEDS_LINK, LEDS_ACT |
| PORT5 LED GREEN | GPIO22 | 1 | Activity | LEDS_2G5, LEDS_LINK, LEDS_ACT |
| PORT5 LED ORANGE | GPIO23 | 1 | Speed | LEDS_1G, LEDS_100M, LEDS_10M, LEDS_LINK, LEDS_ACT |
| SFP LED GREEN | GPIO24 | 6 (SFP J4) | Multi-speed | LEDS_10G, LEDS_5G, LEDS_2G5, LEDS_1G, LEDS_100M, LEDS_LINK, LEDS_ACT |
| LED-SYSTEM | GPIO28 | --- | System status | --- |
## Notes
While [SWTG024AS.md](SWTG024AS.md) can be used as a general reference for hardware concepts and interface specifications, this device should not be assumed to be identical beside the difference implicitely highlighted below. Not all information has been validated for compatibility with the SWTG215AS. Consult the SWTG024AS documentation with caution and verify any critical details against this device's.
## Flashing
For devices with Winbond 25Q16JVSIQ, flashing is possible for example using flashprog with device "W25Q16.V". Note that you should not overwrite the whole flash to keep device-specific data (like the MAC address at 0x1fc000). Also, creating a backup of the entire falsh before is of course a very good idea.
-25
View File
@@ -1,25 +0,0 @@
### ZX-SWTGW218AS
## Brands
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|---|---|---|---|---|---|
| Mokerlink | ZX-SWTGW218AS | Yes| SWTG118AS-V2.0-16029 | 2MB (FM25Q16A)| 8273N + 8224N |
| Sodola | | | | | |
| Horaco | | | | | |
| XikeStor | SKS3200-8E1X | Yes | SWTG118AS-V2.1-17462 | 2MB (25Q16JVSIQ) | |
## Photos
<img src="photos/SWTGW218AS-managed/front.png" width="800" />
<img src="photos/SWTGW218AS-managed/label.jpg" width="800" />
## PCB
See up'n'atom's Repo:
https://github.com/up-n-atom/SWTG118AS/blob/main/photos/SWTG118AS-v2.0/SWTG118AS-v2.0-pcb-top.JPG
https://github.com/up-n-atom/SWTG118AS/blob/main/photos/SWTG118AS-v2.0/SWTG118AS-v2.0-pcb-bottom.JPG
-174
View File
@@ -1,174 +0,0 @@
# TrendNet TEG-S562
Following is documentation for unmanaged switch marked as `TEG-S563/EU H/W: V1.0R`.
Original software is running UART on 57600 baud rate. The software does not allow to
do anything fancy via serial. There is `IP` configuration which can be printed as well.
There might be also some flash upload procedure, but using SPI clamp in-board seems to
be easier method.
The memory chip is `Winbond W25Q16JV` with 16M-bit size.
## What does work
1. 2.5G ports on all advertised speeds.
2. SFP+ communication.
3. Serial, Web UI.
4. All LEDs
## Known issues
None.
## PCB
Manufacturer information be found [on the product page](https://www.trendnet.com/support/support-detail.asp?prod=105_TEG-S562).
Top side
<img src="photos/TEG-S562/TEG-S562-v1.0R-top.jpg" width="300" />
Bottom
<img src="photos/TEG-S562/TEG-S562-v1.0R-bottom.jpg" width="300" />
## Connectors
### Port overview
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ ┌──────────┐ ┌──────────┐ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ SFP 2 │ │ SFP 1 │ │
│ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ PORT 5 │ │ PORT 6 │ │
│ │ PORT 1 │ │ PORT 2 │ │ PORT 3 │ │ PORT 4 │ │ MAC 8 │ │ MAC 3 │ │
│ │ MAC 4 │ │ MAC 5 │ │ MAC 6 │ │ MAC 7 │ │ SerDes 0 │ │ SerDes 1 │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
```
### J2, serial console
| `J2` pin | Signal |
| -------- | ----------- |
| 1 | 3V3 |
| 2 | TX (Output) |
| 3 | RX (Input) |
| 4 | GND |
Note: 1 pin is square shaped, towards the power input.
### J5, power pass-thru
| `J5` pin | Signal |
| -------- | ------ |
| 1 | 12V |
| 2 | 12V |
| 3 | GND |
| 4 | GND |
Note: 1 pin is square shaped.
### U5, I2C eeprom placeholder
| `J5` pin | Signal |
| -------- | ------------- |
| 1 | GND |
| 2 | GND |
| 3 | GND |
| 4 | GND |
| 5 | 3V3 |
| 6 | ??? Logic Low |
| 7 | SCL |
| 8 | SDA |
SOC I2C address is 0x5c.
### SW1 GPIO switch?
Not populated but looks like a switch for selecting
GPIO level. Missing resistors in place.
GPIO mapping unknown.
### S2 Reset ciruit
Not populated but looks like a button can be added on `S2` connector,
requires additional `R571` resistor which will pull signal to ground.
GPIO mapping unknown.
### GPIO
| HEX VAL. | GPIO | When | GPIO | When |
| -------- | ------ | ----------------| ------ | -----------------------|
| 00000001 | GPIO00 | | GPIO32 | |
| 00000002 | GPIO01 | | GPIO33 | |
| 00000004 | GPIO02 | | GPIO34 | Random changes |
| 00000008 | GPIO03 | | GPIO35 | |
| 00000010 | GPIO04 | | GPIO36 | SFP2 Present |
| 00000020 | GPIO05 | | GPIO37 | SFP2 RX Los |
| 00000040 | GPIO06 | | GPIO38 | SFP1 Present |
| 00000080 | GPIO07 | | GPIO39 | |
| 00000100 | GPIO08 | | GPIO40 | |
| 00000200 | GPIO09 | | GPIO41 | |
| 00000400 | GPIO10 | | GPIO42 | Random changes |
| 00000800 | GPIO11 | | GPIO43 | |
| 00001000 | GPIO12 | PORT1 Link | GPIO44 | |
| 00002000 | GPIO13 | PORT1-LED-GREEN | GPIO45 | |
| 00004000 | GPIO14 | PORT1-LED-AMBER | GPIO46 | SFP1 I2C CLK |
| 00008000 | GPIO15 | PORT2 Link | GPIO47 | SFP1 I2C SDA |
| 00010000 | GPIO16 | PORT2-LED-GREEN | GPIO48 | SFP2 I2C CLK |
| 00020000 | GPIO17 | PORT2-LED-AMBER | GPIO49 | SFP2 I2C SDA |
| 00040000 | GPIO18 | PORT3 Link | GPIO50 | SFP1 Rx LOS |
| 00080000 | GPIO19 | PORT3-LED-GREEN | GPIO51 | SFP2 TX Disable |
| 00100000 | GPIO20 | PORT4-LED-AMBER | GPIO52 | |
| 00200000 | GPIO21 | PORT4 Link | GPIO53 | |
| 00400000 | GPIO22 | PORT4-LED-GREEN | GPIO54 | SFP1 TX Disable |
| 00800000 | GPIO23 | PORT4-LED-AMBER | GPIO55 | |
| 01000000 | GPIO24 | | GPIO56 | |
| 02000000 | GPIO25 | | GPIO57 | |
| 04000000 | GPIO26 | | GPIO58 | |
| 08000000 | GPIO27 | | GPIO59 | |
| 10000000 | GPIO28 | | GPIO60 | |
| 20000000 | GPIO29 | | GPIO61 | |
| 40000000 | GPIO30 | | GPIO62 | |
| 80000000 | GPIO31 | | GPIO63 | |
## LEDs
Ports 1-4 are amber for 100M/1G links, Green for 2.5G.
Port 5-6 are green for 10G/1G link. Both should flash on activity.
| NAME | When active |
| ---------------- | ---------------|
| PWR | 3V3 |
| SFP1 | |
| SFP2 | |
| PORT1-LED-GREEN | - |
| PORT2-LED-GREEN | PORT2 2.5G |
| PORT3-LED-GREEN | PORT3 2.5G |
| PORT4-LED-GREEN | PORT4 2.5G |
| PORT1-LED-AMBER | PORT1 1GB/100M |
| PORT2-LED-AMBER | PORT2 1GB/100M |
| PORT3-LED-AMBER | PORT3 1GB/100M |
| PORT4-LED-AMBER | PORT4 1GB/100M |
## Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
Board has two supply rails. `0.95` and `3.3` volt.
### `0.95` Core Voltage
Voltage is made by a `APW8713` (U3).
### `3.3` Voltage
Voltage is crated regulated by chip marked as `GoIAT` (U2).
## SFP SPI
There is separate clock and data lines for both SFP modules. MSDA/MSCK 0 and 1 need to be enabled.
SFP1 slot is connected to SPI0. SFP2 slot is connected to SPI1.
-59
View File
@@ -1,59 +0,0 @@
# ZX310S-4T2XH/
The following is a documentation for the managed switch marked as `ZX310S-4T2XH`
and sold by Horaco.
The original software is running UART on 57600 baud rate. The solder holes
of the UART header are filled in. In order to install a UART header, they
need to be cleared first. A 1.2mm drill can be used, alternatively a
de-soldering wick.
The original firmware uses 57600 baud 8N1
CPU: RTL8372
Flash: 2MByte Winbond W25Q16DV (U3)
PHY RTL8261BE
### Label specifications
- **Name**:
- **Ports**:
- 4 × RJ45: 10/100/1000/2500 Mbps
- 1 x RJ45: 10/100/1000/2500/5000/10000 Mbps
- 1 × SFP+: 1000 / 2500 / 10000 Mbps
- **Power**: 12V DC, 2A barrel connector
<img src="photos/ZX310S-4T2XH/label.jpg" width="300" />
### What works
The device is fully supported:
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
- The 10GBit port works. TODO: Fix EEE, speed selection
- 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-SL310S-4T1T1X-V1.0.1-24107
Top side
<img src="photos/ZX310S-4T2XH/pcb_top.jpg" width="300" />
Bottom
<img src="photos/ZX310S-4T2XH/pcb_bottom.jpg" width="300" />
### J1, serial console
| `J1` pin | Signal |
| -------- | ----------- |
| 1 | TX (Output) |
| 2 | RX (Input) |
| 3 | GND |
| 4 | 3V3 |
## Power supply
Input power is delivered via barell plug, `12V 2A` adapter was provided.
-53
View File
@@ -1,53 +0,0 @@
# ZX310S-4T2XT
The following is a documentation for the managed switch marked as
`ZX310S-4T2XT` and sold by Horaco.
The original software is running UART on 57600 baud rate 8N1.
CPU: RTL8372
Flash: 2MByte Winbond W25Q16DV (U3)
PHY 2x RTL8261BE
### Label specifications
- **Name**:
- **Ports**:
- 4 × RJ45: 10/100/1000/2500 Mbps
- 2 x RJ45: 10/100/1000/2500/5000/10000 Mbps
- **Power**: 12V DC, 2A barrel connector
<img src="photos/ZX310S-4T2XT/label.jpg" width="300" />
### What works
The device is fully supported:
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps, including EEE
- The 10GBit ports works, including EEE.
- LEDs work with the same indiciations as the OEM firmware
### PCB overview
**Board markings**
- Top silkscreen: PCB-SL310S-4T2XT-V1.0.0-22273
Top side
<img src="photos/ZX310S-4T2XT/pcb_top.jpg" width="300" />
Bottom
<img src="photos/ZX310S-4T2XT/pcb_bottom.jpg" width="300" />
### J1, serial console
| `J1` pin | Signal |
| -------- | ----------- |
| 1 | TX (Output) |
| 2 | RX (Input) |
| 3 | GND |
| 4 | 3V3 |
## Power supply
Input power is delivered via barell plug, `12V 2A` adapter was provided.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 560 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 536 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 480 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 715 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 615 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 754 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 521 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 519 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 529 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 531 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 760 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 505 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 907 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 923 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 KiB

Loaded 100 of 251 files, more files were not shown because too many files have changed in this diff. Show more