Author SHA1 Message Date
logicog 7e11be0d97 Add ZoeRax HG0402XG V1.1 to supported devices 2026-10-27 22:05:22 +01:00
logicog 23862bc648 New Device: Add support for ZoeRax HG0402XG V1.1
The ZoeRax HG0402XG is an unmanaged 4 2.5GBit Ethernet, 2 SFP+
device.
2026-10-27 22:05:22 +01:00
feelfree69 413690a748 Merge pull request #711 from DrDoof/fix/installer-toolchain
installer: build with the toolchain from the tree
2026-10-27 22:03:33 +01:00
feelfree69 73bb4c8af2 Merge pull request #709 from L4ky/add-config-path-to-makefile
Add CONFIG parameter to make
2026-10-27 18:21:42 +01:00
feelfree69 0443ba428b Merge pull request #661 from Kamikaze94/feature/improve-strip-rj45-icon
WebUI: Change port strip icon for rj45 ports, latch added
2026-10-27 18:12:43 +01:00
feelfree69 62abd08aa2 Merge pull request #660 from Kamikaze94/bugfix/strip-sfp-icon
WebUI: Fix port strip icon for sfp ports
2026-10-27 18:11:25 +01:00
feelfree69 70426ff24a Merge pull request #720 from brunoz78/de-vlan
i18n(de): translate the new VLAN manager texts
2026-10-27 16:39:20 +01:00
feelfree69 2d62cc493d Merge pull request #719 from nappairam/swtg018as-v2-factory-mac
machine: read factory MAC on SWTG018AS-A V2.0
2026-10-27 16:37:08 +01:00
Mariappan Ramasamy 36de7b7241 machine: read factory MAC on SWTG018AS-A V2.0
Horaco HC-SWTGW218AS units on this PCB keep their factory MAC at
0x1FC000, the offset the other boards in machine/ read it from, so use
it instead of a generated locally administered one. If the flash holds
no valid MAC there, the generated one is still used.
2026-10-27 18:47:22 +08:00
Brunoz78andClaude Opus 5.5 ea320d813d i18n(de): translate the new VLAN manager texts
#609 added six texts to the VLAN page without a German translation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:02:36 +01:00
Luca S. ca2abcc4e1 Merge branch 'main' into add-config-path-to-makefile 2026-10-26 20:01:58 +01:00
René van Dorst 4d7159092c Merge pull request #673 from andrebrait/fix/xdata-startup
startup: clear SFR 0x97 before the C runtime initialises xdata
2026-10-26 17:15:32 +00:00
Andre Brait 98763e3bff startup: clear MAP_FLASH_PAGE_TO_XDATA before the C runtime initialises xdata
Hardware reset starts the firmware with SFR 0x97 = 1, which maps xdata
0x4000-0xbfff to the flash image: reads return flash bytes, writes are
lost. main() cleared it only after __mcs51_genXINIT and the XSEG clear
had run, so XISEG (initialised globals) and the part of XSEG above
0x4000 kept stale RAM contents, e.g. session_timeout = 4484 and LLDP
blocked on logical ports 0, 3 and 5. Clear it in
__sdcc_external_startup(), which SDCC calls before both.

Rename SFR_97 to MAP_FLASH_PAGE_TO_XDATA.
2026-10-26 17:08:27 +01:00
logicog 80a30b705e Merge pull request #706 from DrDoof/feat/banner-compiler
build: show the compiler and the toolchain in the version banner
2026-10-26 14:41:50 +01:00
feelfree69 4c3e1fde81 Merge pull request #609 from mintsoft/vlan-manager-fixes
VLAN manager UI/fixes
2026-10-26 13:59:39 +01:00
feelfree69 5cd14e6227 Merge pull request #714 from rwalli/doc-hc-swtg124as-19650
doc: add HC-SWTG124AS on PCB-SWTG024AS-A-V2.0.1_19650 with SW1 reset …
2026-10-26 12:34:47 +01:00
rwalli@gmx.at 5105018d90 machine: reset button on GPIO48 for HC-SWTG124AS, drop braces around _19650
SW1 on PCB-SWTG024AS-A-V2.0.1_19650 is wired to GPIO48. Measured on
HC-SWTG124AS: GPIO48 reads 1 idle and 0 while the button is held.
HC_SWTG124AS.c is a symlink to PCB_SWTG024AS_A_2_0_1.c.
2026-10-26 12:23:28 +01:00
rwalli@gmx.at 5bc7cf43db doc: merge duplicate HC-SWTG124AS rows, note _19650 variant in existing entry 2026-10-26 12:00:38 +01:00
rwalli@gmx.at c776d10129 doc: add HC-SWTG124AS on PCB-SWTG024AS-A-V2.0.1_19650 with SW1 reset note 2026-10-26 11:30:31 +01:00
Luca S. e95e450813 Add CONFIG parameter on make 2026-10-26 08:27:28 +01:00
d00f c5f62bff95 build: name the sdcc/ revision in the toolchain line
A commit hash can be looked up directly, a checksum cannot. Print the last commit that touched sdcc/, with -dirty for local changes, and fall back to the checksum when git is not available. The toolchain directory keeps the checksum.
2026-10-25 22:49:37 +01:00
d00f 7535c0d9b7 installer: build with the toolchain from the tree
The installer Makefile called whatever sdcc was on the PATH, so an
installer built by hand came out of the system compiler, without the
fixes in sdcc/. Use the same toolchain/sdcc-<cksum> as the main Makefile,
built on demand by sdcc/build.sh if a bare installer build gets there
first, and keep CC= on the command line as the way to pick another
compiler. The README example shows the new command lines.
2026-10-25 22:44:51 +01:00
Luca S. a57319557d Add CONFIG parameter on make 2026-10-25 22:42:06 +01:00
d00f 1b29fb687f build: count the sdcc patches in the toolchain line
The checksum changes with every patch but does not say how many there are. Print the number of patches in sdcc/ next to it.
2026-10-25 21:23:32 +01:00
Rob Emery 2e62f9eea7 Adding the name of the port to the UI so it's easier to see what
you are changing
2026-10-25 16:33:54 +00:00
d00f 1d158d21d1 build: show the compiler and the toolchain in the version banner
The boot banner and the version command print the SDCC release and
revision from the compiler's own macros, and the name of the in-tree
toolchain the Makefile built, which is the checksum of sdcc/ and so
changes with every patch in it. A build with CC given on the command
line says "system" instead, since that compiler need not carry the
patches. A plain release and the same release with the patches report
the same revision, so the toolchain line is what tells them apart.

Costs 66 bytes of BANK2.
2026-10-25 16:04:49 +01:00
Rob Emery 2d5424fedc Fixing double firing of load vlan 1 when the tab is loaded 2026-10-25 09:06:30 +00:00
Rob Emery 23c8b2a8b3 Fixing the unsaved changes not appearing. Previously if a set of
changes were sent as a single cmd using \n separation then the
dirty regex would skip it as $ wouldn't match \n. with /m modifier
the regex will match
2026-10-25 09:06:30 +00:00
Rob Emery c9f6362da5 Previously the vlan 2 regex was assuming there were ports, now
it'll accept just the definition.
Also throughout the regex we have over-specified the number of digits
sometimes ports are 4 digits long, sometimes they are 2. This seems
unnecessary, 1 or more is sufficient
2026-10-25 09:06:30 +00:00
Rob Emery 742aef5461 Adding highlighting to the currently selected VLAN in the top table
so that it is more clear it is selected
2026-10-25 09:06:30 +00:00
Rob Emery a77d219baf Moving the mgmt switch into the bottom section so it applies when
the user clicks apply on the specific vlan. In order for this to
work when the user is simultaneously changing the vlan that their
machine is connected through and the mgmt vlan id, we need to be
able to send a batch of commands through to the switch atomically
so the switch can process all of them and the momentary disconnection
of the machine doesn't matter
2026-10-25 09:06:30 +00:00
Rob Emery f94204e56f Adding rename support for vlan 2026-10-25 09:06:30 +00:00
Rob Emery 8d6adedb56 Removing my changes to the sim, in favour of #629 2026-10-25 09:06:30 +00:00
Rob Emery c3f9acea10 Tidying up the new VLAN page and adding error messages
When adding a new VLAN, we should load it after addition
Prevent deleting the mgmt vlan
Adding a button to promote a vlan to be the management VLAN
We can't create a vlan called d or mgmt as that clashes with the
commands to delete and promote a vlan
Making the Management VLAN more obvious and adding a "confused"
disabled button to where delete and promote are
Switching to the i image and making it so you can click the entire
row apart from the cell where the buttons are (to prevent accidents)
Cleaning up the last bits of ingress filtering I can see
2026-10-25 09:06:30 +00:00
Rob Emery c46261e052 Using PVID=0 for the situation where the port is only in tagged
membership. This was tested on HI_K0801WS and it appears to not
have any negative side-effects
2026-10-25 09:06:30 +00:00
Rob Emery 834403b97b Parking ports with only tagged membership into VLAN 4094 for now
I think this should also resolve the work-flow where you can get
a port's PVID and tagged membership to the same vlan
2026-10-25 09:06:30 +00:00
Rob Emery 48087d3520 Decoupling the load from the spinner so we can get rid of it
Also making the first VLAN in the table load when we load the UI

