diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 31a94891..7097ef48 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,6 +5,11 @@ on: branches: ['**'] pull_request: +permissions: + contents: read + pull-requests: write + issues: write + jobs: build: runs-on: ubuntu-latest @@ -13,18 +18,33 @@ jobs: steps: - uses: actions/checkout@v6 + with: + path: branch + + - uses: actions/checkout@v6 + with: + path: main + ref: main - name: Install dependencies run: | apt update apt install make gcc sdcc xxd python-is-python3 libjson-c-dev zlib1g-dev -y - name: Run the host-side unit tests - run: make -C test + run: cd branch && make -C test - name: Check that every machine definition can be compiled - run: make machine_check + run: cd branch && make machine_check - name: Make project (4x2/RTL8372) - run: make CI=1 MACHINE="KP_9000_6XHML_X2" + run: cd branch && make CI=1 MACHINE="KP_9000_6XHML_X2" && cp output/KP_9000_6XHML_X2/rtlplayground.map /tmp/branch.map - name: Make project (8x1/RTL8373) - run: make CI=1 MACHINE="KP_9000_9XHML_X_V3_1" + run: cd branch && make CI=1 MACHINE="KP_9000_9XHML_X_V3_1" - name: Make project with the health instrumentation - run: make clean && make CI=1 MACHINE="KP_9000_6XHML_X2" HEALTH=1 + run: cd branch && make clean && make CI=1 MACHINE="KP_9000_6XHML_X2" HEALTH=1 + - name: Make main + run: cd main && make CI=1 MACHINE="KP_9000_6XHML_X2" && cp output/KP_9000_6XHML_X2/rtlplayground.map /tmp/main.map + - name: Calculate bank growth + run: | + sed -rn 's/^([XCD]SEG|(BANK[0-9])).*=\s+([0-9]+)\. bytes.*$/MAIN_\1=\3/p' /tmp/main.map | sort -u >> "$GITHUB_ENV" + sed -rn 's/^([XCD]SEG|(BANK[0-9])).*=\s+([0-9]+)\. bytes.*$/BRANCH_\1=\3/p' /tmp/branch.map | sort -u >> "$GITHUB_ENV" + du -sb main/output/KP_9000_6XHML_X2/html_min | awk '{print "MAIN_WEB="$1}' >> "$GITHUB_ENV" + du -sb branch/output/KP_9000_6XHML_X2/html_min | awk '{print "BRANCH_WEB="$1}' >>"$GITHUB_ENV" diff --git a/.gitignore b/.gitignore index f5c8e8c7..9f544835 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,16 @@ .gitignore .idea/ output/ +output-main/ html_data.c html_data.h version.h tools/httpd_sim tools/injector tools/fileadder +build/ # host-test stand-ins for the two generated headers !test/stub/html_data.h !test/stub/version.h +.vscode diff --git a/CHANGELOG.md b/CHANGELOG.md index b66c3013..cb7d22bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,22 @@ ## Fixed +- Time + - `rtl8372_init()` sets SDS 0 to SGMII as the stock firmware does. The masks were 0, so on RTL8372 + boards without 10G ports both SerDes stayed off, and with SDS 0 off `RTL837X_REG_SEC_COUNTER` + does not hold a written value: NTP never retried after a failed first attempt at boot and + froze the clock after a sync. + +- Web UI + - Firefox no longer fills a saved login into the new admin password fields. It also put the + user name into the NTP poll interval, which marked the Time card as edited, so it kept its + defaults (NTP off, no server, UTC-12:00) instead of the switch's settings. + - Accept firmware uploads regardless of the file part's MIME type, including + `application/macbinary` sent by Chrome on macOS for `.bin` files. + +- Health + - `HEALTH=1` builds no longer write past the phase timing arrays at the LLDP checkpoint, which + corrupted the `link` slow counter and the DHCP client state. #658 - Config - A startup configuration line longer than the command buffer no longer stops the replay: the offending line is skipped and the following lines are still applied. diff --git a/Makefile b/Makefile index c95f12af..5754ee08 100644 --- a/Makefile +++ b/Makefile @@ -15,11 +15,10 @@ SUBDIRS := tools SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS)) # $MACHINE selects machine/$(MACHINE).c as the board definition and is passed -# on as -DMACHINE_$(MACHINE), which the rest of the firmware tests with -# #if defined(MACHINE_...), and as -DMACHINE_NAME, which machine.h uses to -# include machine/$(MACHINE).h. Both take the same value, so they cannot drift. +# on as -DMACHINE_NAME, which machine.h uses to include machine/$(MACHINE).h. +# Board selection itself needs no MACHINE_* symbol for #if chains, so the +# definition is all the compiler has to know. ifneq ($(MACHINE),) - CC_FLAGS += -DMACHINE_$(MACHINE) CC_FLAGS += -DMACHINE_NAME=$(MACHINE) endif # Health instrumentation and the "health" console command: HEALTH=1 gmake ... @@ -34,7 +33,16 @@ endif # The board definition being built: one file per MACHINE_* symbol in machine.h. MACHINE_SRC = machine/$(MACHINE).c -BUILDDIR = output/$(MACHINE) +MACHINE_INIT_DEFAULT := machine/default_machine_init.c +MACHINE_INIT_SRC := $(wildcard machine/$(MACHINE)_init.c) +ifeq ($(MACHINE_INIT_SRC),) + MACHINE_INIT_SRC := $(MACHINE_INIT_DEFAULT) +endif + +ifndef BUILDDIR + BUILDDIR = output/$(MACHINE) +endif + VERSION_HEADER := version.h GIT_VERSION := $(shell git rev-parse --short HEAD) @@ -61,6 +69,9 @@ endif # is built, including the tools/ subdirectory. all: create_build_dir $(VERSION_HEADER) $(MACHINE_SRC) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin +bank_size: + tools/bank_occupancy.sh "$(MACHINE)" + create_build_dir: mkdir -p "$(BUILDDIR)" mkdir -p "$(BUILDDIR)/uip" @@ -81,7 +92,7 @@ $(MACHINE_SRC): # invalid $MACHINE value SRCS = \ $(MACHINE_SRC) \ - machine_init.c \ + $(MACHINE_INIT_SRC) \ cmd_editor.c \ cmd_parser.c \ dhcp.c \ @@ -133,7 +144,7 @@ HTML := $(shell find html -name '*.js' -or -name '*.html' -or -name '*.svg' -or # Minified copy of the web UI sources, used as the fileadder input. # The raw html/ sources stay untouched for development; the minified # copy is a build artifact under output/. -HTML_MIN := output/html_min +HTML_MIN := $(BUILDDIR)/html_min .PHONY: html_min html_min: $(HTML) rm -rf $(HTML_MIN) @@ -141,7 +152,7 @@ html_min: $(HTML) @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 + tools/$(BUILDDIR)/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -z -d $(HTML_MIN) -p html_data $(VERSION_HEADER): FORCE @printf '%s\n' "#ifndef VERSION_H" "#define VERSION_H" \ @@ -155,7 +166,7 @@ $(VERSION_HEADER): FORCE httpd: html_data.h $(SUBDIRS): - $(MAKE) -C $@ + $(MAKE) -C $@ BUILDDIR=$(BUILDDIR) clean: $(SUBDIRSCLEAN) -rm -f html_data.c html_data.h $(VERSION_HEADER) @@ -193,31 +204,35 @@ $(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img | tools if [ -e $@ ]; then rm $@; fi - tools/output/imagebuilder -i $^ $@ - tools/output/fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@ - tools/output/fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@ - tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -z -d $(HTML_MIN) -b BANK1 $@ - tools/output/crc_calculator -u $@ - ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin output/rtlplayground.bin + tools/$(BUILDDIR)/imagebuilder -i $^ $@ + tools/$(BUILDDIR)/fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@ + tools/$(BUILDDIR)/fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@ + tools/$(BUILDDIR)/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -z -d $(HTML_MIN) -b BANK1 $@ + tools/$(BUILDDIR)/crc_calculator -u $@ + ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin $(BUILDDIR)/../rtlplayground.bin .PHONY: clean distclean all $(SUBDIRS) $(SUBDIRSCLEAN) create_build_dir # Every machine/ definition is compiled, so a machine added to machine/ is -# covered without registering it anywhere. The machine-specific defines are +# covered without registering it anywhere. The _init.c files are excluded here: +# they are the boot hooks, compiled separately below (the board's own if it +# exists, otherwise default_machine_init.c). The machine-specific defines are # filtered out of $(CC_FLAGS) and supplied per iteration instead, so this also # works as "make machine_check MACHINE=...". -MACHINE_DEFS := $(sort $(patsubst machine/%.c,%,$(wildcard machine/*.c))) +MACHINE_DEFS := $(sort $(patsubst machine/%.c,%,$(filter-out machine/%_init.c,$(wildcard machine/*.c)))) MACHINE_LESS_CC_FLAGS = $(filter-out -DMACHINE_%,$(CC_FLAGS)) -.PHONY: +.PHONY: machine_check machine_check: @mkdir -p $(BUILDDIR)/tmp @set -eo pipefail; \ for MACHINE in $(MACHINE_DEFS); \ do \ echo "Checking $${MACHINE}"; \ - $(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_$${MACHINE} -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine/$${MACHINE}.c; \ - $(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_$${MACHINE} -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine_init.c; \ + $(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine/$${MACHINE}.c; \ + INIT=machine/$${MACHINE}_init.c; \ + if [ ! -e $$INIT ] && [ ! -L $$INIT ]; then INIT=$(MACHINE_INIT_DEFAULT); fi; \ + $(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c $$INIT; \ done @rm -rf $(BUILDDIR)/tmp diff --git a/boot.c b/boot.c index adcb192b..18e9a79d 100644 --- a/boot.c +++ b/boot.c @@ -125,18 +125,6 @@ void early_boot_handle_button(void) __banked void sds_config(uint8_t sds, uint8_t mode) __banked { print_string("sds_config sds: "); print_byte(sds); print_string(", mode: "); print_byte(mode); write_char('\n'); - sds_config_mac(sds, mode); - - if (mode == SDS_10GR || mode == SDS_QXGMII) - sds_write_v(sds, 0x21, 0x10, 0x4480); // Q002110:6480 - else - sds_write_v(sds, 0x21, 0x10, 0x6480); // Q002110:6480 - sds_write_v(sds, 0x21, 0x13, 0x0400); // Q002113:0400 - sds_write_v(sds, 0x21, 0x18, 0x6d02); // Q002118:6d02 - sds_write_v(sds, 0x21, 0x1b, 0x424e); // Q00211b:424e - sds_write_v(sds, 0x21, 0x1d, 0x0002); // Q00211d:0002 - sds_write_v(sds, 0x36, 0x1c, 0x1390); // Q00361c:1390 - sds_write_v(sds, 0x36, 0x14, 0x003f); // Q003614:003f uint8_t page = 0; uint16_t v = 0; @@ -165,6 +153,21 @@ void sds_config(uint8_t sds, uint8_t mode) __banked print_string("Error in SDS Mode\n"); return; } + + sds_config_mac(sds, mode); + + if (mode == SDS_10GR || mode == SDS_QXGMII) + sds_write_v(sds, 0x21, 0x10, 0x4480); // Q002110:6480 + else + sds_write_v(sds, 0x21, 0x10, 0x6480); // Q002110:6480 + + sds_write_v(sds, 0x21, 0x13, 0x0400); // Q002113:0400 + sds_write_v(sds, 0x21, 0x18, 0x6d02); // Q002118:6d02 + sds_write_v(sds, 0x21, 0x1b, 0x424e); // Q00211b:424e + sds_write_v(sds, 0x21, 0x1d, 0x0002); // Q00211d:0002 + sds_write_v(sds, 0x36, 0x1c, 0x1390); // Q00361c:1390 + sds_write_v(sds, 0x36, 0x14, 0x003f); // Q003614:003f + sds_write_v(sds, 0x36, 0x10, v); // Q003610:0200 if (page == 0x2e) { // 10G Fiber / SDS_QXGMII diff --git a/cmd_parser.c b/cmd_parser.c index afc7831a..ab3a5894 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -266,7 +266,7 @@ uint8_t cmd_parse_port(uint8_t idx) { return 0; port = machine.phys_to_log_port[port]; - if (port < machine.min_port || port > machine.max_port) + if (!MACHINE_PORT_VALID(port)) return 0; atoi_results_u8 = port; @@ -743,7 +743,7 @@ void parse_isolate(void) } if (cmd_compare(2, "off")) { - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) members |= ((uint16_t)1) << i; members |= PMASK_CPU; // CPU-port port_isolate(port_configured, members); @@ -797,7 +797,7 @@ void parse_ingress(void) if (!cmd_is_space_or_nul(idx)) goto err; // Setting mode for all ports at once - for (log_port = machine.min_port; log_port <= machine.max_port; log_port++) { + for (log_port = MACHINE_MIN_PORT; log_port <= MACHINE_MAX_PORT; log_port++) { if (!port_ingress_filter(log_port, mode)) { cmd_error("cannot set the ingress filter for port "); print_phys_port(log_port); write_char('\n'); return; @@ -849,7 +849,7 @@ void parse_mirror(void) print_string("NOT Enabled: "); } print_string("Mirroring port: "); - print_phys_port(mirroring_port); + print_phys_port(mPort >> 1); reg_read_m(RTL837x_MIRROR_CONF); uint16_t m = sfr_data[0]; m = (m << 8) | sfr_data[1]; @@ -1019,7 +1019,7 @@ void parse_mtu(void) uint8_t p; if (cmd_compare(1, "show")) { - for (p = machine.min_port; p <= machine.max_port; p++) { + for (p = MACHINE_MIN_PORT; p <= MACHINE_MAX_PORT; p++) { reg_read_m(RTL8373_REG_MAC_L2_PORT_MAX_LEN + ((uint16_t) p << 8)); uint16_t mtu = SFR_DATA_U16 & 0x3fff; print_string("Port "); print_phys_port(p); @@ -2329,6 +2329,7 @@ void health_show(void) __banked ph_line("tx ", HEALTH_PH_TX); ph_line("stp ", HEALTH_PH_STP); ph_line("cmd ", HEALTH_PH_CMD); + ph_line("lldp", HEALTH_PH_LLDP); /* Stack: current depth plus how much of the painted area is untouched */ print_string("sp "); diff --git a/cmd_parser.h b/cmd_parser.h index 2359eb16..e6a073ab 100644 --- a/cmd_parser.h +++ b/cmd_parser.h @@ -19,8 +19,8 @@ extern __xdata uint8_t err_status; #define HEALTH_PH_TX 3 #define HEALTH_PH_STP 4 #define HEALTH_PH_CMD 5 -#define HEALTH_PHASES 6 -#define HEALTH_LLDP 7 +#define HEALTH_PH_LLDP 6 +#define HEALTH_PHASES (HEALTH_PH_LLDP + 1) /* last id + 1: sizes the arrays in cmd_parser.c */ extern __xdata uint16_t health_rx_frames; #define health_rx_frame() health_rx_frames++ diff --git a/doc/adding-a-device.md b/doc/adding-a-device.md index 8d45d198..7e2aa150 100644 --- a/doc/adding-a-device.md +++ b/doc/adding-a-device.md @@ -1,6 +1,6 @@ # Adding a new device -A device is supported by adding one board definition `.h` and board configuration `.c` file +A device is supported by adding one board header `.h` and board definition `.c` file under `machine/`. the build selects the definition by name, and CI compiles every file it finds. @@ -14,27 +14,35 @@ make MACHINE= | File | Purpose | |------|---------| | `machine/.c` | the `struct machine machine` board definition | -| `machine/.h` | `MACHINE_MODEL`, the model string shown in the UI and the CLI | +| `machine/.h` | `MACHINE_MODEL` (the model string shown in the UI and the CLI) and `MACHINE_CHIPSET` (`RTL8372` or `RTL8373`) | +| `machine/_init.c` | optional `machine_custom_init()` boot hook, for registers the machine definition cannot express | | `doc/devices/.md` + `doc/supported_devices.md` | (only if the board is verified and you want to support it publicly) user-facing documentation | `` is the machine symbol without its `MACHINE_` prefix, so `MACHINE` is passed exactly as spelled on the command line: `make MACHINE=MY_BOARD_1_0` needs `machine/MY_BOARD_1_0.c` and `machine/MY_BOARD_1_0.h`. -## Step 1: the model header +## Step 1: the board header -`machine/.h` only carries the product string. Use the existing files as -the template: +`machine/.h` carries the product string and the SoC family. Use the +existing files as the template: ```c #ifndef _MACHINE_MY_BOARD_1_0_H_ #define _MACHINE_MY_BOARD_1_0_H_ #define MACHINE_MODEL "Brand Model V1.0" +#define MACHINE_CHIPSET RTL8373 #endif ``` +`MACHINE_CHIPSET` is `RTL8373` or `RTL8372`; a build without it will fail. It selects the default +logical port range: `MACHINE_MIN_PORT` is `0` for RTL8373 and `3` for RTL8372, while +`MACHINE_MAX_PORT` is `8`, the highest logical port index. A board with a different range defines +`MACHINE_MIN_PORT` and/or `MACHINE_MAX_PORT` in its header to override the +defaults. + The device product string is what the CLI or the Web-Interface will print to identify the device; `machine.h` includes it by name. > [!NOTE] @@ -55,10 +63,7 @@ ports and the same number of SFP+ cages. #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, @@ -89,13 +94,16 @@ __code const struct machine machine = { }; ``` +`MACHINE_COMMON_SETTING` (from `machine_defs.h`) initializes `machine_name` and +`isRTL8373` from the header's `MACHINE_MODEL` and `MACHINE_CHIPSET`. The logical +port range comes from `MACHINE_MIN_PORT` and `MACHINE_MAX_PORT` in `machine.h`. +Keep it as the first initializer and list the board-specific fields after it. + ### Fields | Field | Meaning | |-------|---------| -| `machine_name` | always `MACHINE_MODEL` | -| `isRTL8373` | `1` for an RTL8373 SoC, `0` for RTL8372 | -| `min_port` / `max_port` | range of logical port numbers the device has; `min_port` is `0` for RTL8373 boards and `3` for RTL8372 boards (logical ports 1–2 are the SoC's internal ports on the 8372), `max_port` is usually 8. | +| `MACHINE_COMMON_SETTING` | expands to `machine_name` (`MACHINE_MODEL`) and `isRTL8373` (`1` for `RTL8373`, `0` for `RTL8372`); both are derived from the header's `MACHINE_CHIPSET` (see Step 1) | | `n_sfp` | number of SFP+ cages | | `n_10g` | SerDes 10G capability used by the RTL837xN init: `0` none, `1` one, `2` two 10G-capable SerDes | | `log_to_phys_port[9]` | logical port (0-based index) → physical front-panel port number | @@ -130,14 +138,30 @@ apart: ln -s KP_9000_6XHML_X2.c machine/MY_BOARD_1_0.c ``` -The new board still needs `machine/MY_BOARD_1_0.h` (pick the version number on the PCB) with its own -`MACHINE_MODEL`, because `MACHINE_MODEL` is what distinguishes the products. +The new board still needs `machine/MY_BOARD_1_0.h` (pick the version number on +the PCB) with its own `MACHINE_MODEL` and `MACHINE_CHIPSET`: `MACHINE_MODEL` is +what distinguishes the products, and `MACHINE_CHIPSET` must match the SoC of +the board definition being reused. Existing examples: `machine/PCB_K0402WS_V3.c`, `machine/KP_9000_9XHML_X_V3_2.c` and the six `KP_9000_*` revision variants. Two files that differ only in whitespace or comments are duplicates and should be collapsed this way. +### Optional custom init hook + +If the board needs custom initialization, add +`machine/_init.c` defining `machine_custom_init()`. The Makefile picks the +file up by name and compiles it. + +Boards that need the same hook share one file: keep the code in a single +`machine/_init.c` whose `machine/.c` is a real file (not a symlink), +and make the other boards' `_init.c` symlinks to it, for example: + +``` +ln -s KP_9000_6XH_X2_init.c machine/MY_BOARD_1_0_init.c +``` + ## Step 3: build and verify ``` @@ -151,7 +175,7 @@ file, before anything is compiled. Then run the checks CI runs: ``` -make machine_check # compiles machine/.c and machine_init.c for every machine +make machine_check # compiles machine/.c and its optional _init.c for every machine make -C test # host-side unit tests ``` diff --git a/doc/devices/2M-PCB51-ML-V1_1.md b/doc/devices/2M-PCB51-ML-V1_1.md index d2c6cb9c..f621f3c3 100644 --- a/doc/devices/2M-PCB51-ML-V1_1.md +++ b/doc/devices/2M-PCB51-ML-V1_1.md @@ -1,11 +1,13 @@ # MokerLink POE-2G080110GS The `POE-2G080110GS` is an unmanaged 8x2.5G RJ45 and 1xSFP+ PoE switch sold by Mokerlink. There is also a `POE-2G080110GSM` managed version of the switch which may be similar but this has not been verified on actual hardware. +The`KP-9000-9XHP-X` is the KeepLink rebrand for same product. ## Brands | Brand | Type |Managed| PCB | Flash | Chip RTL | |--------|------------------|-------|------------------|-----------------|---------------| | Mokerlink | POE-2G080110GS | No | 2M-PCB51-ML-V1.1 | 4MB (W25Q32JV) | 8373N + 8224N | +| KeepLink | KP-9000-9XHP-X | No | 2M-PCB51-ML-V1.1 | 4MB (W25Q32JV) | 8373N + 8224N | ## Hardware overview Front diff --git a/doc/health.md b/doc/health.md index 736d52b7..af6b8a28 100644 --- a/doc/health.md +++ b/doc/health.md @@ -14,6 +14,7 @@ rx max 00 slow 0x0000 tx max 00 slow 0x0000 stp max 04 slow 0x0001 cmd max 02 slow 0x0001 +lldp max 00 slow 0x0000 sp 80 untouched 62 tcp st 00 tmr 00 rtx 00 rto 00 len 0x0000 mss 0x05b4 lport 0x0000 rport 0x0000 rip 0x0000 0x0000 @@ -46,7 +47,7 @@ a flooded CPU port from a stalled loop, which look identical from outside. ## Phases Each line is one section of the main loop: the link poll, SFP handling, -frame reception, TCP transmission, the STP timers and the command dispatch. +frame reception, TCP transmission, the STP timers, the LLDP timer and the command dispatch. `max` is the worst time that section has taken, in ticks of 5 ms; `slow` counts the passes that took two ticks or more. A misbehaving subsystem names itself here, which is the difference between knowing that the loop is diff --git a/doc/supported_devices.md b/doc/supported_devices.md index 3d3d5ba2..5e918c1d 100644 --- a/doc/supported_devices.md +++ b/doc/supported_devices.md @@ -29,6 +29,7 @@ The following devices have been tested and are fully working: | keepLINK | KP-9000-9XHML-X | Yes | [2M-PCB23-V2.2](devices/2M-PCB23-V2_2.md) | 2M | 8 + 1 | | keepLINK | KP-9000-9XHML-X | Yes | [2M-PCB23-V3.1](devices/2M-PCB23-V3_1.md) | 2M | 8 + 1 | | keepLINK | KP-9000-9XHML-X | Yes | [2M-PCB23-V3.2](devices/2M-PCB23-V3_2.md) | 2M | 8 + 1 | +| keepLINK | KP-9000-9XHP-X | No | [2M-PCB51-ML-V1.1](devices/2M-PCB51-ML-V1_1.md) | 4M | 8 + 1 | | LIANGUO | HYWS-SGT0108S | No | [2G5F_20G_V1.01](devices/HYWS-SGT0108S.md) | 0.5M | 8 + 1 | | LIANGUO | SWTG024AS | No | [SWTG024AS-v2.0-17452](devices/SWTG024AS.md) | 0.5M | 4 + 2 | | LIANGUO | ZX-SWTGW215AS | Yes | [PCB-SWTG115AS-V2.0 / PCB-SWTG115AS-V2.1](devices/SWTGW215AS.md) | 2M | 5 + 1 | diff --git a/html/app.js b/html/app.js index 1599e3f0..97960236 100644 --- a/html/app.js +++ b/html/app.js @@ -16,7 +16,7 @@ d_system:"System",d_traffic:"Traffic", d_traffic_h:"packets/s, live",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX bad",d_rxbad:"RX bad", i_host:"Hostname",i_ip:"IP address",i_mask:"Netmask",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware", i_built:"Built",i_hw:"Hardware",i_temp:"Temperature",i_flash:"Flash",i_syslog:"Syslog", -p_state:"State",p_disabled:"disabled",p_up:"up",p_txgb:"TX good / bad",p_rxgb:"RX good / bad", +p_state:"State",p_disabled:"disabled",p_up:"up", p_pkts:"pkts",p_module:"Module",p_temp:"Temperature",p_vcc:"Vcc",p_txbias:"TX bias",p_txpower:"TX power", p_rxpower:"RX power",p_txfault:"TX fault",p_txdis:"TX disabled",p_rxlos:"RX LOS",p_adv:"Advertising", pt_title:"Port configuration",pt_conn:"Devices learned",pt_speed:"Speed",pt_mtu:"MTU", @@ -147,7 +147,7 @@ d_system:"システム",d_traffic:"トラフィック", d_traffic_h:"パケット/秒、リアルタイム",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 異常",d_rxbad:"RX 異常", i_host:"ホスト名",i_ip:"IP アドレス",i_mask:"ネットマスク",i_gw:"ゲートウェイ",i_mac:"MAC",i_fw:"ファームウェア", i_built:"ビルド日",i_hw:"ハードウェア",i_temp:"温度",i_flash:"フラッシュ",i_syslog:"Syslog", -p_state:"状態",p_disabled:"無効",p_up:"アップ",p_txgb:"TX 正常 / 異常",p_rxgb:"RX 正常 / 異常", +p_state:"状態",p_disabled:"無効",p_up:"アップ", p_pkts:"pkts",p_module:"モジュール",p_temp:"温度",p_vcc:"電圧",p_txbias:"TX バイアス",p_txpower:"TX 電力", p_rxpower:"RX 電力",p_txfault:"TX 障害",p_txdis:"TX 無効",p_rxlos:"RX 信号ロス",p_adv:"アドバタイズ", pt_title:"ポート設定",pt_conn:"学習済みデバイス",pt_speed:"速度",pt_mtu:"MTU", @@ -260,7 +260,7 @@ d_system:"系统",d_traffic:"流量", d_traffic_h:"包/秒,实时",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 错误",d_rxbad:"RX 错误", i_host:"主机名",i_ip:"IP 地址",i_mask:"子网掩码",i_gw:"网关",i_mac:"MAC",i_fw:"固件", i_built:"构建日期",i_hw:"硬件",i_temp:"温度",i_flash:"Flash",i_syslog:"Syslog", -p_state:"状态",p_disabled:"已禁用",p_up:"已连接",p_txgb:"TX 正常 / 错误",p_rxgb:"RX 正常 / 错误", +p_state:"状态",p_disabled:"已禁用",p_up:"已连接", p_pkts:"个包",p_module:"模块",p_temp:"温度",p_vcc:"供电电压",p_txbias:"TX 偏置电流",p_txpower:"TX 光功率", p_rxpower:"RX 光功率",p_txfault:"TX 故障",p_txdis:"TX 禁用",p_rxlos:"RX 信号丢失",p_adv:"通告能力", pt_title:"端口配置",pt_conn:"已学习设备",pt_speed:"速率",pt_mtu:"MTU", @@ -373,7 +373,7 @@ d_system:"Sistema",d_traffic:"Tráfico", d_traffic_h:"paquetes/s, en vivo",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX erróneos",d_rxbad:"RX erróneos", i_host:"Nombre de host",i_ip:"Dirección IP",i_mask:"Máscara de red",i_gw:"Puerta de enlace",i_mac:"MAC",i_fw:"Firmware", i_built:"Compilado",i_hw:"Hardware",i_flash:"Flash",i_syslog:"Syslog", -p_state:"Estado",p_disabled:"deshabilitado",p_up:"activo",p_txgb:"TX correctos / erróneos",p_rxgb:"RX correctos / erróneos", +p_state:"Estado",p_disabled:"deshabilitado",p_up:"activo", p_pkts:"paquetes",p_module:"Módulo",p_temp:"Temperatura",p_vcc:"Vcc",p_txbias:"Polarización TX",p_txpower:"Potencia TX", p_rxpower:"Potencia RX",p_txfault:"Fallo TX",p_txdis:"TX deshabilitado",p_rxlos:"Pérdida RX (LOS)",p_adv:"Anunciado", pt_title:"Configuración de puerto",pt_conn:"Dispositivos aprendidos",pt_speed:"Velocidad",pt_mtu:"MTU", @@ -485,7 +485,7 @@ d_system:"Système",d_traffic:"Trafic", d_traffic_h:"paquets/s (en direct)",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX KO",d_rxbad:"RX KO", i_host:"Nom d'hote",i_ip:"Adresse IP",i_mask:"Masque réseau",i_gw:"Passerelle",i_mac:"Adresse MAC",i_fw:"Micro logiciel", i_built:"Compilé le",i_hw:"Matériel",i_temp:"Température",i_flash:"Taille Flash",i_syslog:"Journal système", -p_state:"Etat",p_disabled:"Inactif",p_up:"Actif",p_txgb:"TX bon / mauvais",p_rxgb:"RX bon / mauvais", +p_state:"Etat",p_disabled:"Inactif",p_up:"Actif", p_pkts:"paquets",p_module:"Module",p_temp:"Température",p_vcc:"Vcc",p_txbias:"TX biais",p_txpower:"TX puissance", p_rxpower:"RX puissance",p_txfault:"TX erreur",p_txdis:"TX désactivé",p_rxlos:"RX pertes de signaux",p_adv:"Capacités", pt_title:"Configuration du port",pt_conn:"Appareils appris",pt_speed:"Vitesse",pt_mtu:"MTU", @@ -602,7 +602,7 @@ d_system:"System",d_traffic:"Datenverkehr", d_traffic_h:"Pakete/s, live",d_txpps:"TX Pakete/s",d_rxpps:"RX Pakete/s",d_txbad:"TX fehlerhaft",d_rxbad:"RX fehlerhaft", i_host:"Hostname",i_ip:"IP-Adresse",i_mask:"Netzmaske",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware", i_built:"Erstellt",i_hw:"Hardware",i_temp:"Temperatur",i_flash:"Flash",i_syslog:"Syslog", -p_state:"Zustand",p_disabled:"deaktiviert",p_up:"verbunden",p_txgb:"TX gut / fehlerhaft",p_rxgb:"RX gut / fehlerhaft", +p_state:"Zustand",p_disabled:"deaktiviert",p_up:"verbunden", p_pkts:"Pakete",p_module:"Modul",p_temp:"Temperatur",p_vcc:"Vcc",p_txbias:"TX-Bias",p_txpower:"Sendeleistung", p_rxpower:"Empfangsleistung",p_txfault:"TX-Fehler",p_txdis:"TX deaktiviert",p_rxlos:"RX LOS",p_adv:"Angeboten", pt_title:"Port-Konfiguration",pt_conn:"Gelernte Geräte",pt_speed:"Geschwindigkeit",pt_mtu:"MTU", @@ -836,6 +836,7 @@ function isConfCmd(line){ function setDirty(d){ S.dirty=d; $("dirty").classList.toggle("show",d); + $("saveBtn").classList.toggle("pri",d); } function postCmd(cmd,quiet){ return api("/cmd",{method:"POST",body:cmd}).then(function(r){ @@ -1024,8 +1025,10 @@ function portRows(p){ var rows=[[t("c_port"),String(p.portNum)],[t("c_type"),p.isSFP?"SFP":"RJ45"]]; if(p.name)rows.push([t("c_name"),p.name]); rows.push([t("p_state"),!p.enabled?t("p_disabled"):(p.link>0?t("p_up")+" "+LINKS[p.link]:t("c_down"))]); - rows.push([t("p_txgb"),BigInt(p.txG)+" / "+BigInt(p.txB)+" "+t("p_pkts")]); - rows.push([t("p_rxgb"),BigInt(p.rxG)+" / "+BigInt(p.rxB)+" "+t("p_pkts")]); + rows.push([t("st_txg"),BigInt(p.txG)+" "+t("p_pkts")]); + rows.push([t("st_txb"),BigInt(p.txB)+" "+t("p_pkts")]); + rows.push([t("st_rxg"),BigInt(p.rxG)+" "+t("p_pkts")]); + rows.push([t("st_rxb"),BigInt(p.rxB)+" "+t("p_pkts")]); if(p.isSFP){ if(p.sfp_vendor)rows.push([t("p_module"),[p.sfp_vendor,p.sfp_model,p.sfp_serial].filter(Boolean).join(" / ")]); var ext=p.sfp_options&0x40; @@ -2243,14 +2246,14 @@ var CONF_OVERWRITE=[ /^ntp\s+server\b/,/^ntp\s+interval\b/,/^ntp\s+timezone\b/,/^ntp\s+dst\b/, /^vlan\s+\d{1,4}\s+mgmt$/,/^vlan\s+\d{1,4}(?!\s+mgmt\b)/, /^pvid\s+\d{1,2}\b/, - /^port\s+\d{1,2}(?!\s+name\b)/,/^port\s+\d{1,2}\s+name\b/, + /^port\s+\d{1,2}(?!\s+(name|lldp)\b)/,/^port\s+\d{1,2}\s+name\b/, /^mirror\b/, /^lag\s+\d\b/,/^laghash\s+\d\b/,/^isolate\s+\d{1,2}\b/, /^stp\s+(prio|hello|maxage|fwd|txhold|version)\b/, /^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+(edge|cost|prio|guard|filter|p2p)\b/, /^igmp\b/,/^mtu\s+\d{1,2}\b/,/^storm\s+\d{1,2}\s+(bcast|mcast|ucast|umcast)\b/, ]; -var CONF_TOGGLE=[/^(syslog)\s+(on|off)$/,/^(ntp)\s+(on|off)$/,/^(stp)\s+(on|off)$/,/^(stp\s+(port\s+\d{1,2}|lag\s+[1-4]))\s+(on|off)$/]; +var CONF_TOGGLE=[/^(syslog)\s+(on|off)$/,/^(ntp)\s+(on|off)$/,/^(stp)\s+(on|off)$/,/^(lldp)\s+(on|off)$/,/^(stp\s+(port\s+\d{1,2}|lag\s+[1-4]))\s+(on|off)$/]; function mergeConf(base,texts){ var conf=base.slice(); function drop(rx){conf=conf.filter(function(c){return!rx.test(c)})} @@ -2268,6 +2271,7 @@ function mergeConf(base,texts){ } if((m=line.match(/^lag (\d) lacp off$/))){drop(new RegExp("^lag "+m[1]+" lacp( |$)"));return;} if(line==="mirror off"){drop(/^mirror /);return;} + if((m=line.match(/^(port \d{1,2} lldp) (permit|block)$/))){drop(new RegExp("^"+m[1]+" (permit|block)$"));conf.push(line);return;} if(!isConfCmd(line))return; if((m=line.match(/^ingress (.+)$/))){ if(/^[tua]$/.test(m[1])){drop(/^ingress /);conf.push(line);return;} @@ -2300,7 +2304,7 @@ function mergeConf(base,texts){ var key=line.match(rx)[0]; conf=conf.filter(function(item){ return!(item===key||(item.indexOf(key+" ")===0 - &&!/\smgmt$/.test(item)&&item.indexOf(key+" name ")!==0)); + &&!/\smgmt$/.test(item)&&item.indexOf(key+" name ")!==0&&item.indexOf(key+" lldp ")!==0)); }); break; } diff --git a/html/index.html b/html/index.html index f95c8219..43a3fe54 100644 --- a/html/index.html +++ b/html/index.html @@ -89,6 +89,7 @@ table.t th{ padding:6px 8px;border-bottom:1px solid var(--bd);white-space:nowrap; } table.t th[data-sort]{cursor:pointer;user-select:none} +table.t th.num{text-align:right} table.t td{padding:6px 8px;border-bottom:1px solid var(--bd);vertical-align:middle} table.t tr:last-child td{border-bottom:0} table.t tr:hover td{background:var(--sel)} @@ -223,7 +224,7 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
unsaved changes - +
@@ -437,8 +438,8 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}

The switch has no battery backed clock.

Admin password

- - + +

Takes effect immediately; save to flash to keep it after reboot.

diff --git a/httpd/httpd.c b/httpd/httpd.c index f2ca2d36..688513f8 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -55,8 +55,8 @@ __xdata uint8_t boundary[72]; #define CONFIG_UPLOAD_BUF (CONFIG_LEN + 384) __xdata uint8_t config_upload; __xdata uint8_t config_buf[CONFIG_UPLOAD_BUF]; -// bytes buffered in config_buf so far (config body, or a firmware part -// header); accumulates across TCP segments +// bytes buffered in config_buf so far (HTTP header, POST body, or a firmware +// part header); accumulates across TCP segments __xdata uint16_t pre_acc; __xdata uint8_t * __xdata content_type = 0; __xdata uint8_t * __xdata session = 0; @@ -75,9 +75,6 @@ __xdata uint8_t postbody_endpoint; __xdata uint16_t postbody_start; __xdata char passwd[21]; -// Set when a verified firmware upload awaits its response ACK, after -// which the chip resets to apply the staged image -__xdata uint8_t fw_reset_pending; __xdata char session_id[SESSION_ID_LENGTH + 1]; __xdata uint8_t authenticated; __xdata uint32_t now; @@ -90,6 +87,7 @@ __xdata uint32_t last_session_use; #define TSTATE_POST 4 #define TSTATE_MULTIPART 5 #define TSTATE_POSTBODY 6 +#define TSTATE_HEADER 7 extern __xdata uint16_t crc_value; __xdata uint16_t crc_final; @@ -109,8 +107,8 @@ void httpd_init(void) __banked uip_listen(HTONS(80)); // Not through uip_conn: it only points at a connection while uIP is // handling one, and nothing has set it yet at init time. - uip_conns[0].appstate.tstate = TSTATE_CLOSED; - fw_reset_pending = 0; // xdata is not zeroed by the startup code + for (uint8_t i = 0; i < UIP_CONNS; i++) + uip_conns[i].appstate.tstate = TSTATE_CLOSED; } @@ -450,15 +448,9 @@ static uint8_t config_take(void) // unlike scan_header(), keeps no auth state, so it may run on every buffered segment static uint16_t preamble_payload_start(uint16_t n) { - uint16_t pos; + // Skip the HTTP header separator retained by handle_post(). + uint16_t pos = 4; - for (pos = 0; pos + 24 <= n; pos++) { - if (strstart(&config_buf[pos], "application/octet-stream")) - break; - } - if (pos + 24 > n) - return 0; - pos += 24; while (pos + 3 < n && !strstart(&config_buf[pos], "\r\n\r\n")) pos++; if (pos + 3 >= n) @@ -511,7 +503,7 @@ uint8_t stream_upload(void) "Content-Type: text/plain\r\n\r\n" "OK: checksum verified, rebooting\n"); // Reset once the response is fully ACKed - fw_reset_pending = 1; + s->fw_reset_pending = 1; } else { print_string("Checksum incorrect! Aborting.\n"); slen = strtox(outbuf, "HTTP/1.1 400 Bad Request\r\nContent-Length: 33\r\n" @@ -746,7 +738,42 @@ static void post_body_continue(void) } -void handle_post(void) + +/* + * Buffer an HTTP request header across TCP receive events. Stop copying at + * CRLFCRLF so any body bytes in the final segment stay in uip_appdata. + * + * Return the body offset in the current receive buffer, 0 while incomplete, + * or 0xffff after sending an error response. + */ +static uint16_t request_header_take(void) +{ + uint16_t i; + + for (i = 0; i < uip_len; i++) { + if (pre_acc + 1 >= CONFIG_UPLOAD_BUF) { + uip_conn->appstate.tstate = TSTATE_NONE; + send_bad_request(); + return 0xffff; + } + config_buf[pre_acc++] = ((__xdata uint8_t *)uip_appdata)[i]; + config_buf[pre_acc] = NUL; + if (pre_acc >= 4 + && config_buf[pre_acc - 4] == '\r' + && config_buf[pre_acc - 3] == '\n' + && config_buf[pre_acc - 2] == '\r' + && config_buf[pre_acc - 1] == '\n') { + uip_conn->appstate.tstate = TSTATE_NONE; + return i + 1; + } + } + + postbody_start = ticks; + uip_conn->appstate.tstate = TSTATE_HEADER; + return 0; +} + +void handle_post(uint16_t body_off) { __xdata struct httpd_state * __xdata s = &(uip_conn->appstate); __xdata uint8_t *p = uip_appdata; @@ -759,6 +786,9 @@ void handle_post(void) // Was the multipart header sent in multiple packets? if (s->tstate != TSTATE_MULTIPART) { + p = config_buf; + request_path = p + 6; + dbg_string("Is POST\n"); p += 5; // Skip post // Find end of request path @@ -772,9 +802,12 @@ void handle_post(void) dbg_string("Boundary: >"); dbg_string_x(boundary); dbg_string("<\n"); if (!*p || !content_type) { dbg_string("Bad Request!\n"); - send_not_found(); + send_bad_request(); return; } + + pre_acc = 0; + p = (__xdata uint8_t *)uip_appdata + body_off; if (is_word(request_path, "upload")) { if (!authenticated) { send_unauthorized(); @@ -800,7 +833,10 @@ void handle_post(void) dbg_string("Configuration upload\n"); verify_crc = 0; config_upload = 1; - pre_acc = 0; + // config_take() matches CRLF-prefixed delimiters, including the first. + config_buf[0] = '\r'; + config_buf[1] = '\n'; + pre_acc = 2; } // Check for other POST requests, which are not multipart, below } else { @@ -824,7 +860,6 @@ void handle_post(void) handle_firmware_fragment(p); return; } else if (is_word(request_path, "cmd")) { - p += 4; if (!authenticated) { send_unauthorized(); return; @@ -843,7 +878,6 @@ void handle_post(void) return; } - p += 4; postbody_endpoint = POSTBODY_LOGIN; if (!post_body_take(p)) return; @@ -874,9 +908,10 @@ void httpd_appcall(void) print_byte(s->tstate); write_char(' '); #endif - if(uip_connected() && s->tstate == TSTATE_CLOSED) { + if(uip_connected()) { dbg_string("Connected...\n"); s->tstate = TSTATE_NONE; + s->fw_reset_pending = 0; // explicitly initialize reused XDATA appstate } else if (uip_closed()) { dbg_string("Connection closed\n"); s->tstate = TSTATE_CLOSED; @@ -890,9 +925,9 @@ void httpd_appcall(void) dbg_string("Closing because everything has been transmitted\n"); uip_close(); s->tstate = TSTATE_CLOSED; - } else if (s->tstate == TSTATE_POSTBODY + } else if ((s->tstate == TSTATE_POSTBODY || s->tstate == TSTATE_HEADER) && (uint16_t)ticks - postbody_start > POSTBODY_TIMEOUT) { - dbg_string("Body never arrived\n"); + dbg_string("HTTP request never completed\n"); uip_abort(); s->tstate = TSTATE_CLOSED; } @@ -928,7 +963,7 @@ void httpd_appcall(void) cont_len -= slen; cont_addr += slen; s->tstate = TSTATE_TX; - } else if (fw_reset_pending) { + } else if (s->fw_reset_pending) { // The upload verdict has been fully ACKed by the client; // now it is safe to reset and apply the staged image print_string("Resetting to apply update\n"); @@ -955,6 +990,7 @@ void httpd_appcall(void) cont_len = 0; dbg_char('<'); dbg_short(uip_len); dbg_char('\n'); __xdata uint8_t *p = uip_appdata; + uint16_t body_off = 0; // Mark end of request header with \0 p[uip_len] = 0; #ifdef DEBUG @@ -963,9 +999,21 @@ void httpd_appcall(void) dbg_char('\n'); #endif p = uip_appdata; - if (is_word(p, "POST") || s->tstate == TSTATE_MULTIPART - || s->tstate == TSTATE_POSTBODY) { - handle_post(); + if (s->tstate != TSTATE_MULTIPART && s->tstate != TSTATE_POSTBODY) { + if (s->tstate != TSTATE_HEADER) + pre_acc = 0; + body_off = request_header_take(); + if (!body_off) { + uip_len = 0; + return; + } + if (body_off == 0xffff) + goto do_send; + } + + if (s->tstate == TSTATE_MULTIPART || s->tstate == TSTATE_POSTBODY + || is_word(config_buf, "POST")) { + handle_post(body_off); // If this is an ongoing post stream, then wait for the next packet if (s->tstate == TSTATE_POST || s->tstate == TSTATE_MULTIPART || s->tstate == TSTATE_POSTBODY) { @@ -975,12 +1023,11 @@ void httpd_appcall(void) goto do_send; } - // We only expect a GET request here. + p = config_buf; if (!is_word(p, "GET")) { send_bad_request(); goto do_send; } - dbg_string("GET request "); p += 4; scan_header(p); diff --git a/httpd/httpd.h b/httpd/httpd.h index 91b83b22..5cabe3d5 100644 --- a/httpd/httpd.h +++ b/httpd/httpd.h @@ -12,6 +12,7 @@ for each TCP connection. */ typedef struct httpd_state { uint8_t tstate; + uint8_t fw_reset_pending; } uip_tcp_appstate_t; /* Finally we define the application function to be called by uIP. */ diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 006d2dbe..7f107b7d 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -341,7 +341,7 @@ void send_vlan(uint16_t vlan) } slen += strtox(outbuf + slen, "\",\"pvid\":\"0x"); uint16_t pvid_mask = 0; - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { if (port_pvid_get(i) == vlan) pvid_mask |= (1 << i); } @@ -357,7 +357,7 @@ void send_vlan(uint16_t vlan) bool send_counters(uint8_t phys_port) { uint8_t phys_port_idx = phys_port - 1; - if (phys_port_idx > (machine.max_port - machine.min_port)) + if (phys_port_idx > (MACHINE_MAX_PORT - MACHINE_MIN_PORT)) goto err; uint8_t log_port = machine.phys_to_log_port[phys_port_idx]; @@ -676,7 +676,7 @@ void send_stp(void) slen += strtox(outbuf + slen, "\",\"ports\":["); reg_read_m(RTL837X_MSTP_STATES); for (i = 0; i < STP_ENTITIES; i++) { - if (i < STP_LAG_BASE && (i < machine.min_port || i > machine.max_port)) + if (i < STP_LAG_BASE && !MACHINE_PORT_VALID(i)) continue; if (i < STP_LAG_BASE && stp_ent_of[i] != i) continue; @@ -761,7 +761,7 @@ void send_lacp(void) } slen -= 1; // remove comma slen += strtox(outbuf + slen, "],\"ports\":["); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { slen += strtox(outbuf + slen, "{\"p\":"); itoa_html(machine.log_to_phys_port[i]); slen += strtox(outbuf + slen, ",\"lag\":"); @@ -793,7 +793,7 @@ void send_lldp(void) bool_to_html(lldp_enabled); slen += strtox(outbuf + slen, ",\"portStatus\":["); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { slen += strtox(outbuf + slen, "{\"portNum\":"); itoa_html(machine.log_to_phys_port[i]); @@ -808,7 +808,7 @@ void send_lldp(void) bool_to_html(1 & (lldp_logical_port_status >> i)); slen += strtox(outbuf + slen, "}"); - if (i < machine.max_port) + if (i < MACHINE_MAX_PORT) char_to_html(','); else char_to_html(']'); @@ -825,7 +825,7 @@ void send_eee(void) uint8_t eee_ablty = sfr_data[3]; char_to_html('['); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { slen += strtox(outbuf + slen, "{\"portNum\":"); itoa_html(machine.log_to_phys_port[i]); @@ -857,7 +857,7 @@ void send_eee(void) bool_to_html(eee_ablty & (1 << i)); } char_to_html('}'); - if (i < machine.max_port) + if (i < MACHINE_MAX_PORT) char_to_html(','); else char_to_html(']'); @@ -870,7 +870,7 @@ void send_bandwidth(void) dbg_string("send_bandwidth called\n"); slen = strtox(outbuf, HTTP_RESPONCE_JSON); char_to_html('['); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { slen += strtox(outbuf + slen, "{\"portNum\":"); itoa_html(machine.log_to_phys_port[i]); slen += strtox(outbuf + slen, ",\"iLimited\":"); @@ -900,7 +900,7 @@ void send_bandwidth(void) byte_to_html(sfr_data[3]); char_to_html('"'); char_to_html('}'); - if (i < machine.max_port) + if (i < MACHINE_MAX_PORT) char_to_html(','); else char_to_html(']'); @@ -914,7 +914,7 @@ void send_storm(void) slen = strtox(outbuf, HTTP_RESPONCE_JSON); char_to_html('['); - for (i = machine.min_port; i <= machine.max_port; i++) { + for (i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { slen += strtox(outbuf + slen, "{\"portNum\":"); itoa_html(machine.log_to_phys_port[i]); slen += strtox(outbuf + slen, ",\"en\":\""); @@ -934,7 +934,7 @@ void send_storm(void) } char_to_html('"'); char_to_html('}'); - if (i < machine.max_port) + if (i < MACHINE_MAX_PORT) char_to_html(','); else char_to_html(']'); @@ -949,7 +949,7 @@ void send_isolation(void) dbg_string("send_isolation called\n"); slen = strtox(outbuf, HTTP_RESPONCE_JSON); char_to_html('['); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { slen += strtox(outbuf + slen, "{\"portNum\":"); itoa_html(machine.log_to_phys_port[i]); slen += strtox(outbuf + slen, ",\"allow\":\""); @@ -958,7 +958,7 @@ void send_isolation(void) byte_to_html(allow & 0xff); char_to_html('"'); char_to_html('}'); - if (i < machine.max_port) + if (i < MACHINE_MAX_PORT) char_to_html(','); } char_to_html(']'); @@ -970,7 +970,7 @@ void send_mtu(void) dbg_string("send_mtu called\n"); slen = strtox(outbuf, HTTP_RESPONCE_JSON); char_to_html('['); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { slen += strtox(outbuf + slen, "{\"portNum\":"); itoa_html(machine.log_to_phys_port[i]); slen += strtox(outbuf + slen, ",\"mtu\":\"0x"); @@ -980,7 +980,7 @@ void send_mtu(void) byte_to_html(mtu & 0xff); char_to_html('"'); char_to_html('}'); - if (i < machine.max_port) + if (i < MACHINE_MAX_PORT) char_to_html(','); else char_to_html(']'); @@ -994,7 +994,7 @@ void send_status(void) dbg_string("sending status\n"); char_to_html('['); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { slen += strtox(outbuf + slen, "{\"portNum\":"); itoa_html(machine.log_to_phys_port[i]); slen += strtox(outbuf + slen, ",\"logPort\":"); @@ -1115,7 +1115,7 @@ void send_status(void) slen += strtox(outbuf + slen, "\",\"macs\":\"0x"); reg_to_html(RTL837X_L2_LRN_PORT_CONSTRT_CNT + (i << 2)); slen += strtox(outbuf + slen, "\"}"); - if (i < machine.max_port) + if (i < MACHINE_MAX_PORT) char_to_html(','); else char_to_html(']'); diff --git a/machine.h b/machine.h index c0e10cd5..78dfd77a 100644 --- a/machine.h +++ b/machine.h @@ -15,8 +15,51 @@ #define MACHINE_INC(dir,file) MACHINE_STR(dir/file) +#define RTL8370 0x70 +#define RTL8372 0x72 +#define RTL8373 0x73 + #include MACHINE_INC(MACHINE_DEF_DIR,MACHINE_NAME.h) + +#ifndef MACHINE_CHIPSET +#error "MACHINE_CHIPSET shall be defined in .h file" +#endif + +#ifndef MACHINE_MIN_PORT +#if MACHINE_CHIPSET == RTL8372 +#define MACHINE_MIN_PORT 3 +#else +#define MACHINE_MIN_PORT 0 +#endif +#endif + +#ifndef MACHINE_MAX_PORT +#if MACHINE_CHIPSET == RTL8370 +#define MACHINE_MAX_PORT 7 +#else +#define MACHINE_MAX_PORT 8 +#endif +#endif + +#define MACHINE_PORT_VALID(p) \ + ((uint8_t)((p) - MACHINE_MIN_PORT) <= (MACHINE_MAX_PORT - MACHINE_MIN_PORT)) + +// auto derive SOC_FAMILY +#define RTL836X 6 +#define RTL837X 7 + +#ifdef SOC_FAMILY +#error "SOC_FAMILY can not be manually defined, shall be auto derived" +#endif +#if (MACHINE_CHIPSET == RTL8372) || (MACHINE_CHIPSET == RTL8373) +#define SOC_FAMILY RTL837X +#elif (MACHINE_CHIPSET == RTL8370 ) +#define SOC_FAMILY RTL836X +#else +#error "Unsupported MACHINE_CHIPSET is specified!" +#endif + #define LED_27 1 // SYSTEM LED #define LED_28_SYS 2 @@ -41,10 +84,6 @@ struct sfp_port struct machine { char machine_name[30]; uint8_t isRTL8373; - // Lowest logical port number - uint8_t min_port; - // Highest logical port number - uint8_t max_port; uint8_t n_sfp; uint8_t n_10g; uint8_t log_to_phys_port[9]; diff --git a/machine/2G08110GSN.h b/machine/2G08110GSN.h index f54133d0..46cd230f 100644 --- a/machine/2G08110GSN.h +++ b/machine/2G08110GSN.h @@ -2,5 +2,6 @@ #define _MACHINE_2G08110GSN_H_ #define MACHINE_MODEL "MokerLink 2G08110GSN" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/2G5F4_10G2_V1_01.c b/machine/2G5F4_10G2_V1_01.c index 9a08e19f..caca361d 100644 --- a/machine/2G5F4_10G2_V1_01.c +++ b/machine/2G5F4_10G2_V1_01.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, /* Same 2M-PCB43-V1.1 board family as the KP-9000-6XH-X2 (see * machine/KP_9000_6XHML_X2.c), but the two SFP+ cages (physical ports 5 and @@ -44,8 +41,8 @@ __code const struct machine machine = { * at 2.5G only) and LED-ID2 carries the SFP single LED. The "solid" * conditions (LINK/speed) barely drive the LEDs here and ACT is what * actually lights them, which is why the white LED used to glow faintly at - * non-2.5G speeds; the fix for that is LED_GLB_IO_EN bit 6, set in - * machine_init.c. */ + * non-2.5G speeds; the fix for that is LED_GLB_IO_EN bit 6, set in the + * shared machine_custom_init() hook (machine/2G5F4_10G2_V1_01_init.c). */ .led_sets = { { LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, LEDS_2G5 | LEDS_LINK | LEDS_10G, LEDS_1G | LEDS_LINK, diff --git a/machine/2G5F4_10G2_V1_01.h b/machine/2G5F4_10G2_V1_01.h index d372b58a..80a90fbd 100644 --- a/machine/2G5F4_10G2_V1_01.h +++ b/machine/2G5F4_10G2_V1_01.h @@ -2,5 +2,6 @@ #define _MACHINE_2G5F4_10G2_V1_01_H_ #define MACHINE_MODEL "2G5F4_10G2_V1.01 / SGT0204S" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/2G5F4_10G2_V1_01_init.c b/machine/2G5F4_10G2_V1_01_init.c new file mode 120000 index 00000000..37370e2a --- /dev/null +++ b/machine/2G5F4_10G2_V1_01_init.c @@ -0,0 +1 @@ +KP_9000_6XH_X2_init.c \ No newline at end of file diff --git a/machine/DEFAULT_8C_1SFP.h b/machine/DEFAULT_8C_1SFP.h index 2b802a30..f19507e1 100644 --- a/machine/DEFAULT_8C_1SFP.h +++ b/machine/DEFAULT_8C_1SFP.h @@ -2,5 +2,6 @@ #define _MACHINE_DEFAULT_8C_1SFP_H_ #define MACHINE_MODEL "8+1 SFP Port Switch" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/F7008_2_5.c b/machine/F7008_2_5.c index e2d08e61..df6643cc 100644 --- a/machine/F7008_2_5.c +++ b/machine/F7008_2_5.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/F7008_2_5.h b/machine/F7008_2_5.h index c3b0cbbf..f8c78cae 100644 --- a/machine/F7008_2_5.h +++ b/machine/F7008_2_5.h @@ -2,5 +2,6 @@ #define _MACHINE_F7008_2_5_H_ #define MACHINE_MODEL "F7008-2.5 8+1 SFP Port Switch" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/FG_4GT_2SX_V2_0.c b/machine/FG_4GT_2SX_V2_0.c index 9590c6f0..9931a1a1 100644 --- a/machine/FG_4GT_2SX_V2_0.c +++ b/machine/FG_4GT_2SX_V2_0.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/FG_4GT_2SX_V2_0.h b/machine/FG_4GT_2SX_V2_0.h index 8f9697e7..8c819abf 100644 --- a/machine/FG_4GT_2SX_V2_0.h +++ b/machine/FG_4GT_2SX_V2_0.h @@ -2,5 +2,6 @@ #define _MACHINE_FG_4GT_2SX_V2_0_H_ #define MACHINE_MODEL "FG-4GT-2SX_V2.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/FG_4GT_2SX_V2_0_init.c b/machine/FG_4GT_2SX_V2_0_init.c new file mode 100644 index 00000000..c9b9ddab --- /dev/null +++ b/machine/FG_4GT_2SX_V2_0_init.c @@ -0,0 +1,6 @@ +#include "machine_init_defs.h" + +void machine_custom_init(void) __banked +{ + REG_SET(RTL837X_REG_LED_GLB_IO_EN, 0x7624155b); +} diff --git a/machine/FG_8GT_1SX.c b/machine/FG_8GT_1SX.c index 0fd3dee0..c232d92a 100644 --- a/machine/FG_8GT_1SX.c +++ b/machine/FG_8GT_1SX.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/FG_8GT_1SX.h b/machine/FG_8GT_1SX.h index e75a9946..789d8a9b 100644 --- a/machine/FG_8GT_1SX.h +++ b/machine/FG_8GT_1SX.h @@ -2,5 +2,6 @@ #define _MACHINE_FG_8GT_1SX_H_ #define MACHINE_MODEL "FG-8GT-1SX" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/FNS1200P.h b/machine/FNS1200P.h index e5691b48..f058e5eb 100644 --- a/machine/FNS1200P.h +++ b/machine/FNS1200P.h @@ -2,5 +2,6 @@ #define _MACHINE_FNS1200P_H_ #define MACHINE_MODEL "FNS-1200P" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/FNS1200P_init.c b/machine/FNS1200P_init.c new file mode 120000 index 00000000..37370e2a --- /dev/null +++ b/machine/FNS1200P_init.c @@ -0,0 +1 @@ +KP_9000_6XH_X2_init.c \ No newline at end of file diff --git a/machine/GT_ST018M.h b/machine/GT_ST018M.h index c4550c26..66b0c51f 100644 --- a/machine/GT_ST018M.h +++ b/machine/GT_ST018M.h @@ -2,5 +2,6 @@ #define _MACHINE_GT_ST018M_H_ #define MACHINE_MODEL "GoodTop GT-ST018M" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/GT_ST024M.h b/machine/GT_ST024M.h index be57f788..8662bb31 100644 --- a/machine/GT_ST024M.h +++ b/machine/GT_ST024M.h @@ -2,5 +2,6 @@ #define _MACHINE_GT_ST024M_H_ #define MACHINE_MODEL "GoodTop GT-ST024M" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/HASIVO_S1100P_8GT_1SX_S.c b/machine/HASIVO_S1100P_8GT_1SX_S.c index 4db8de17..9af4d8c3 100644 --- a/machine/HASIVO_S1100P_8GT_1SX_S.c +++ b/machine/HASIVO_S1100P_8GT_1SX_S.c @@ -1,11 +1,8 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, + MACHINE_COMMON_SETTING, .mac_flash_offset = 0x1FC000, - .min_port = 0, - .max_port = 8, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/HASIVO_S1100P_8GT_1SX_S.h b/machine/HASIVO_S1100P_8GT_1SX_S.h index b34d03ef..89f03ce5 100644 --- a/machine/HASIVO_S1100P_8GT_1SX_S.h +++ b/machine/HASIVO_S1100P_8GT_1SX_S.h @@ -2,5 +2,6 @@ #define _MACHINE_HASIVO_S1100P_8GT_1SX_S_H_ #define MACHINE_MODEL "Hasivo S1100P-8GT-1SX-S" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/HASIVO_S1100WP_8GT_1SX_SE.h b/machine/HASIVO_S1100WP_8GT_1SX_SE.h index d50dfc22..433a42f2 100644 --- a/machine/HASIVO_S1100WP_8GT_1SX_SE.h +++ b/machine/HASIVO_S1100WP_8GT_1SX_SE.h @@ -2,5 +2,6 @@ #define _MACHINE_HASIVO_S1100WP_8GT_1SX_SE_H_ #define MACHINE_MODEL "Hasivo S1100WP-8GT-1SX-SE" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/HASIVO_S600W_4GT_2XGT_SE.c b/machine/HASIVO_S600W_4GT_2XGT_SE.c index e43477d8..223c990f 100644 --- a/machine/HASIVO_S600W_4GT_2XGT_SE.c +++ b/machine/HASIVO_S600W_4GT_2XGT_SE.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 0, .n_10g = 2, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, diff --git a/machine/HASIVO_S600W_4GT_2XGT_SE.h b/machine/HASIVO_S600W_4GT_2XGT_SE.h index 97beb686..dcb40306 100644 --- a/machine/HASIVO_S600W_4GT_2XGT_SE.h +++ b/machine/HASIVO_S600W_4GT_2XGT_SE.h @@ -2,5 +2,6 @@ #define _MACHINE_HASIVO_S600W_4GT_2XGT_SE_H_ #define MACHINE_MODEL "Hasivo S600W-4GT-2XGT-SE" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/HC_SWTG124AS.h b/machine/HC_SWTG124AS.h index 8d4dd648..f1936317 100644 --- a/machine/HC_SWTG124AS.h +++ b/machine/HC_SWTG124AS.h @@ -2,5 +2,6 @@ #define _MACHINE_HC_SWTG124AS_H_ #define MACHINE_MODEL "Horaco HC-SWTG124AS" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/HG0402XG_V1_1.c b/machine/HG0402XG_V1_1.c index 5d7be1e9..5f20e295 100644 --- a/machine/HG0402XG_V1_1.c +++ b/machine/HG0402XG_V1_1.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/HG0402XG_V1_1.h b/machine/HG0402XG_V1_1.h index 628dc168..5b578acc 100644 --- a/machine/HG0402XG_V1_1.h +++ b/machine/HG0402XG_V1_1.h @@ -2,5 +2,6 @@ #define _MACHINE_HG0402XG_V1_1_H_ #define MACHINE_MODEL "HG0402XG V1.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/HI_K0402WS.c b/machine/HI_K0402WS.c index 3ad7b241..2c59d8bc 100644 --- a/machine/HI_K0402WS.c +++ b/machine/HI_K0402WS.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/HI_K0402WS.h b/machine/HI_K0402WS.h index d930fce9..18416117 100644 --- a/machine/HI_K0402WS.h +++ b/machine/HI_K0402WS.h @@ -2,5 +2,6 @@ #define _MACHINE_HI_K0402WS_H_ #define MACHINE_MODEL "PCB-K0402WS-V3.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/HI_K0402WS_init.c b/machine/HI_K0402WS_init.c new file mode 120000 index 00000000..37370e2a --- /dev/null +++ b/machine/HI_K0402WS_init.c @@ -0,0 +1 @@ +KP_9000_6XH_X2_init.c \ No newline at end of file diff --git a/machine/HI_K0801WS.c b/machine/HI_K0801WS.c index 8fba5e82..cc06d550 100644 --- a/machine/HI_K0801WS.c +++ b/machine/HI_K0801WS.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/HI_K0801WS.h b/machine/HI_K0801WS.h index 4321d0fe..ff5a7721 100644 --- a/machine/HI_K0801WS.h +++ b/machine/HI_K0801WS.h @@ -2,5 +2,6 @@ #define _MACHINE_HI_K0801WS_H_ #define MACHINE_MODEL "Hi-Source HI-k0801WS" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/K0501W_V2_0.c b/machine/K0501W_V2_0.c index 75f36c6b..51224523 100644 --- a/machine/K0501W_V2_0.c +++ b/machine/K0501W_V2_0.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/K0501W_V2_0.h b/machine/K0501W_V2_0.h index dbe10df6..b657edf4 100644 --- a/machine/K0501W_V2_0.h +++ b/machine/K0501W_V2_0.h @@ -2,5 +2,6 @@ #define _MACHINE_K0501W_V2_0_H_ #define MACHINE_MODEL "K0501W V2.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XHML_X2.c b/machine/KP_9000_6XHML_X2.c index a6520f01..850d7e2a 100644 --- a/machine/KP_9000_6XHML_X2.c +++ b/machine/KP_9000_6XHML_X2.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/KP_9000_6XHML_X2.h b/machine/KP_9000_6XHML_X2.h index da850ae4..67551b56 100644 --- a/machine/KP_9000_6XHML_X2.h +++ b/machine/KP_9000_6XHML_X2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XHML_X2_H_ #define MACHINE_MODEL "keepLink KP-9000-6XHML-X2" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XHML_X2_V1_1.h b/machine/KP_9000_6XHML_X2_V1_1.h index 1e8b2c49..8d491998 100644 --- a/machine/KP_9000_6XHML_X2_V1_1.h +++ b/machine/KP_9000_6XHML_X2_V1_1.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XHML_X2_V1_1_H_ #define MACHINE_MODEL "keepLink KP-9000-6XHML V1.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XHML_X2_V1_2.h b/machine/KP_9000_6XHML_X2_V1_2.h index 484ff3e2..df5fd559 100644 --- a/machine/KP_9000_6XHML_X2_V1_2.h +++ b/machine/KP_9000_6XHML_X2_V1_2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XHML_X2_V1_2_H_ #define MACHINE_MODEL "keepLink KP-9000-6XHML V1.2" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XHML_X2_V2_1.h b/machine/KP_9000_6XHML_X2_V2_1.h index 4cea1de7..3b276ac7 100644 --- a/machine/KP_9000_6XHML_X2_V2_1.h +++ b/machine/KP_9000_6XHML_X2_V2_1.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XHML_X2_V2_1_H_ #define MACHINE_MODEL "keepLink KP-9000-6XHML V2.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XHML_X2_V2_1_init.c b/machine/KP_9000_6XHML_X2_V2_1_init.c new file mode 120000 index 00000000..37370e2a --- /dev/null +++ b/machine/KP_9000_6XHML_X2_V2_1_init.c @@ -0,0 +1 @@ +KP_9000_6XH_X2_init.c \ No newline at end of file diff --git a/machine/KP_9000_6XH_X.c b/machine/KP_9000_6XH_X.c index 50dcc10b..bd4b52a3 100644 --- a/machine/KP_9000_6XH_X.c +++ b/machine/KP_9000_6XH_X.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/KP_9000_6XH_X.h b/machine/KP_9000_6XH_X.h index f52d0ad6..664c830b 100644 --- a/machine/KP_9000_6XH_X.h +++ b/machine/KP_9000_6XH_X.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XH_X_H_ #define MACHINE_MODEL "keepLink KP-9000-6XH-X" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XH_X2.c b/machine/KP_9000_6XH_X2.c index aa6a2655..9ea09451 100644 --- a/machine/KP_9000_6XH_X2.c +++ b/machine/KP_9000_6XH_X2.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/KP_9000_6XH_X2.h b/machine/KP_9000_6XH_X2.h index 5493dc79..2d7a8374 100644 --- a/machine/KP_9000_6XH_X2.h +++ b/machine/KP_9000_6XH_X2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XH_X2_H_ #define MACHINE_MODEL "keepLink KP-9000-6XH-X2" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XH_X2_V1_1.h b/machine/KP_9000_6XH_X2_V1_1.h index 183cc276..f3d2d068 100644 --- a/machine/KP_9000_6XH_X2_V1_1.h +++ b/machine/KP_9000_6XH_X2_V1_1.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XH_X2_V1_1_H_ #define MACHINE_MODEL "keepLink KP-9000-6XH V1.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XH_X2_V1_2.h b/machine/KP_9000_6XH_X2_V1_2.h index 4fcd94af..2de3183e 100644 --- a/machine/KP_9000_6XH_X2_V1_2.h +++ b/machine/KP_9000_6XH_X2_V1_2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XH_X2_V1_2_H_ #define MACHINE_MODEL "keepLink KP-9000-6XH V1.2" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XH_X2_V2_1.h b/machine/KP_9000_6XH_X2_V2_1.h index a144dc96..dd1a954c 100644 --- a/machine/KP_9000_6XH_X2_V2_1.h +++ b/machine/KP_9000_6XH_X2_V2_1.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XH_X2_V2_1_H_ #define MACHINE_MODEL "keepLink KP-9000-6XH-X2 V2.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XH_X2_V2_1_init.c b/machine/KP_9000_6XH_X2_V2_1_init.c new file mode 120000 index 00000000..37370e2a --- /dev/null +++ b/machine/KP_9000_6XH_X2_V2_1_init.c @@ -0,0 +1 @@ +KP_9000_6XH_X2_init.c \ No newline at end of file diff --git a/machine/KP_9000_6XH_X2_init.c b/machine/KP_9000_6XH_X2_init.c new file mode 100644 index 00000000..394f71ef --- /dev/null +++ b/machine/KP_9000_6XH_X2_init.c @@ -0,0 +1,6 @@ +#include "machine_init_defs.h" + +void machine_custom_init(void) __banked +{ + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6); +} diff --git a/machine/KP_9000_9XHML_X_V2_2.c b/machine/KP_9000_9XHML_X_V2_2.c index e73a7514..6c8338b0 100644 --- a/machine/KP_9000_9XHML_X_V2_2.c +++ b/machine/KP_9000_9XHML_X_V2_2.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, .phys_to_log_port = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, diff --git a/machine/KP_9000_9XHML_X_V2_2.h b/machine/KP_9000_9XHML_X_V2_2.h index 2d6d0a7f..4bb261ac 100644 --- a/machine/KP_9000_9XHML_X_V2_2.h +++ b/machine/KP_9000_9XHML_X_V2_2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_9XHML_X_V2_2_H_ #define MACHINE_MODEL "keepLink KP-9000-9XHML-X V2.2" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/KP_9000_9XHML_X_V3_1.c b/machine/KP_9000_9XHML_X_V3_1.c index 26ea751f..515b59ac 100644 --- a/machine/KP_9000_9XHML_X_V3_1.c +++ b/machine/KP_9000_9XHML_X_V3_1.c @@ -2,10 +2,7 @@ // 2M-PCB23-V3.2 is wired like V3.1 (SFP detection, LEDs, factory MAC location) __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/KP_9000_9XHML_X_V3_1.h b/machine/KP_9000_9XHML_X_V3_1.h index c100b5f8..ae5e8e55 100644 --- a/machine/KP_9000_9XHML_X_V3_1.h +++ b/machine/KP_9000_9XHML_X_V3_1.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_9XHML_X_V3_1_H_ #define MACHINE_MODEL "keepLink KP-9000-9XHML-X V3.1" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/KP_9000_9XHML_X_V3_2.h b/machine/KP_9000_9XHML_X_V3_2.h index e3b4eec2..416cb327 100644 --- a/machine/KP_9000_9XHML_X_V3_2.h +++ b/machine/KP_9000_9XHML_X_V3_2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_9XHML_X_V3_2_H_ #define MACHINE_MODEL "keepLink KP-9000-9XHML-X V3.2" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/KP_9000_9XH_X_EU.c b/machine/KP_9000_9XH_X_EU.c index 7209e82b..17562565 100644 --- a/machine/KP_9000_9XH_X_EU.c +++ b/machine/KP_9000_9XH_X_EU.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/KP_9000_9XH_X_EU.h b/machine/KP_9000_9XH_X_EU.h index 2269b8fb..74c20b33 100644 --- a/machine/KP_9000_9XH_X_EU.h +++ b/machine/KP_9000_9XH_X_EU.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_9XH_X_EU_H_ #define MACHINE_MODEL "keepLink KP-9000-9XH-X-EU" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/LIANGUO_HYWS_SGT0108S.c b/machine/LIANGUO_HYWS_SGT0108S.c index aff1713c..1160585a 100644 --- a/machine/LIANGUO_HYWS_SGT0108S.c +++ b/machine/LIANGUO_HYWS_SGT0108S.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {2, 1, 4, 3, 5, 6, 7, 8, 9}, .phys_to_log_port = {1, 0, 3, 2, 4, 5, 6, 7, 8}, diff --git a/machine/LIANGUO_HYWS_SGT0108S.h b/machine/LIANGUO_HYWS_SGT0108S.h index f82bd128..310ee653 100644 --- a/machine/LIANGUO_HYWS_SGT0108S.h +++ b/machine/LIANGUO_HYWS_SGT0108S.h @@ -2,5 +2,6 @@ #define _MACHINE_LIANGUO_HYWS_SGT0108S_H_ #define MACHINE_MODEL "Lianguo HYWS-SGT0108S" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/LIANGUO_ZX_SWTGW215AS.c b/machine/LIANGUO_ZX_SWTGW215AS.c index 70414eca..dfd48f49 100644 --- a/machine/LIANGUO_ZX_SWTGW215AS.c +++ b/machine/LIANGUO_ZX_SWTGW215AS.c @@ -1,11 +1,8 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, + MACHINE_COMMON_SETTING, .mac_flash_offset = 0x1FC000, - .min_port = 3, - .max_port = 8, .n_sfp = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/LIANGUO_ZX_SWTGW215AS.h b/machine/LIANGUO_ZX_SWTGW215AS.h index 6c4e2210..840acd4a 100644 --- a/machine/LIANGUO_ZX_SWTGW215AS.h +++ b/machine/LIANGUO_ZX_SWTGW215AS.h @@ -2,5 +2,6 @@ #define _MACHINE_LIANGUO_ZX_SWTGW215AS_H_ #define MACHINE_MODEL "Lianguo ZX-SWTGW215AS" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/ONT_S207CW_62TS_SE.c b/machine/ONT_S207CW_62TS_SE.c index 6ba60778..65e339e6 100644 --- a/machine/ONT_S207CW_62TS_SE.c +++ b/machine/ONT_S207CW_62TS_SE.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 5, 4, 3, 2, 1, 6}, .phys_to_log_port = {7, 6, 5, 4, 3, 8, 0, 0, 0}, diff --git a/machine/ONT_S207CW_62TS_SE.h b/machine/ONT_S207CW_62TS_SE.h index 9938b004..1367900c 100644 --- a/machine/ONT_S207CW_62TS_SE.h +++ b/machine/ONT_S207CW_62TS_SE.h @@ -2,5 +2,6 @@ #define _MACHINE_ONT_S207CW_62TS_SE_H_ #define MACHINE_MODEL "ONT-S207CW-62TS-SE / Binardat 2G06-04210GSM / Binardat 2G06-04210GS" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/PB_2132.c b/machine/PB_2132.c index 8822c066..55388d98 100644 --- a/machine/PB_2132.c +++ b/machine/PB_2132.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/PB_2132.h b/machine/PB_2132.h index a3668767..ac50906b 100644 --- a/machine/PB_2132.h +++ b/machine/PB_2132.h @@ -2,5 +2,6 @@ #define _MACHINE_PB_2132_H_ #define MACHINE_MODEL "PB-2132" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/PCB_K0402WS_V1.c b/machine/PCB_K0402WS_V1.c index 0f365025..59b62387 100644 --- a/machine/PCB_K0402WS_V1.c +++ b/machine/PCB_K0402WS_V1.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/PCB_K0402WS_V1.h b/machine/PCB_K0402WS_V1.h index d1170aa7..189da400 100644 --- a/machine/PCB_K0402WS_V1.h +++ b/machine/PCB_K0402WS_V1.h @@ -2,5 +2,6 @@ #define _MACHINE_PCB_K0402WS_V1_H_ #define MACHINE_MODEL "PCB-K0402WS-V1.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/PCB_K0402WS_V2.c b/machine/PCB_K0402WS_V2.c index 71334029..33a9a93d 100644 --- a/machine/PCB_K0402WS_V2.c +++ b/machine/PCB_K0402WS_V2.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/PCB_K0402WS_V2.h b/machine/PCB_K0402WS_V2.h index eb5337ab..36352e43 100644 --- a/machine/PCB_K0402WS_V2.h +++ b/machine/PCB_K0402WS_V2.h @@ -2,5 +2,6 @@ #define _MACHINE_PCB_K0402WS_V2_H_ #define MACHINE_MODEL "PCB-K0402WS-V2.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/PCB_K0402WS_V2_init.c b/machine/PCB_K0402WS_V2_init.c new file mode 120000 index 00000000..37370e2a --- /dev/null +++ b/machine/PCB_K0402WS_V2_init.c @@ -0,0 +1 @@ +KP_9000_6XH_X2_init.c \ No newline at end of file diff --git a/machine/PCB_K0402WS_V3.h b/machine/PCB_K0402WS_V3.h index f206079d..b31bd3bb 100644 --- a/machine/PCB_K0402WS_V3.h +++ b/machine/PCB_K0402WS_V3.h @@ -2,5 +2,6 @@ #define _MACHINE_PCB_K0402WS_V3_H_ #define MACHINE_MODEL "PCB-K0402WS-V3.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/PCB_K0402WS_V3_init.c b/machine/PCB_K0402WS_V3_init.c new file mode 120000 index 00000000..37370e2a --- /dev/null +++ b/machine/PCB_K0402WS_V3_init.c @@ -0,0 +1 @@ +KP_9000_6XH_X2_init.c \ No newline at end of file diff --git a/machine/PCB_SWTG018AS_V2_1_0.c b/machine/PCB_SWTG018AS_V2_1_0.c index 1501de45..1eb77872 100644 --- a/machine/PCB_SWTG018AS_V2_1_0.c +++ b/machine/PCB_SWTG018AS_V2_1_0.c @@ -2,11 +2,8 @@ __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, + MACHINE_COMMON_SETTING, .mac_flash_offset = 0x1FC000, - .min_port = 0, - .max_port = 8, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/PCB_SWTG018AS_V2_1_0.h b/machine/PCB_SWTG018AS_V2_1_0.h index fce78470..546fe4d0 100644 --- a/machine/PCB_SWTG018AS_V2_1_0.h +++ b/machine/PCB_SWTG018AS_V2_1_0.h @@ -2,5 +2,6 @@ #define _MACHINE_PCB_SWTG018AS_V2_1_0_H_ #define MACHINE_MODEL "SWTGW218AS (SWTG018AS-V2.1.0)" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/PCB_SWTG018AS_V2_1_0_init.c b/machine/PCB_SWTG018AS_V2_1_0_init.c new file mode 100644 index 00000000..bce0b814 --- /dev/null +++ b/machine/PCB_SWTG018AS_V2_1_0_init.c @@ -0,0 +1,18 @@ +#include "machine_init_defs.h" + +static __code const struct { uint16_t reg; uint32_t val; } custom_init_regs[] = { + { RTL837X_REG_LED3_0_SET1, 0x00100000UL }, + { RTL837X_REG_LED1_0_SET1, 0x01400155UL }, + { RTL837X_REG_LED1_0_SET0, 0x01740141UL }, + { RTL837X_REG_LED_GLB_IO_EN, 0x7f24977fUL }, + { RTL837X_PIN_MUX_0, 0x20db6880UL }, +}; + +void machine_custom_init(void) __banked +{ + uint8_t i; + // REG_SET is a multi-statement macro without a do-while wrapper: braces required + for (i = 0; i < sizeof(custom_init_regs) / sizeof(custom_init_regs[0]); i++) { + REG_SET(custom_init_regs[i].reg, custom_init_regs[i].val); + } +} diff --git a/machine/PCB_SWTG024AS_A_2_0_1.c b/machine/PCB_SWTG024AS_A_2_0_1.c index 169e479a..0d20de50 100644 --- a/machine/PCB_SWTG024AS_A_2_0_1.c +++ b/machine/PCB_SWTG024AS_A_2_0_1.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/PCB_SWTG024AS_A_2_0_1.h b/machine/PCB_SWTG024AS_A_2_0_1.h index 2d3b5c22..6785140a 100644 --- a/machine/PCB_SWTG024AS_A_2_0_1.h +++ b/machine/PCB_SWTG024AS_A_2_0_1.h @@ -2,5 +2,6 @@ #define _MACHINE_PCB_SWTG024AS_A_2_0_1_H_ #define MACHINE_MODEL "PCB-SWTG024AS-A-2.0.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/PCB_SWTG024AS_A_2_0_1_init.c b/machine/PCB_SWTG024AS_A_2_0_1_init.c new file mode 100644 index 00000000..311bda3e --- /dev/null +++ b/machine/PCB_SWTG024AS_A_2_0_1_init.c @@ -0,0 +1,9 @@ +#include "machine_init_defs.h" + +void machine_custom_init(void) __banked +{ + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6); + reg_bit_set(RTL837X_REG_LED_MODE, 17); + reg_bit_clear(RTL837X_REG_LED_MODE, 9); + reg_bit_clear(RTL837X_REG_LED_MODE, 7); +} diff --git a/machine/POE_2G080110GS.c b/machine/POE_2G080110GS.c index 73f6dc8c..acd4129f 100644 --- a/machine/POE_2G080110GS.c +++ b/machine/POE_2G080110GS.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/POE_2G080110GS.h b/machine/POE_2G080110GS.h index 40ce3415..3fafc0d5 100644 --- a/machine/POE_2G080110GS.h +++ b/machine/POE_2G080110GS.h @@ -2,5 +2,6 @@ #define _MACHINE_POE_2G080110GS_H_ #define MACHINE_MODEL "MokerLink POE-2G080110GS" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/SIRIVISION_S25G2206FP_V1_1.c b/machine/SIRIVISION_S25G2206FP_V1_1.c index fde745b5..3f0db022 100644 --- a/machine/SIRIVISION_S25G2206FP_V1_1.c +++ b/machine/SIRIVISION_S25G2206FP_V1_1.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/SIRIVISION_S25G2206FP_V1_1.h b/machine/SIRIVISION_S25G2206FP_V1_1.h index 6dbb7c71..7bb5c9a2 100644 --- a/machine/SIRIVISION_S25G2206FP_V1_1.h +++ b/machine/SIRIVISION_S25G2206FP_V1_1.h @@ -2,5 +2,6 @@ #define _MACHINE_SIRIVISION_S25G2206FP_V1_1_H_ #define MACHINE_MODEL "SIRIVISION S25G2206FP V1.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/SKS3200_8E1X.h b/machine/SKS3200_8E1X.h index e644baf4..ca1e7846 100644 --- a/machine/SKS3200_8E1X.h +++ b/machine/SKS3200_8E1X.h @@ -2,6 +2,7 @@ #define _MACHINE_SKS3200_8E1X_H_ #define MACHINE_MODEL "XikeStor SKS3200-8E1X" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/STEAMEMO_IG204_V1.c b/machine/STEAMEMO_IG204_V1.c index 23d876a7..a7d765e3 100644 --- a/machine/STEAMEMO_IG204_V1.c +++ b/machine/STEAMEMO_IG204_V1.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/STEAMEMO_IG204_V1.h b/machine/STEAMEMO_IG204_V1.h index 170840d7..752493d2 100644 --- a/machine/STEAMEMO_IG204_V1.h +++ b/machine/STEAMEMO_IG204_V1.h @@ -2,5 +2,6 @@ #define _MACHINE_STEAMEMO_IG204_V1_H_ #define MACHINE_MODEL "Steamemo IG204 V1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/SWGT024_V2_0_MANAGED.c b/machine/SWGT024_V2_0_MANAGED.c index ad52bc5b..b3997fd3 100644 --- a/machine/SWGT024_V2_0_MANAGED.c +++ b/machine/SWGT024_V2_0_MANAGED.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/SWGT024_V2_0_MANAGED.h b/machine/SWGT024_V2_0_MANAGED.h index c5f95a04..4ee99e67 100644 --- a/machine/SWGT024_V2_0_MANAGED.h +++ b/machine/SWGT024_V2_0_MANAGED.h @@ -2,5 +2,6 @@ #define _MACHINE_SWGT024_V2_0_MANAGED_H_ #define MACHINE_MODEL "SWGT024 V2.0 Managed" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/SWGT024_V2_0_UNMANAGED.c b/machine/SWGT024_V2_0_UNMANAGED.c index 9008bb4b..b07f6d8f 100644 --- a/machine/SWGT024_V2_0_UNMANAGED.c +++ b/machine/SWGT024_V2_0_UNMANAGED.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/SWGT024_V2_0_UNMANAGED.h b/machine/SWGT024_V2_0_UNMANAGED.h index 8391b42a..cf286b04 100644 --- a/machine/SWGT024_V2_0_UNMANAGED.h +++ b/machine/SWGT024_V2_0_UNMANAGED.h @@ -2,5 +2,6 @@ #define _MACHINE_SWGT024_V2_0_UNMANAGED_H_ #define MACHINE_MODEL "SWGT024 V2.0 Unmanaged" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/SWTG018AS_A_V_2_0.c b/machine/SWTG018AS_A_V_2_0.c index 8304bf7e..7d749fde 100644 --- a/machine/SWTG018AS_A_V_2_0.c +++ b/machine/SWTG018AS_A_V_2_0.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/SWTG018AS_A_V_2_0.h b/machine/SWTG018AS_A_V_2_0.h index 82b7f632..60c499ec 100644 --- a/machine/SWTG018AS_A_V_2_0.h +++ b/machine/SWTG018AS_A_V_2_0.h @@ -2,5 +2,6 @@ #define _MACHINE_SWTG018AS_A_V_2_0_H_ #define MACHINE_MODEL "SWTG018AS-A V2.0" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/SWTG024AS_A_2_0_1_5C_1SFP.c b/machine/SWTG024AS_A_2_0_1_5C_1SFP.c index 2a3ad97b..de37693e 100644 --- a/machine/SWTG024AS_A_2_0_1_5C_1SFP.c +++ b/machine/SWTG024AS_A_2_0_1_5C_1SFP.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/SWTG024AS_A_2_0_1_5C_1SFP.h b/machine/SWTG024AS_A_2_0_1_5C_1SFP.h index f492765f..6345a9ce 100644 --- a/machine/SWTG024AS_A_2_0_1_5C_1SFP.h +++ b/machine/SWTG024AS_A_2_0_1_5C_1SFP.h @@ -2,5 +2,6 @@ #define _MACHINE_SWTG024AS_A_2_0_1_5C_1SFP_H_ #define MACHINE_MODEL "SWTG024AS-A-V2.0.1-5C-1SFP" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/SWTG024AS_A_2_0_1_5C_1SFP_init.c b/machine/SWTG024AS_A_2_0_1_5C_1SFP_init.c new file mode 120000 index 00000000..6297e789 --- /dev/null +++ b/machine/SWTG024AS_A_2_0_1_5C_1SFP_init.c @@ -0,0 +1 @@ +SWTG024AS_V2_0_init.c \ No newline at end of file diff --git a/machine/SWTG024AS_V2_0.c b/machine/SWTG024AS_V2_0.c index eb0652e2..b1902329 100644 --- a/machine/SWTG024AS_V2_0.c +++ b/machine/SWTG024AS_V2_0.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/SWTG024AS_V2_0.h b/machine/SWTG024AS_V2_0.h index bd37eece..53287e84 100644 --- a/machine/SWTG024AS_V2_0.h +++ b/machine/SWTG024AS_V2_0.h @@ -2,5 +2,6 @@ #define _MACHINE_SWTG024AS_V2_0_H_ #define MACHINE_MODEL "SWTG024AS-V2.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/SWTG024AS_V2_0_init.c b/machine/SWTG024AS_V2_0_init.c new file mode 100644 index 00000000..98d2f0c6 --- /dev/null +++ b/machine/SWTG024AS_V2_0_init.c @@ -0,0 +1,20 @@ +#include "machine_init_defs.h" + +void machine_custom_init(void) __banked +{ + uint16_t pval; + + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6); + reg_bit_set(RTL837X_REG_LED_MODE, 17); + reg_bit_clear(RTL837X_REG_LED_MODE, 9); + reg_bit_clear(RTL837X_REG_LED_MODE, 7); + + // OEM firmware sets these companion SDS0 polarity bits for the RTL8221B. + sds_read(0, 0, 0); + pval = SFR_DATA_U16; + sds_write_v(0, 0, 0, pval | 0x100); + + sds_read(0, 6, 2); + pval = SFR_DATA_U16; + sds_write_v(0, 6, 2, pval | 0x4000); +} diff --git a/machine/SWTGW218AS.c b/machine/SWTGW218AS.c index cbb2a2f0..0d9d3f6e 100644 --- a/machine/SWTGW218AS.c +++ b/machine/SWTGW218AS.c @@ -2,11 +2,8 @@ __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, + MACHINE_COMMON_SETTING, .mac_flash_offset = 0x1FC000, - .min_port = 0, - .max_port = 8, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/SWTGW218AS.h b/machine/SWTGW218AS.h index ed9c9e54..33812670 100644 --- a/machine/SWTGW218AS.h +++ b/machine/SWTGW218AS.h @@ -2,5 +2,6 @@ #define _MACHINE_SWTGW218AS_H_ #define MACHINE_MODEL "SWTGW218AS 8+1 Managed Switch" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/TRENDNET_TEG_S562.c b/machine/TRENDNET_TEG_S562.c index 3cfc12c5..a37bc84a 100644 --- a/machine/TRENDNET_TEG_S562.c +++ b/machine/TRENDNET_TEG_S562.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/TRENDNET_TEG_S562.h b/machine/TRENDNET_TEG_S562.h index c08ae7a9..724369ea 100644 --- a/machine/TRENDNET_TEG_S562.h +++ b/machine/TRENDNET_TEG_S562.h @@ -2,5 +2,6 @@ #define _MACHINE_TRENDNET_TEG_S562_H_ #define MACHINE_MODEL "Trendnet TEG-S562" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/YS25_0402M.h b/machine/YS25_0402M.h index 1df79241..67550200 100644 --- a/machine/YS25_0402M.h +++ b/machine/YS25_0402M.h @@ -2,5 +2,6 @@ #define _MACHINE_YS25_0402M_H_ #define MACHINE_MODEL "YuanLey YS25-0402M" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/ZX310S_4T2XH.c b/machine/ZX310S_4T2XH.c index f5313e02..583263e4 100644 --- a/machine/ZX310S_4T2XH.c +++ b/machine/ZX310S_4T2XH.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .n_10g = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, diff --git a/machine/ZX310S_4T2XH.h b/machine/ZX310S_4T2XH.h index f0873be3..1f51c9dd 100644 --- a/machine/ZX310S_4T2XH.h +++ b/machine/ZX310S_4T2XH.h @@ -2,5 +2,6 @@ #define _MACHINE_ZX310S_4T2XH_H_ #define MACHINE_MODEL "ZX310S-4T2XH" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/ZX310S_4T2XT.c b/machine/ZX310S_4T2XT.c index c7ec95b9..825cf810 100644 --- a/machine/ZX310S_4T2XT.c +++ b/machine/ZX310S_4T2XT.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 0, .n_10g = 2, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, diff --git a/machine/ZX310S_4T2XT.h b/machine/ZX310S_4T2XT.h index 15b76217..8903d9f6 100644 --- a/machine/ZX310S_4T2XT.h +++ b/machine/ZX310S_4T2XT.h @@ -2,5 +2,6 @@ #define _MACHINE_ZX310S_4T2XT_H_ #define MACHINE_MODEL "ZX310S_4T2XT" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/ZX310S_4T2XT_init.c b/machine/ZX310S_4T2XT_init.c new file mode 100644 index 00000000..38a96e25 --- /dev/null +++ b/machine/ZX310S_4T2XT_init.c @@ -0,0 +1,8 @@ +#include "machine_init_defs.h" + +void machine_custom_init(void) __banked +{ + // For this device, the reset value of RTL837X_PIN_MUX_0 is 0x30000000, + // which would disables all LEDS, enable them manually: + REG_SET(RTL837X_PIN_MUX_0, 0x30db68bf); +} diff --git a/machine/default_machine.h b/machine/default_machine.h index 0919674f..56233fee 100644 --- a/machine/default_machine.h +++ b/machine/default_machine.h @@ -11,7 +11,11 @@ * MACHINE_MODEL is deliberately not defined here: a build that reaches this * header must not silently pick up some default model string. Any code that * needs MACHINE_MODEL therefore fails to compile unless a real machine is - * selected. + * selected. MACHINE_CHIPSET has to be present because machine.h requires it; + * the tests supply their own `machine` object, so the chipset-derived port + * defaults below it are unused. */ +#define MACHINE_CHIPSET RTL8373 + #endif diff --git a/machine/default_machine_init.c b/machine/default_machine_init.c new file mode 100644 index 00000000..1ee200f5 --- /dev/null +++ b/machine/default_machine_init.c @@ -0,0 +1,6 @@ +/* + * Fallback boot hook for boards without a machine/_init.c. + */ +#include "machine_init_defs.h" + +void machine_custom_init(void) __banked { } diff --git a/machine/machine_defs.h b/machine/machine_defs.h index 94b989c4..be77636d 100644 --- a/machine/machine_defs.h +++ b/machine/machine_defs.h @@ -41,4 +41,8 @@ (scl_pin) == GPIO50_I2C_SCL2_UART1_TX ? 2 : \ (scl_pin) == GPIO40_I2C_SCL3_MDC1 ? 3 : I2CBUS_INVALID) +#define MACHINE_COMMON_SETTING \ + .machine_name = MACHINE_MODEL, \ + .isRTL8373 = MACHINE_CHIPSET == RTL8373 + #endif diff --git a/machine/machine_init_defs.h b/machine/machine_init_defs.h new file mode 100644 index 00000000..b3507d25 --- /dev/null +++ b/machine/machine_init_defs.h @@ -0,0 +1,10 @@ +#ifndef _MACHINE_INIT_DEFS_H_ +#define _MACHINE_INIT_DEFS_H_ + + +#include "machine_defs.h" + +#pragma codeseg BANK2 +#pragma constseg BANK2 + +#endif diff --git a/machine_init.c b/machine_init.c deleted file mode 100644 index efb16e61..00000000 --- a/machine_init.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Per-machine one-shot boot hooks, hosted in BANK2 so board-specific - * tables and code do not consume the common bank. - */ -#include -#include "machine.h" -#include "rtl837x_pins.h" -#include "rtl837x_leds.h" -#include "rtl837x_sfr.h" -#include "rtl837x_regs.h" -#include "rtl837x_common.h" - -#pragma codeseg BANK2 -#pragma constseg BANK2 - -#if defined(MACHINE_KP_9000_6XH_X2) || \ - defined(MACHINE_KP_9000_6XH_X2_V2_1) || \ - defined(MACHINE_KP_9000_6XHML_X2_V2_1) || \ - defined(MACHINE_HI_K0402WS) || \ - defined(MACHINE_PCB_K0402WS_V2) || \ - defined(MACHINE_PCB_K0402WS_V3) || \ - defined(MACHINE_2G5F4_10G2_V1_01) || \ - defined(MACHINE_FNS1200P) -void machine_custom_init(void) __banked -{ - reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6); -} - -#elif defined MACHINE_PCB_SWTG018AS_V2_1_0 -// Stock-firmware values for what the LED-set encoding cannot express: the -// bi-color SFP LED (blue pin at 10G) and the PIN_MUX_0 routing of that pin -// to the LED controller. Runs after leds_setup(), which covers the rest. -static __code const struct { uint16_t reg; uint32_t val; } custom_init_regs[] = { - { RTL837X_REG_LED3_0_SET1, 0x00100000UL }, - { RTL837X_REG_LED1_0_SET1, 0x01400155UL }, - { RTL837X_REG_LED1_0_SET0, 0x01740141UL }, - { RTL837X_REG_LED_GLB_IO_EN, 0x7f24977fUL }, - { RTL837X_PIN_MUX_0, 0x20db6880UL }, -}; - -void machine_custom_init(void) __banked -{ - uint8_t i; - // REG_SET is a multi-statement macro without a do-while wrapper: braces required - for (i = 0; i < sizeof(custom_init_regs) / sizeof(custom_init_regs[0]); i++) { - REG_SET(custom_init_regs[i].reg, custom_init_regs[i].val); - } -} - -#elif defined MACHINE_PCB_SWTG024AS_A_2_0_1 -void machine_custom_init(void) __banked -{ - reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6); - reg_bit_set(RTL837X_REG_LED_MODE, 17); - reg_bit_clear(RTL837X_REG_LED_MODE, 9); - reg_bit_clear(RTL837X_REG_LED_MODE, 7); -} - -#elif defined(MACHINE_SWTG024AS_A_2_0_1_5C_1SFP) || \ - defined(MACHINE_SWTG024AS_V2_0) -void machine_custom_init(void) __banked -{ - uint16_t pval; - - reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6); - reg_bit_set(RTL837X_REG_LED_MODE, 17); - reg_bit_clear(RTL837X_REG_LED_MODE, 9); - reg_bit_clear(RTL837X_REG_LED_MODE, 7); - - // OEM firmware sets these companion SDS0 polarity bits for the RTL8221B. - sds_read(0, 0, 0); - pval = SFR_DATA_U16; - sds_write_v(0, 0, 0, pval | 0x100); - - sds_read(0, 6, 2); - pval = SFR_DATA_U16; - sds_write_v(0, 6, 2, pval | 0x4000); -} - -#elif defined MACHINE_ZX310S_4T2XT -void machine_custom_init(void) __banked -{ - // For this device, the reset value of RTL837X_PIN_MUX_0 is 0x30000000, - // which would disables all LEDS, enable them manually: - REG_SET(RTL837X_PIN_MUX_0, 0x30db68bf); -} - -#elif defined MACHINE_FG_4GT_2SX_V2_0 -void machine_custom_init(void) __banked -{ - REG_SET(RTL837X_REG_LED_GLB_IO_EN, 0x7624155b); -} - -#else -void machine_custom_init(void) __banked { } -#endif diff --git a/rtl837x_common.h b/rtl837x_common.h index 4d4047f9..ae7a1b29 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -154,6 +154,7 @@ void print_long(uint32_t a); void print_short(uint16_t a); void print_byte(uint8_t a); void itoa(uint8_t v); +void itoa_no_syslog(uint8_t v); void itoa_short(uint16_t v); void print_sfr_data(void); void print_phy_data(void); diff --git a/rtl837x_igmp.c b/rtl837x_igmp.c index 35940446..f996cd3f 100644 --- a/rtl837x_igmp.c +++ b/rtl837x_igmp.c @@ -126,7 +126,7 @@ void igmp_setup(void) __banked * For now the IGMP protocols are flooded (01), MLD which MAC-based is handled by ASIC * All messages are allowed and maximum MC group is 0xff */ - for (i = machine.min_port; i <= machine.max_port; i++) + for (i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), IGMP_MAX_GROUP | IGMP_PROTOCOL_ENABLE | IGMP_FLOOD); /* // Allow all physical ports to be dynamic router ports @@ -155,7 +155,7 @@ void igmp_enable(void) __banked // Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping, // bits 16-24 configure max MC group used by that port. Trap to CPU (10) - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), IGMP_MAX_GROUP | IGMP_PROTOCOL_ENABLE | IGMP_TRAP); } } @@ -180,7 +180,7 @@ void igmp_router_port_set(uint16_t pmask) __banked void igmp_show(void) __banked { print_string("igmp_show called\n"); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { write_char('0' + i); write_char(':'); reg_read_m(RTL837X_IGMP_PORT_CFG + (i << 2)); print_sfr_data(); diff --git a/rtl837x_init.c b/rtl837x_init.c index c7b7e71e..cc2adfcd 100644 --- a/rtl837x_init.c +++ b/rtl837x_init.c @@ -221,9 +221,11 @@ void rtl8372_init(void) __banked } else if(machine.n_10g == 2) { REG_SET(RTL837X_REG_SDS_MODES, 0x1ad); // Both 10g ports use SDS_QXGMII } else { + // Replace the reset value 0xbff (both SDS off) instead of ORing into it: + // RTL837X_REG_SEC_COUNTER only holds a written value while SDS 0 is on reg_read_m(RTL837X_REG_SDS_MODES); - sfr_mask_data(1, 0, 0x03); - sfr_mask_data(0, 0, 0xe2); + sfr_mask_data(1, 0xff, 0x03); + sfr_mask_data(0, 0xff, 0xe2); reg_write_m(RTL837X_REG_SDS_MODES); } @@ -246,7 +248,7 @@ void rtl8372_init(void) __banked // [...] /// uint16_t reg = 0x1238 + 0x300; // Port base register for the bits we set - for (char i = machine.min_port; i <= machine.max_port; i++) { + for (char i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { // Bit 7 (0x40) enables replacement of the RTL-VLAN tag with an 802.1Q VLAN tag REG_SET(reg, 0xe77); reg += 0x100; diff --git a/rtl837x_lacp.c b/rtl837x_lacp.c index 2573bc34..c8d6b1d6 100644 --- a/rtl837x_lacp.c +++ b/rtl837x_lacp.c @@ -165,7 +165,7 @@ void lacp_mux_update(void) __banked if (!lacp_lag_ports[lag]) continue; lacp_scratch_mask = 0; - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { if (lacp_port_lag[i] != lag) continue; if ((lacp_actor_state[i] & LACP_STATE_FULL) == LACP_STATE_FULL @@ -248,7 +248,7 @@ void lacp_in(void) __banked return; port = ((uint8_t)HTONS(LACP_H->rtl_tag.pmask)) & 0x0f; - if (port < machine.min_port || port > machine.max_port) + if (!MACHINE_PORT_VALID(port)) return; lag = lacp_port_lag[port]; @@ -298,7 +298,7 @@ void lacp_in(void) __banked static void lacp_step(void) { - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { if (lacp_port_lag[i] == LACP_LAG_NONE) continue; @@ -328,7 +328,7 @@ static void lacp_step(void) if (!lacp_agg_valid[lag]) continue; - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { if (lacp_port_lag[i] == lag && lacp_rx_state[i] == LACP_RX_CURRENT && lacp_sys_eq(lacp_partner_sys[i], lacp_agg_sys[lag])) { any_current = 1; @@ -422,7 +422,7 @@ void lacp_lag_set(uint8_t lag, __xdata uint16_t ports) __banked return; lacp_scratch_flag = lacp_any_lag(); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { if (lacp_port_lag[i] == lag && !(ports & PORT_BIT(i))) { lacp_port_lag[i] = LACP_LAG_NONE; lacp_port_release(i); @@ -438,7 +438,7 @@ void lacp_lag_set(uint8_t lag, __xdata uint16_t ports) __banked if (ports && !lacp_scratch_flag) lacp_engine_on(); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { if (!(ports & PORT_BIT(i))) continue; lacp_scratch_lag = lacp_port_lag[i]; @@ -490,7 +490,7 @@ void lacp_show(void) __banked print_string(" members "); print_short(lacp_members_last[l]); write_char('\n'); } - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { print_string("port "); print_byte(machine.log_to_phys_port[i]); print_string(" actor "); print_byte(lacp_actor_state[i]); print_string(" partner "); print_byte(lacp_partner_state[i]); diff --git a/rtl837x_leds.c b/rtl837x_leds.c index d1b8cf91..5757060c 100644 --- a/rtl837x_leds.c +++ b/rtl837x_leds.c @@ -37,10 +37,10 @@ void leds_setup(void) __banked // Set up all Port-LEDs to belong to RLDP sfr_data[3] = sfr_data[2] = sfr_data[1] = sfr_data[0] = 0; - for (uint8_t i = machine.min_port; i <= (machine.max_port > 7 ? 7 : machine.max_port); i++) + for (uint8_t i = MACHINE_MIN_PORT; i <= (MACHINE_MAX_PORT > 7 ? 7 : MACHINE_MAX_PORT); i++) sfr_data[3 - (i >> 2)] |= i & 1 ? 0xf0 : 0x0f; reg_write_m(RTL837X_REG_LED_RLDP_2); - if (machine.max_port == 8) + if (MACHINE_MAX_PORT == 8) REG_SET(RTL837X_REG_LED_RLDP_3, 0x0000000f); // Port 8 // Configure high LEDs 27-29: mux and LED enable @@ -110,7 +110,7 @@ void leds_setup(void) __banked // Configure the LED-set of a port sfr_data[3] = sfr_data[2] = sfr_data[1] = sfr_data[0] = 0; - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) sfr_data[3 - (i >> 2)] |= machine.port_led_set[i] << ((i & 3) << 1); reg_write_m(RTL837X_LED_PORT_SET_SEL); diff --git a/rtl837x_leds_dump.c b/rtl837x_leds_dump.c index 8a820e3a..5bf04d0f 100644 --- a/rtl837x_leds_dump.c +++ b/rtl837x_leds_dump.c @@ -87,7 +87,7 @@ void leds_dump(void) __banked } write_char('\n'); } - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { reg_read_m(RTL837X_LED_PORT_SET_SEL); __xdata uint8_t set = sfr_data[3 - (i >> 2)]; set = (set >> ((i & 3) << 1)); diff --git a/rtl837x_lldp.c b/rtl837x_lldp.c index 84208433..441e7eb4 100644 --- a/rtl837x_lldp.c +++ b/rtl837x_lldp.c @@ -108,7 +108,7 @@ void lldp_send(void) __banked __reentrant */ uip_len = MAC_ADDR_LEN + MAC_ADDR_LEN + sizeof(struct rtl_tag) + LLDP_ETHERTYPE_LENGTH + (p - LLDP_O->payload); - for (uint8_t port = machine.min_port; port <= machine.max_port; port++) { + for (uint8_t port = MACHINE_MIN_PORT; port <= MACHINE_MAX_PORT; port++) { if ((1 << port) & lldp_logical_port_status) { LLDP_O->payload[port_position] = '0' + machine.log_to_phys_port[port]; diff --git a/rtl837x_port.c b/rtl837x_port.c index 1c44d0b5..41b7e984 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -271,7 +271,7 @@ void vlan_setup(void) __banked wait_table_ready(); // Set PVID 1 for every port. TODO: Skip unused ports! - for (uint8_t i = machine.min_port; i <= CPU_PORT; i++) { // CPU MAC is independent of the last user port + for (uint8_t i = MACHINE_MIN_PORT; i <= CPU_PORT; i++) { // CPU MAC is independent of the last user port uint16_t reg = RTL837x_PVID_BASE_REG + ((i >> 1) << 2); #ifdef DEBUG print_byte(i); write_char(':'); write_char(' '); print_short(reg); write_char('='); @@ -459,7 +459,7 @@ void port_l2_setup(void) __banked port_l2_forget(); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { // Limit the number of automatically learned MAC-Entries per port to 0x1040 uint8_t idx = (i << 2); REG_SET(RTL837X_L2_LRN_PORT_CONSTRAINT + idx, 0x00001040); @@ -511,7 +511,7 @@ void port_media_show(uint8_t port) __banked void port_stats_print(void) __banked { print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\t\tMACs\n"); - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { print_phys_port(i); write_char('\t'); if (!machine.is_sfp[i]) { @@ -594,14 +594,14 @@ void port_stats_print(void) __banked void port_isolate(uint8_t port, __xdata uint16_t pmask) __banked { - if (port <= machine.max_port) + if (port <= MACHINE_MAX_PORT) REG_SET(RTL837X_PORT_ISOLATION_BASE + (port << 2), pmask); } uint16_t port_isolation_get(uint8_t port) __banked { - if (port > machine.max_port) + if (port > MACHINE_MAX_PORT) return 0; reg_read_m(RTL837X_PORT_ISOLATION_BASE + (port << 2)); @@ -775,7 +775,7 @@ void port_eee_status(uint8_t port) __banked void port_eee_enable_all(__xdata uint8_t speed) __banked { - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { if (i == 3 && machine.n_10g) { port_eee_enable(i, speed); } else if (i == 8 && machine.n_10g == 2) { @@ -792,7 +792,7 @@ void port_eee_enable_all(__xdata uint8_t speed) __banked void port_eee_disable_all(void) __banked { - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { port_eee_disable(i); } } @@ -800,7 +800,7 @@ void port_eee_disable_all(void) __banked void port_eee_status_all(void) __banked { - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { port_eee_status(i); } } @@ -908,7 +908,7 @@ void vlan_dump(void) __banked { print_string("Ingress VLAN configuration:\n"); print_string("Port\tPVID\tType\tFiltering\n"); - for (uint8_t port = machine.min_port; port <= machine.max_port; port++) { + for (uint8_t port = MACHINE_MIN_PORT; port <= MACHINE_MAX_PORT; port++) { print_vlan_ingress_port(port); } print_vlan_ingress_port(9); @@ -923,7 +923,7 @@ void vlan_dump(void) __banked /** Set the ingress VLAN filtering */ bool port_ingress_vlan_filter_set(uint8_t port, __xdata bool enabled) __banked { - if (port < machine.min_port || (port > machine.max_port && port != CPU_PORT)) { + if (!MACHINE_PORT_VALID(port) && port != CPU_PORT) { return false; } if (enabled) @@ -937,7 +937,7 @@ bool port_ingress_vlan_filter_set(uint8_t port, __xdata bool enabled) __banked /** Get the ingress VLAN filtering status */ bool port_ingress_vlan_filter_get(uint8_t port) __banked { - if (port < machine.min_port || (port > machine.max_port && port != CPU_PORT)) { + if (!MACHINE_PORT_VALID(port) && port != CPU_PORT) { return false; } diff --git a/rtl837x_storm.c b/rtl837x_storm.c index 2308b210..23cfc83a 100644 --- a/rtl837x_storm.c +++ b/rtl837x_storm.c @@ -67,7 +67,7 @@ void storm_show(void) __banked { uint8_t i, t, idx; - for (i = machine.min_port; i <= machine.max_port; i++) { + for (i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) { print_string("port "); write_char('0' + machine.log_to_phys_port[i]); for (t = 0; t < STORM_TYPES; t++) { diff --git a/rtl837x_stp.c b/rtl837x_stp.c index bc810d96..118e265c 100644 --- a/rtl837x_stp.c +++ b/rtl837x_stp.c @@ -335,7 +335,7 @@ static uint8_t stp_ent_active(uint8_t e) __reentrant return 0; if (e >= STP_LAG_BASE) return stp_lag_mask[e - STP_LAG_BASE] != 0; - return e >= machine.min_port && e <= machine.max_port && stp_ent_of[e] == e; + return MACHINE_PORT_VALID(e) && stp_ent_of[e] == e; } @@ -410,7 +410,7 @@ static void stp_topology_change(uint8_t port) __reentrant stp_tc_count++; stp_tc_while = ((uint16_t)stp_maxage_s + stp_fwddelay_s) * STP_HZ; if (port >= STP_LAG_BASE) { - for (uint8_t i = machine.min_port; i <= machine.max_port; i++) + for (uint8_t i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) if (stp_ent_has(port, i)) port_l2_forget_port(i); } else { @@ -565,7 +565,7 @@ void stp_in(void) __banked /* Ingress port: low nibble of the CPU tag's pmask on RX */ stp_scratch = ((uint8_t)HTONS(STP_H->rtl_tag.pmask)) & 0x0f; - if (stp_scratch < machine.min_port || stp_scratch > machine.max_port) + if (!MACHINE_PORT_VALID(stp_scratch)) return; port = stp_ent_of[stp_scratch]; @@ -658,7 +658,7 @@ void stp_in(void) __banked if (!stp_tc_while) { uint8_t i; stp_tc_count++; - for (i = machine.min_port; i <= machine.max_port; i++) + for (i = MACHINE_MIN_PORT; i <= MACHINE_MAX_PORT; i++) if (!stp_ent_has(port, i) && (stp_pflags[stp_ent_of[i]] & STP_PF_ENABLED) && !(stp_pflags[stp_ent_of[i]] & STP_PF_OPEREDGE)) @@ -714,7 +714,7 @@ void stp_timers(void) __banked if (stp_map_dirty) { stp_map_dirty = 0; for (stp_i = 0; stp_i < STP_LAG_BASE; stp_i++) { - if (stp_i < machine.min_port || stp_i > machine.max_port) + if (!MACHINE_PORT_VALID(stp_i)) continue; if (stp_ent_of[stp_i] != stp_i) { stp_loop_held[stp_i] = 0; @@ -747,14 +747,14 @@ void stp_timers(void) __banked { __xdata static uint16_t eff; eff = 0; - for (stp_i = machine.min_port; stp_i <= machine.max_port; stp_i++) + for (stp_i = MACHINE_MIN_PORT; stp_i <= MACHINE_MAX_PORT; stp_i++) if ((stp_link_now >> stp_i) & 1) eff |= (uint16_t)1 << stp_ent_of[stp_i]; stp_link_now = eff; } if (stp_link_now != stp_link_prev) { for (stp_i = 0; stp_i < STP_ENTITIES; stp_i++) { - if (stp_i < STP_PORTS && (stp_i < machine.min_port || stp_i > machine.max_port)) + if (stp_i < STP_PORTS && !MACHINE_PORT_VALID(stp_i)) continue; if (stp_i < STP_PORTS && stp_ent_of[stp_i] != stp_i) continue; @@ -890,7 +890,7 @@ static void stp_fdb_update(__xdata uint16_t pmask) continue; port_l2mc_set(0x00, stp_fdb_vid, pmask); } - for (stp_fdb_i = machine.min_port; stp_fdb_i <= machine.max_port; stp_fdb_i++) { + for (stp_fdb_i = MACHINE_MIN_PORT; stp_fdb_i <= MACHINE_MAX_PORT; stp_fdb_i++) { stp_fdb_vid = port_pvid_get(stp_fdb_i); port_l2mc_set(0x00, stp_fdb_vid, pmask); } @@ -910,7 +910,7 @@ void stp_setup(void) __banked stp_tx_count[stp_i] = 0; port_timers[stp_i] = 0; port_hello[stp_i] = (uint16_t)stp_hello_s * STP_HZ; - if (stp_i < STP_PORTS && (stp_i < machine.min_port || stp_i > machine.max_port)) + if (stp_i < STP_PORTS && !MACHINE_PORT_VALID(stp_i)) continue; if (stp_i >= STP_LAG_BASE && !stp_lag_mask[stp_i - STP_LAG_BASE]) continue; @@ -939,7 +939,7 @@ void stp_setup(void) __banked reg_read_m(RTL837X_REG_LINKS_STS); stp_link_now = (uint16_t)sfr_data[1] | ((uint16_t)sfr_data[2] << 8); stp_link_prev = 0; - for (stp_i = machine.min_port; stp_i <= machine.max_port; stp_i++) + for (stp_i = MACHINE_MIN_PORT; stp_i <= MACHINE_MAX_PORT; stp_i++) if ((stp_link_now >> stp_i) & 1) stp_link_prev |= (uint16_t)1 << stp_ent_of[stp_i]; @@ -952,7 +952,7 @@ void stp_setup(void) __banked void stp_off(void) __banked { sfr_data[0] = sfr_data[1] = sfr_data[2] = sfr_data[3] = 0; - for (stp_i = machine.min_port; stp_i <= machine.max_port; stp_i++) { + for (stp_i = MACHINE_MIN_PORT; stp_i <= MACHINE_MAX_PORT; stp_i++) { // Set STP port state to forwarding // States are: 00 disable, 01 blocking, 10 learning, 11 forwarding sfr_data[3 - (stp_i >> 2)] |= (uint8_t)(STP_ST_FORWARDING << ((stp_i << 1) & 0x7)); diff --git a/rtlplayground.c b/rtlplayground.c index 0afa93c8..95681c49 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -305,6 +305,19 @@ void itoa(uint8_t v) } +void itoa_no_syslog(uint8_t v) +{ + uint8_t t = (v / 100); + uint8_t print_zeros = t; + if (print_zeros) + write_char_no_syslog('0' + t); + t = (v / 10) % 10; + print_zeros |= t; + if (print_zeros) + write_char_no_syslog('0' + t); + write_char_no_syslog('0' + (v % 10)); +} + /* Same as itoa(), one decade wider: enough for a port number. Kept separate * rather than widening itoa() itself, because every existing caller passes a * byte and would start paying for 16-bit divisions it does not need. */ @@ -1203,7 +1216,7 @@ static void handle_tick(void) lacp_timers(); health_phase(HEALTH_PH_STP); lldp_tick(); - health_phase(HEALTH_LLDP); + health_phase(HEALTH_PH_LLDP); cabletest_tick(); } diff --git a/sfp.c b/sfp.c index 05599717..57065289 100644 --- a/sfp.c +++ b/sfp.c @@ -59,8 +59,9 @@ static inline uint8_t sfp_rate_to_sds_config(uint8_t rate) return SDS_1000BX_FIBER; if (rate >= 0x19 && rate <= 0x20) // Ethernet 2.5 GBit return SDS_HSG; - if (rate >= 0x62 && rate < 0x70) + if (rate >= 0x62 /* && rate < 0x70 */) // Force higher rates to 10G (e.g., 25G, 50G) return SDS_10GR; + return 0xff; } diff --git a/test/Makefile b/test/Makefile index 6376ded9..6b145fb1 100644 --- a/test/Makefile +++ b/test/Makefile @@ -74,8 +74,8 @@ $(BUILDDIR)/test_httpd_tx: test_httpd_tx.c $(SRCROOT)/httpd/httpd.c $(SRCROOT)/u $(CC) $(CFLAGS) $(filter %.c,$^) -o $@ $(LDFLAGS) # CPU VLAN initialization with full and reduced user-port ranges. -$(BUILDDIR)/test_cpu_vlan_restricted: CFLAGS += -DRTLP_TEST_MAX_PORT=7 -$(BUILDDIR)/test_cpu_vlan_8372: CFLAGS += -DRTLP_TEST_MAX_PORT=7 -DRTLP_TEST_MIN_PORT=3 -DRTLP_TEST_IS8373=0 +$(BUILDDIR)/test_cpu_vlan_restricted: CFLAGS += -DMACHINE_MAX_PORT=7 +$(BUILDDIR)/test_cpu_vlan_8372: CFLAGS += -DMACHINE_MAX_PORT=7 -DMACHINE_MIN_PORT=3 -DRTLP_TEST_IS8373=0 $(BUILDDIR)/test_cpu_vlan_full $(BUILDDIR)/test_cpu_vlan_restricted $(BUILDDIR)/test_cpu_vlan_8372: test_cpu_vlan.c $(TABLE_ENV) | $(BUILDDIR) $(CC) $(CFLAGS) $(filter %.c,$^) -o $@ $(LDFLAGS) diff --git a/test/env_tables.c b/test/env_tables.c index d4a9895c..494499ff 100644 --- a/test/env_tables.c +++ b/test/env_tables.c @@ -57,19 +57,11 @@ const uint8_t hex_chars[] = "0123456789abcdef"; uint8_t *hex = (uint8_t *)hex_chars; /* ---- a 9-port RTL8373 whose logical ports map to themselves ---- */ -#ifndef RTLP_TEST_MAX_PORT -#define RTLP_TEST_MAX_PORT 8 -#endif -#ifndef RTLP_TEST_MIN_PORT -#define RTLP_TEST_MIN_PORT 0 -#endif #ifndef RTLP_TEST_IS8373 #define RTLP_TEST_IS8373 1 #endif const struct machine machine = { .machine_name = "HOSTTEST", - .min_port = RTLP_TEST_MIN_PORT, - .max_port = RTLP_TEST_MAX_PORT, .n_sfp = 0, .log_to_phys_port = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, .phys_to_log_port = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, diff --git a/test/test_cpu_vlan.c b/test/test_cpu_vlan.c index f1ca6d0b..4bb133db 100644 --- a/test/test_cpu_vlan.c +++ b/test/test_cpu_vlan.c @@ -12,13 +12,13 @@ int main(void) { hw_reg_set(RTL837X_VLAN_PORT_EGR_TAG,0xa50fffff); hw_reg_set(RTL837x_PVID_BASE_REG+16,0x5a123456); vlan_setup(); - uint32_t untouched=(1u<<(machine.min_port*2))-1; + uint32_t untouched=(1u<<(MACHINE_MIN_PORT*2))-1; CHECK(hw_reg_get(RTL837X_VLAN_PORT_EGR_TAG)==(0xa5000000|untouched),"CPU egress set, unrelated bits preserved"); CHECK(hw_reg_get(RTL837x_PVID_BASE_REG+16)==0x5a001001,"CPU PVID initialized explicitly"); - uint16_t active=((1u<<(machine.max_port+1))-1)&~((1u< sizeof(flash_written) - flash_written_len) { + flash_write_bad = 1; + return; + } + memcpy(flash_written + flash_written_len, ptr, flash_region.len); + flash_written_len += flash_region.len; +} const char *get_flash_size_str(void) { return "512 kB"; } void crc16_bank1(uint8_t *v) { (void)v; } -void reset_chip(void) { } +static unsigned reset_calls; +void reset_chip(void) { reset_calls++; } void delay(uint16_t t) { (void)t; } void write_char(char c) { (void)c; } void write_char_no_syslog(char c) { (void)c; } +void itoa_no_syslog(uint8_t v) { (void)v; } void print_string(const char *p) { (void)p; } +void print_string_no_syslog(const char *p) { (void)p; } void print_string_newline_no_syslog(const char *p) { (void)p; } void set_sys_led_state(uint8_t state) { (void)state; } void cmd_parser(void) { } @@ -156,6 +192,10 @@ void send_vlanlist(void) { } void send_lldp(void) {} extern uint8_t authenticated; +extern char session_id[]; +extern char passwd[21]; +extern uint16_t session_timeout; +extern uint32_t last_session_use; /* uip.c defines the listen table but no header declares it; the bench reads it * to confirm the port httpd_init() asked for is the one uIP is watching. */ @@ -362,6 +402,22 @@ static int first_body_mismatch(void) return -1; } +static int stream_contains(const char *needle) +{ + size_t n = strlen(needle); + + for (int i = 0; i + (int)n <= stream_len; i++) + if (!memcmp(stream + i, needle, n)) + return 1; + return 0; +} + +static void login_session_start(void) +{ + session_start(MSS_FULL); + strcpy(passwd, "1234"); +} + static void report(const char *tag) { if (verbose) @@ -493,6 +549,541 @@ static void scenario_bad_l4_checksum(void) "bad checksum control: the file that follows is intact"); } + +/* Private HTTP lifecycle values; drive the real callback, not a model. */ +enum { TSTATE_NONE = 0, TSTATE_TX = 1 }; +extern uint16_t slen, cont_len, sent_len, bindex, crc_final, write_len; +extern uint8_t boundary[], verify_crc, outbuf[]; +extern struct { uint8_t *p; uint16_t bptr, plen; } upload_settings; +extern uint8_t stream_upload(void); + +static void scenario_upload_reset_owner(void) +{ + uint8_t byte = 0; + uint8_t get[] = "GET " FILE_NAME " HTTP/1.1\r\nHost: sw\r\n\r\n"; + int initialized = 1; + + /* The firmware has one TCP slot. Its appstate can contain stale bytes. */ + uip_conn = &uip_conns[0]; + reset_calls = 0; + for (unsigned state = 0; state <= 0xff; state++) { + uip_conn->appstate.tstate = state; + uip_conn->appstate.fw_reset_pending = 0xaa; + uip_flags = UIP_CONNECTED; + httpd_appcall(); + if (uip_conn->appstate.tstate != TSTATE_NONE + || uip_conn->appstate.fw_reset_pending != 0) + initialized = 0; + } + CHECK(initialized, "connect initializes both fields for every stale state"); + CHECK(reset_calls == 0, "connection initialization does not reset"); + + /* End-of-part verdict with flash/CRC hardware edges mocked. */ + boundary[0] = 0; + bindex = 0; + verify_crc = 1; + crc_final = 0xb001; + write_len = 0; + upload_settings.p = &byte; + upload_settings.bptr = 0; + upload_settings.plen = 1; + stream_upload(); + CHECK(uip_conn->appstate.fw_reset_pending == 1, + "verified upload records reset intent in its slot"); + + uip_conn->appstate.tstate = TSTATE_TX; + uip_conn->mss = MSS_FULL; + slen = 10; + sent_len = 5; + cont_len = 0; + uip_flags = UIP_ACKDATA; + httpd_appcall(); + CHECK(reset_calls == 0 && slen == 5 && sent_len == 5, + "partial verdict ACK sends the remainder without resetting"); + uip_flags = UIP_ACKDATA; + httpd_appcall(); + CHECK(reset_calls == 1 && slen == 0, + "final verdict ACK resets after all response bytes are acknowledged"); + + /* No verdict ACK: a later connection reuses the same slot. */ + reset_calls = 0; + uip_conn->appstate.tstate = TSTATE_TX; + uip_conn->appstate.fw_reset_pending = 1; + uip_flags = UIP_CONNECTED; + httpd_appcall(); + CHECK(uip_conn->appstate.tstate == TSTATE_NONE + && uip_conn->appstate.fw_reset_pending == 0, + "slot reuse clears an unacknowledged upload's reset intent"); + uip_appdata = get; + uip_len = strlen((char *)get); + uip_flags = UIP_NEWDATA; + httpd_appcall(); + CHECK(uip_conn->appstate.tstate == TSTATE_TX && slen > 0, + "reused slot serves a subsequent plain GET"); + for (unsigned i = 0; i < 20 && uip_conn->appstate.tstate == TSTATE_TX; i++) { + uip_flags = UIP_ACKDATA; + httpd_appcall(); + } + CHECK(reset_calls == 0 && slen == 0 && cont_len == 0, + "subsequent GET response ACKs cannot inherit reset intent"); + + for (unsigned i = 0; i < 2; i++) { + uip_conn->appstate.tstate = TSTATE_TX; + uip_conn->appstate.fw_reset_pending = 1; + reset_calls = 0; + uip_flags = i ? UIP_TIMEDOUT : UIP_ABORT; + httpd_appcall(); + CHECK(reset_calls == 0, "abort/timeout does not reset"); + uip_flags = UIP_CONNECTED; + httpd_appcall(); + CHECK(uip_conn->appstate.tstate == TSTATE_NONE + && uip_conn->appstate.fw_reset_pending == 0, + "connect after abort/timeout clears old upload intent"); + uip_conn->appstate.tstate = TSTATE_TX; + slen = 0; + cont_len = 0; + sent_len = 0; + uip_flags = UIP_ACKDATA; + httpd_appcall(); + CHECK(reset_calls == 0, "new connection ACK cannot inherit reset"); + } + + crc_final = 0; + bindex = 0; + stream_upload(); + CHECK(uip_conn->appstate.fw_reset_pending == 0, + "failed CRC does not request reset"); + CHECK(strstr((char *)outbuf, "HTTP/1.1 400 Bad Request") != NULL, + "failed CRC returns an error verdict"); + uip_conn->appstate.tstate = TSTATE_TX; + sent_len = slen; + cont_len = 0; + uip_flags = UIP_ACKDATA; + httpd_appcall(); + CHECK(reset_calls == 0, "failed CRC verdict ACK does not reset"); + +} + +static void scenario_fragmented_post_header(void) +{ + static const char first[] = + "POST /login HTTP/1.1\r\n" + "Host: sw\r\n" + "Content-Len"; + static const char second[] = + "gth: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "\r\n" + "pwd=1234"; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "fragmented header: incomplete first fragment has no response"); + + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("HTTP/1.1 302 Found\r\n"), + "fragmented header: split Content-Length is accepted"); + CHECK(stream_contains("Location: index.html\r\n"), + "fragmented header: login body is parsed after reassembly"); +} + +static void scenario_split_content_type(void) +{ + static const char first[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Ty"; + static const char second[] = + "pe: application/x-www-form-urlencoded\r\n" + "\r\n" + "pwd=1234"; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "split Content-Type: incomplete header has no response"); + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("Location: index.html\r\n"), + "split Content-Type: field name can span receive events"); +} + +static void scenario_split_header_terminator(void) +{ + static const char first[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "\r"; + static const char second[] = "\npwd=1234"; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "split terminator: CRLFCR fragment has no premature response"); + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("Location: index.html\r\n"), + "split terminator: CRLFCRLF can span receive events"); +} + +static void scenario_header_then_body(void) +{ + static const char header[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "\r\n"; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, header, (int)strlen(header)); + CHECK(stream_len == 0, + "header-only segment: waits for the declared body"); + client_send(TCP_ACK | TCP_PSH, "pwd=1234", 8); + CHECK(stream_contains("Location: index.html\r\n"), + "header-only segment: following body completes login"); +} + +static void scenario_header_with_partial_body(void) +{ + static const char first[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "\r\n" + "pwd="; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "partial body: waits when final header segment has only part of body"); + client_send(TCP_ACK | TCP_PSH, "1234", 4); + CHECK(stream_contains("Location: index.html\r\n"), + "partial body: existing body reassembly takes over correctly"); +} + +static void scenario_post_header_timeout(void) +{ + static const char partial[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"; + + login_session_start(); + ticks = 0; + client_send(TCP_ACK | TCP_PSH, partial, (int)strlen(partial)); + CHECK(stream_len == 0, + "header timeout: incomplete header has no immediate response"); + + /* The firmware timeout is 5 seconds; 2000 host ticks is safely beyond it. */ + ticks = 2000; + run_periodic(1); + CHECK(!uip_conn_active(0), + "header timeout: connection is aborted when the header never completes"); +} + +static void scenario_oversized_post_header(void) +{ + static const char start[] = + "POST /login HTTP/1.1\r\n" + "X-Fill: "; + char fill[1200]; + + login_session_start(); + memset(fill, 'a', sizeof(fill)); + client_send(TCP_ACK | TCP_PSH, start, (int)strlen(start)); + + /* Keep extending a header with no CRLFCRLF until the fixed buffer refuses it. */ + for (int i = 0; i < 16 && !stream_contains("400 Bad Request"); i++) + client_send(TCP_ACK | TCP_PSH, fill, (int)sizeof(fill)); + + CHECK(stream_contains("HTTP/1.1 400 Bad Request\r\n"), + "oversized header: rejected before the header buffer overflows"); +} + +static void scenario_fragmented_missing_content_length(void) +{ + static const char first[] = + "POST /login HTTP/1.1\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"; + static const char second[] = "\r\npwd=1234"; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("HTTP/1.1 411 Length Required\r\n"), + "fragmented header: missing Content-Length still returns 411"); +} + + +static void scenario_fragmented_get_cookie(void) +{ + static const char first[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Host: sw\r\n" + "Cook"; + static const char second[] = + "ie: session=0123456789ab\r\n" + "\r\n"; + + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "fragmented GET cookie: no redirect before the header completes"); + + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("HTTP/1.1 200 OK\r\n"), + "fragmented GET cookie: protected index is served"); + CHECK(!stream_contains("Location: login.html\r\n"), + "fragmented GET cookie: session is not lost on the redirected GET"); +} + +static void scenario_fragmented_get_cookie_value(void) +{ + static const char first[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Host: sw\r\n" + "Cookie: session=012345"; + static const char second[] = + "6789ab\r\n" + "\r\n"; + + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "fragmented GET cookie value: waits for the rest of the header"); + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("HTTP/1.1 200 OK\r\n"), + "fragmented GET cookie value: split session value authenticates"); +} + +static void scenario_split_get_header_terminator(void) +{ + static const char first[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Cookie: session=0123456789ab\r\n" + "\r"; + static const char second[] = "\n"; + + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "fragmented GET terminator: CRLFCR does not trigger parsing"); + client_send(TCP_ACK | TCP_PSH, second, 1); + CHECK(stream_contains("HTTP/1.1 200 OK\r\n"), + "fragmented GET terminator: CRLFCRLF may span receive events"); +} + +static void scenario_fragmented_get_without_cookie(void) +{ + static const char first[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Host: sw\r\n"; + static const char second[] = "\r\n"; + + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("HTTP/1.1 302 Found\r\n"), + "fragmented GET without cookie: protected file still redirects"); + CHECK(stream_contains("Location: login.html\r\n"), + "fragmented GET without cookie: authentication is not carried over"); +} + +static void scenario_get_header_timeout(void) +{ + static const char partial[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Host: sw\r\n" + "Cookie: session=012345"; + + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + ticks = 0; + + client_send(TCP_ACK | TCP_PSH, partial, (int)strlen(partial)); + CHECK(stream_len == 0, + "fragmented GET timeout: incomplete header has no immediate response"); + + ticks = 2000; + run_periodic(1); + CHECK(!uip_conn_active(0), + "fragmented GET timeout: incomplete request is eventually aborted"); +} + +static void scenario_oversized_get_header(void) +{ + static const char start[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "X-Fill: "; + char fill[1200]; + + session_start(MSS_FULL); + memset(fill, 'a', sizeof(fill)); + + client_send(TCP_ACK | TCP_PSH, start, (int)strlen(start)); + for (int i = 0; i < 16 && !stream_contains("400 Bad Request"); i++) + client_send(TCP_ACK | TCP_PSH, fill, (int)sizeof(fill)); + + CHECK(stream_contains("HTTP/1.1 400 Bad Request\r\n"), + "oversized GET header: fixed header buffer is bounds checked"); +} + +static void scenario_split_method_names(void) +{ + static const char get[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Cookie: session=0123456789ab\r\n\r\n"; + static const char post[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n\r\n" + "pwd=1234"; + int get_waits = 1, get_ok = 1, post_waits = 1, post_ok = 1; + + for (int split = 1; split < 3; split++) { + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + client_send(TCP_ACK | TCP_PSH, get, split); + if (stream_len) + get_waits = 0; + client_send(TCP_ACK | TCP_PSH, get + split, (int)strlen(get) - split); + if (!stream_contains("HTTP/1.1 200 OK\r\n")) + get_ok = 0; + } + CHECK(get_waits, "split GET method: incomplete verb waits for the header"); + CHECK(get_ok, "split GET method: every split inside GET serves the file"); + + for (int split = 1; split < 4; split++) { + login_session_start(); + client_send(TCP_ACK | TCP_PSH, post, split); + if (stream_len) + post_waits = 0; + client_send(TCP_ACK | TCP_PSH, post + split, (int)strlen(post) - split); + if (!stream_contains("Location: index.html\r\n")) + post_ok = 0; + } + CHECK(post_waits, "split POST method: incomplete verb waits for the header"); + CHECK(post_ok, "split POST method: every split inside POST completes login"); +} + +static void scenario_config_upload(void) +{ + static const char expected[] = "hostname upload-test\nip 10.0.0.1\n"; + static const char body[] = + "--upload-boundary\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"config.txt\"\r\n" + "Content-Type: text/plain\r\n\r\n" + "hostname upload-test\nip 10.0.0.1\n" + "\r\n--upload-boundary--\r\n"; + char request[768]; + int request_len, first_bad_response = -1, first_bad_flash = -1; + + request_len = snprintf(request, sizeof(request), + "POST /config HTTP/1.1\r\n" + "Host: sw\r\n" + "Cookie: session=0123456789ab\r\n" + "Content-Type: multipart/form-data; boundary=upload-boundary\r\n" + "Content-Length: %zu\r\n\r\n%s", sizeof(body) - 1, body); + if (request_len < 0 || request_len >= (int)sizeof(request)) { + CHECK(0, "multipart/config: test request fits the client buffer"); + return; + } + + /* The same well-formed request must work in one event and with a split + * anywhere in its HTTP header, first multipart delimiter, part headers, + * configuration, or closing delimiter. No extra CRLF is added to the body. */ + for (int split = 0; split <= request_len; split++) { + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + config_erases = config_writes = 0; + written_config_len = 0; + memset(written_config, 0xa5, sizeof(written_config)); + if (split) + client_send(TCP_ACK | TCP_PSH, request, split); + if (split < request_len) + client_send(TCP_ACK | TCP_PSH, request + split, request_len - split); + if (!stream_contains("HTTP/1.1 200 OK\r\n") && first_bad_response < 0) + first_bad_response = split; + if ((config_erases != 1 || config_writes != 1 + || config_erase_addr != CONFIG_START || config_write_addr != CONFIG_START + || written_config_len != sizeof(expected) + || memcmp(written_config, expected, sizeof(expected))) && first_bad_flash < 0) + first_bad_flash = split; + } + if (first_bad_response >= 0) + printf(" multipart/config: first rejected request split at byte %d\n", first_bad_response); + if (first_bad_flash >= 0) + printf(" multipart/config: first incorrect flash write at split %d\n", first_bad_flash); + CHECK(first_bad_response < 0, + "multipart/config: complete request and every two-event split return 200"); + CHECK(first_bad_flash < 0, + "multipart/config: every split writes the exact configuration and NUL to its sector"); +} + +/* Requiring octet-stream would leave alternate or absent MIME types buffered + * as headers forever instead of staging the binary and checking its CRC. */ +static void scenario_upload(const char *name, const char *part_type, int split) +{ + static const uint8_t payload[] = { 0x00, 0xff, 'R', '\r', '\n', '-', 0x80, 0x00 }; + static const uint8_t staged[] = { 0x00, 0xff, 'R', '\r', '\n', '-', 0x80, 0x00, 0x00 }; + static const char closing[] = "\r\n--upload-boundary--\r\n"; + char preamble[256], request[512]; + uint32_t saved_flash_size = flash_size; + int preamble_len, header_len, request_len; + + printf("\n-- upload: %s --\n", name); + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + session_timeout = 200; + last_session_use = 0; /* read_reg_timer() returns zero in this bench. */ + flash_size = 0x100000; + flash_written_len = 0; + flash_write_bad = 0; + reset_calls = 0; + + preamble_len = snprintf(preamble, sizeof(preamble), + "--upload-boundary\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"firmware.bin\"\r\n" + "%s\r\n", part_type); + header_len = snprintf(request, sizeof(request), + "POST /upload HTTP/1.1\r\nHost: sw\r\n" + "Cookie: session=0123456789ab\r\n" + "Content-Type: multipart/form-data; boundary=upload-boundary\r\n" + "Content-Length: %zu\r\n\r\n%s", + (size_t)preamble_len + sizeof(payload) + sizeof(closing) - 1, preamble); + memcpy(request + header_len, payload, sizeof(payload)); + memcpy(request + header_len + sizeof(payload), closing, sizeof(closing) - 1); + request_len = header_len + sizeof(payload) + sizeof(closing) - 1; + if (split) { + /* Cut the part's CRLFCRLF between its final CR and LF. */ + client_send(TCP_ACK | TCP_PSH, request, header_len - 1); + CHECK(stream_len == 0 && flash_written_len == 0, + "upload: incomplete part headers stage nothing and await more data"); + client_send(TCP_ACK | TCP_PSH, request + header_len - 1, + request_len - header_len + 1); + } else { + client_send(TCP_ACK | TCP_PSH, request, request_len); + } + drain(MSS_FULL); + + CHECK(!flash_write_bad && flash_written_len == sizeof(staged) && + !memcmp(flash_written, staged, sizeof(staged)), + "upload: exact binary payload plus zero terminator staged at image address"); + CHECK(stream_len >= 12 && !memcmp(stream, "HTTP/1.1 400", 12), + "upload: invalid firmware is rejected with HTTP 400"); + CHECK(!uip_conn->appstate.fw_reset_pending && reset_calls == 0, + "upload: deliberately invalid CRC never schedules or triggers reset"); + flash_size = saved_flash_size; +} + int main(int argc, char **argv) { if (argc > 1 && !strcmp(argv[1], "-v")) @@ -504,6 +1095,26 @@ int main(int argc, char **argv) scenario_growing_window(); scenario_rexmit_after_shrink(); scenario_bad_l4_checksum(); + scenario_upload_reset_owner(); + scenario_fragmented_post_header(); + scenario_split_content_type(); + scenario_split_header_terminator(); + scenario_header_then_body(); + scenario_header_with_partial_body(); + scenario_post_header_timeout(); + scenario_oversized_post_header(); + scenario_fragmented_missing_content_length(); + scenario_fragmented_get_cookie(); + scenario_fragmented_get_cookie_value(); + scenario_split_get_header_terminator(); + scenario_fragmented_get_without_cookie(); + scenario_get_header_timeout(); + scenario_oversized_get_header(); + scenario_split_method_names(); + scenario_config_upload(); + scenario_upload("octet-stream control", "Content-Type: application/octet-stream\r\n", 0); + scenario_upload("MacBinary, split part terminator", "Content-Type: application/macbinary\r\n", 1); + scenario_upload("no part Content-Type", "", 0); printf("\n%s (%d failure%s)\n", failures ? "BENCH: FAILURES" : "BENCH: ALL PASS", diff --git a/test/test_lacp.c b/test/test_lacp.c index 160c773e..56b8e56f 100644 --- a/test/test_lacp.c +++ b/test/test_lacp.c @@ -14,8 +14,11 @@ uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE]; uint16_t uip_len; struct uip_eth_addr uip_ethaddr = { .addr = {0x02,0x11,0x22,0x33,0x44,0x55} }; -const struct machine machine = { .min_port = 0, .max_port = 7, +const struct machine machine = { .log_to_phys_port = {5, 1, 2, 3, 4, 6, 7, 8, 9} }; +/* Logical ports of the mock machine above */ +#define TEST_MIN_PORT 0 +#define TEST_MAX_PORT 7 struct machine_runtime machine_detected = { .isRTL8373 = 1 }; uint8_t lacpEnabled; uint16_t management_vlan; /* mocked; slow-protocol path zeroes it per-frame */ @@ -216,7 +219,7 @@ int main(int argc, char **argv) lacp_lag_set(0, 0x00ff); step(8); int all_tx = 1, sane = 1; - for (int i = machine.min_port; i <= machine.max_port; i++) { + for (int i = TEST_MIN_PORT; i <= TEST_MAX_PORT; i++) { if (!tx_count[i]) all_tx = 0; if (last_tx[i].ethertype != HTONS(0x8809) || last_tx[i].subtype != 1 || last_tx[i].dst[5] != 0x02 diff --git a/tools/Makefile b/tools/Makefile index 1b1c6685..80ac9743 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,6 +1,8 @@ CC = gcc CCFLAGS = -Wall -o -BUILDDIR = output +ifndef BUILDDIR + BUILDDIR = output +endif all: create_build_dir $(BUILDDIR)/injector $(BUILDDIR)/fileadder $(BUILDDIR)/httpd_sim\ $(BUILDDIR)/crc_calculator $(BUILDDIR)/imagebuilder diff --git a/tools/bank_occupancy.sh b/tools/bank_occupancy.sh new file mode 100755 index 00000000..8638d390 --- /dev/null +++ b/tools/bank_occupancy.sh @@ -0,0 +1,31 @@ +#!/bin/bash +MACHINE="$1" +if [[ ! -s output-main/rtlplayground.map ]]; then + original_branch=$(git branch --show-current) + #trap 'git switch "$original_branch"' EXIT + git switch main && make CI=1 MACHINE="$MACHINE" BUILDDIR=output-main + git switch "$original_branch" +fi +source <(sed -rn 's/^([XCD]SEG|(BANK[0-9])).*=\s+([0-9]+)\. bytes.*$/main_\1=\3/p' output-main/rtlplayground.map | sort -u) + +main_WEB=$(du -sb output-main/html_min | awk '{print $1}') +if [[ ! -s "output/$MACHINE/rtlplayground.map" ]]; then + make CI=1 MACHINE="$MACHINE" +fi +source <(sed -rn 's/^([XCD]SEG|(BANK[0-9])).*=\s+([0-9]+)\. bytes.*$/branch_\1=\3/p' output/"$MACHINE"/rtlplayground.map | sort -u) +branch_WEB=$(du -sb output/html_min | awk '{print $1}') + +print_line() { + local name=$1 main=$2 branch=$3 + printf '%-20s %-20s %-20s %-20s\n' "$name" "$main" "$branch" "$((branch - main))" +} + +printf '%-20s %-20s %-20s %-20s\n' "segment" "main" "branch" "change" + +print_line "BANK1" "$main_BANK1" "$branch_BANK1" +print_line "BANK2" "$main_BANK2" "$branch_BANK2" +print_line "BANK3" "$main_BANK3" "$branch_BANK3" +print_line "CSEG" "$main_CSEG" "$branch_CSEG" +print_line "DSEG" "$main_DSEG" "$branch_DSEG" +print_line "XSEG" "$main_XSEG" "$branch_XSEG" +print_line "WEB" "$main_WEB" "$branch_WEB" diff --git a/uip/uip.c b/uip/uip.c index c8d0f20b..6c25d364 100644 --- a/uip/uip.c +++ b/uip/uip.c @@ -98,6 +98,7 @@ #include "../rtl837x_regs.h" extern __xdata uint8_t rx_headers[16]; +extern volatile __xdata uint32_t ticks; /*---------------------------------------------------------------------------*/ /* Variable definitions. */ @@ -243,6 +244,9 @@ __xdata struct uip_stats uip_stat; #if UIP_LOGGING == 1 #define UIP_LOG(m) print_string_newline_no_syslog(m); +#define FRAGDROP_WINDOW (5 * SYS_TICK_HZ) +static __xdata u16_t fragdrop_mark; +static __xdata u8_t fragdrop_count; #else #define UIP_LOG(m) #endif /* UIP_LOGGING == 1 */ @@ -710,6 +714,17 @@ uip_process(u8_t flag) __banked /* Check if we were invoked because of the perodic timer fireing. */ } else if(flag == UIP_TIMER) { // print_string("T1\n"); +#if UIP_LOGGING == 1 + if(fragdrop_count && (u16_t)ticks - fragdrop_mark >= FRAGDROP_WINDOW) { + print_string_no_syslog("ip: fragments dropped: "); + itoa_no_syslog(fragdrop_count); + if(fragdrop_count == 0xff) + write_char_no_syslog('+'); + write_char_no_syslog('\n'); + fragdrop_mark = (u16_t)ticks; + fragdrop_count = 0; + } +#endif /* UIP_LOGGING == 1 */ #if UIP_IDLE_TIMEOUT if(uip_connr == uip_conns) { uip_idle_age = 0; @@ -915,7 +930,10 @@ uip_process(u8_t flag) __banked #else /* UIP_REASSEMBLY */ UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.fragerr); - UIP_LOG("ip: fragment dropped."); +#if UIP_LOGGING == 1 + if(fragdrop_count != 0xff) + ++fragdrop_count; +#endif /* UIP_LOGGING == 1 */ goto drop; #endif /* UIP_REASSEMBLY */ }