Removing the tickbox for the PVID, I'll swap this out to ticks
or something later on, but the PVID will be automatically set
based on the untagged membership, otherwise it will be 1

Send the vlan with name command when attempting to add a new VLAN
Because of the structure of the vlan command, we need to send the name as well if its set

Set the PVID based on the untagged membership and reload the
table when applied. We need to block setting the PVID to the tagged by proxy

Blue button

Need to provide array of pvid commands not concat
Storing state of each vlan so we can refer later

Blue button
2026-10-25 09:06:30 +00:00
Rob Emery 1d359afba5 Adding vlanlist support into http_sim so it's easier to work on
Also improving vlan.json to mirror the real output
2026-10-25 09:06:30 +00:00
Kamikaze94 3c00ab0ae9 WebUI: Cleanup color settings 2026-10-22 00:40:46 +02:00
Kamikaze94 6d539bfb1b WebUI: Change port strip sfp icon 2026-10-20 22:46:15 +02:00
Kamikaze94 2a9f9b2508 WebUI: Change port strip rj45 icon, latch added 2026-10-19 23:58:57 +02:00
Kamikaze94 723d16b4cb WebUI: Fix port strip icon for sfp ports 2026-10-19 18:32:37 +02:00
21 changed files with 516 additions and 203 deletions

No files matched your search

+6
View File
@@ -47,6 +47,12 @@
- The web UI and the configuration upload now refuse a line the replay cannot take,
instead of writing it to flash.
- Startup
- Initialised and zero-initialised globals above xdata 0x4000 now get their values at boot.
Hardware reset leaves SFR 0x97 at 1, which maps xdata 0x4000-0xbfff to the flash image,
and it was cleared only in `main()`, after the C startup code had copied and cleared them.
This showed as a random web session timeout and LLDP blocked on some ports without config.
## Breaking changes
- Config
+37 -8
View File
@@ -4,11 +4,25 @@ DEFAULT_CONFIG_LOCATION = 454656
CONFIG_LOCATION = 458752
HTML_LOCATION = 262144
SDCC_PREFIX = toolchain/sdcc-$(shell cat sdcc/* | cksum | cut -d' ' -f1)
# Startup configuration embedded in the image. Override it to build a specific
# machine with its own configuration: make MACHINE=<name> CONFIG=<file>
CONFIG ?= config.txt
SDCC_TOOLCHAIN = sdcc-$(shell cat sdcc/* | cksum | cut -d' ' -f1)
SDCC_PREFIX = toolchain/$(SDCC_TOOLCHAIN)
ifeq ($(origin CC),default)
SDCC = $(SDCC_PREFIX)/bin/sdcc
CC = $(SDCC)
ASM = $(SDCC_PREFIX)/bin/sdas8051
SDCC_REV := $(shell git log -1 --format=%h -- sdcc 2>/dev/null)
ifneq ($(SDCC_REV),)
ifneq ($(shell git status --porcelain --untracked-files=no -- sdcc 2>/dev/null),)
SDCC_REV := $(SDCC_REV)-dirty
endif
endif
SDCC_BANNER = $(if $(SDCC_REV),sdcc/ at $(SDCC_REV),$(SDCC_TOOLCHAIN)) ($(words $(wildcard sdcc/*.patch)) patches)
else
SDCC_BANNER = system
endif
CC_FLAGS = -mmcs51 -I. -Imachine -Ihttpd -Iuip
ASM ?= sdas8051
@@ -46,6 +60,7 @@ ifndef BUILDDIR
BUILDDIR = output/$(MACHINE)
endif
CONFIG_STAMP := $(BUILDDIR)/.config
VERSION_HEADER := version.h
GIT_VERSION := $(shell git rev-parse --short HEAD)
@@ -68,9 +83,10 @@ BUILD_DATE := $(shell date -u -d @$(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S" 2>/d
|| date -u -r $(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S")
endif
# $(MACHINE_SRC) is listed here so an unknown $MACHINE fails before anything else
# is built, including the tools/ subdirectory.
all: create_build_dir $(VERSION_HEADER) $(MACHINE_SRC) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
# $(MACHINE_SRC) and $(CONFIG) are listed here so an unknown $MACHINE or a
# missing config file fails before anything else is built, including the tools/
# subdirectory.
all: create_build_dir $(VERSION_HEADER) $(MACHINE_SRC) $(CONFIG) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
bank_size:
tools/bank_occupancy.sh "$(MACHINE)"
@@ -91,6 +107,12 @@ $(MACHINE_SRC):
@echo " Example: make MACHINE=KP_9000_6XHML_X2" >&2
@false
# Fail with a clear message when CONFIG names a file that does not exist.
$(CONFIG):
@echo "ERROR: CONFIG='$(CONFIG)' does not exist." >&2
@echo " Point CONFIG at a configuration file, or omit it to use config.txt." >&2
@false
# Keep the per-machine definition in first position to fail immediately on an
# invalid $MACHINE value
SRCS = \
@@ -172,6 +194,7 @@ $(VERSION_HEADER): FORCE
@printf '%s\n' "#ifndef VERSION_H" "#define VERSION_H" \
"#define VERSION_SW \"$(VERSION_EXTENSION)\"" \
"#define BUILD_DATE \"$(BUILD_DATE)\"" \
"#define SDCC_TOOLCHAIN \"$(SDCC_BANNER)\"" \
"#endif" > $(VERSION_HEADER).tmp
@cmp -s $(VERSION_HEADER).tmp $(VERSION_HEADER) \
&& rm -f $(VERSION_HEADER).tmp \
@@ -209,6 +232,12 @@ FORCE:
$(CCFLAGS_STAMP): FORCE | create_build_dir
@echo '$(CC_FLAGS)' | cmp -s - $@ 2>/dev/null || echo '$(CC_FLAGS)' > $@
# The same for $(CONFIG): its path is stamped so switching to a config file
# older than the image still rebuilds it, while $(CONFIG) itself as a normal
# prerequisite covers edits to the selected file.
$(CONFIG_STAMP): FORCE | create_build_dir
@echo '$(CONFIG)' | cmp -s - $@ 2>/dev/null || echo '$(CONFIG)' > $@
$(BUILDDIR)/%.rel: %.c $(CCFLAGS_STAMP) | create_build_dir html_data.h
$(CC) -MMD $(CC_FLAGS) -o $@ -c $<
@@ -222,11 +251,11 @@ $(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtbank.rel $(BUILDDIR)/crc16
$(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx
objcopy --input-target=ihex -O binary $< $@
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img | tools
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img $(CONFIG) $(CONFIG_STAMP) | tools
if [ -e $@ ]; then rm $@; fi
tools/$(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)/imagebuilder -i $(BUILDDIR)/rtlplayground.img $@
tools/$(BUILDDIR)/fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d "$(CONFIG)" $@
tools/$(BUILDDIR)/fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d "$(CONFIG)" $@
tools/$(BUILDDIR)/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -z -d $(HTML_MIN) -b BANK1 $@
tools/$(BUILDDIR)/crc_calculator -u $@
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin $(BUILDDIR)/../rtlplayground.bin
+10 -3
View File
@@ -127,6 +127,13 @@ The name selects the board definition `machine/<name>.c`; `make` without a
`MACHINE` value stops with an error listing what is expected. If your board is
not in the list yet, see [Adding a new device](doc/adding-a-device.md).
To embed a machine-specific startup configuration, pass `CONFIG`:
```
make MACHINE=DEFAULT_8C_1SFP CONFIG=configs/DEFAULT_8C_1SFP.txt
```
`CONFIG` defaults to `config.txt`; the selected file is embedded in the image
and changing it triggers a rebuild.
> [!TIP]
> You can write configuration parameters in config.txt (see below) in order your switch to get
> straight at the first boot, a correct IP configuration.
@@ -170,9 +177,9 @@ example of compilation console output
RTLPlayground/installer$ make
mkdir -p output
gcc updatebuilder.c -o output/updatebuilder
sdas8051 -plosgff -o output/crtstart.rel crtstart.asm
sdcc -mmcs51 --code-loc 0x1000 -o output/installer.rel -c installer.c
sdcc -mmcs51 -Wl-bHOME=0x1100 -Wl-r -o output/rtlinstaller.ihx output/crtstart.rel output/installer.rel
../toolchain/sdcc-3390765201/bin/sdas8051 -plosgff -o output/crtstart.rel crtstart.asm
../toolchain/sdcc-3390765201/bin/sdcc -mmcs51 --code-loc 0x1000 -o output/installer.rel -c installer.c
../toolchain/sdcc-3390765201/bin/sdcc -mmcs51 -Wl-bHOME=0x1100 -Wl-r -o output/rtlinstaller.ihx output/crtstart.rel output/installer.rel
./output/updatebuilder -i output/rtlinstaller.ihx -o output/rtlplayground_oem_upgrade.bin ../output/rtlplayground.bin
Input file size: 524288
Bytes read: 524288
+4 -2
View File
@@ -1840,6 +1840,8 @@ void print_gpio_status(void) {
void print_sw_version(void) __banked {
print_string("Software version: " VERSION_SW);
print_string("\nBuild date: " BUILD_DATE);
print_string("\nCompiler: SDCC " STR(__SDCC_VERSION_MAJOR) "." STR(__SDCC_VERSION_MINOR) "." STR(__SDCC_VERSION_PATCH) " #" STR(__SDCC_REVISION));
print_string("\nToolchain: " SDCC_TOOLCHAIN);
print_string("\nHardware: ");
print_string(machine.machine_name);
write_char('\n');
@@ -2015,10 +2017,10 @@ void cmd_parser(void) __banked
cmd_error("lacp (show | off); a group starts LACP with: lag <1-4> lacp <port>...\n");
} else if (cmd_compare(0, "pvid")) {
if (cmd_words_len == 3 && cmd_parse_port_separator(cmd_words_b[1]) != 0
&& atoi_short(cmd_words_b[2]) && atoi_results_short && atoi_results_short <= 4094)
&& atoi_short(cmd_words_b[2]) && atoi_results_short <= 4094)
port_pvid_set(atoi_results_u8, atoi_results_short);
else {
cmd_error("pvid <port> <1-4094>\n");
cmd_error("pvid <port> <0-4094>\n");
}
} else if (cmd_compare(0, "vlan")) {
parse_vlan();
+3 -1
View File
@@ -5,7 +5,7 @@ It is highly similar to SWTG024AS-V2.0, with the only difference being the GPIO
|Brand |Type |Managed|PCB |Flash |Chip RTL|
|---------|--------------|-------|------------------------------|----------------|--------|
| Horaco | ZX-SG4T2 | No | PCB-SWTG024AS-A-V2.0.1_19650 | 512K (P25D40SH)| 8372N |
| Horaco | HC-SWTG124AS | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M (W25Q16JV)| 8372N |
| Horaco | HC-SWTG124AS | Yes | PCB-SWTG024AS-A-V2.0.1_19650 | 2M (W25Q16JV)| 8372N |
| GoodTop | GT-ST024M | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M | 8372N |
### Label specifications
@@ -35,6 +35,8 @@ Bottom
<img src="photos/SWTG024AS-A-V2_0_1_19650/horaco-zx-sg4t2-pcb-bottom.jpg" width="300" />
On Horaco HC-SWTG124AS with board PCB-SWTG024AS-A-V2.0.1_19650 the reset button is soldered at `SW1` (on the top left, GPIO48).
### J1, serial console
| `J1` pin | Signal |
+36
View File
@@ -0,0 +1,36 @@
### HG0402XG V1.1
## Brands
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|---|---|---|---|---|---|
| ZoeRax | HG0402XG | No| HG0402XG V1.1 | 1M (Winbond 25Q) | |
### Label specifications
- **Name**: ZOERAX 2.5G 2SFP 4-Port Gigabit Switch
- **Model**: HG0402XG-EU
- **Ports**:
- 4 × RJ45: 10/100/1000/2500 Mbps
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
<img src="photos/HG0402XG_V1_1/HG0402XG_V1_1_bottom.jpg" width="300" />
## PCB
<img src="photos/HG0402XG_V1_1/HG0402XG_V1_1_top.jpg" width="300" />
<img src="photos/HG0402XG_V1_1/HG0402XG_V1_1_bottom.jpg" width="300" />
Be aware that the UART header is metric, the pitch is 2mm. The JST PH2.0mm header shown was addeded after purchase
The slider switch controls microcontroller U4 in order to configure the VLAN on/off settings. U4 can reset the SoC
and also write into its registers to configure VLAN. With RTLPlayground the slider cannot be used for anything else
than triggering reset. Any change in the position will trigger this reset.
### Installation
Using SPI clamp on-board is the only method for initial installation.
### What works
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
- SFP ports with various 1G/10G Fiber and Ethernet modules
- LEDs
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

+1
View File
@@ -52,6 +52,7 @@ The following devices have been tested and are fully working:
| YuanLey | YS25-0402 | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | 2M | 4 + 2 |
| YuanLey | YS25-0402M | Yes | [SIRIVISION_S25G2206FP_V1_1](devices/SIRIVISION_S25G2206FP_V1_1.md) | 2M | 4 + 2 |
| Ztyuav | Z-QWYT0402 | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
| ZoeRax | HG0402XG | No | [HG0402XG_V1.1](devices/ZOERAX_HG0402XG_V1.1.md) | 1M | 4 + 2 |
For KP-9000-6XH-X2 / KP-9000-6XHML-X2 / Mokerlink 2G040210GSM devices, select
the machine target by PCB revision. The ML/non-ML or managed/unmanaged label
+324 -166
View File
@@ -44,20 +44,19 @@ lldp_enabled: "LLDP Enabled",lldp_title:"Service Status",lldp_portname:"Name",ll
st_title:"Port statistics",st_h:"totals since boot",st_txg:"TX good",st_txb:"TX bad",st_rxg:"RX good",
st_rxb:"RX bad",st_details:"Details",st_counters:"MIB counters",st_nonzero:"non-zero only",
st_autoref:"auto-refresh",st_counter:"Counter",st_value:"Value",st_fail:"failed to load counters",
v_title:"VLANs",v_vid:"VID",v_members:"Members",v_tagged:"Tagged",v_untagged:"Untagged",v_pvid_on:"PVID on",
v_title:"VLANs",v_vid:"VLAN ID",v_members:"Members",v_tagged:"Tagged",v_untagged:"Untagged",v_pvid_on:"PVID on",
v_empty:"No VLANs configured.",v_mgmt:"Management VLAN",v_mgmt_none:"untagged",v_editor:"VLAN editor",
v_optional:"optional",v_setmgmt:"Set as mgmt VLAN",v_setmgmt_t:"Make this the management VLAN",
v_member:"Member",v_pvid:"PVID",
v_legend:"U = untagged member, T = tagged member, - = not a member. PVID assigns this VLAN to untagged ingress traffic.",
v_ingress:"Ingress filtering",v_ingress_h:"write-only: the state is not readable from the switch",
v_accept:"Accept",v_ing_all:"All",v_ing_apply:"Apply ingress modes",v_del_t:"Delete VLAN",
v_optional:"optional",v_setmgmt_q:"Set {n} as the management ID?",v_setmgmt_t:"Management VLAN",
v_member:"Member",v_pvid:"PVID",v_add:"Add a new VLAN", v_mgmt_c:"WARNING: You must be able to access this VLAN to continue to manage the switch.",
v_legend:"U = untagged member, T = tagged member, - = not a member. PVID is automatically assigned based on the untagged membership.",
v_accept:"Accept",v_ing_all:"All",v_del_t:"Delete VLAN",v_rename:"Rename",v_rename_t:"Rename VLAN",
v_del_q:"Delete VLAN {n}?",v_del_d:"Ports keep their PVID until reassigned.",
v_vid_err:"Enter a VLAN ID (1-4094)",v_name_err:"Name must start with a letter (letters, digits, _)",
v_vid_err:"Enter a VLAN ID (1-4094)",v_name_err:"Name must start with a letter (letters, digits, _) and cannot be just 'd' or 'mgmt'",
v_loaded:"Loaded VLAN {n}",v_notfound:"VLAN {n} not found (a new one can still be created)",
v_nomember:"Select at least one member port (or delete the VLAN instead)",
v_ing_none:"Pick an ingress mode for at least one port",v_vid_first:"Enter a VLAN ID first",
v_mgmt_q:"Set VLAN {n} as management VLAN?",
v_nomember:"Select at least one member port (or delete the VLAN instead)",v_vid_first:"Enter a VLAN ID first",
v_mgmt_q:"Set VLAN {n} as management VLAN?",v_vid_err:"VLAN ID already exists",
v_mgmt_d:"The switch will start tagging its own traffic with that VLAN. If the port you are connected through does not carry it, this page becomes unreachable and the setting can only be undone over the console.",
v_mgmt_tt:"The management VLAN cannot be deleted, you need to assign management to another VLAN first.",
l2_title:"MAC address table",l2_filter:"filter...",l2_flush:"Flush learned entries",l2_static:"static",
l2_learned:"learned",l2_loading:"loading...",l2_failed:"load failed",l2_entries:"entries",
l2_del_t:"Delete entry",l2_flush_q:"Flush all learned MAC entries?",
@@ -179,14 +178,12 @@ v_empty:"VLAN は設定されていません。",v_mgmt:"管理 VLAN",v_mgmt_non
v_optional:"任意",v_setmgmt:"管理 VLAN に設定",v_setmgmt_t:"この VLAN を管理 VLAN にする",
v_member:"メンバー",v_pvid:"PVID",
v_legend:"U = タグ無しメンバー、T = タグ付きメンバー、- = 非メンバー。PVID はタグ無し受信トラフィックをこの VLAN に割り当てます。",
v_ingress:"受信フィルタ",v_ingress_h:"書き込み専用: 現在の状態はスイッチから読み取れません",
v_accept:"受け入れ",v_ing_all:"すべて",v_ing_apply:"受信モードを適用",v_del_t:"VLAN を削除",
v_del_q:"VLAN {n} を削除しますか?",v_del_d:"ポートの PVID は再割り当てされるまで維持されます。",
v_vid_err:"VLAN ID (1〜4094) を入力してください",v_name_err:"名前は英字で始めてください (英字、数字、_)",
v_loaded:"VLAN {n} を読み込みました",v_notfound:"VLAN {n} は存在しません (新規作成は可能です)",
v_nomember:"メンバーポートを 1 つ以上選択してください (または VLAN を削除してください)",
v_ing_none:"1 つ以上のポートの受信モードを選択してください",v_vid_first:"先に VLAN ID を入力してください",
v_mgmt_q:"VLAN {n} を管理 VLAN に設定しますか?",
v_vid_first:"先に VLAN ID を入力してください",v_mgmt_q:"VLAN {n} を管理 VLAN に設定しますか?",
v_mgmt_d:"スイッチは自身のトラフィックにこの VLAN のタグを付けるようになります。接続中のポートがこの VLAN を通さない場合、このページにアクセスできなくなり、コンソールからしか元に戻せません。",
l2_title:"MAC アドレステーブル",l2_filter:"フィルタ...",l2_flush:"学習エントリを消去",l2_static:"静的",
l2_learned:"学習",l2_loading:"読み込み中...",l2_failed:"読み込み失敗",l2_entries:"エントリ",
@@ -292,14 +289,12 @@ v_empty:"尚未配置 VLAN。",v_mgmt:"管理 VLAN",v_mgmt_none:"untagged",v_edi
v_optional:"可选",v_setmgmt:"设为管理 VLAN",v_setmgmt_t:"将此 VLAN 设为管理 VLAN",
v_member:"成员",v_pvid:"PVID",
v_legend:"U = untagged 成员,T = tagged 成员,- = 非成员。PVID 将入方向的未标记流量归入此 VLAN。",
v_ingress:"入方向过滤",v_ingress_h:"只写: 当前状态无法从交换机读取",
v_accept:"接受",v_ing_all:"全部",v_ing_apply:"应用入方向模式",v_del_t:"删除 VLAN",
v_del_q:"删除 VLAN {n}?",v_del_d:"端口的 PVID 在重新分配前保持不变。",
v_vid_err:"请输入 VLAN ID (1-4094)",v_name_err:"名称必须以字母开头 (字母、数字、_)",
v_loaded:"已读取 VLAN {n}",v_notfound:"VLAN {n} 不存在 (仍可新建)",
v_nomember:"请至少选择一个成员端口 (或改为删除该 VLAN)",
v_ing_none:"请至少为一个端口选择入方向模式",v_vid_first:"请先输入 VLAN ID",
v_mgmt_q:"将 VLAN {n} 设为管理 VLAN?",
v_vid_first:"请先输入 VLAN ID",v_mgmt_q:"将 VLAN {n} 设为管理 VLAN?",
v_mgmt_d:"交换机将开始为自身流量打上该 VLAN 标签。如果您所连接的端口不属于该 VLAN,本页面将无法访问,且只能通过控制台撤销此设置。",
l2_title:"MAC 地址表",l2_filter:"筛选...",l2_flush:"清除学习条目",l2_static:"静态",
l2_learned:"动态学习",l2_loading:"加载中...",l2_failed:"加载失败",l2_entries:"条",
@@ -405,14 +400,12 @@ v_empty:"No hay VLANs configuradas.",v_mgmt:"VLAN de gestión",v_mgmt_none:"sin
v_optional:"opcional",v_setmgmt:"Establecer como VLAN de gestión",v_setmgmt_t:"Hacer esta la VLAN de gestión",
v_member:"Miembro",v_pvid:"PVID",
v_legend:"U = miembro sin etiquetar, T = miembro etiquetado, - = no miembro. PVID asigna esta VLAN al tráfico entrante sin etiquetar.",
v_ingress:"Filtrado de entrada",v_ingress_h:"solo escritura: el estado no se puede leer desde el switch",
v_accept:"Aceptar",v_ing_all:"Todos",v_ing_apply:"Aplicar modos de entrada",v_del_t:"Eliminar VLAN",
v_del_q:"¿Eliminar VLAN {n}?",v_del_d:"Los puertos conservan su PVID hasta que se reasignen.",
v_vid_err:"Introduce un ID de VLAN (1-4094)",v_name_err:"El nombre debe empezar por una letra (letras, dígitos, _)",
v_loaded:"VLAN {n} cargada",v_notfound:"VLAN {n} no encontrada (aún se puede crear una nueva)",
v_nomember:"Selecciona al menos un puerto miembro (o elimina la VLAN)",
v_ing_none:"Elige un modo de entrada para al menos un puerto",v_vid_first:"Introduce primero un ID de VLAN",
v_mgmt_q:"¿Establecer VLAN {n} como VLAN de gestión?",
v_vid_first:"Introduce primero un ID de VLAN",v_mgmt_q:"¿Establecer VLAN {n} como VLAN de gestión?",
v_mgmt_d:"El switch empezará a etiquetar su propio tráfico con esa VLAN. Si el puerto por el que te conectas no la transporta, esta página dejará de ser accesible y el ajuste solo podrá deshacerse por la consola.",
l2_title:"Tabla de direcciones MAC",l2_filter:"filtrar...",l2_flush:"Vaciar entradas aprendidas",l2_static:"estática",
l2_learned:"aprendida",l2_loading:"cargando...",l2_failed:"error de carga",l2_entries:"entradas",
@@ -518,14 +511,12 @@ v_empty:"Aucun VLANs configuré.",v_mgmt:"VLAN de management",v_mgmt_none:"déta
v_optional:"optionel",v_setmgmt:"Mette en VLAN de management",v_setmgmt_t:"Mettre celui-ci en VLAN de management",
v_member:"Membre",v_pvid:"PVID",
v_legend:"U = Membre détagué (UnTagged), T = membre tagué (Tagged), - = non membre. PVID (Port VLan ID) assigne ce VLAN au trafic entrant non tagué.",
v_ingress:"Filtrage entrant",v_ingress_h:"en ériture seule: cet état n'est pas lisible depuis le communtateur réseau",
v_accept:"Accepté",v_ing_all:"Tous",v_ing_apply:"Appliquer les filtes",v_del_t:"Supprimer le VLAN",
v_del_q:"Supprimer le VLAN {n}?",v_del_d:"Les ports conservent leur PVID tant qu'ils ne sont pas réassignés.",
v_vid_err:"Entrez un identifiant VLAN (1-4094)",v_name_err:"Le nom doit commencer par une lettre (lettre, chiffres, _)",
v_loaded:"VLAN chargés {n}",v_notfound:"VLAN {n} non trouvé (un nouveau peut toutefois être créé)",
v_nomember:"Selectionnez au moins un port membre (ou supprimez le VLAN)",
v_ing_none:"Sélectionnez le mode entrant pour au moins un port",v_vid_first:"Entrez un identifiant VLAN d'abord",
v_mgmt_q:"Mettre ce VLAN {n} en tant que VLAN de management?",
v_vid_first:"Entrez un identifiant VLAN d'abord",v_mgmt_q:"Mettre ce VLAN {n} en tant que VLAN de management?",
v_mgmt_d:"Ce commutateur commencera par taguer son propre trafic avec ce VLAN. Si le port avec lequel vous êtes connecté ne le permet pas, cette page deviendra inaccessible et les paramètres ne pourront plus être changés que via la console.",
l2_title:"Table des adresses MAC",l2_filter:"filtre...",l2_flush:"Effacer les entrées apprises",l2_static:"static",
l2_learned:"appris",l2_loading:"chargement...",l2_failed:"chargement non réussi",l2_entries:"entrées",
@@ -644,17 +635,18 @@ st_autoref:"automatisch aktualisieren",st_counter:"Zähler",st_value:"Wert",st_f
v_title:"VLANs",v_vid:"VID",v_members:"Mitglieder",v_tagged:"Tagged",v_untagged:"Untagged",v_pvid_on:"PVID auf",
v_empty:"Keine VLANs konfiguriert.",v_mgmt:"Management-VLAN",v_mgmt_none:"untagged",v_editor:"VLAN-Editor",
v_optional:"optional",v_setmgmt:"Als Management-VLAN",v_setmgmt_t:"Dieses VLAN zum Management-VLAN machen",
v_setmgmt_q:"{n} als Management-VLAN setzen?",v_add:"Neues VLAN hinzufügen",
v_mgmt_c:"WARNUNG: Du musst dieses VLAN erreichen können, um den Switch weiter verwalten zu können.",
v_member:"Mitglied",v_pvid:"PVID",
v_legend:"U = Mitglied untagged, T = Mitglied tagged, - = kein Mitglied. PVID ordnet eingehenden Verkehr ohne Tag diesem VLAN zu.",
v_ingress:"Ingress-Filter",v_ingress_h:"nur schreibbar: der Zustand lässt sich vom Switch nicht auslesen",
v_accept:"Annehmen",v_ing_all:"Alle",v_ing_apply:"Ingress-Modi übernehmen",v_del_t:"VLAN löschen",
v_accept:"Annehmen",v_ing_all:"Alle",v_ing_apply:"Ingress-Modi übernehmen",v_del_t:"VLAN löschen",v_rename:"Umbenennen",v_rename_t:"VLAN umbenennen",
v_del_q:"VLAN {n} löschen?",v_del_d:"Die Ports behalten ihre PVID, bis sie neu zugewiesen wird.",
v_vid_err:"VLAN-ID eingeben (1-4094)",v_name_err:"Der Name muss mit einem Buchstaben beginnen (Buchstaben, Ziffern, _)",
v_loaded:"VLAN {n} geladen",v_notfound:"VLAN {n} nicht gefunden (es kann neu angelegt werden)",
v_nomember:"Mindestens einen Mitglieds-Port wählen (oder das VLAN stattdessen löschen)",
v_ing_none:"Für mindestens einen Port einen Ingress-Modus wählen",v_vid_first:"Zuerst eine VLAN-ID eingeben",
v_mgmt_q:"VLAN {n} als Management-VLAN setzen?",
v_vid_first:"Zuerst eine VLAN-ID eingeben",v_mgmt_q:"VLAN {n} als Management-VLAN setzen?",
v_mgmt_d:"Der Switch versieht dann seinen eigenen Verkehr mit diesem VLAN-Tag. Führt der Port, über den du verbunden bist, dieses VLAN nicht, ist diese Seite nicht mehr erreichbar und die Einstellung lässt sich nur noch über die serielle Konsole zurücknehmen.",
v_mgmt_tt:"Das Management-VLAN lässt sich nicht löschen. Lege zuerst ein anderes VLAN als Management-VLAN fest.",
l2_title:"MAC-Adresstabelle",l2_filter:"filtern...",l2_flush:"Gelernte Einträge löschen",l2_static:"statisch",
l2_learned:"gelernt",l2_loading:"lädt...",l2_failed:"Laden fehlgeschlagen",l2_entries:"Einträge",
l2_del_t:"Eintrag löschen",l2_flush_q:"Alle gelernten MAC-Einträge löschen?",
@@ -811,34 +803,49 @@ function getJSON(p){return api(p).then(function(r){if(!r.ok)throw new Error(p+"
function getText(p){return api(p).then(function(r){if(!r.ok)throw new Error(p+" "+r.status);return r.body})}
var CONF_CMDS=[
/^ip\s+(\d{1,3}\.){3}\d{1,3}$/,/^ip\s+dhcp$/,
/^gw\s+(\d{1,3}\.){3}\d{1,3}$/,/^netmask\s+(\d{1,3}\.){3}\d{1,3}$/,
/^syslog\s+(on|off)$/,/^syslog\s+ip\s+(\d{1,3}\.){3}\d{1,3}$/,/^syslog\s+port\s+\d{1,5}$/,
/^ip\s+(\d{1,3}\.){3}\d{1,3}$/,
/^ip\s+dhcp$/,
/^gw\s+(\d{1,3}\.){3}\d{1,3}$/,
/^netmask\s+(\d{1,3}\.){3}\d{1,3}$/,
/^syslog\s+(on|off)$/,
/^syslog\s+ip\s+(\d{1,3}\.){3}\d{1,3}$/,
/^syslog\s+port\s+\d{1,5}$/,
/^session\s+\d{1,5}$/,
/^dns\s+server\s+(\d{1,3}\.){3}\d{1,3}(\s+(\d{1,3}\.){3}\d{1,3})?$/,
/^ntp\s+(on|off)$/,/^ntp\s+server\s+[A-Za-z0-9.-]{1,47}$/,/^ntp\s+interval\s+\d{1,4}$/,
/^ntp\s+timezone\s+[+-]?\d{1,2}(:\d{2})?$/,/^ntp\s+dst\s+(off|eu|us)$/,
/^ntp\s+(on|off)$/,
/^ntp\s+server\s+[A-Za-z0-9.-]{1,47}$/,
/^ntp\s+interval\s+\d{1,4}$/,
/^ntp\s+timezone\s+[+-]?\d{1,2}(:\d{2})?$/,
/^ntp\s+dst\s+(off|eu|us)$/,
/^passwd\s+\S+$/,/^hostname\s+\S{1,23}$/,
/^vlan\s+\d{1,4}\s+d$/,/^vlan\s+\d{1,4}\s+mgmt$/,
/^vlan\s+\d{1,4}(\s+[a-zA-Z]\w*)?(\s+\d{1,2}t?)+$/,
/^pvid\s+\d{1,2}\s+\d{1,4}$/,
/^ingress(\s+\d{1,2}[tua])+$/,/^ingress\s+[tua]$/,
/^port\s+\d{1,2}\s+(10m|100m|1g|2g5|5g|10g|auto|on|off)(\s+(half|full))?$/,
/^port\s+\d{1,2}\s+name\s+\S+$/,
/^port\s+\d{1,2}\s+lldp\s+(permit|block)+$/,
/^eee\s+(on|off)(\s+\d{1,2})?(\s+(100m|1g|2g5))?$/,
/^mirror(\s+\d{1,2})(\s+\d{1,2}[tr]?)+$/,/^mirror\s+off$/,
/^lag\s+[1-4](\s+\d{1,2})+$/,/^lag\s+[1-4]\s+d$/,/^lag\s+[1-4]\s+lacp(\s+\d{1,2})+$/,/^lag\s+[1-4]\s+lacp\s+off$/,/^laghash\s+[1-4](\s+\w+)+$/,
/^isolate\s+\d{1,2}(\s+(off|\d{1,2}))+$/,
/^stp\s+(on|off)$/,/^stp\s+(prio|hello|maxage|fwd|txhold)\s+\d{1,2}$/,
/^vlan\s+\d+\s+(d|mgmt)$/m,
/^vlan\s+\d+(\s+[a-zA-Z]\w*)?(\s+\d+t?)*$/m,
/^pvid\s+\d+\s+\d+$/m,
/^ingress(\s+\d+[tua])+$/,/^ingress\s+[tua]$/,
/^port\s+\d+\s+(10m|100m|1g|2g5|5g|10g|auto|on|off)(\s+(half|full))?$/,
/^port\s+\d+\s+name\s+\S+$/,
/^port\s+\d+\s+lldp\s+(permit|block)+$/,
/^eee\s+(on|off)(\s+\d+)?(\s+(100m|1g|2g5))?$/,
/^mirror(\s+\d+)(\s+\d+[tr]?)+$/,/^mirror\s+off$/,
/^lag\s+[1-4](\s+\d+)+$/,/^lag\s+[1-4]\s+d$/,
/^lag\s+[1-4]\s+lacp(\s+\d+)+$/,
/^lag\s+[1-4]\s+lacp\s+off$/,
/^laghash\s+[1-4](\s+\w+)+$/,
/^isolate\s+\d+(\s+(off|\d+))+$/,
/^stp\s+(on|off)$/,/^stp\s+(prio|hello|maxage|fwd|txhold)\s+\d+$/,
/^stp\s+version\s+(rstp|stp)$/,
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+(on|off)$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+edge\s+(on|off|auto)$/,
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+cost\s+\d{1,9}$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+prio\s+\d{1,3}$/,
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+guard\s+(none|bpdu|root)$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+filter\s+(on|off)$/,
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+p2p\s+(auto|on|off)$/,
/^igmp\s+(on|off)$/,/^mtu\s+\d{1,2}\s+\d+$/,/^lldp\s+(on|off)$/,
/^bw\s+(in|out)\s+\d{1,2}\s+\S+$/,
/^storm\s+\d{1,2}\s+(bcast|mcast|ucast|umcast)\s+(off|\d{1,8}\s+(pps|kbps))$/,
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+(on|off)$/,
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+edge\s+(on|off|auto)$/,
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+cost\s+\d+$/,
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+prio\s+\d+$/,
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+guard\s+(none|bpdu|root)$/,
/^stp\s+(port\s+\d+|lag\s+[1-4])\s+filter\s+(on|off)$/,
/^stp\s+(port\s+\d=|lag\s+[1-4])\s+p2p\s+(auto|on|off)$/,
/^igmp\s+(on|off)$/,
/^mtu\s+\d+\s+\d+$/,
/^lldp\s+(on|off)$/,
/^bw\s+(in|out)\s+\d+\s+\S+$/,
/^storm\s+\d+\s+(bcast|mcast|ucast|umcast)\s+(off|\d+\s+(pps|kbps))$/,
];
function isConfCmd(line){
for(var i=0;i<CONF_CMDS.length;i++)if(CONF_CMDS[i].test(line))return true;
@@ -862,7 +869,6 @@ function postCmds(list){
list.forEach(function(c){p=p.then(function(){return postCmd(c,true)})});
return p.then(function(){toast(t("t_cmds",{n:list.length}),"ok")});
}
function toast(msg,cls){
var el=h("div",{class:"toast "+(cls||""),text:msg});
$("toasts").appendChild(el);
@@ -948,6 +954,7 @@ function byPort(a){return a.sort(function(x,y){return x.portNum-y.portNum})}
function pollStatus(){
return getJSON("/status.json").then(function(s){
byPort(s);
S.ports=s;
var now=Date.now();
if(!S.n){
S.n=s.length;
@@ -969,7 +976,7 @@ function pollStatus(){
};
});
}
S.prev=s;S.prevT=now;S.ports=s;
S.prev=s;S.prevT=now;
updateStrip();
var hk=tabHooks[curTab];
if(hk&&hk.status)hk.status();
@@ -1475,131 +1482,282 @@ function rangeStr(list){
}
return parts.join(", ");
}
function vlanRefresh(){
var tb=$("vtable").tBodies[0];
return getJSON("/vlanlist").then(function(d){
var vl=d.vlan||[];
$("vmgmtcur").textContent=d.mgmt?String(d.mgmt):t("v_mgmt_none");
$("vempty").style.display=vl.length?"none":"";
tb.innerHTML="";
var p=Promise.resolve();
vl.forEach(function(v){
p=p.then(function(){return getJSON("/vlan.json?vid="+v.id).catch(function(){return null})}).then(function(d){
var tr=tb.insertRow();
tr.insertCell().appendChild(h("a",{href:"#vlan",text:String(v.id),onclick:function(e){
e.preventDefault();$("vvid").value=v.id;vlanLoad();
}}));
tr.insertCell().textContent=v.name||"";
if(!d){for(var c=0;c<4;c++)tr.insertCell().textContent="?";}
else{
var m=parseInt(d.members,16),mem=m&0x3ff,unt=((m>>10)&0x3ff)&mem;
var pv=parseInt(d.pvid,16)&0x3ff;
tr.insertCell().textContent=rangeStr(maskToPorts(mem));
tr.insertCell().textContent=rangeStr(maskToPorts(mem&~unt));
tr.insertCell().textContent=rangeStr(maskToPorts(unt));
tr.insertCell().textContent=rangeStr(maskToPorts(pv));
function vlanRefresh() {
var tb = $("vtable").tBodies[0];
tb.style="cursor:pointer;"
return getJSON("/vlanlist").then(function(d) {
var vl = d.vlan || [];
$("vmgmtcur").dataset.id = d.mgmt;
$("vempty").style.display = vl.length ? "none" : "";
tb.innerHTML = "";
var p = Promise.resolve();
vl.forEach(function(v) {
p = p.then(function() {
return getJSON("/vlan.json?vid=" + v.id).catch(function() {
return null
})
}).then(function(d) {
var tr = tb.insertRow();
tr.onclick = function(e) {
e.preventDefault();
vlanLoad(v.id);
};
var l = h("a", {
href: "#vlan",
text: String(v.id) + ($("vmgmtcur").dataset.id == v.id ? " ("+t("v_mgmt")+")":""),
"data-id": v.id,
"data-name": v.name
});
tr.insertCell().appendChild(l);
tr.insertCell().textContent = v.name || "";
if (!d) {
for (var c = 0; c < 4; c++) tr.insertCell().textContent = "?";
} else {
var m = parseInt(d.members, 16),
mem = m & 0x3ff,
unt = ((m >> 10) & 0x3ff) & mem,
tag = mem & ~unt;
var pv = parseInt(d.pvid, 16) & 0x3ff;
tr.insertCell().textContent = rangeStr(maskToPorts(mem));
tr.insertCell().textContent = rangeStr(maskToPorts(tag));
tr.insertCell().textContent = rangeStr(maskToPorts(unt));
tr.insertCell().textContent = rangeStr(maskToPorts(pv));
l.dataset.t = maskToPorts(tag);
l.dataset.u = maskToPorts(unt);
}
var del=tr.insertCell();
if(v.id!==1)del.appendChild(h("button",{class:"ctl",text:"\u2715",title:t("v_del_t"),onclick:function(){
confirmModal(t("v_del_q",{n:v.id}),t("v_del_d"),function(){
postCmd("vlan "+v.id+" d").then(vlanRefresh).catch(function(){});
});
}}));
}).catch(function(){});
var act = tr.insertCell();
act.onclick=function(e){e.stopPropagation()};
act.appendChild(h("button", {
class: "ctl",
text: t("v_rename"),
title: t("v_rename_t"),
onclick: function() {
var body = h("div");
body.appendChild(h("p", null, [
h("label", {class: "row"}, [
h("span",{class:"lb", "data-i18n":"c_name"},[document.createTextNode(t("c_name"))]),
h("input", {id: "nvlrename", class: "in", size: "12", maxlength: "15", "data-i18n-p": "v_optional", value:(v.name||"")})
])
]));
modal("Rename VLAN "+v.id, body, [h("button", {
class: "ctl pri", text: t("v_rename_t"),
onclick: function(){
if(!validVlanName($("nvlrename").value)) return;
postCmd(vlan2str(v.id,$("nvlrename").value,mySplit(l.dataset.t),mySplit(l.dataset.u))).then(function(){closeModal();vlanRefresh()});
}
})]);
},
}));
if (v.id == $("vmgmtcur").dataset.id) {
act.appendChild(h("span",{class:"ctl", title:t("v_mgmt_tt"), class:"hint", style:"color: var(--fg2); font-size: 150%; padding-left: 10px;"},[document.createTextNode("\u{1F6C8}")]));
} else {
act.appendChild(h("button", {
class: "ctl",
text: "\u2715",
title: t("v_del_t"),
style: "margin-left: 5px;",
onclick: function() {
confirmModal(t("v_del_q", { n: v.id }), t("v_del_d"), function() {
postCmd("vlan " + v.id + " d").then(vlanRefresh).catch(function() {});
});
}
}));
}
}).catch(function() {});
});
return p;
});
}
function buildVlanEdit(){
var tb=$("vedit").tBodies[0];
if(tb.rows.length||!S.n)return;
var hd=tb.insertRow();hd.insertCell().className="mut";
var rM=tb.insertRow();rM.insertCell().textContent=t("v_member");
var rP=tb.insertRow();rP.insertCell().textContent=t("v_pvid");
for(var p=1;p<=S.n;p++)(function(p){
hd.insertCell().innerHTML='<b>'+p+'</b>';
var seg=h("span",{class:"seg",id:"vm"+p});
["-","U","T"].forEach(function(s,ix){
seg.appendChild(h("button",{text:s,"data-v":ix,onclick:function(){
seg.querySelectorAll("button").forEach(function(b){b.classList.remove("on")});
this.classList.add("on");
}}));
function buildVlanEdit() {
var tb = $("vedit").tBodies[0];
if (tb.rows.length || !S.n) return;
var hd = tb.insertRow();
hd.insertCell().className = "mut";
var rN = tb.insertRow();
rN.insertCell().textContent = t("c_name");
var rM = tb.insertRow();
rM.insertCell().textContent = t("v_member");
var rP = tb.insertRow();
rP.insertCell().textContent = t("v_pvid");
for (var p = 1; p <= S.n; p++)(function(p) {
hd.insertCell().innerHTML = '<b>' + p + '</b>';
var seg = h("span", { class: "seg", id: "vm" + p });
["-", "U", "T"].forEach(function(s, ix) {
seg.appendChild(h("button", {
text: s,
"data-v": ix,
onclick: function() {
seg.querySelectorAll("button").forEach(function(b) { b.classList.remove("on") });
this.classList.add("on");
}
}));
});
seg.children[0].classList.add("on");
rN.insertCell().appendChild(document.createTextNode((S.ports.filter(x=>x.portNum==p)[0]).name));
rM.insertCell().appendChild(seg);
rP.insertCell().appendChild(h("input",{type:"checkbox",id:"vp"+p}));
rP.insertCell().appendChild(h("span", { id: "vp" + p }));
})(p);
var it=$("ingress").tBodies[0];
var ih=it.insertRow();ih.insertCell().className="mut";
var ir=it.insertRow();ir.insertCell().textContent=t("v_accept");
for(var q=1;q<=S.n;q++)(function(q){
ih.insertCell().innerHTML='<b>'+q+'</b>';
var sel=h("select",{class:"in",id:"ing"+q});
[["","-"],["a",t("v_ing_all")],["u",t("v_untagged")],["t",t("v_tagged")]].forEach(function(o){
sel.appendChild(h("option",{value:o[0],text:o[1]}));
});
ir.insertCell().appendChild(sel);
})(q);
}
function segVal(p){
return Number($("vm"+p).querySelector("button.on").getAttribute("data-v"));
}
function segSet(p,v){
$("vm"+p).querySelectorAll("button").forEach(function(b,i){b.classList.toggle("on",i===v)});
}
function vlanLoad(){
var vid=parseInt($("vvid").value,10);
if(!vid||vid<1||vid>4094){toast(t("v_vid_err"),"err");return;}
getJSON("/vlan.json?vid="+vid).then(function(d){
$("vname").value=d.name||"";
var m=parseInt(d.members,16),mem=m&0x3ff,unt=((m>>10)&0x3ff)&mem;
var pv=parseInt(d.pvid,16)&0x3ff;
for(var p=1;p<=S.n;p++){
var bit=S.physToLog[p-1];
segSet(p,(mem>>bit)&1?(((unt>>bit)&1)?1:2):0);
$("vp"+p).checked=!!((pv>>bit)&1);
}
toast(t("v_loaded",{n:vid}),"ok");
}).catch(function(){toast(t("v_notfound",{n:vid}),"err")});
}
function vlanApply(){
var vid=parseInt($("vvid").value,10);
if(!vid||vid<1||vid>4094){toast(t("v_vid_err"),"err");return;}
var name=$("vname").value.trim();
if(name&&!/^[a-zA-Z]\w*$/.test(name)){toast(t("v_name_err"),"err");return;}
var cmd="vlan "+vid+(name?" "+name:""),members=0;
for(var p=1;p<=S.n;p++){
var v=segVal(p);
if(v===1){cmd+=" "+p;members++;}
else if(v===2){cmd+=" "+p+"t";members++;}
}
if(!members){toast(t("v_nomember"),"err");return;}
var cmds=[cmd];
for(var q=1;q<=S.n;q++)if($("vp"+q).checked)cmds.push("pvid "+q+" "+vid);
postCmds(cmds).then(vlanRefresh).catch(function(){});
}
function ingressApply(){
var cmd="ingress",any=false;
for(var p=1;p<=S.n;p++){
var v=$("ing"+p).value;
if(v){cmd+=" "+p+v;any=true;}
}
if(!any){toast(t("v_ing_none"),"err");return;}
postCmd(cmd).catch(function(){});
}
$("vload").addEventListener("click",vlanLoad);
$("vapply").addEventListener("click",vlanApply);
$("ingapply").addEventListener("click",ingressApply);
$("vmgmt").addEventListener("click",function(){
var vid=parseInt($("vvid").value,10);
if(!vid){toast(t("v_vid_first"),"err");return;}
confirmModal(t("v_mgmt_q",{n:vid}),t("v_mgmt_d"),
function(){postCmd("vlan "+vid+" mgmt").then(vlanRefresh).catch(function(){})});
});
tabHooks.vlan={
enter:function(){needPorts(function(){buildVlanEdit();vlanRefresh().catch(function(){})})},
};
function segVal(p) {
return Number($("vm" + p).querySelector("button.on").getAttribute("data-v"));
}
function segSet(p, v) {
$("vm" + p).querySelectorAll("button").forEach(function(b, i) { b.classList.toggle("on", i === v) });
}
function vlanLoad(vid) {
if (!vid || vid < 1 || vid > 4094) {
toast(t("v_vid_err"), "err");
return;
}
getJSON("/vlan.json?vid=" + vid).then(function(d) {
$("vtitle").innerText = "VLAN " + vid + (d.name ? " (" + (d.name) + ")" : "");
$("vtitle").dataset.id = vid;
$("vtitle").dataset.name = d.name;
var m = parseInt(d.members, 16),
mem = m & 0x3ff,
unt = ((m >> 10) & 0x3ff) & mem;
var pv = parseInt(d.pvid, 16) & 0x3ff;
for (var p = 1; p <= S.n; p++) {
var bit = S.physToLog[p - 1];
segSet(p, (mem >> bit) & 1 ? (((unt >> bit) & 1) ? 1 : 2) : 0);
$("vp" + p).innerText = (!!((pv >> bit) & 1))?"Y":"N";
}
$("vmgmtpromote").checked = ($("vmgmtcur").dataset.id == vid);
toast(t("v_loaded", {n: vid}), "ok");
for(const vlanRow of $("vtable").tBodies[0].rows) {
vlanRow.className=vlanRow.firstChild.firstChild.dataset.id == vid ? "sel":"";
}
}).catch(function() {toast(t("v_notfound", {n: vid}), "err")});
}
function vlan2str(i, n, t, u){
return ("vlan " + i + (n ? " " + n : "") + " " + t.map((x)=>x+"t").concat(u).join(" ")).trim();
}
function pvidcmd(i, p){
return "pvid " + p + " " + i;
}
function mySplit(a){
if(a.trim()=="") return [];
return a.trim().split(",");
}
function vlanApply() {
var vid = $("vtitle").dataset.id;
var vname = $("vtitle").dataset.name;
if (!vid || vid < 1 || vid > 4094) {
toast(t("v_vid_err"), "err");
return;
}
var top_cmds = [], tail_cmds = [], vlansPerPort=[], thisVlanInStructure={id:vid, tagged:[], untagged:[]};
for (var p = 1; p <= S.n; p++) {
var v = segVal(p);
vlansPerPort[p]={t:[],u:[]};
if (v === 1) {
thisVlanInStructure.untagged.push(p);
vlansPerPort[p].u.push(vid);
} else if (v === 2) {
thisVlanInStructure.tagged.push(p);
vlansPerPort[p].t.push(vid);
}
}
if (thisVlanInStructure.tagged.length + thisVlanInStructure.untagged.length == 0) {
toast(t("v_nomember"), "err");
return;
}
for(const vlanRow of $("vtable").tBodies[0].rows){
var rowData = vlanRow.firstChild.firstChild.dataset,
rowUntagged = mySplit(rowData.u),
rowTagged = mySplit(rowData.t);
if(rowData.id == vid) continue;
for(const newVlanPort of thisVlanInStructure.untagged) {
if(rowUntagged.includes(""+newVlanPort)) rowUntagged.splice(rowUntagged.indexOf(""+newVlanPort),1);
}
for(const rut of rowUntagged) {
vlansPerPort[rut].u.push(rowData.id);
}
for(const rt of rowTagged) {
vlansPerPort[rt].t.push(rowData.id)
}
top_cmds.push(vlan2str(rowData.id,rowData.name,rowTagged,rowUntagged));
}
tail_cmds.push(vlan2str(vid, vname, thisVlanInStructure.tagged, thisVlanInStructure.untagged));
for (p in vlansPerPort){/*park all ports with only tagged membership*/
if (vlansPerPort[p].u.length == 0 && vlansPerPort[p].t.length > 0) {
tail_cmds.push(pvidcmd(0, p));
}
}
for(const up of thisVlanInStructure.untagged){
tail_cmds.push(pvidcmd(vid,up));
}
if($("vmgmtpromote").checked){/*must be the last command*/
tail_cmds.push("vlan " + vid + " mgmt");
}
var cmd = top_cmds.concat(tail_cmds);
postCmd(cmd.join("\n"),true).then(function(){toast(t("t_cmds",{n:cmd.length}),"ok")}).then(vlanRefresh).catch(function() {}).then(function() {
vlanLoad(vid)
});
}
$("vapply").addEventListener("click", vlanApply);
$("vlan_add").addEventListener("click", function() {
var body = h("div");
body.appendChild(h("p", null, [
h("label", {class: "row"}, [
h("span",{class:"lb", "data-i18n":"v_vid"},[document.createTextNode(t("v_vid"))]),
h("input", {id: "nvlid", class: "in sm", type: "number", min: "1", max: "4094"})
])
]));
body.appendChild(h("p", null, [
h("label", {class: "row"}, [
h("span",{class:"lb", "data-i18n":"c_name"},[document.createTextNode(t("c_name"))]),
h("input", {id: "nvlname", class: "in", size: "12", maxlength: "15", "data-i18n-p": "v_optional"})
])
]));
modal("Add VLAN", body, [h("button", {
class: "ctl pri", text: t("v_add"),
onclick: addVlan
})]);
});
function validVlanName(n){
if (n && (!/^[a-zA-Z]\w*$/.test(n) || n == "d" || n == "mgmt")) {
toast(t("v_name_err"), "err");
return false;
}
return true;
}
function addVlan() {
var vid = parseInt($("nvlid").value, 10);
for (const r of $("vtable").tBodies[0].rows) {
if (r.firstChild.firstChild.dataset.id == vid) {
toast(t("v_vid_err"), "err");
return;
}
}
var name = $("nvlname").value;
if(!validVlanName(name)) return false;
var cmd = "vlan " + vid + (name ? " " + name : "");
postCmd(cmd).then(function() {
closeModal();
vlanRefresh().then(function(){vlanLoad(vid)});
}).catch(function() {});
}
tabHooks.vlan = {
enter: function() {
needPorts(function() {
buildVlanEdit();
vlanRefresh().catch(function() {}).then(function() {
VlanInit();
})
})
},
};
function VlanInit() {
vlanLoad($("vtable").tBodies[0].firstChild.firstChild.firstChild.dataset.id)
};
var l2Rows=[],l2SortCol="pport",l2SortDir=1,l2Gen=0;
function l2Load(){
var seen={},all=[],idx=0,guard=0,gen=++l2Gen;
+19 -16
View File
@@ -93,6 +93,7 @@ table.t th.num{text-align:right}
table.t td{padding:6px 8px;border-bottom:1px solid var(--bd);vertical-align:middle}
table.t tr:last-child td{border-bottom:0}
table.t tr:hover td{background:var(--sel)}
table.t tr.sel{background:var(--panel2); font-weight: bold;}
.num{font-variant-numeric:tabular-nums;text-align:right}
.scrollx{overflow-x:auto}
input.in,select.in,textarea.in{
@@ -124,12 +125,20 @@ label.row span.lb{width:110px;flex:none;color:var(--fg2);font-size:13px}
.port .pn{font-weight:650;font-size:12px}
.port .ps{font-size:9px;color:var(--fg2);display:block;line-height:1.2}
.port .jack{
display:block;width:16px;height:10px;margin:2px auto 1px;border-radius:2px;
border:2px solid var(--fg2);border-top-width:4px;opacity:.55;
display:block;width:21px;height:12px;margin:4px auto 2px;border-radius:2px;
border:2px solid var(--fg2);border-top-width:8px;opacity:.55;position:relative;
}
.port.sfp .jack{width:24px;height:9px;border-top-width:3px}
.port .jack:before{content:"";
position:absolute;bottom:100%;left:50%;transform:translateX(-50%);
width:6px;height:5px;margin-bottom:7px;border-radius: 1px 1px 0 0;
background-color:var(--fg2);
}
.port.sfp .jack{width:24px;height:16px;margin:0 auto 2px;border-top-width:5px}
.port.sfp .jack:before{width:10px;margin-bottom:2px;border-radius:0 0 1px 1px;background-color:var(--panel2)}
.port.up{border-color:var(--pc);background:color-mix(in srgb,var(--pc) 10%,var(--panel2))}
.port.up .jack{border-color:var(--pc);opacity:1}
.port.up .jack:before{background-color:var(--pc)}
.port.up.sfp .jack:before{background-color:color-mix(in srgb,var(--pc) 10%,var(--panel2))}
.port.up .ps{color:var(--pc);font-weight:600}
.port.dis{opacity:.45;border-style:dashed}
.badge{font-size:11px;font-weight:600;border-radius:10px;padding:1px 8px;background:var(--panel2);color:var(--fg2)}
@@ -286,27 +295,21 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
</section>
<section class="tab" id="tab-vlan">
<div class="card"><h2><span data-i18n="v_title">VLANs</span> <span class="hint"><span data-i18n="v_mgmt">Management VLAN</span>: <span id="vmgmtcur">-</span></span></h2>
<div class="card"><h2><span data-i18n="v_title">VLANs</span><span id="vmgmtcur"></span></h2>
<div class="scrollx"><table class="t" id="vtable">
<thead><tr><th data-i18n="v_vid">VID</th><th data-i18n="c_name">Name</th><th data-i18n="v_members">Members</th><th data-i18n="v_tagged">Tagged</th><th data-i18n="v_untagged">Untagged</th><th data-i18n="v_pvid_on">PVID on</th><th></th></tr></thead>
<tbody></tbody></table></div>
<p class="small mut" id="vempty" style="display:none;margin-top:6px" data-i18n="v_empty">No VLANs configured.</p>
<button class="ctl pri" id="vlan_add" data-i18n="v_add">Add a new VLAN</button>
</div>
<div class="card"><h2 data-i18n="v_editor">VLAN editor</h2>
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:10px">
<label><span data-i18n="v_vid">VID</span> <input class="in sm" id="vvid" type="number" min="1" max="4094"></label>
<label><span data-i18n="c_name">Name</span> <input class="in" id="vname" size="12" maxlength="15" data-i18n-p="v_optional"></label>
<button class="ctl" id="vload" data-i18n="c_load">Load</button>
<button class="ctl pri" id="vapply" data-i18n="c_apply">Apply</button>
<button class="ctl" id="vmgmt" data-i18n="v_setmgmt" data-i18n-t="v_setmgmt_t">Set as mgmt VLAN</button>
</div>
<div class="card"><h2><span data-i18n="v_editor">VLAN editor</span> <span class="hint" id="vtitle"></span></h2>
<div><label class="row"><span class="lb" style="width:150px;" data-i18n="v_setmgmt_t"></span>
<span class="switch"><input type="checkbox" id="vmgmtpromote"><i></i></span>
</label></div>
<div class="scrollx"><table class="t" id="vedit"><tbody></tbody></table></div>
<div style="margin-top:10px"><button class="ctl pri" id="vapply" data-i18n="c_apply">Apply</button></div>
<p class="small mut" style="margin-top:6px" data-i18n="v_legend">U = untagged member, T = tagged member, - = not a member. PVID assigns this VLAN to untagged ingress traffic.</p>
</div>
<div class="card"><h2><span data-i18n="v_ingress">Ingress filtering</span> <span class="hint" data-i18n="v_ingress_h">write-only: the state is not readable from the switch</span></h2>
<div class="scrollx"><table class="t" id="ingress"><tbody></tbody></table></div>
<div style="margin-top:10px"><button class="ctl pri" id="ingapply" data-i18n="v_ing_apply">Apply ingress modes</button></div>
</div>
</section>
<section class="tab" id="tab-l2">
+13 -3
View File
@@ -1,9 +1,14 @@
CODE_LOCATION=0x1000
INSTALLER_ADDRESS=0x1100
CC = sdcc
SDCC_PREFIX = ../toolchain/sdcc-$(shell cat ../sdcc/* | cksum | cut -d' ' -f1)
ifeq ($(origin CC),default)
SDCC = $(SDCC_PREFIX)/bin/sdcc
CC = $(SDCC)
ASM = $(SDCC_PREFIX)/bin/sdas8051
endif
CC_FLAGS = -mmcs51
ASM = sdas8051
ASM ?= sdas8051
AFLAGS= -plosgff
BUILDDIR = output
@@ -13,9 +18,14 @@ OBJS = ${SRCS:%.c=$(BUILDDIR)/%.rel}
all: create_build_dir $(BUILDDIR)/updatebuilder $(BUILDDIR)/rtlplayground_oem_upgrade.bin
create_build_dir:
create_build_dir: $(SDCC)
mkdir -p $(BUILDDIR)
ifneq ($(SDCC),)
$(SDCC):
sh ../sdcc/build.sh $(abspath $(SDCC_PREFIX))
endif
$(BUILDDIR)/updatebuilder: updatebuilder.c
gcc $^ -o $@
+1 -1
View File
@@ -348,7 +348,7 @@ void installer(void)
{
CKCON = 0; // Initial Clock configuration
SFR_97 = 0; // HADDR?
MAP_FLASH_PAGE_TO_XDATA = 0; // HADDR?
// Set in managed mode:
SFR_b9 = 0x00;
+1 -1
View File
@@ -21,7 +21,7 @@ __code const struct machine machine = {
.sfp_port[1].sds = 1,
.sfp_port[1].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.reset_pin = GPIO48_I2C_SCL1,
.high_leds = { .mux = LED_28_SYS | LED_29, .enable = LED_27 | LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
+1
View File
@@ -2,6 +2,7 @@
__code const struct machine machine = {
MACHINE_COMMON_SETTING,
.mac_flash_offset = 0x1FC000,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
+41
View File
@@ -0,0 +1,41 @@
#include "machine_defs.h"
__code const struct machine machine = {
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},
.is_sfp = {0, 0, 0, 1, 0, 0, 0, 0, 2},
// Left SFP port (5)
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
// Right SFP port (6)
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[1].pin_los = GPIO_NA,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
/* On Ethernet: Left led is orange, right green
* 100M and 1G give right led green with activity
* 2.5GBit adds solid left orange LED
* LEDs for the SFP-ports are the same as for the Ethernet ports
*/
.led_sets = { { LEDS_2G5 | LEDS_LINK | LEDS_ACT,
0,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
LEDS_2G5 | LEDS_LINK | LEDS_ACT
},
{ LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M |
LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5,
LEDS_1G | LEDS_LINK,
LEDS_LINK,
LEDS_COL | LEDS_DUPLEX
}
}
};
+7
View File
@@ -0,0 +1,7 @@
#ifndef _MACHINE_ZOERAX_HG0402XG_V1_1_H_
#define _MACHINE_ZOERAX_HG0402XG_V1_1_H_
#define MACHINE_MODEL "ZoeRax HG0402XG V1.1"
#define MACHINE_CHIPSET RTL8372
#endif
+2
View File
@@ -19,6 +19,8 @@
#define MAC_ADDR_LEN 6
#define PORT_BIT(p) ((uint16_t)1 << (p))
#define NUL '\0'
#define STR_(x) #x
#define STR(x) STR_(x)
// Define Port-masks for 9-port devices and 6-port devices
#define PMASK_9 0x1ff
+1 -1
View File
@@ -55,7 +55,7 @@ __sfr __at(0xbb) SFR_BANK_RET;
__sfr __at(0x8e) CKCON;
__sfr __at(0x97) SFR_97; // HADDR?
__sfr __at(0x97) MAP_FLASH_PAGE_TO_XDATA; // 1 (hardware reset default): xdata 0x4000-0xbfff reads the flash image; 0: RAM
__sfr __at(0xb9) SFR_b9;
__sfr __at(0xba) SFR_ba;
+9 -1
View File
@@ -1567,6 +1567,15 @@ void check_and_flash_update_image(void)
}
/* Called by the SDCC startup code before it copies XINIT to XISEG and clears XSEG.
* Hardware reset starts us with MAP_FLASH_PAGE_TO_XDATA = 1, which maps xdata
* 0x4000-0xbfff to the flash image (reads return flash, writes are lost), so it
* must be 0 by then. */
unsigned char __sdcc_external_startup(void)
{
MAP_FLASH_PAGE_TO_XDATA = 0;
return 0;
}
void main(void)
{
@@ -1577,7 +1586,6 @@ void main(void)
sbuf_ptr = 0;
CKCON = 0; // Initial Clock configuration
SFR_97 = 0; // HADDR?
// Set in managed mode:
SFR_b9 = 0x00;