Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
018eab9810 | ||
|
|
ec36658ab9 | ||
|
|
eeded0f788 | ||
|
|
8f3b738e59 | ||
|
|
62065875e3 | ||
|
|
94e34a5991 | ||
|
|
b58b1dfb35 | ||
|
|
4ca5b4e87a | ||
|
|
5a8a8ed91b | ||
|
|
ad64e450e1 | ||
|
|
cfeffc434d | ||
|
|
8670709b6e | ||
|
|
1a457c29ac | ||
|
|
ce496ab25f | ||
|
|
964ef2da7a | ||
|
|
8c61010a84 | ||
|
|
053dbe286e | ||
|
|
e68e5cef46 | ||
|
|
b5543b6aeb | ||
|
|
a51fcf1478 | ||
|
|
247cb4dd2f | ||
|
|
394fc99485 | ||
|
|
cf0707475d | ||
|
|
73b99b2f08 | ||
|
|
005eaa3248 | ||
|
|
98f1e9443a | ||
|
|
4c2be334d5 | ||
|
|
073cc1e4a4 | ||
|
|
ba919280ac | ||
|
|
dcc60c3824 | ||
|
|
caad366b3b | ||
|
|
ce0ee859d6 | ||
|
|
a369e46fe6 | ||
|
|
defb37c06a | ||
|
|
a5f77e4caf | ||
|
|
1311cb9ea9 | ||
|
|
7d0d8525d2 | ||
|
|
201289990b | ||
|
|
3a93ce1786 | ||
|
|
4b42be8cae | ||
|
|
32f9b91def | ||
|
|
21f33abfa7 | ||
|
|
d253c9feee | ||
|
|
2552f586d8 | ||
|
|
f113b2c0e5 | ||
|
|
2d912d80c9 | ||
|
|
0682df3027 | ||
|
|
4b40efafbb | ||
|
|
02992771ad | ||
|
|
f81c497728 | ||
|
|
b46cc2087f | ||
|
|
3904daced7 | ||
|
|
623247da4f | ||
|
|
aa5368cf34 | ||
|
|
2b39d723c7 | ||
|
|
f6cb1152f9 | ||
|
|
bf9fa35338 | ||
|
|
8ab2a6a9da | ||
|
|
2316ffd493 | ||
|
|
a71eb57702 | ||
|
|
a2b2dbcfbf | ||
|
|
8cee16e96b | ||
|
|
a1135863bb | ||
|
|
ede4137101 | ||
|
|
0106f99ee0 | ||
|
|
733348059d | ||
|
|
950b763d69 | ||
|
|
22aaa9fbfe | ||
|
|
89e22f0893 | ||
|
|
809efaa8d8 | ||
|
|
271878a62f | ||
|
|
299b54f2a3 | ||
|
|
f47fec7098 | ||
|
|
04ce2cb8a1 | ||
|
|
96eddf5a0c | ||
|
|
2cd6f5d782 | ||
|
|
c6dc5cc21c | ||
|
|
502033590e | ||
|
|
f81529bd07 | ||
|
|
9714818b1f | ||
|
|
9c668969d4 | ||
|
|
241bcb273f | ||
|
|
10367d0cdb | ||
|
|
09d90d6d97 | ||
|
|
12c98ba6bd | ||
|
|
3f66a18104 | ||
|
|
8abbececd1 | ||
|
|
d6dbf4e4dd | ||
|
|
e2b3201c9f | ||
|
|
a7f4543698 | ||
|
|
2e0e55967c | ||
|
|
7877ce60f3 | ||
|
|
a3dd25e0fe | ||
|
|
441340a4d4 | ||
|
|
9a3f8c359d | ||
|
|
63ab6500c0 | ||
|
|
ec5f74bbed | ||
|
|
a597d2d08b | ||
|
|
abc9cb7afd | ||
|
|
6d579c4f00 | ||
|
|
c342964327 | ||
|
|
fd3a272255 | ||
|
|
4f4f69ecc1 | ||
|
|
c8e21b394b | ||
|
|
c34249b90a | ||
|
|
042f4324a4 | ||
|
|
e849af4a70 | ||
|
|
812bf3bb67 | ||
|
|
da8ec8fe88 | ||
|
|
f7989cc737 | ||
|
|
2e48415c95 | ||
|
|
22f8b9a287 | ||
|
|
c91177d992 | ||
|
|
c1a414833d | ||
|
|
2a9c7d2828 | ||
|
|
d776118815 | ||
|
|
f7b8aed2f7 | ||
|
|
7eb3676aaf | ||
|
|
eaa21d5975 | ||
|
|
193eacf51b | ||
|
|
b60811b984 | ||
|
|
b85861347b | ||
|
|
b21bfac917 |
@@ -12,15 +12,25 @@ AFLAGS= -plosgff
|
||||
SUBDIRS := tools
|
||||
SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS))
|
||||
|
||||
BUILDDIR = output
|
||||
VERSION_HEADER := version.h
|
||||
|
||||
ifeq ($(MACHINE),)
|
||||
MACHINE:= $(shell grep "^\s*#define MACHINE_" machine.h | sed "s/^\s*#define MACHINE_//")
|
||||
else
|
||||
CC_FLAGS += -DMACHINE_$(MACHINE)
|
||||
endif
|
||||
|
||||
all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)/rtlplayground.bin
|
||||
BUILDDIR = output/$(MACHINE)
|
||||
VERSION_HEADER := version.h
|
||||
|
||||
GIT_VERSION := $(shell git rev-parse --short HEAD)
|
||||
ifeq ($(shell git status --porcelain --untracked-files=no),)
|
||||
else
|
||||
GIT_VERSION := $(GIT_VERSION)-dirty
|
||||
endif
|
||||
|
||||
VERSION_EXTENSION = v$(VERSION)-$(GIT_VERSION)
|
||||
FILENAME_EXTENSION = $(VERSION_EXTENSION)-$(MACHINE)
|
||||
|
||||
all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
|
||||
|
||||
create_build_dir:
|
||||
mkdir -p $(BUILDDIR)
|
||||
@@ -28,20 +38,20 @@ create_build_dir:
|
||||
mkdir -p $(BUILDDIR)/httpd
|
||||
|
||||
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_leds.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c
|
||||
SRCS += rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c cmd_editor.c rtl837x_bandwidth.c rtl837x_init.c
|
||||
SRCS += uip/timer.c uip/uip.c uip/uip_arp.c uip/uiplib.c uip/uip-fw.c uip/uip-neighbor.c uip/uip-split.c
|
||||
SRCS += rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c cmd_editor.c rtl837x_bandwidth.c rtl837x_init.c syslog.c
|
||||
SRCS += uip/timer.c uip/uip.c uip/uip_arp.c uip/uiplib.c uip/uip-fw.c uip/uip-neighbor.c uip/uip-split.c udp_apps.c
|
||||
SRCS += httpd/httpd.c httpd/page_impl.c
|
||||
OBJS = ${SRCS:%.c=$(BUILDDIR)/%.rel}
|
||||
DEPS := ${SRCS:%.c=$(BUILDDIR)/%.d}
|
||||
HTML := $(shell find $(html) -name '*.js' -or -name '*.html' -or -name '*.svg')
|
||||
|
||||
html_data.c html_data.h: $(HTML) tools/$(BUILDDIR)/fileadder
|
||||
tools/$(BUILDDIR)/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -d html -p html_data
|
||||
html_data.c html_data.h: $(HTML) tools/output/fileadder
|
||||
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -d html -p html_data
|
||||
|
||||
$(VERSION_HEADER):
|
||||
@echo "#ifndef VERSION_H" > $(VERSION_HEADER)
|
||||
@echo "#define VERSION_H" >> $(VERSION_HEADER)
|
||||
@echo "#define VERSION_SW \"v$(VERSION)-g$(shell git rev-parse --short HEAD)\"" >> $(VERSION_HEADER)
|
||||
@echo "#define VERSION_SW \"$(VERSION_EXTENSION)\"" >> $(VERSION_HEADER)
|
||||
@echo "#define BUILD_DATE \"$(shell date +"%Y-%m-%d %H:%M:%S")\"" >> $(VERSION_HEADER)
|
||||
@echo "#endif" >> $(VERSION_HEADER)
|
||||
|
||||
@@ -51,6 +61,10 @@ $(SUBDIRS):
|
||||
$(MAKE) -C $@
|
||||
|
||||
clean:
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER)
|
||||
-if [ -d $(BUILDDIR) ]; then find $(BUILDDIR) -type f ! -name "*.bin" -delete; fi
|
||||
|
||||
distclean:
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER)
|
||||
-rm -rf $(BUILDDIR)
|
||||
|
||||
@@ -67,14 +81,14 @@ $(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtstart.rel $(BUILDDIR)/crc1
|
||||
$(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx
|
||||
objcopy --input-target=ihex -O binary $< $@
|
||||
|
||||
$(BUILDDIR)/rtlplayground.bin: $(BUILDDIR)/rtlplayground.img
|
||||
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img
|
||||
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)/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -d html -p html_data -b BANK1 $@
|
||||
tools/$(BUILDDIR)/crc_calculator -u $@
|
||||
|
||||
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) -d html -p html_data -b BANK1 $@
|
||||
tools/output/crc_calculator -u $@
|
||||
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin output/rtlplayground.bin
|
||||
|
||||
.PHONY: clean all $(SUBDIRS) $(VERSION_HEADER)
|
||||
|
||||
|
||||
@@ -52,88 +52,145 @@ devices by looking at the image using e.g. Ghidra. If you want to contribute to
|
||||
design of the web-interface or get a feeling for the interface first, a standalone
|
||||
device simulator is provided, which runs entirely under Linux as a local webserver.
|
||||
|
||||
## Compiling
|
||||
## (0) Compiling Requirements
|
||||
|
||||
Install the following particular build requisites (Debian 12/13), note that Ubuntu 24.04
|
||||
still has an older version of sdcc, but you will need sdcc version 4.5 for the code to compile:
|
||||
```
|
||||
sudo apt install make gcc sdcc xxd python-is-python3 libjson-c-dev
|
||||
```
|
||||
|
||||
## (1) Compiling for direct chip flashing AND upgrading an existing RTLPlayground running device
|
||||
|
||||
Edit machine.h with an editor like vi or nano. Select the correct machine the firmware should build for.
|
||||
|
||||
> [!TIP]
|
||||
> You can write configuration parameters in config.txt (see below) in order your switch to get
|
||||
> straight at the first boot, a correct IP configuration.
|
||||
|
||||
Now, building the firmware image should work:
|
||||
```
|
||||
make
|
||||
```
|
||||
Note, that the image generated ends in .bin, not .img, in order to make
|
||||
IMSProg happy.
|
||||
Note, that the image generated ends in .bin, not .img, in order to make IMSProg happy.
|
||||
|
||||
image location is stored in `RTLPlayground/output/rtlplayground_version_machine.bin`
|
||||
for example
|
||||
```
|
||||
rtlplayground-v0.1.0-12c98ba-dirty-LIANGUO_ZX_SWTGW215AS.bin
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> This image can be flashed directly to the chip OR through the firmware update/upgrade
|
||||
> interface of RTLPlaygound interface
|
||||
|
||||
## (2) Compiling for OEM running device with management options (web upgrade)
|
||||
|
||||
Managed switches can be updated from the existing original firmware using a SPECIFIC upgrade image.
|
||||
You first need to build the firmware for direct chip flashing : See below (1)
|
||||
|
||||
Then
|
||||
|
||||
```
|
||||
cd installer
|
||||
make
|
||||
```
|
||||
image location is stored in `RTLPlayground/installer/output/rtlplayground_oem_upgrade.bin`
|
||||
|
||||
> [!CAUTION]
|
||||
> This image must ONLY be used for original OEM firmware web interface firmware upgrade.
|
||||
> You do not need this image if you are already on RTLplayground firmware.
|
||||
> Unless you go back to the original OEM firmware, you would only flash this specific firmware
|
||||
> only once. Future upgrades of RTLPlayground will only need to follow (1)
|
||||
|
||||
example of compilation console output
|
||||
|
||||
Managed switches can be updated from the existing original firmware using an upgrade image.
|
||||
In the `installer`folder of the source code you will need to run `make` which will build
|
||||
an image out of `rtlplayground.bin` built in the previous step:
|
||||
```
|
||||
RTLPlayground/installer$ make
|
||||
mkdir -p output/
|
||||
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
|
||||
cp ../output//rtlplayground.bin output/
|
||||
./output//updatebuilder -i output/rtlinstaller.ihx output/rtlplayground.bin
|
||||
./output/updatebuilder -i output/rtlinstaller.ihx -o output/rtlplayground_oem_upgrade.bin ../output/rtlplayground.bin
|
||||
Input file size: 524288
|
||||
Bytes read: 524288
|
||||
EOF
|
||||
Payload sum 1 is: 0x29d10
|
||||
Payload sum 2 is: 0x29d10
|
||||
Payload sum with header is: 0x2b0fc
|
||||
Payload sum is: 0xad8a75
|
||||
Header checksum is: 0x4c3
|
||||
Payload sum 1 is: 0x25100
|
||||
Payload sum 2 is: 0x25100
|
||||
Payload sum with header is: 0x264ec
|
||||
Payload sum is: 0xf8fe94
|
||||
Header checksum is: 0x5a1
|
||||
```
|
||||
The resulting image can be found in `RTLPlayground/installer/output/rtlplayground.bin`
|
||||
> [!CAUTION]
|
||||
> DO NOT UPLOAD THE UPGADE IMAGE UNLESS YOU CAN MAKE A BACKUP USING A SOIC CLAMP OF THE
|
||||
> ORIGINAL FIRMWARE!
|
||||
|
||||
## Installation
|
||||
## (3) Sandbox Usage with Ghidra (optional)
|
||||
|
||||
You can play with the image using ghidra or flash real Switch Hardware. For
|
||||
ghidra see this information about [Ghidra images](ghidra.md).
|
||||
|
||||
## (4) Installation through the Web interface (software way)
|
||||
|
||||
Managed switches (OEM firmware of RTLplaygroud firmware) can be upgraded via the web interface.
|
||||
Unmanaged switch cannot be flashed this way (see 5).
|
||||
|
||||
Go to "Firmware update" tab, select the correct file.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If your device already runs RTLPlayground, you must upload the binary file /RTLPlayground/output/rtlplayground_Version_Machine.bin
|
||||
> If your device is OEM, you must upload the binary file /RTLPlayground/installer/outputrtlplayground_oem_upgrade.bin
|
||||
|
||||
> [!CAUTION]
|
||||
> NOTE THAT WHILE THIS PROCEDURE HAS BEEN SUCCESSFULLY TESTED ON ALL DEVICES ABOVE,
|
||||
> ABSOLUTELY NO GUARANTY CAN BE GIVEN THAT YOU WILL NOT DESTROY YOUR SWITCH,
|
||||
> ANY OTHER EQUIPMENT INVOLVED OR HARM YOURSELF BY OPENING THE ELECTRONIC
|
||||
> DEVICE. OPENING THE SWITCH WILL VOID ITS WARRANTY.
|
||||
> Check one more time that your device matches the machine type before flashing.
|
||||
> Be shure you have a backup of the original firmware before diving in RTLPlaygroung.
|
||||
|
||||
You can upload the upgrade image of managed switches via the web interface of the
|
||||
original firmware just as if you were installing a firmware upgrade. However,
|
||||
this is strongly discouraged, as you may brick your device, unless you can make
|
||||
firmware backups via a SOIC clamp or soldered flash socket, first!
|
||||
Finally, push the Upload File Button and you're done !
|
||||
|
||||
For unmanaged devices, the only way to install RTLPlayground is by flashing the
|
||||
Flash memory directly.
|
||||
|
||||
You will need to open your switch to flash the image directly onto the flash chip,
|
||||
which is done easiest using a SOIC-8 clip (alternatively you de-solder the
|
||||
flash chip and install a SOIC adapter):
|
||||
- Disconnect power from switch
|
||||
- Attach the clip onto the flash chip
|
||||
- Connect USB of flash programmer, the power LED on the switch will light
|
||||
up, check cabling if not. Don't panic, mixing up GND and 3.3V does not
|
||||
seem to destroy the switch (at leasts the on I did this to).
|
||||
- Use IMSProg (flashrom should work, too) to detect the clip
|
||||
- MAKE A BACKUP OF THE EXISTING FIRMWARE!
|
||||
- then load the firmware into IMSProg
|
||||
- and program flash
|
||||
## (5) Flashing the ROM directly (hardware way, but also only way to rescue)
|
||||
|
||||
Now you can connect a serial cable to the UART port found on all the
|
||||
devices, set 8N1 @ 115200 baud and power up the switch.
|
||||
This procedure is the only way to flash unmanaged switches, if the ROM chip is large enough.
|
||||
This is also the only way to unbrick your device if something went wroong.
|
||||
|
||||
The device will perform some examples and provide a minimal console, the
|
||||
documentation of which can be found in the source code rtlplayground.c`.
|
||||
> [!IMPORTANT]
|
||||
> You need a SOIC-8 clip to flash the ROM chip directly onboard.
|
||||
> Alternatively you can de-solder the flash chip and install a SOIC adapter).
|
||||
> For flashing the chip directly, you must use the binary file /RTLPlayground/output/rtlplayground_Version_Machine.bin
|
||||
|
||||
## The web-interface
|
||||
The web-interface can be reached under the [default 192.168.10.247](http://192.168.10.247).
|
||||
The default password is `1234`.
|
||||
> [!CAUTION]
|
||||
> As you need to open your switch case, consider that the warranty is gone.
|
||||
|
||||
- Disconnect power from switch.
|
||||
- Open the switch.
|
||||
- Attach the clip onto the flash chip (Red line on Pin 1, Pin 1 has a point marker).
|
||||
- Connect USB of flash programmer, the power LED on the switch will light up, check cabling if not.
|
||||
- Don't panic, mixing up GND and 3.3V usually does not destroy the switch.
|
||||
- Use IMSProg, Flashrom, or whatever Programmer to detect the chip.
|
||||
- MAKE A BACKUP (DUMP) OF THE EXISTING FIRMWARE !
|
||||
- ERASE THE ROM (BLANK) !
|
||||
- Load the firmware into IMSProg.
|
||||
- Flash is to the ROM chip.
|
||||
- Disconect the clip from the ROM chip.
|
||||
- You're done, ready for the first boot.
|
||||
|
||||
## (6) Connecting a serial interface (optional)
|
||||
|
||||
You can connect a serial cable to the UART port found on all the devices, set 8N1 @ 115200 baud.
|
||||
|
||||
## (7) Power Up
|
||||
|
||||
When you power up the switch, the device will perform some examples and provide a minimal console
|
||||
(if wired to a serial interface), the documentation of which can be found in the source code rtlplayground.c`.
|
||||
|
||||
## (8) The web-interface
|
||||
|
||||
The web-interface can be reached under the [default 192.168.10.247](http://192.168.10.247) unless you
|
||||
specified an IP adress in the config.txt before compilation.
|
||||
|
||||
> [!TIP]
|
||||
> The default password is `1234`.
|
||||
|
||||
## (9) The command line
|
||||
|
||||
## The command line
|
||||
The command line is very rudimentary and mostly for testing purposes.
|
||||
The following is a boot-log with some examples:
|
||||
```
|
||||
@@ -198,7 +255,6 @@ PORT 04 1G
|
||||
<MODULE INSERTED> Rate: 67 Encoding: 01
|
||||
Lightron Inc. WSPXG-ES3LC-IHA 0000
|
||||
|
||||
|
||||
> stat
|
||||
CMD: stat
|
||||
Port State Link TxGood TxBad RxGood RxBad
|
||||
@@ -216,17 +272,40 @@ Lightron Inc. WSPXG-ES3LC-IHA 0000
|
||||
CMD: sfp
|
||||
Rate: 67 Encoding: 01
|
||||
Lightron Inc. WSPXG-ES3LC-IHA 0000
|
||||
```
|
||||
|
||||
## (10) Advanced configuration
|
||||
|
||||
You can configure more deeply the switch without the need of the console mode.
|
||||
|
||||
While in compilation part, you might write directly to config.txt file before making the binary firmware
|
||||
|
||||
```
|
||||
nano config.txt
|
||||
```
|
||||
|
||||
If you want to modify settings after the flash is done, go to the Advanced Settings tab in System Settings
|
||||
|
||||
<img width="1085" height="646" alt="ADVANCED SETTINGS" src="doc/images/advanced_settings.png" />
|
||||
|
||||
```
|
||||
ip xxx.xxx.xxx.xxx = IP adress of the switch
|
||||
gw yyy.yyy.yyy.yyy = IP adress of the gateway
|
||||
netmask zzz.zzz.zzz.zzz = Network mask of the switch
|
||||
port x name xxx = Name xxx the port number x
|
||||
port z 1g = Set 1g speed for port z
|
||||
igmp on/off = Turn IGMP on or off
|
||||
```
|
||||
[To be continue]
|
||||
|
||||
Enjoy playing!
|
||||
|
||||
## Other documents
|
||||
The following documents give further documentation on specific features of
|
||||
the RTL837x SoCs:
|
||||
## (11) Other documents
|
||||
|
||||
The following documents give further documentation on specific features of the RTL837x SoCs:
|
||||
- [RTL8372/3 Feature support](doc/hardware.md)
|
||||
- [CPU Port](doc/CpuPort.md)
|
||||
- [L2 learning](doc/l2.md)
|
||||
- [CPU Port](doc/CpuPort.md)
|
||||
- [IGMP (IP-MC streaming)](doc/igmp.md)
|
||||
- [SFP+ ports](doc/sfp.md)
|
||||
- [Trunking aka. port aggregation](doc/trunking.md)
|
||||
|
||||
@@ -197,7 +197,7 @@ void cmd_edit(void) __banked
|
||||
if (cmd_line_len)
|
||||
cmd_available = 1;
|
||||
else
|
||||
print_string("\n> ");
|
||||
print_cmd_prompt();
|
||||
cursor = 0;
|
||||
cmd_line_len = 0;
|
||||
history_editptr = 0xffff;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "rtl837x_igmp.h"
|
||||
#include "rtl837x_bandwidth.h"
|
||||
#include "dhcp.h"
|
||||
#include "syslog.h"
|
||||
#include "uip/uip.h"
|
||||
#include "version.h"
|
||||
|
||||
@@ -47,6 +48,8 @@ __xdata uint16_t vlan_ptr;
|
||||
__xdata char port_names[9][PORT_NAME_SIZE];
|
||||
|
||||
extern __xdata uint16_t management_vlan;
|
||||
extern __xdata uint8_t sfp_speed[2];
|
||||
extern __xdata uint8_t sfp_pins_last;
|
||||
__xdata uint8_t gpio_last_value[8] = { 0 };
|
||||
|
||||
// Temporatly for str to hex convertion value.
|
||||
@@ -330,6 +333,8 @@ void parse_vlan(void)
|
||||
vlan_settings.vlan = 0;
|
||||
vlan_settings.members = 0;
|
||||
vlan_settings.tagged = 0;
|
||||
if (cmd_words_len < 2)
|
||||
goto err;
|
||||
if (!atoi_short(&vlan_settings.vlan, cmd_words_b[1])) {
|
||||
if (cmd_words_len == 3 && cmd_buffer[cmd_words_b[2]] == 'd') {
|
||||
vlan_delete(vlan_settings.vlan);
|
||||
@@ -346,10 +351,11 @@ void parse_vlan(void)
|
||||
uint8_t w = 2;
|
||||
if (cmd_words_len > w && isletter(cmd_buffer[cmd_words_b[w]])) {
|
||||
register uint8_t i = 0;
|
||||
vlan_name_remove(vlan_settings.vlan);
|
||||
vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 8) & 0xf];
|
||||
vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 4) & 0xf] ;
|
||||
vlan_names[vlan_ptr++] = hex[vlan_settings.vlan & 0xf];
|
||||
while(cmd_buffer[cmd_words_b[w] + i] != ' ') {
|
||||
while(cmd_buffer[cmd_words_b[w] + i] != ' ' && cmd_buffer[cmd_words_b[w] + i] != '\0') {
|
||||
write_char(cmd_buffer[cmd_words_b[w] + i]);
|
||||
vlan_names[vlan_ptr++] = cmd_buffer[cmd_words_b[w] + i++];
|
||||
}
|
||||
@@ -661,6 +667,14 @@ void parse_port(void)
|
||||
else if (cmd_compare(3, "full"))
|
||||
phy_settings.duplex = PHY_DUPLEX_FULL;
|
||||
phy_set_speed();
|
||||
} else if (cmd_compare(2, "10g")) {
|
||||
print_string(" 10G\n");
|
||||
phy_settings.speed = PHY_SPEED_10G;
|
||||
phy_set_speed();
|
||||
} else if (cmd_compare(2, "5g")) {
|
||||
print_string(" 5G\n");
|
||||
phy_settings.speed = PHY_SPEED_5G;
|
||||
phy_set_speed();
|
||||
} else if (cmd_compare(2, "2g5")) {
|
||||
print_string(" 2.5G\n");
|
||||
phy_settings.speed = PHY_SPEED_2G5;
|
||||
@@ -684,9 +698,9 @@ void parse_port(void)
|
||||
} else if (cmd_compare(2, "duplex")) {
|
||||
print_string(" DUPLEX\n");
|
||||
if (cmd_compare(3, "full"))
|
||||
phy_settings.speed = PHY_DUPLEX_FULL;
|
||||
phy_settings.duplex = PHY_DUPLEX_FULL;
|
||||
else
|
||||
phy_settings.speed = PHY_DUPLEX_HALF;
|
||||
phy_settings.duplex = PHY_DUPLEX_HALF;
|
||||
phy_set_duplex();
|
||||
} else {
|
||||
print_string("Unknown port command\n");
|
||||
@@ -739,6 +753,64 @@ void sfp_print_measurements(uint8_t sfp)
|
||||
}
|
||||
|
||||
|
||||
void parse_sfp(void)
|
||||
{
|
||||
uint8_t slot;
|
||||
|
||||
if (cmd_words_len != 1 && cmd_words_len != 3)
|
||||
goto err;
|
||||
|
||||
if (cmd_words_len == 1) {
|
||||
for (slot = 0; slot < machine.n_sfp; slot++) {
|
||||
print_string("\nSlot "); write_char('1' + slot);
|
||||
if (gpio_pin_test(machine.sfp_port[slot].pin_detect)) {
|
||||
print_string(" - empty\n");
|
||||
continue;
|
||||
}
|
||||
print_string(" - Rate: "); print_byte(sfp_read_reg(slot, 12));
|
||||
print_string(" Encoding: "); print_byte(sfp_read_reg(slot, 11));
|
||||
write_char('\n');
|
||||
sfp_print_info(slot);
|
||||
sfp_print_measurements(slot);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (cmd_buffer[cmd_words_b[1]] < '1' || cmd_buffer[cmd_words_b[1]] > '2' || cmd_buffer[cmd_words_b[1] + 1] != ' ' ) {
|
||||
print_string("Illegal SFP slot number\n");
|
||||
return;
|
||||
}
|
||||
slot = cmd_buffer[cmd_words_b[1]] - '1';
|
||||
if (slot >= machine.n_sfp) {
|
||||
print_string("SFP slot not present\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd_compare(2, "10g")) {
|
||||
print_string(" 10G\n");
|
||||
sfp_speed[slot] = SFP_SPEED_10G;
|
||||
} else if (cmd_compare(2, "2g5")) {
|
||||
print_string(" 2.5G\n");
|
||||
sfp_speed[slot] = SFP_SPEED_2G5;
|
||||
} else if (cmd_compare(2, "1g")) {
|
||||
print_string(" 1G\n");
|
||||
sfp_speed[slot] = SFP_SPEED_1G;
|
||||
} else if (cmd_compare(2, "100m")) {
|
||||
print_string(" 100M\n");
|
||||
sfp_speed[slot] = SFP_SPEED_100M;
|
||||
} else if (cmd_compare(2, "auto")) {
|
||||
print_string(" AUTO\n");
|
||||
sfp_speed[slot] = SFP_SPEED_AUTO;
|
||||
} else {
|
||||
goto err;
|
||||
}
|
||||
sfp_pins_last |= 0x1 << (slot << 2);
|
||||
handle_sfp();
|
||||
return;
|
||||
err:
|
||||
print_string("\nUsage:\n\tsfp\n\tsfp [1|2] [1g|2g5|10g]\n");
|
||||
}
|
||||
|
||||
|
||||
void parse_regget(void)
|
||||
{
|
||||
uint16_t reg = 0;
|
||||
@@ -778,7 +850,7 @@ void parse_regset(void)
|
||||
{
|
||||
uint16_t reg = 0;
|
||||
|
||||
if (cmd_words_len != 2) {
|
||||
if (cmd_words_len != 3) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1062,6 +1134,9 @@ void parse_eee(void)
|
||||
__xdata int8_t port = -1;
|
||||
__xdata uint8_t speed = EEE_2G5;
|
||||
__xdata uint8_t speed_word = 0;
|
||||
|
||||
if (machine.n_10g)
|
||||
speed = EEE_10G;
|
||||
// Check if word 2 is a speed (contains 'g' or 'm') or a port number
|
||||
if (cmd_words_len >= 3) {
|
||||
uint8_t idx = cmd_words_b[2];
|
||||
@@ -1188,6 +1263,52 @@ err:
|
||||
print_string("usage: bw [in|out|status] <port> [<hexvalue>|off|drop|fc]\n");
|
||||
}
|
||||
|
||||
void parse_syslog(void)
|
||||
{
|
||||
if (cmd_words_len < 2) // no argument -> print status
|
||||
{
|
||||
print_string("Current syslog status: ");
|
||||
if (syslog_state.enabled) {
|
||||
print_string("enabled, sending to ");
|
||||
itoa(syslog_state.server_ip[0]); write_char('.'); itoa(syslog_state.server_ip[1]); write_char('.');
|
||||
itoa(syslog_state.server_ip[2]); write_char('.'); itoa(syslog_state.server_ip[3]);
|
||||
write_char('\n');
|
||||
} else {
|
||||
print_string("disabled\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd_compare(1, "on")) {
|
||||
syslog_start();
|
||||
} else if (cmd_compare(1, "off")){
|
||||
syslog_stop();
|
||||
} else if (cmd_compare(1, "ip")) {
|
||||
if (cmd_words_len < 3) { // no additional arguemnt -> print current ip
|
||||
print_string("Current syslog IP: ");
|
||||
itoa(syslog_state.server_ip[0]); write_char('.'); itoa(syslog_state.server_ip[1]); write_char('.');
|
||||
itoa(syslog_state.server_ip[2]); write_char('.'); itoa(syslog_state.server_ip[3]);
|
||||
return;
|
||||
} else if (!parse_ip(cmd_words_b[2])) {
|
||||
uint8_t was_enabled = syslog_state.enabled;
|
||||
if (was_enabled)
|
||||
syslog_stop();
|
||||
print_string("Setting new syslog IP.\n");
|
||||
syslog_state.server_ip[0] = ip[0]; syslog_state.server_ip[1] = ip[1];
|
||||
syslog_state.server_ip[2] = ip[2]; syslog_state.server_ip[3] = ip[3];
|
||||
if (was_enabled)
|
||||
syslog_start();
|
||||
} else {
|
||||
print_string("Invalid IP address\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print_string("Error: syslog [on|off|ip [ip-address]]\n");
|
||||
print_string(" on/off enables or disables syslog, ip sets the syslog server IP address\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Parse command into words
|
||||
// cmd_words_len contains the number of words found.
|
||||
// cmd_words_b[] contains only start of a word offset.
|
||||
@@ -1297,18 +1418,7 @@ void cmd_parser(void) __banked
|
||||
print_string("\nRESET\n\n");
|
||||
reset_chip();
|
||||
} else if (cmd_compare(0, "sfp")) {
|
||||
print_string("\nSlot 1 - Rate: "); print_byte(sfp_read_reg(0, 12));
|
||||
print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11));
|
||||
print_string("\n");
|
||||
sfp_print_info(0);
|
||||
sfp_print_measurements(0);
|
||||
if (machine.n_sfp == 2) {
|
||||
print_string("\nSlot 2 - Rate: "); print_byte(sfp_read_reg(1, 12));
|
||||
print_string(" Encoding: "); print_byte(sfp_read_reg(1, 11));
|
||||
print_string("\n");
|
||||
sfp_print_info(1);
|
||||
sfp_print_measurements(1);
|
||||
}
|
||||
parse_sfp();
|
||||
} else if (cmd_compare(0, "stat")) {
|
||||
port_stats_print();
|
||||
} else if (cmd_compare(0, "flash") && cmd_words_len == 2) {
|
||||
@@ -1339,6 +1449,8 @@ void cmd_parser(void) __banked
|
||||
parse_port();
|
||||
} else if (cmd_compare(0, "mtu")) {
|
||||
parse_mtu();
|
||||
} else if (cmd_compare(0, "syslog")) {
|
||||
parse_syslog();
|
||||
} else if (cmd_compare(0, "ip")) {
|
||||
if (cmd_compare(1, "dhcp")) {
|
||||
dhcp_start();
|
||||
@@ -1579,3 +1691,37 @@ config_done:
|
||||
clear_command_history();
|
||||
save_cmd = 1;
|
||||
}
|
||||
|
||||
// Execute multiple commands
|
||||
// If a command is too long or can't be tokenized, remaining commands are not executed
|
||||
// Returns the status via `err_status`-variable.
|
||||
void execute_commands(__xdata uint8_t *p) __banked {
|
||||
err_status = ERR_OK;
|
||||
uint8_t cmd_idx = 0;
|
||||
while (1) {
|
||||
if (*p == 0 || *p == '\n' || *p == '\r') {
|
||||
if (cmd_idx) {
|
||||
cmd_buffer[cmd_idx] = '\0';
|
||||
cmd_tokenize();
|
||||
if (err_status != ERR_OK)
|
||||
return;
|
||||
cmd_parser();
|
||||
}
|
||||
if (*p == 0)
|
||||
return;
|
||||
cmd_idx = 0;
|
||||
} else {
|
||||
if (cmd_idx < (CMD_BUF_SIZE - 1)) {
|
||||
cmd_buffer[cmd_idx++] = *p;
|
||||
} else {
|
||||
cmd_buffer[CMD_BUF_SIZE - 1] = '\0';
|
||||
print_string("ERROR: Command too long: ");
|
||||
print_string_x(cmd_buffer);
|
||||
write_char('\n');
|
||||
err_status = ERR_CMD_TOO_LONG;
|
||||
return;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,10 +7,13 @@
|
||||
|
||||
extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
|
||||
extern __xdata uint8_t cmd_available;
|
||||
extern __xdata uint8_t err_status;
|
||||
|
||||
void cmd_tokenize(void) __banked;
|
||||
void cmd_parser(void) __banked;
|
||||
void execute_config(void) __banked;
|
||||
void execute_commands(__xdata uint8_t *p) __banked;
|
||||
void print_sw_version(void) __banked;
|
||||
void clear_command_history(void) __banked;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -348,8 +348,10 @@ void dhcp_stop(void) __banked
|
||||
}
|
||||
|
||||
|
||||
void dhcp_callback(void) __banked
|
||||
void dhcp_callback(uint16_t lport) __banked
|
||||
{
|
||||
if (lport != HTONS(DHCPC_CLIENT_PORT)) // Is this call for us? If not, ignore it
|
||||
return;
|
||||
if (!dhcp_state.state)
|
||||
return;
|
||||
if (uip_closed()) {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
void dhcp_start(void) __banked;
|
||||
void dhcp_stop(void) __banked;
|
||||
// void dhcp_periodic(void) __banked;
|
||||
void dhcp_callback(void) __banked;
|
||||
void dhcp_callback(uint16_t lport) __banked;
|
||||
|
||||
|
||||
struct dhcp_state {
|
||||
@@ -40,9 +40,4 @@ struct dhcp_state {
|
||||
|
||||
typedef struct dhcp_state uip_udp_appstate_t;
|
||||
|
||||
/* Finally we define the application function to be called by uIP. */
|
||||
#ifndef UIP_UDP_APPCALL
|
||||
#define UIP_UDP_APPCALL dhcp_callback
|
||||
#endif /* UIP_APPCALL */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# FOXNEO FNS-1200P
|
||||
|
||||
RTL8372-based 4×2.5G PoE+ + 2×SFP+ unmanaged switch.
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Manufacturer**: FOXNEO
|
||||
- **Model**: FNS-1200P
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps with PoE+
|
||||
- 2 × SFP+: 1G / 2.5G / 10G
|
||||
|
||||
### What works
|
||||
|
||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps (PoE+ is not configurable via RTLPlayground)
|
||||
- Both SFP+ ports supporting 1G, 2.5G and 10G modules
|
||||
- LEDs: amber (2.5G) and green (1G/100M/10M) per copper port; combined link/act on SFP ports
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-K0402W-U13-V2.0 / DIP-K0402WB-V2.0
|
||||
|
||||
**Key components**
|
||||
- U3: SPI NOR flash, 2 MiB
|
||||
- U7: unpopulated SOP8 footprint — I2C bus (RTL8372 slave at 0x5c) is accessible from its pads, useful for register dumps
|
||||
- S1: unpopulated slide switch footprint (three through-holes used as serial console)
|
||||
|
||||
Front panel
|
||||
|
||||
<img src="photos/FNS-1200P/chassis-front.jpg" width="400" />
|
||||
|
||||
Top side (PCB)
|
||||
|
||||
<img src="photos/FNS-1200P/PCB-top.jpg" width="300" />
|
||||
|
||||
### Port layout
|
||||
|
||||
| Front panel position | Logical port | Physical port | Type |
|
||||
|----------------------|--------------|---------------|---------|
|
||||
| SFP left | 8 | 5 | SFP+ |
|
||||
| RJ45 1 | 4 | 1 | Copper |
|
||||
| RJ45 2 | 5 | 2 | Copper |
|
||||
| RJ45 3 | 6 | 3 | Copper |
|
||||
| RJ45 4 | 7 | 4 | Copper |
|
||||
| SFP right | 3 | 6 | SFP+ |
|
||||
|
||||
### Serial console
|
||||
|
||||
The PCB has three unpopulated through-holes intended for a slide switch, directly connected to UART0.
|
||||
Numbered from the left (SFP port side), the pinout is:
|
||||
|
||||
| Position (left→right) | Signal | GPIO |
|
||||
|-----------------------|--------|--------------------------|
|
||||
| 1 (leftmost) | RX | GPIO32\_UART0\_RX (32) |
|
||||
| 2 (middle) | GND | GND |
|
||||
| 3 (rightmost) | TX | GPIO31\_UART0\_TX (31) |
|
||||
|
||||
- **Settings**: 115200 baud / 8N1 / 3.3V TTL
|
||||
- Connect a USB-TTL adapter: adapter TX → pin 1, GND → pin 2, adapter RX → pin 3
|
||||
|
||||
### LED configuration
|
||||
|
||||
Copper ports use LED SET0, SFP ports use LED SET1.
|
||||
|
||||
| SET | LED0 | LED2 |
|
||||
|------|--------------------------------------------------|---------------------------------------------------|
|
||||
| SET0 | Amber — lights on 2.5G link | Green — lights on 1G / 100M / 10M link |
|
||||
| SET1 | All speeds — lights on any link with activity | — |
|
||||
|
||||
LED pad to physical port mapping:
|
||||
|
||||
| GPIO pads | Port |
|
||||
|-----------|-------------------------|
|
||||
| GPIO8–11 | Physical port 5 (left SFP) |
|
||||
| GPIO12–14 | Physical port 1 (RJ45 1) |
|
||||
| GPIO15–17 | Physical port 2 (RJ45 2) |
|
||||
| GPIO18–20 | Physical port 3 (RJ45 3) |
|
||||
| GPIO21–23 | Physical port 4 (RJ45 4) |
|
||||
| GPIO24–27 | Physical port 6 (right SFP) |
|
||||
|
||||
### SFP GPIO assignments
|
||||
|
||||
| SFP | pin\_detect (ModAbs) | pin\_los | SerDes | I2C SDA | I2C SCL |
|
||||
|------------------|-----------------------------|------------------------|--------|----------------------|--------------------------|
|
||||
| Left (logical 8) | GPIO30\_ACL\_BIT3\_EN | GPIO37 | SDS1 | GPIO39\_I2C\_SDA4 | GPIO40\_I2C\_SCL3\_MDC1 |
|
||||
| Right (logical 3)| GPIO50\_I2C\_SCL2\_UART1\_TX | GPIO51\_I2C\_SDA2\_UART1\_RX | SDS0 | GPIO41\_I2C\_SDA3\_MDIO1 | GPIO40\_I2C\_SCL3\_MDC1 |
|
||||
|
||||
GPIO assignments were verified by observing GPIO state changes during SFP module insertion/removal
|
||||
and cross-checked against an original firmware register dump.
|
||||
`pin_tx_disable` is GPIO\_NA on both ports (original firmware keeps all GPIOs as inputs).
|
||||
@@ -1,62 +0,0 @@
|
||||
# Hisource Hi-K0402WS
|
||||
|
||||
Following is documentation for unmanaged switch marked as `Hi-K0402WS`.
|
||||
|
||||
Original software is running UART on 9600 baud rate.
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
|
||||
The board has two flash chips `BY25Q16BS` with 16M-bit size. The front switch, switches between the two flash chips.
|
||||
These can be programed independently by using said switch - so it is e.g. possible to run the original and new firmware in parallel.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**: 2.5G Ethernet Switch
|
||||
- **Model**: Hi-K0402WS
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP: 1000 / 2500 / 10000 Mbps
|
||||
|
||||
### What works (expected from label + similar devices)
|
||||
|
||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- Both SFP ports supporting 1G, 2.5G and 10G modules
|
||||
- LEDs
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-KO4022W-V3.0 / DIP-KO4022WS-V3.0
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/K0402W-V3.0-unmanaged\PCB-top.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/K0402W-V3.0-unmanaged\PCB-bottom.jpg" width="300" />
|
||||
|
||||
### T2, serial console
|
||||
|
||||
| `J2` pin | Signal |
|
||||
| -------- | ----------- |
|
||||
| 1 | 3V3 |
|
||||
| 2 | RX (Input) |
|
||||
| 3 | TX (Output) |
|
||||
| 4 | GND |
|
||||
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
Board has two supply rails. `0.95` and `3.3` volt.
|
||||
|
||||
### `0.95` Core Voltage
|
||||
|
||||
Voltage is made by a `Techcode TD1720` .
|
||||
|
||||
### `3.3` Voltage
|
||||
|
||||
Voltage is created by chip marked as `Techcode TD1720`.
|
||||
|
||||
**There seems to have been a miscalculation when choosing the inductor and the device is ~25% more efficient with an 5V power supply.**
|
||||
@@ -0,0 +1,36 @@
|
||||
# Hisource Hi-K0801WS
|
||||
|
||||
Following is documentation for unmanaged switch marked as `Hi-K0801WS`.
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**: 2.5G Ethernet Switch
|
||||
- **Model**: Hi-K0801WS
|
||||
- **Ports**:
|
||||
- 8 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 1 × SFP: 1000 / 2500 / 10000 Mbps
|
||||
|
||||
### What works (expected from label + similar devices)
|
||||
|
||||
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- SFP port supporting 1G, 2.5G and 10G modules
|
||||
- LEDs
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-KO801W-V2.0 / DIP-KO801WS-V2.0
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/K0801W-V2.0-unmanaged\PCB-top.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/K0801W-V2.0-unmanaged\PCB-bottom.jpg" width="300" />
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Keeplink KP-9000-6XH-X2
|
||||
|
||||
Following is documentation for unmanaged switch marked as `KP-9000-6XH-X2`.
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**: 4X 2.5G RJ45 Port + 2 X 10G SFP+ Port
|
||||
- **Model**: KP-9000-6XH-X2
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||
|
||||
### What works
|
||||
|
||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- SFP port with 10G modules
|
||||
- LEDs
|
||||
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
|
||||
|
||||
### Hardware overview
|
||||
|
||||
Front side:
|
||||
|
||||
<img src="photos/2M-PCB43-V2.1-unmanaged/KP-9000-6XH-X2-front.jpg" width="600" />
|
||||
|
||||
Label:
|
||||
|
||||
<img src="photos/2M-PCB43-V2.1-unmanaged/KP-9000-6XH-X2-label.jpg" width="600" />
|
||||
|
||||
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: 2M-PCB43-V2.1
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/2M-PCB43-V2.1-unmanaged/2M-PCB43-V2.1-top.jpg" width="600" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/2M-PCB43-V2.1-unmanaged/2M-PCB43-V2.1-bottom.jpg" width="600" />
|
||||
|
||||
## Reset Button
|
||||
|
||||
There's an unpopulated Reset button on the front left side of the PCB.
|
||||
It can easily be soldered, you'll need an 4.5mmx4.5mm 90° button switch with a 3-pin footprint.
|
||||
I got mine here: https://de.aliexpress.com/item/1005007295346702.html
|
||||
The front case has already the hole in the metal case, you just have to punch a hole through the foil.
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
# PCB-K0402WS-V3.0
|
||||
|
||||
Following is documentation for a variety of unmanaged switch internally marked as `PCB-K0402WS-V3.0`. They are sold under many brands.
|
||||
|
||||
Original software is running UART on 9600 baud rate.
|
||||
|
||||
Note during opening the device: there might be a hidden 5th screw on the back
|
||||
of the device just above the big label, might be covered by a QC sticker.
|
||||
|
||||
### Brands
|
||||
|
||||
* Hisource Hi-K0402WS
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/HiSource_HI-K0402WS.jpg" width="300" />
|
||||
|
||||
* Ztyuav Z-QWYT0402
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/Ztyuav_Z-QWYT0402.jpg" width="300" />
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/Ztyuav_Z-QWYT0402_label.jpg" width="300" />
|
||||
|
||||
### Programming
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
|
||||
The board has two flash chips `BY25Q16BS` with 16M-bit size. The front switch, switches between the two flash chips.
|
||||
These can be programed independently by using said switch - so it is e.g. possible to run the original and new firmware in parallel.
|
||||
The switch actually controls the HOLD line of each flash chip, and toggling the switch results in a reboot.
|
||||
|
||||
If the programming clip keeps HOLD not connected, the flashing will commence on whatever the switch selected, regardless on which chip was clipped.
|
||||
|
||||
For the initial flash (at least with flashrom), the bin file produced by the build is much smaller than the flash chip, it is suggested to pad the file to keep flashrom happy: `truncate -s 2097152 rtlplayground-*-PCB_K0402WS_V3.bin`. Note: do not then proceed to use this resulting padded file for the web flashing (as it bricks the device), use the original unpadded .bin.
|
||||
|
||||
### What works (expected from label + similar devices)
|
||||
|
||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- Both SFP ports supporting 1G, 2.5G and 10G modules
|
||||
- LEDs
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-KO4022W-V3.0 / DIP-KO4022WS-V3.0
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/PCB-top.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/PCB-bottom.jpg" width="300" />
|
||||
|
||||
### T2, serial console
|
||||
|
||||
| `J2` pin | Signal |
|
||||
| -------- | ----------- |
|
||||
| 1 | 3V3 |
|
||||
| 2 | RX (Input) |
|
||||
| 3 | TX (Output) |
|
||||
| 4 | GND |
|
||||
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
Board has two supply rails. `0.95` and `3.3` volt.
|
||||
|
||||
### `0.95` Core Voltage
|
||||
|
||||
Voltage is made by a `Techcode TD1720` .
|
||||
|
||||
### `3.3` Voltage
|
||||
|
||||
Voltage is created by chip marked as `Techcode TD1720`.
|
||||
|
||||
**There seems to have been a miscalculation when choosing the inductor and the device is ~25% more efficient with an 5V power supply.**
|
||||
@@ -0,0 +1,59 @@
|
||||
# ZX310S-4T2XH/
|
||||
|
||||
The following is a documentation for the managed switch marked as `ZX310S-4T2XH`
|
||||
and sold by Horaco.
|
||||
|
||||
The original software is running UART on 57600 baud rate. The solder holes
|
||||
of the UART header are filled in. In order to install a UART header, they
|
||||
need to be cleared first. A 1.2mm drill can be used, alternatively a
|
||||
de-soldering wick.
|
||||
The original firmware uses 57600 baud 8N1
|
||||
|
||||
CPU: RTL8372
|
||||
Flash: 2MByte Winbond W25Q16DV (U3)
|
||||
PHY RTL8261BE
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**:
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 1 x RJ45: 10/100/1000/2500/5000/10000 Mbps
|
||||
- 1 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||
- **Power**: 12V DC, 2A barrel connector
|
||||
|
||||
<img src="photos/ZX310S-4T2XH/label.jpg" width="300" />
|
||||
|
||||
### What works
|
||||
The device is fully supported:
|
||||
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||
- The 10GBit port works. TODO: Fix EEE, speed selection
|
||||
- The SFP+ port supports 1G, 2.5G and 10G modules
|
||||
- LEDs work with the same indiciations as the OEM firmware
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-SL310S-4T1T1X-V1.0.1-24107
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/ZX310S-4T2XH/pcb_top.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/ZX310S-4T2XH/pcb_bottom.jpg" width="300" />
|
||||
|
||||
### J1, serial console
|
||||
|
||||
| `J1` pin | Signal |
|
||||
| -------- | ----------- |
|
||||
| 1 | TX (Output) |
|
||||
| 2 | RX (Input) |
|
||||
| 3 | GND |
|
||||
| 4 | 3V3 |
|
||||
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 2A` adapter was provided.
|
||||
@@ -0,0 +1,53 @@
|
||||
# ZX310S-4T2XT
|
||||
|
||||
The following is a documentation for the managed switch marked as
|
||||
`ZX310S-4T2XT` and sold by Horaco.
|
||||
|
||||
The original software is running UART on 57600 baud rate 8N1.
|
||||
|
||||
CPU: RTL8372
|
||||
Flash: 2MByte Winbond W25Q16DV (U3)
|
||||
PHY 2x RTL8261BE
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**:
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 x RJ45: 10/100/1000/2500/5000/10000 Mbps
|
||||
- **Power**: 12V DC, 2A barrel connector
|
||||
|
||||
<img src="photos/ZX310S-4T2XT/label.jpg" width="300" />
|
||||
|
||||
### What works
|
||||
The device is fully supported:
|
||||
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps, including EEE
|
||||
- The 10GBit ports works, including EEE.
|
||||
- LEDs work with the same indiciations as the OEM firmware
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-SL310S-4T2XT-V1.0.0-22273
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/ZX310S-4T2XT/pcb_top.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/ZX310S-4T2XT/pcb_bottom.jpg" width="300" />
|
||||
|
||||
### J1, serial console
|
||||
|
||||
| `J1` pin | Signal |
|
||||
| -------- | ----------- |
|
||||
| 1 | TX (Output) |
|
||||
| 2 | RX (Input) |
|
||||
| 3 | GND |
|
||||
| 4 | 3V3 |
|
||||
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 2A` adapter was provided.
|
||||
|
After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 521 KiB After Width: | Height: | Size: 521 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 531 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 2.6 MiB After Width: | Height: | Size: 2.6 MiB |
|
Before Width: | Height: | Size: 3.1 MiB After Width: | Height: | Size: 3.1 MiB |
|
Before Width: | Height: | Size: 2.8 MiB After Width: | Height: | Size: 2.8 MiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 152 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 2.7 MiB |
|
After Width: | Height: | Size: 3.3 MiB |
|
After Width: | Height: | Size: 2.2 MiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 2.7 MiB |
|
After Width: | Height: | Size: 64 KiB |
@@ -9,6 +9,7 @@ The following devices have been tested and are fully working:
|
||||
- No-Name ZX-SWTGW215AS, managed version of kp-9000-6hx-x, ordered on
|
||||
AliExpress as keepLINK 5+1 port managed
|
||||
- TrendNet TEG-S562 (RTL8372: 4x 2.5GBit + 2x 10GBit SFP+)
|
||||
- FNS-1200P (RTL8372: 4x 2.5GBit + 2x 10GBit SFP+)
|
||||
|
||||
Other device based on RTL8272/3 that may work are described here: [Up-N-Atoms 2.5 GBit RTL Switch hacking guide]
|
||||
(https://github.com/up-n-atom/SWTG118AS)
|
||||
|
||||
@@ -79,6 +79,12 @@ vlan <VLAN-ID> d
|
||||
vlan show
|
||||
Dumps the current ingress vlan settings.
|
||||
|
||||
vlan <VLAN-ID> mgmt
|
||||
Restricts network access to the switch (web UI, syslog) to the given
|
||||
VLAN. Use `vlan 0 mgmt` to disable the filter. Default is `vlan 1 mgmt`.
|
||||
Warning: setting this to an unreachable VLAN locks out the web UI;
|
||||
recovery requires serial console.
|
||||
|
||||
pvid <port> <VLAN-ID>
|
||||
assigns PVID to a port. ports are numbered as on the casing
|
||||
|
||||
|
||||
@@ -1,35 +1,84 @@
|
||||
var configInterval = Number();
|
||||
var configuration = [];
|
||||
const conf_cmds = [
|
||||
/ip\s+(\d{1,3}\.){3}\d{1,3}/, /gw\s+(\d{1,3}\.){3}\d{1,3}/, /netmask\s+(\d{1,3}\.){3}\d{1,3}/,
|
||||
/eee(\s+\d)?\s+(on|off)/, /mirror(\s+(\d|10))(\s+(\d|10)(t|r)?)+/, /vlan\s+(\d{1,4})(\s+(\d|10)(t|u)?)+/
|
||||
/^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}$/,
|
||||
/^passwd\s+\S+$/,
|
||||
/^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}[tu]?)+$/,
|
||||
/^pvid\s+\d{1,2}\s+\d{1,4}$/,
|
||||
/^ingress(\s+\d{1,2}[tua])+$/,
|
||||
/^ingress\s+[tua]$/,
|
||||
/^port\s+\d{1,2}\s+name\s+\S+$/,
|
||||
/^eee(\s+\d{1,2})?\s+(on|off)$/,
|
||||
/^mirror(\s+\d{1,2})(\s+\d{1,2}[tr]?)+$/,
|
||||
/^lag\s+\d(\s+\d{1,2})+$/,
|
||||
/^laghash\s+\d(\s+\w+)+$/,
|
||||
/^isolate\s+\d{1,2}(\s+(off|\d{1,2}))+$/,
|
||||
/^stp\s+(on|off)$/,
|
||||
/^igmp\s+(on|off)$/,
|
||||
/^mtu\s+\d{1,2}\s+\d+$/,
|
||||
/^bw\s+(in|out)\s+\d{1,2}\s+\S+$/,
|
||||
];
|
||||
const conf_overwrite = [
|
||||
/ip/, /gw/, /netmask/, /eee\s+\w+/, /eee(\s+\w)/, /mirror/, /vlan\s+(\d{1,4})/
|
||||
/^ip\b/,
|
||||
/^gw\b/,
|
||||
/^netmask\b/,
|
||||
/^syslog\s+ip\b/,
|
||||
/^syslog\b/,
|
||||
/^passwd\b/,
|
||||
/^vlan\s+\d{1,4}\s+mgmt$/,
|
||||
/^vlan\s+\d{1,4}(?!\s+mgmt\b)/,
|
||||
/^pvid\s+\d{1,2}\b/,
|
||||
/^ingress\b/,
|
||||
/^port\s+\d{1,2}\s+name\b/,
|
||||
/^eee\s+\d{1,2}\b/,
|
||||
/^eee\b/,
|
||||
/^mirror\b/,
|
||||
/^lag\s+\d+\b/,
|
||||
/^laghash\b/,
|
||||
/^isolate\s+\d{1,2}\b/,
|
||||
/^stp\b/,
|
||||
/^igmp\b/,
|
||||
/^mtu\s+\d{1,2}\b/,
|
||||
/^bw\s+(in|out)\s+\d{1,2}\b/,
|
||||
];
|
||||
|
||||
function parseConf(s){
|
||||
var a = s.split(/\r\n|\n/);
|
||||
for (var l = 0; l < a.length; l++) {
|
||||
if (!a[l].length || a[l] == "\n" || a[l] == "\r\n")
|
||||
continue;
|
||||
console.log(l + ' --> ' + a[l]);
|
||||
var ignore = true;
|
||||
for (const x of conf_cmds)
|
||||
if (x.test(a[l])) ignore = false;
|
||||
if (ignore) continue;
|
||||
for (const x of conf_overwrite) {
|
||||
if (x.test(a[l])) {
|
||||
console.log("Match ", x, " to ", a[l]);
|
||||
m = a[l].match(x);
|
||||
console.log("Starts with ", m[0]);
|
||||
configuration = configuration.filter(item => !(item.startsWith(m[0])));
|
||||
}
|
||||
}
|
||||
configuration.push(a[l]);
|
||||
for (var l = 0; l < a.length; l++) {
|
||||
var line = a[l].trim().replace(/\s+/g, ' ');
|
||||
if (!line.length) continue;
|
||||
const deleteMatch = line.match(/^vlan\s+(\d{1,4})\s+d$/);
|
||||
if (deleteMatch) {
|
||||
const prefix = "vlan " + deleteMatch[1] + " ";
|
||||
configuration = configuration.filter(c =>
|
||||
c !== "vlan " + deleteMatch[1] && !c.startsWith(prefix));
|
||||
continue;
|
||||
}
|
||||
console.log("Configuration now:");
|
||||
for (const x of configuration) { console.log(x); }
|
||||
console.log(l + ' --> ' + line);
|
||||
var ignore = true;
|
||||
for (const x of conf_cmds)
|
||||
if (x.test(line)) { ignore = false; break; }
|
||||
if (ignore) continue;
|
||||
for (const x of conf_overwrite) {
|
||||
if (x.test(line)) {
|
||||
let m = line.match(x);
|
||||
let matchStr = m[0];
|
||||
configuration = configuration.filter(item =>
|
||||
!(item === matchStr || item.startsWith(matchStr + " ")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
configuration.push(line);
|
||||
}
|
||||
console.log("Configuration now:");
|
||||
for (const x of configuration) { console.log(x); }
|
||||
}
|
||||
|
||||
async function fetchConfig() {
|
||||
|
||||
@@ -164,7 +164,9 @@ function update(callback) {
|
||||
} else {
|
||||
psvg.style.opacity = 1.0;
|
||||
pState[n] = p.link;
|
||||
if (p.link == 4 || p.link == 5 || p.link == 6) {
|
||||
if (p.link == 5 || p.link == 7) {
|
||||
leds[0].style.fill = "green"; leds[1].style.fill = "blue";
|
||||
} else if (p.link == 4 || p.link == 6) {
|
||||
leds[0].style.fill = "green"; leds[1].style.fill = "orange";
|
||||
} else if (p.link == 1 || p.link == 2 || p.link == 3) {
|
||||
leds[0].style.fill = "green"; leds[1].style.fill = "green";
|
||||
|
||||
@@ -163,3 +163,4 @@ margin: 30px 0;
|
||||
}
|
||||
select { text-align-last: right; font-family: monospace}
|
||||
option { direction: rtl; font-family: sans-serif}
|
||||
#vlanTable td { text-align: left; }
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<div class="tab-bar">
|
||||
<button class="tab-btn active" onclick="openTab(event, 'system-tab')">System</button>
|
||||
<button class="tab-btn" onclick="openTab(event, 'advanced-tab')">Advanced</button>
|
||||
<button class="tab-btn" onclick="openTab(event, 'console-tab')">Console</button>
|
||||
</div>
|
||||
<nav id="sidebar"></nav>
|
||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||
@@ -56,6 +57,17 @@
|
||||
<input style="width:40%;" class="action" id="switch_reset" onclick="resetSwitch();" type="button" value="Reset Switch">
|
||||
</div>
|
||||
|
||||
<div id="console-tab" class="tab-content">
|
||||
<h1>Console Command</h1>
|
||||
<label for="console_command">Enter command:</label>
|
||||
<input type="text" id="console_cmd" name="console_cmd" style="width:40%;">
|
||||
<input style="width:20%;" class="action" id="cmd_sub" onclick="cmdSub();" type="button" value="Send Command"><br/>
|
||||
<br/><br/>
|
||||
Be careful when entering console commands, you can lock yourself out!<br/>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="/config.js"></script>
|
||||
<script src="/system.js"></script>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var systemInterval = Number();
|
||||
var isSaving = false;
|
||||
const ips = ["ip", "netmask", "gw"];
|
||||
|
||||
function checkIp(ip) {
|
||||
@@ -12,51 +13,70 @@ async function ipSub() {
|
||||
if (!checkIp(document.getElementById(ips[i]).value))
|
||||
return;
|
||||
}
|
||||
var cmd = '';
|
||||
for (let i=0; i<3;i++){
|
||||
var cmd = ips[i]+' '+document.getElementById(ips[i]).value;
|
||||
try {
|
||||
const response = await fetch('/cmd', {
|
||||
method: 'POST',
|
||||
body: cmd
|
||||
});
|
||||
console.log('Completed!', response);
|
||||
fetchIP();
|
||||
} catch(err) {
|
||||
console.error(`Error: ${err}`);
|
||||
}
|
||||
cmd += ips[i]+' '+document.getElementById(ips[i]).value+'\n';
|
||||
}
|
||||
try {
|
||||
const response = await fetch('/cmd', {
|
||||
method: 'POST',
|
||||
body: cmd
|
||||
});
|
||||
console.log('Completed!', response);
|
||||
fetchIP();
|
||||
} catch(err) {
|
||||
console.error(`Error: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function cmdSub() {
|
||||
var cmd = document.getElementById('console_cmd').value;
|
||||
try {
|
||||
const response = await fetch('/cmd', {
|
||||
method: 'POST',
|
||||
body: cmd
|
||||
});
|
||||
console.log('Completed!', response);
|
||||
} catch(err) {
|
||||
console.error(`Error: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function sendConfig(c) {
|
||||
const form = new FormData();
|
||||
if (isSaving) return;
|
||||
isSaving = true;
|
||||
clearInterval(systemInterval);
|
||||
const form = new FormData();
|
||||
form.append("MAX_FILE_SIZE", "4096");
|
||||
form.append("configuration", new Blob([c], {type: "application/octet-stream"}));
|
||||
form.append("configuration", new Blob([c], {type: "application/octet-stream"}), "config.txt");
|
||||
try {
|
||||
const response = await fetch('/config', {
|
||||
method: 'POST',
|
||||
body: form
|
||||
});
|
||||
console.log('Completed!', response);
|
||||
try {
|
||||
await fetch('/cmd_log_clear', { method: 'GET' });
|
||||
} catch(e) {}
|
||||
} catch(err) {
|
||||
console.error(`Error: ${err}`);
|
||||
} finally {
|
||||
isSaving = false;
|
||||
systemInterval = setInterval(fetchIP, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function flashSave() {
|
||||
fetchConfig().then((s) => {
|
||||
parseConf(s);
|
||||
fetchCmdLog().then((s) => {
|
||||
parseConf(s);
|
||||
var body = "";
|
||||
for (const x of configuration) { body = body + x + "\n"; }
|
||||
console.log("CONFIGURATION to save: ", body);
|
||||
sendConfig(body);
|
||||
});
|
||||
});
|
||||
setTimeout(() => {
|
||||
fetchIP();
|
||||
}, 500);
|
||||
configuration = [];
|
||||
const savedConfig = await fetchConfig();
|
||||
const cmdLog = await fetchCmdLog();
|
||||
if (savedConfig) parseConf(savedConfig);
|
||||
if (cmdLog) parseConf(cmdLog);
|
||||
const body = configuration.join('\n') + '\n';
|
||||
console.log("CONFIGURATION to save: ", body);
|
||||
await sendConfig(body);
|
||||
}
|
||||
|
||||
async function flashStartupSave() {
|
||||
|
||||
@@ -10,6 +10,13 @@
|
||||
<div id="ports"></div>
|
||||
<h1>VLAN Configuration</h1>
|
||||
<form id="vform" action="/vlan.html">
|
||||
<div>
|
||||
<label for="vlanSelect">VLAN auswählen:</label>
|
||||
<select id="vlanSelect" style="margin: 0 0 0 8px">
|
||||
<option value="" disabled selected>— VLAN wählen —</option>
|
||||
</select>
|
||||
</div>
|
||||
<br/>
|
||||
<div>
|
||||
<label for="vid">VLAN ID:</label>
|
||||
<input type="number" min="1" max="4094" id="vid" name="vid">
|
||||
@@ -29,6 +36,22 @@
|
||||
<br/> <input style="width:40%;" class="action" id="vlan_sub" onclick="vlanSub();" type="button" value="Update / Create">
|
||||
<script src="/vlan_sub.js"></script>
|
||||
</form>
|
||||
<h2>Configured VLANs</h2>
|
||||
<table id="vlanTable" style="width:90%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>VLAN</th>
|
||||
<th>Name</th>
|
||||
<th>Member Ports</th>
|
||||
<th>Tagged Ports</th>
|
||||
<th>Untagged Ports</th>
|
||||
<th>PVID Ports</th>
|
||||
<th>Delete</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="vlanTableBody">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<script src="/navigation.js"></script>
|
||||
</body>
|
||||
|
||||
@@ -83,9 +83,129 @@ function fetchVLAN() {
|
||||
sendXHTTP(xhttp);
|
||||
}
|
||||
|
||||
function portsToRange(mask, nPorts) {
|
||||
var parts = [];
|
||||
var start = -1, prev = -1;
|
||||
for (var p = 1; p <= nPorts; p++) {
|
||||
var bit = physToLogPort[p - 1];
|
||||
if ((mask >> bit) & 1) {
|
||||
if (start < 0) start = p;
|
||||
prev = p;
|
||||
} else {
|
||||
if (start >= 0) {
|
||||
parts.push(start === prev ? String(start) : start + '-' + prev);
|
||||
start = -1; prev = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (start >= 0)
|
||||
parts.push(start === prev ? String(start) : start + '-' + prev);
|
||||
return parts.length ? parts.join(',') : '-';
|
||||
}
|
||||
|
||||
async function loadVlanTable() {
|
||||
var tbody = document.getElementById('vlanTableBody');
|
||||
if (!tbody) return;
|
||||
tbody.innerHTML = '';
|
||||
var resp;
|
||||
try { resp = await fetch('/vlanlist'); } catch(e) { return; }
|
||||
if (!resp.ok) return;
|
||||
var vlans = await resp.json();
|
||||
for (var i = 0; i < vlans.length; i++) {
|
||||
var v = vlans[i];
|
||||
var vresp;
|
||||
try { vresp = await fetch('/vlan.json?vid=' + v.id); } catch(e) { continue; }
|
||||
if (!vresp.ok) continue;
|
||||
var s = await vresp.json();
|
||||
var m = parseInt(s.members, 16);
|
||||
var members = m & 0x3FF;
|
||||
var untag = ((m >> 10) & 0x3FF) & members;
|
||||
var tagged = members & ~untag;
|
||||
var pvid = parseInt(s.pvid, 16) & 0x3FF;
|
||||
var tr = document.createElement('tr');
|
||||
var td, a, btn;
|
||||
td = document.createElement('td');
|
||||
a = document.createElement('a');
|
||||
a.href = '#';
|
||||
a.textContent = v.id;
|
||||
(function(vid) {
|
||||
a.onclick = function(e) {
|
||||
e.preventDefault();
|
||||
document.getElementById('vid').value = vid;
|
||||
fetchVLAN();
|
||||
};
|
||||
})(v.id);
|
||||
td.appendChild(a); tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
td.textContent = v.name || ''; tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
td.textContent = portsToRange(members, numPorts); tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
td.textContent = portsToRange(tagged, numPorts); tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
td.textContent = portsToRange(untag, numPorts); tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
td.textContent = portsToRange(pvid, numPorts); tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
if (v.id !== 1) {
|
||||
btn = document.createElement('button');
|
||||
btn.textContent = '✕';
|
||||
(function(vid) {
|
||||
btn.onclick = function() { deleteVlan(vid); };
|
||||
})(v.id);
|
||||
td.appendChild(btn);
|
||||
}
|
||||
tr.appendChild(td);
|
||||
tbody.appendChild(tr);
|
||||
}
|
||||
}
|
||||
|
||||
function deleteVlan(id) {
|
||||
if (!confirm('Delete VLAN ' + id + '?')) return;
|
||||
fetch('/cmd', { method: 'POST', body: 'vlan ' + id + ' d' })
|
||||
.then(function() { refreshVlanViews(); })
|
||||
.catch(function(err) { console.error('Delete failed:', err); });
|
||||
}
|
||||
|
||||
function refreshVlanViews() {
|
||||
loadVlanList();
|
||||
loadVlanTable();
|
||||
}
|
||||
|
||||
function loadVlanList() {
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState !== 4) return;
|
||||
var sel = document.getElementById('vlanSelect');
|
||||
if (this.status !== 200) {
|
||||
sel.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
var vlans = JSON.parse(this.responseText);
|
||||
if (!vlans.length) {
|
||||
sel.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
sel.options.length = 1;
|
||||
for (var i = 0; i < vlans.length; i++) {
|
||||
var opt = document.createElement('option');
|
||||
opt.value = vlans[i].id;
|
||||
opt.text = vlans[i].name ? vlans[i].id + ' — ' + vlans[i].name : String(vlans[i].id);
|
||||
sel.appendChild(opt);
|
||||
}
|
||||
};
|
||||
xhttp.open('GET', '/vlanlist', true);
|
||||
sendXHTTP(xhttp);
|
||||
}
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
update( () => {
|
||||
vlanForm();
|
||||
refreshVlanViews();
|
||||
document.getElementById('vlanSelect').onchange = function() {
|
||||
document.getElementById('vid').value = this.value;
|
||||
fetchVLAN();
|
||||
};
|
||||
const interval = setInterval(update, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,6 +28,7 @@ async function vlanSub() {
|
||||
});
|
||||
console.log('Completed!', response);
|
||||
}
|
||||
refreshVlanViews();
|
||||
} catch(err) {
|
||||
console.error(`Error: ${err}`);
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
#define SESSION_ID_LENGTH 12
|
||||
#define SESSION_TIMEOUT 200
|
||||
|
||||
// SPI FLASH MEMORY PAGE SIZE.
|
||||
#define FLASHMEM_PAGE_SIZE 0x100
|
||||
|
||||
#define CMARK_S 6
|
||||
|
||||
#pragma codeseg BANK1
|
||||
@@ -60,11 +57,12 @@ __xdata uint32_t now;
|
||||
__xdata uint8_t *timeptr;
|
||||
__xdata uint32_t last_session_use;
|
||||
|
||||
#define TSTATE_NONE 0
|
||||
#define TSTATE_TX 1
|
||||
#define TSTATE_ACKED 2
|
||||
#define TSTATE_CLOSED 3
|
||||
#define TSTATE_POST 4
|
||||
#define TSTATE_NONE 0
|
||||
#define TSTATE_TX 1
|
||||
#define TSTATE_ACKED 2
|
||||
#define TSTATE_CLOSED 3
|
||||
#define TSTATE_POST 4
|
||||
#define TSTATE_MULTIPART 5
|
||||
|
||||
extern __xdata uint16_t crc_value;
|
||||
__xdata uint16_t crc_final;
|
||||
@@ -118,33 +116,88 @@ char strcmp(__xdata uint8_t *c, __code uint8_t * __xdata d)
|
||||
}
|
||||
|
||||
|
||||
char is_word(__xdata uint8_t *c, __code uint8_t * __xdata d)
|
||||
bool is_word(__xdata uint8_t *xdata_str_p, __code uint8_t * __xdata code_str_p)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
uint8_t u, c;
|
||||
|
||||
while (d[i] && (d[i] == c[i]))
|
||||
i++;
|
||||
while (1) {
|
||||
u = *xdata_str_p++;
|
||||
c = *code_str_p++;
|
||||
|
||||
if (d[i])
|
||||
return 0;
|
||||
if (c[i] != ' ' && c[i] != '\t' && c[i] != ':' && c[i] != '?' && c[i] != '=' && c[i] != '\n' && c[i] != '\r' && c[i])
|
||||
return 0;
|
||||
return 1;
|
||||
if (c == '\0') {
|
||||
if (u != '\0' && u != ' ' && u != '\t' && u != ':' && u != '?' && u != '=' && u != '\n' && u != '\r')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (c != u) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char is_word_x(__xdata uint8_t *c, __xdata uint8_t *d)
|
||||
bool is_url_word_x(__xdata uint8_t *uri_str_p, __xdata uint8_t *src_str_p)
|
||||
{
|
||||
register uint8_t i = 0;
|
||||
uint8_t u, s;
|
||||
|
||||
while (d[i] && (d[i] == c[i]))
|
||||
i++;
|
||||
while(1) {
|
||||
u = *uri_str_p++;
|
||||
s = *src_str_p++;
|
||||
|
||||
if (d[i])
|
||||
return 0;
|
||||
if (c[i] != ' ' && c[i] != '\t' && c[i] != ':' && c[i] != '?' && c[i] != '=' && c[i] != '\n' && c[i] != '\r' && c[i])
|
||||
return 0;
|
||||
return 1;
|
||||
if (s == '\0') {
|
||||
if (u != '\0' && u != ' ' && u != '\t' && u != ':' && u != '?' && u != '=' && u != '\n' && u != '\r')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (u == '%') {
|
||||
bool again = true;
|
||||
u = 0;
|
||||
|
||||
while(1) {
|
||||
// Swap instruction is fine for rotation
|
||||
u = (u << 4) | (u >> 4);
|
||||
|
||||
uint8_t p = *uri_str_p++;
|
||||
u |= p - '0' < 10 ? (p - '0') : (p - 'A' + 10);
|
||||
|
||||
// force `jbc`-instruction.
|
||||
if (again) {
|
||||
again = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (u == '+') {
|
||||
u = ' ';
|
||||
}
|
||||
|
||||
if (s != u) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool is_word_x(__xdata uint8_t *lhs_str_p, __xdata uint8_t *rhs_str_p)
|
||||
{
|
||||
uint8_t u, c;
|
||||
|
||||
while (1) {
|
||||
u = *lhs_str_p++;
|
||||
c = *rhs_str_p++;
|
||||
|
||||
if (c == '\0') {
|
||||
if (u != '\0' && u != ' ' && u != '\t' && u != ':' && u != '?' && u != '=' && u != '\n' && u != '\r')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (c != u) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -294,14 +347,14 @@ uint8_t stream_upload(uint16_t bptr)
|
||||
if (verify_crc) {
|
||||
dbg_string("CRC16: "); dbg_short(crc_final); dbg_char('\n');
|
||||
if (crc_final == 0xb001) {
|
||||
print_string("Checksum OK.");
|
||||
print_string("Checksum OK.\nUpload to flash done, will reset!\n");
|
||||
// close connection to avoid retries by browser
|
||||
uip_close();
|
||||
reset_chip();
|
||||
} else {
|
||||
print_string("Checksum incorrect!");
|
||||
print_string("Checksum incorrect! Aborting.\n");
|
||||
uip_close();
|
||||
}
|
||||
print_string("\nUpload to flash done, will reset!\n");
|
||||
// close connection to avoid retries by browser
|
||||
uip_close();
|
||||
reset_chip();
|
||||
}
|
||||
// Make sure there is a 0 at the end of the uploaded data
|
||||
flash_buf[0] = 0;
|
||||
@@ -329,18 +382,22 @@ uint8_t stream_upload(uint16_t bptr)
|
||||
}
|
||||
crc16(p + bptr);
|
||||
flash_buf[write_len++] = p[bptr++];
|
||||
if (write_len >= FLASHMEM_PAGE_SIZE) {
|
||||
if (write_len >= FLASH_PAGE_SIZE) {
|
||||
dbg_string("len: "); dbg_short(write_len); dbg_char(' ');
|
||||
dbg_string("CRC16: "); dbg_short(crc_value); dbg_char('\n');
|
||||
if (uptr % FLASH_SECTOR_SIZE == 0) {
|
||||
flash_region.addr = uptr;
|
||||
flash_sector_erase();
|
||||
}
|
||||
flash_region.addr = uptr;
|
||||
flash_region.len = FLASHMEM_PAGE_SIZE;
|
||||
flash_region.len = FLASH_PAGE_SIZE;
|
||||
flash_write_bytes(flash_buf);
|
||||
uptr += FLASHMEM_PAGE_SIZE;
|
||||
write_len -= FLASHMEM_PAGE_SIZE;
|
||||
uptr += FLASH_PAGE_SIZE;
|
||||
write_len -= FLASH_PAGE_SIZE;
|
||||
|
||||
// Copy the remaining byte for the next page to the beginning of the buffer.
|
||||
if (write_len > 0) {
|
||||
memcpy(flash_buf, flash_buf + FLASHMEM_PAGE_SIZE, write_len);
|
||||
memcpy(flash_buf, flash_buf + FLASH_PAGE_SIZE, write_len);
|
||||
}
|
||||
}
|
||||
bindex = 0;
|
||||
@@ -355,39 +412,74 @@ void handle_post(void)
|
||||
__xdata uint8_t *p = uip_appdata;
|
||||
__xdata uint8_t *request_path = p + 6;
|
||||
|
||||
dbg_string("Is POST\n");
|
||||
p += 5; // Skip post
|
||||
// Find end of request path
|
||||
while (*p && !is_separator(*p))
|
||||
p++;
|
||||
*p++ = '\0';
|
||||
// Was the multipart header sent in multiple packets?
|
||||
if (s->tstate != TSTATE_MULTIPART) {
|
||||
dbg_string("Is POST\n");
|
||||
p += 5; // Skip post
|
||||
// Find end of request path
|
||||
while (*p && !is_separator(*p))
|
||||
p++;
|
||||
*p++ = '\0';
|
||||
|
||||
// Find end of request header
|
||||
boundary[0] ='\0';
|
||||
p = scan_header(p);
|
||||
dbg_string("Boundary: >"); dbg_string_x(boundary); dbg_string("<\n");
|
||||
if (!*p || !content_type) {
|
||||
dbg_string("Bad Request!\n");
|
||||
send_not_found();
|
||||
return;
|
||||
// Find end of request header
|
||||
boundary[0] ='\0';
|
||||
p = scan_header(p);
|
||||
dbg_string("Boundary: >"); dbg_string_x(boundary); dbg_string("<\n");
|
||||
if (!*p || !content_type) {
|
||||
dbg_string("Bad Request!\n");
|
||||
send_not_found();
|
||||
return;
|
||||
}
|
||||
if (is_word(request_path, "upload")) {
|
||||
if (flash_size < FIRMWARE_UPLOAD_START*2)
|
||||
{
|
||||
print_string("Flash too small for firmware upload!\n");
|
||||
send_bad_request();
|
||||
return;
|
||||
}
|
||||
print_string("Firmware upload started.");
|
||||
uptr = FIRMWARE_UPLOAD_START;
|
||||
verify_crc = 1;
|
||||
max_upload = 1024576;
|
||||
} else if (is_word(request_path, "config")) {
|
||||
if (!authenticated) {
|
||||
send_unauthorized();
|
||||
return;
|
||||
}
|
||||
dbg_string("Configuration upload, erasing config mem!\n");
|
||||
uptr = CONFIG_START;
|
||||
verify_crc = 0;
|
||||
max_upload = 2048;
|
||||
flash_region.addr = CONFIG_START;
|
||||
flash_sector_erase();
|
||||
}
|
||||
// Check for other POST requests, which are not multipart, below
|
||||
} else {
|
||||
dbg_string("Multipart request\n");
|
||||
}
|
||||
|
||||
if (is_word(request_path, "cmd")) {
|
||||
register uint8_t i = 0;
|
||||
p += 4;
|
||||
if (!authenticated) {
|
||||
send_unauthorized();
|
||||
return;
|
||||
}
|
||||
while (*p && *p != '\n' && *p != '\r')
|
||||
cmd_buffer[i++] = *p++;
|
||||
cmd_buffer[i] = '\0';
|
||||
if (i)
|
||||
cmd_available = 1;
|
||||
execute_commands(p);
|
||||
if (err_status != ERR_OK) {
|
||||
send_bad_request();
|
||||
return;
|
||||
}
|
||||
} else if (is_word(request_path, "login")) {
|
||||
dbg_string("POST login\n");
|
||||
|
||||
if (!content_type || !is_word(content_type, "application/x-www-form-urlencoded")) {
|
||||
dbg_string("Bad request!\n");
|
||||
send_bad_request();
|
||||
return;
|
||||
}
|
||||
|
||||
p += 8; // Read also over "pwd="
|
||||
if (is_word_x(p, passwd)) {
|
||||
if (is_url_word_x(p, passwd)) {
|
||||
dbg_string("Password accepted!\n");
|
||||
read_reg_timer(&last_session_use);
|
||||
gen_random_bytes(session_id, SESSION_ID_LENGTH);
|
||||
@@ -398,10 +490,11 @@ void handle_post(void)
|
||||
outbuf[slen++] = session_id[i];
|
||||
slen += strtox(outbuf + slen, "; SameSite=Strict\r\n\r\n");
|
||||
} else {
|
||||
dbg_string("Password invalid!\n");
|
||||
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\nLocation: login.html\r\n\r\n");
|
||||
}
|
||||
return;
|
||||
} else if (is_word(request_path, "upload") || is_word(request_path, "config")) {
|
||||
} else if (s->tstate == TSTATE_MULTIPART || is_word(request_path, "upload") || is_word(request_path, "config")) {
|
||||
dbg_string("POST upload/config request\n");
|
||||
if (!authenticated) {
|
||||
send_unauthorized();
|
||||
@@ -415,8 +508,10 @@ void handle_post(void)
|
||||
// We skip the intial parts as part of the header
|
||||
do {
|
||||
p = skip_boundary(p);
|
||||
if (!*p)
|
||||
goto bad_request;
|
||||
if (!*p) {
|
||||
s->tstate = TSTATE_MULTIPART;
|
||||
return;
|
||||
}
|
||||
p = scan_header(p);
|
||||
if (!*p)
|
||||
goto bad_request;
|
||||
@@ -426,25 +521,6 @@ void handle_post(void)
|
||||
dbg_string("Have content octets\n");
|
||||
p += 4; // Skip \r\n\r\n sequence at end of preamble of part
|
||||
|
||||
if (is_word(request_path, "upload")) {
|
||||
if (flash_size < FIRMWARE_UPLOAD_START*2)
|
||||
{
|
||||
print_string("Flash too small for firmware upload!\n");
|
||||
send_bad_request();
|
||||
return;
|
||||
}
|
||||
print_string("Firmware upload started.");
|
||||
uptr = FIRMWARE_UPLOAD_START;
|
||||
verify_crc = 1;
|
||||
max_upload = 1024576;
|
||||
} else {
|
||||
dbg_string("Configuration upload, erasing config mem!\n");
|
||||
uptr = CONFIG_START;
|
||||
verify_crc = 0;
|
||||
max_upload = 2048;
|
||||
flash_region.addr = CONFIG_START;
|
||||
flash_sector_erase();
|
||||
}
|
||||
flash_init(0); // Re-initialize flash for non-DIO operation, otherwise flashing fails
|
||||
set_sys_led_state(SYS_LED_FAST);
|
||||
|
||||
@@ -473,6 +549,12 @@ void httpd_appcall(void)
|
||||
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
|
||||
|
||||
dbg_char('P');
|
||||
#ifdef DEBUG
|
||||
if (uip_newdata())
|
||||
write_char('N');
|
||||
print_byte(s->tstate);
|
||||
write_char(' ');
|
||||
#endif
|
||||
if(uip_connected() && s->tstate == TSTATE_CLOSED) {
|
||||
dbg_string("Connected...\n");
|
||||
s->tstate = TSTATE_NONE;
|
||||
@@ -544,10 +626,10 @@ void httpd_appcall(void)
|
||||
dbg_char('\n');
|
||||
#endif
|
||||
p = uip_appdata;
|
||||
if (is_word(p, "POST")) {
|
||||
if (is_word(p, "POST") || s->tstate == TSTATE_MULTIPART) {
|
||||
handle_post();
|
||||
// If this is an ongoing post stream, then wait for the next packet
|
||||
if (s->tstate == TSTATE_POST) {
|
||||
if (s->tstate == TSTATE_POST || s->tstate == TSTATE_MULTIPART) {
|
||||
uip_len = 0;
|
||||
return;
|
||||
}
|
||||
@@ -600,6 +682,8 @@ void httpd_appcall(void)
|
||||
send_mtu();
|
||||
} else if (is_word(q, "/lag.json")) {
|
||||
send_lag();
|
||||
} else if (is_word(q, "/vlanlist")) {
|
||||
send_vlanlist();
|
||||
} else if (is_word(q, "/config")) {
|
||||
send_config();
|
||||
} else if (is_word(q, "/cmd_log")) {
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
#include "version.h"
|
||||
#include "machine.h"
|
||||
#include "page_impl.h"
|
||||
#include "syslog.h"
|
||||
|
||||
// #define DEBUG
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#define L2_MAX_TRANSFER 30
|
||||
|
||||
#pragma codeseg BANK1
|
||||
@@ -97,6 +97,19 @@ void itoa_html(uint8_t v)
|
||||
char_to_html('0' + (v % 10));
|
||||
}
|
||||
|
||||
void itoa16_html(uint16_t v) /* sufficient for VLAN IDs (max 4094) */
|
||||
{
|
||||
uint8_t print_zeros = 0;
|
||||
uint8_t d;
|
||||
d = v / 1000;
|
||||
if (d) { char_to_html('0' + d); print_zeros = 1; }
|
||||
d = (v / 100) % 10;
|
||||
if (d || print_zeros) { char_to_html('0' + d); print_zeros = 1; }
|
||||
d = (v / 10) % 10;
|
||||
if (d || print_zeros) char_to_html('0' + d);
|
||||
char_to_html('0' + (v % 10));
|
||||
}
|
||||
|
||||
void string_to_html(__code char *s)
|
||||
{
|
||||
while (*s) char_to_html(*s++);
|
||||
@@ -227,6 +240,11 @@ void send_basic_info(void)
|
||||
itoa_html(uip_netmask[0] >> 8); char_to_html('.');
|
||||
itoa_html(uip_netmask[1]); char_to_html('.');
|
||||
itoa_html(uip_netmask[1] >> 8);
|
||||
slen += strtox(outbuf + slen, "\",\"syslog_server_ip\":\"");
|
||||
itoa_html(syslog_state.server_ip[0]); char_to_html('.');
|
||||
itoa_html(syslog_state.server_ip[1]); char_to_html('.');
|
||||
itoa_html(syslog_state.server_ip[2]); char_to_html('.');
|
||||
itoa_html(syslog_state.server_ip[3]);
|
||||
slen += strtox(outbuf + slen, "\",\"mac_address\":\"");
|
||||
byte_to_html(uip_ethaddr.addr[0]); char_to_html(':');
|
||||
byte_to_html(uip_ethaddr.addr[1]); char_to_html(':');
|
||||
@@ -243,14 +261,16 @@ void send_basic_info(void)
|
||||
slen += strtox(outbuf + slen, "\",\"flash_size\":\"");
|
||||
string_to_html(get_flash_size_str());
|
||||
|
||||
slen += strtox(outbuf + slen, "\",\"sfp_slot_0\":\"");
|
||||
send_sfp_info(0);
|
||||
char_to_html('"');
|
||||
if (machine.n_sfp == 2) {
|
||||
slen += strtox(outbuf + slen, ",\"sfp_slot_1\":\"");
|
||||
send_sfp_info(1);
|
||||
char_to_html('"');
|
||||
if (machine.n_sfp) {
|
||||
slen += strtox(outbuf + slen, "\",\"sfp_slot_0\":\"");
|
||||
send_sfp_info(0);
|
||||
if (machine.n_sfp == 2) {
|
||||
slen += strtox(outbuf + slen, "\",\"sfp_slot_1\":\"");
|
||||
send_sfp_info(1);
|
||||
}
|
||||
}
|
||||
char_to_html('"');
|
||||
|
||||
char_to_html('}');
|
||||
}
|
||||
|
||||
@@ -818,3 +838,46 @@ void send_cmd_log(void)
|
||||
p = (p + 1) & CMD_HISTORY_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void send_vlanlist(void)
|
||||
{
|
||||
/* Worst case per entry: {"id":4094,"name":"<117-char name>"} = 138 bytes
|
||||
* (name bound: CMD_BUF_SIZE=128 minus command prefix); +1 for closing ']'.
|
||||
* At worst case ~18 VLANs fit; typical configs with short names fit many more. */
|
||||
__xdata uint16_t i;
|
||||
__xdata uint16_t n;
|
||||
uint8_t first = 1;
|
||||
|
||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||
char_to_html('[');
|
||||
|
||||
for (i = 1; i < 4095; i++) {
|
||||
if (vlan_get(i) < 0)
|
||||
continue;
|
||||
if (!(sfr_data[0] & 0x02)) /* bit 1: VLAN table entry valid */
|
||||
continue;
|
||||
|
||||
if (slen + 139 > TCP_OUTBUF_SIZE) /* 138 bytes worst-case entry + 1 byte for closing ']' */
|
||||
break;
|
||||
|
||||
if (!first)
|
||||
char_to_html(',');
|
||||
first = 0;
|
||||
|
||||
slen += strtox(outbuf + slen, "{\"id\":");
|
||||
itoa16_html(i);
|
||||
slen += strtox(outbuf + slen, ",\"name\":\"");
|
||||
|
||||
n = vlan_name(i);
|
||||
if (n != 0xffff) {
|
||||
while (vlan_names[n] && vlan_names[n] != ' ')
|
||||
char_to_html(vlan_names[n++]);
|
||||
}
|
||||
|
||||
slen += strtox(outbuf + slen, "\"}");
|
||||
|
||||
}
|
||||
|
||||
char_to_html(']');
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ void send_mtu(void);
|
||||
void send_config(void);
|
||||
void send_cmd_log(void);
|
||||
void send_lag(void);
|
||||
void send_vlanlist(void);
|
||||
|
||||
/* Convert only the lower nibble to ascii HEX char.
|
||||
For convenience the upper nibble is masked out.
|
||||
|
||||
@@ -6,37 +6,36 @@ CC_FLAGS = -mmcs51
|
||||
ASM = sdas8051
|
||||
AFLAGS= -plosgff
|
||||
|
||||
BUILDDIR = output/
|
||||
BUILDDIR = output
|
||||
|
||||
SRCS = installer.c
|
||||
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
|
||||
OBJS = ${SRCS:%.c=$(BUILDDIR)/%.rel}
|
||||
|
||||
all: create_build_dir $(BUILDDIR)updatebuilder $(BUILDDIR)rtlplayground.bin
|
||||
all: create_build_dir $(BUILDDIR)/updatebuilder $(BUILDDIR)/rtlplayground_oem_upgrade.bin
|
||||
|
||||
create_build_dir:
|
||||
mkdir -p $(BUILDDIR)
|
||||
|
||||
$(BUILDDIR)updatebuilder: updatebuilder.c
|
||||
$(BUILDDIR)/updatebuilder: updatebuilder.c
|
||||
gcc $^ -o $@
|
||||
|
||||
$(BUILDDIR)installer.rel: installer.c
|
||||
$(BUILDDIR)/installer.rel: installer.c
|
||||
$(CC) $(CC_FLAGS) --code-loc ${CODE_LOCATION} -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)crtstart.rel: crtstart.asm
|
||||
$(BUILDDIR)/crtstart.rel: crtstart.asm
|
||||
$(ASM) $(AFLAGS) -o $@ $<
|
||||
|
||||
$(BUILDDIR)%.rel: $(BUILDDIR)%.asm
|
||||
$(BUILDDIR)/%.rel: $(BUILDDIR)/%.asm
|
||||
${ASM} ${AFLAGS} -o $@ $^
|
||||
|
||||
$(BUILDDIR)%.rel: %.c
|
||||
$(BUILDDIR)/%.rel: %.c
|
||||
$(CC) $(CC_FLAGS) -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)rtlinstaller.ihx: $(BUILDDIR)crtstart.rel $(OBJS)
|
||||
$(BUILDDIR)/rtlinstaller.ihx: $(BUILDDIR)/crtstart.rel $(OBJS)
|
||||
$(CC) $(CC_FLAGS) -Wl-bHOME=${INSTALLER_ADDRESS} -Wl-r -o $@ $^
|
||||
|
||||
$(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlinstaller.ihx ../$(BUILDDIR)/rtlplayground.bin
|
||||
cp ../$(BUILDDIR)/rtlplayground.bin $(BUILDDIR)
|
||||
./$(BUILDDIR)/updatebuilder -i $< $(BUILDDIR)rtlplayground.bin
|
||||
$(BUILDDIR)/rtlplayground_oem_upgrade.bin: $(BUILDDIR)/rtlinstaller.ihx ../$(BUILDDIR)/rtlplayground.bin
|
||||
./$(BUILDDIR)/updatebuilder -i $< -o $(BUILDDIR)/rtlplayground_oem_upgrade.bin ../$(BUILDDIR)/rtlplayground.bin
|
||||
|
||||
clean:
|
||||
rm -r $(BUILDDIR)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "machine.h"
|
||||
#include "rtl837x_pins.h"
|
||||
#include "rtl837x_leds.h"
|
||||
#include "rtl837x_sfr.h"
|
||||
#include "rtl837x_regs.h"
|
||||
#include "rtl837x_common.h"
|
||||
|
||||
@@ -73,6 +74,58 @@ __code const struct machine machine = {
|
||||
|
||||
void machine_custom_init(void) { }
|
||||
|
||||
#elif defined MACHINE_KP_9000_6XH_X2
|
||||
__code const struct machine machine = {
|
||||
.machine_name = "keepLink KP-9000-6XH-X2",
|
||||
.isRTL8373 = 0,
|
||||
.min_port = 3,
|
||||
.max_port = 8,
|
||||
.n_sfp = 2,
|
||||
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
|
||||
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
|
||||
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
|
||||
|
||||
// Left SFP port
|
||||
.sfp_port[0].pin_detect = GPIO38,
|
||||
.sfp_port[0].pin_los = GPIO_NA,
|
||||
.sfp_port[0].sds = 1,
|
||||
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||
|
||||
// Right SFP port
|
||||
.sfp_port[1].pin_detect = GPIO37,
|
||||
.sfp_port[1].pin_los = GPIO_NA,
|
||||
.sfp_port[1].sds = 0,
|
||||
.sfp_port[1].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||
|
||||
.reset_pin = GPIO48_I2C_SCL1, // Button-Switch is unpopulated on PCB, but can be added manually (hole in case is already there)
|
||||
.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 = {
|
||||
{
|
||||
LEDS_2G5 | LEDS_LINK, // Left LED (Amber)
|
||||
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // Right LED (Green)
|
||||
0,
|
||||
0
|
||||
},
|
||||
{
|
||||
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
},
|
||||
},
|
||||
.led_mux_custom = 1,
|
||||
.led_mux = {
|
||||
0x00,0x01,0x04,0x05,0x08,0x09,0x0c,0x3f,0x0d,0x10,
|
||||
0x11,0x0e,0x14,0x11,0x12,0x15,0x15,0x16,0x18,0x19,
|
||||
0x1a,0x19,0x1d,0x1e,0x1c,0x1d,0x20,0x21
|
||||
},
|
||||
};
|
||||
|
||||
void machine_custom_init(void) {
|
||||
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
||||
}
|
||||
|
||||
#elif defined MACHINE_KP_9000_9XH_X_EU
|
||||
__code const struct machine machine = {
|
||||
.machine_name = "keepLink KP-9000-9XH-X-EU",
|
||||
@@ -214,15 +267,19 @@ __code const struct machine machine = {
|
||||
.sfp_port[1].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 }, /* GPIO 40 */
|
||||
.reset_pin = GPIO54_ACL_BIT2_EN,
|
||||
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
|
||||
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
|
||||
.led_sets = {
|
||||
{
|
||||
/* Green LED */
|
||||
{ /* RJ45: Green LED */
|
||||
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
|
||||
0,
|
||||
/* Amber LED */
|
||||
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
|
||||
0
|
||||
}, { /* SFP PORT: SINGLE GREEN LED */
|
||||
LEDS_10M | LEDS_100M | LEDS_1G | LEDS_2G5 | LEDS_10G | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -253,15 +310,19 @@ __code const struct machine machine = {
|
||||
.sfp_port[1].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 }, /* GPIO 40 */
|
||||
.reset_pin = GPIO_NA,
|
||||
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
|
||||
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
|
||||
.led_sets = {
|
||||
{
|
||||
/* Green LED */
|
||||
{ /* RJ45: Green LED */
|
||||
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
|
||||
0,
|
||||
/* Amber LED */
|
||||
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
|
||||
0
|
||||
}, { /* SFP PORT: SINGLE GREEN LED */
|
||||
LEDS_10M | LEDS_100M | LEDS_1G | LEDS_2G5 | LEDS_10G | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -484,9 +545,9 @@ __code const struct machine machine = {
|
||||
|
||||
void machine_custom_init(void) { }
|
||||
|
||||
#elif defined MACHINE_HI_K0402WS
|
||||
#elif defined(MACHINE_PCB_K0402WS_V3) || defined(MACHINE_HI_K0402WS) // Sold as a variety of devices, see doc/
|
||||
__code const struct machine machine = {
|
||||
.machine_name = "HiSource HI-K0402WS",
|
||||
.machine_name = "PCB-K0402WS-V3.0",
|
||||
.isRTL8373 = 0,
|
||||
.min_port = 3,
|
||||
.max_port = 8,
|
||||
@@ -544,7 +605,6 @@ __code const struct machine machine = {
|
||||
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
|
||||
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
|
||||
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
|
||||
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
|
||||
.sfp_port[0].pin_los = GPIO37,
|
||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||
@@ -571,6 +631,262 @@ __code const struct machine machine = {
|
||||
|
||||
void machine_custom_init(void) { }
|
||||
|
||||
#elif defined MACHINE_ZX310S_4T2XH
|
||||
__code const struct machine machine = {
|
||||
.machine_name = "ZX310S-4T2XH",
|
||||
.isRTL8373 = 0,
|
||||
.min_port = 3,
|
||||
.max_port = 8,
|
||||
.n_sfp = 1,
|
||||
.n_10g = 1,
|
||||
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
|
||||
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
|
||||
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
.sfp_port[0].pin_detect = GPIO38,
|
||||
.sfp_port[0].pin_los = GPIO_NA,
|
||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||
.sfp_port[0].sds = 1,
|
||||
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||
.reset_pin = GPIO48_I2C_SCL1,
|
||||
.high_leds = { .mux = LED_28_SYS, .enable = LED_27 | LED_28_SYS | LED_29 },
|
||||
.led_mux_custom = 1,
|
||||
.led_mux = { 0x00, 0x01, 0x04, 0x05, 0x08, // 65e0
|
||||
0x09, 0x0c, 0x3f, 0x0d, 0x10, // 65e4
|
||||
0x11, 0x0e, 0x14, 0x11, 0x12, // 65e8
|
||||
0x15, 0x15, 0x16, 0x18, 0x19, // 65ec
|
||||
0x1a, 0x19, 0x1d, 0x1e, 0x1c, // 65f0
|
||||
0x1d, 0x20, 0x21 },
|
||||
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
|
||||
/* Ports 1-4: Orange: 2.5GBit, Green: 10/100/1000MBit
|
||||
* Port 5: Blue: 10GBit, Green: 10Mbit-5GBit
|
||||
* SFP-port: Blue: 10GBit, Green 100MBit-5GBit
|
||||
*/
|
||||
.led_sets = { { LEDS_2G5 | LEDS_LINK | LEDS_ACT,
|
||||
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
LEDS_DUPLEX,
|
||||
LEDS_2G5 | LEDS_LINK | LEDS_ACT },
|
||||
{
|
||||
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT | LEDS_5G,
|
||||
LEDS_LINK | LEDS_ACT | LEDS_10G,
|
||||
LEDS_2G5 | LEDS_LINK,
|
||||
LEDS_COL | LEDS_DUPLEX
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
void machine_custom_init(void) { }
|
||||
|
||||
#elif defined MACHINE_HI_K0801WS
|
||||
__code const struct machine machine = {
|
||||
.machine_name = "Hi-Source HI-k0801WS",
|
||||
.isRTL8373 = 1,
|
||||
.min_port = 0,
|
||||
.max_port = 8,
|
||||
.n_sfp = 1,
|
||||
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
|
||||
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
|
||||
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
|
||||
.sfp_port[0].pin_los = GPIO37,
|
||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||
.sfp_port[0].sds = 1,
|
||||
.sfp_port[0].i2c = {
|
||||
.sda = GPIO39_I2C_SDA4,
|
||||
.scl = GPIO40_I2C_SCL3_MDC1
|
||||
},
|
||||
|
||||
.reset_pin = GPIO_NA,
|
||||
|
||||
.high_leds = {
|
||||
.mux = LED_27 | LED_29,
|
||||
.enable = LED_28_SYS | LED_29
|
||||
},
|
||||
|
||||
/* Ports 1-8 use set 0, port 9 SFP uses set 1 */
|
||||
.port_led_set = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
|
||||
.led_sets = {
|
||||
{ /* Set 0: RJ45 copper ports
|
||||
* Amber = 2.5G
|
||||
* Green = 1G/100M/10M with activity
|
||||
*/
|
||||
LEDS_2G5 | LEDS_LINK | LEDS_ACT, /* Amber */
|
||||
0,
|
||||
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, /* Green */
|
||||
0
|
||||
},
|
||||
{ /* Set 1: SFP port, single green LED for all valid speeds */
|
||||
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
void machine_custom_init(void) { }
|
||||
|
||||
#elif defined MACHINE_FNS1200P
|
||||
__code const struct machine machine = {
|
||||
.machine_name = "FNS-1200P",
|
||||
.isRTL8373 = 0,
|
||||
.min_port = 3,
|
||||
.max_port = 8,
|
||||
.n_sfp = 2,
|
||||
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
|
||||
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
|
||||
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
|
||||
|
||||
/* Left SFP (logical 8, SDS1): GPIO30=ModAbs, GPIO37=RX_LOS */
|
||||
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
|
||||
.sfp_port[0].pin_los = GPIO37,
|
||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||
.sfp_port[0].sds = 1,
|
||||
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||
|
||||
/* Right SFP (logical 3, SDS0): GPIO50=ModAbs, GPIO51=RX_LOS */
|
||||
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
|
||||
.sfp_port[1].pin_los = GPIO51_I2C_SDA2_UART1_RX,
|
||||
.sfp_port[1].pin_tx_disable = GPIO_NA,
|
||||
.sfp_port[1].sds = 0,
|
||||
.sfp_port[1].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||
|
||||
.reset_pin = GPIO_NA,
|
||||
|
||||
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
|
||||
|
||||
/* Copper ports use SET0; SFP ports use SET1 */
|
||||
.port_led_set = {0, 0, 0, 1, 0, 0, 0, 0, 1},
|
||||
|
||||
.led_sets = {
|
||||
{ /* SET0: copper — LED0=amber (2.5G), LED2=green (1G/100M/10M) */
|
||||
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
0
|
||||
},
|
||||
{ /* SET1: SFP — all speeds link/act */
|
||||
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
0, 0
|
||||
},
|
||||
},
|
||||
|
||||
.led_mux_custom = 1,
|
||||
.led_mux = {
|
||||
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* GPIO0-7: unused */
|
||||
0x0f, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, /* GPIO8-14 */
|
||||
0x14, 0x15, 0x16, 0x18, 0x19, 0x1a, /* GPIO15-20 */
|
||||
0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23 /* GPIO21-27 */
|
||||
},
|
||||
};
|
||||
|
||||
void machine_custom_init(void)
|
||||
{
|
||||
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
|
||||
}
|
||||
|
||||
|
||||
#elif defined MACHINE_PCB_SWTG024AS_A_2_0_1
|
||||
__code const struct machine machine = {
|
||||
.machine_name = "PCB-SWTG024AS-A-2.0.1",
|
||||
.isRTL8373 = 0,
|
||||
.min_port = 3,
|
||||
.max_port = 8,
|
||||
.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},
|
||||
|
||||
// SFP port on SDS0 / logical port 3
|
||||
.sfp_port[0].pin_detect = GPIO37,
|
||||
.sfp_port[0].pin_los = GPIO_NA,
|
||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||
.sfp_port[0].sds = 0,
|
||||
.sfp_port[0].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||
|
||||
// SFP port on SDS1 / logical port 8
|
||||
.sfp_port[1].pin_detect = GPIO38,
|
||||
.sfp_port[1].pin_los = GPIO_NA,
|
||||
.sfp_port[1].pin_tx_disable = GPIO_NA,
|
||||
.sfp_port[1].sds = 1,
|
||||
.sfp_port[1].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||
|
||||
.reset_pin = GPIO_NA,
|
||||
.high_leds = { .mux = LED_28_SYS | LED_29, .enable = LED_27 | LED_28_SYS | LED_29 },
|
||||
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
|
||||
.led_sets = {
|
||||
{
|
||||
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
|
||||
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
LEDS_DUPLEX,
|
||||
LEDS_2G5 | LEDS_LINK | LEDS_ACT
|
||||
},
|
||||
{
|
||||
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT,
|
||||
LEDS_10G | LEDS_LINK | LEDS_ACT,
|
||||
LEDS_2G5 | LEDS_LINK,
|
||||
LEDS_COL | LEDS_DUPLEX
|
||||
},
|
||||
},
|
||||
.led_mux_custom = 1,
|
||||
.led_mux = {
|
||||
0x00,0x01,0x04,0x05,0x08,0x09,0x0c,0x3f,0x0d,0x10,0x11,0x0e,0x14,0x11,0x12,0x15,0x15,0x16,0x18,0x19,0x1a,0x19,0x1d,0x1e,0x1c,0x1d,0x20,0x21
|
||||
},
|
||||
};
|
||||
|
||||
void machine_custom_init(void)
|
||||
{
|
||||
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_ZX310S_4T2XT
|
||||
__code const struct machine machine = {
|
||||
.machine_name = "ZX310S_4T2XT",
|
||||
.isRTL8373 = 0,
|
||||
.min_port = 3,
|
||||
.max_port = 8,
|
||||
.n_sfp = 0,
|
||||
.n_10g = 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, 0, 0, 0, 0, 0, 0},
|
||||
.reset_pin = GPIO48_I2C_SCL1,
|
||||
.high_leds = { .mux = LED_28_SYS | LED_29, .enable = LED_27 | LED_28_SYS | LED_29 },
|
||||
.led_mux_custom = 1,
|
||||
.led_mux = { 0x00, 0x01, 0x04, 0x05, 0x08, // 65e0
|
||||
0x09, 0x0c, 0x3f, 0x0d, 0x10, // 65e4
|
||||
0x11, 0x0e, 0x14, 0x11, 0x12, // 65e8
|
||||
0x15, 0x15, 0x16, 0x18, 0x19, // 65ec
|
||||
0x1a, 0x19, 0x1d, 0x1e, 0x1c, // 65f0
|
||||
0x1d, 0x20, 0x21 },
|
||||
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
|
||||
/* Ports 1-4: Green: 2.5GBit, Orange: 10/100/1000MBit
|
||||
* Ports 5-6: Green: 10GBit, Orange: <= 5GBit
|
||||
*/
|
||||
.led_sets = { { LEDS_2G5 | LEDS_LINK | LEDS_ACT,
|
||||
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
LEDS_DUPLEX,
|
||||
LEDS_2G5 | LEDS_LINK | LEDS_ACT },
|
||||
{
|
||||
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT,
|
||||
LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_5G,
|
||||
LEDS_2G5 | LEDS_LINK,
|
||||
LEDS_COL | LEDS_DUPLEX
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
void machine_custom_init(void) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Please select a machine type in machine.h"
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
// #define MACHINE_KP_9000_6XHML_X2
|
||||
// #define MACHINE_KP_9000_6XH_X
|
||||
// #define MACHINE_KP_9000_6XH_X2
|
||||
// #define MACHINE_KP_9000_9XH_X_EU
|
||||
// #define MACHINE_KP_9000_9XHML_X_V2_2
|
||||
// #define MACHINE_KP_9000_9XHML_X_V3_1
|
||||
@@ -17,10 +18,15 @@
|
||||
// #define MACHINE_HG0402XG_V1_1
|
||||
// #define MACHINE_SWTG018AS_A_V_2_0
|
||||
// #define MACHINE_SWTGW218AS
|
||||
// #define MACHINE_HI_K0402WS
|
||||
// #define MACHINE_PCB_K0402WS_V3
|
||||
// #define MACHINE_K0501W_V2_0
|
||||
// #define MACHINE_LIANGUO_ZX_SWTGW215AS
|
||||
// #define MACHINE_ZX310S_4T2XH
|
||||
// #define MACHINE_ZX310S_4T2XT
|
||||
// #define MACHINE_DEFAULT_8C_1SFP
|
||||
// #define MACHINE_HI_K0801WS
|
||||
// #define MACHINE_FNS1200P
|
||||
// #define MACHINE_PCB_SWTG024AS_A_2_0_1
|
||||
|
||||
typedef struct {
|
||||
// GPIO pins for SDA/SCL
|
||||
@@ -58,6 +64,7 @@ typedef struct machine {
|
||||
// Highest logical port number
|
||||
uint8_t max_port;
|
||||
uint8_t n_sfp;
|
||||
uint8_t n_10g;
|
||||
uint8_t log_to_phys_port[9];
|
||||
uint8_t phys_to_log_port[9]; // Starts at 0 for port 1
|
||||
uint8_t is_sfp[9]; // 0 for non-SFP ports 1 or 2 for the I2C port number
|
||||
|
||||
@@ -22,16 +22,21 @@
|
||||
#define PHY_ANEG_CTRL 0x00
|
||||
#define PHY_ANEG_ADV 0x10
|
||||
#define PHY_ANEG_LP_ABILITY 0x13
|
||||
#define PHY_ANEG_MGBASE_CTRL 0x20
|
||||
#define PHY_ANEG_MGBASE_ADV 0x21
|
||||
#define PHY_ANEG_MGBASE_CTRL 0x20
|
||||
#define PHY_ANEG_MGBASE_ADV 0x21
|
||||
#define PHY_EEE_ADV 0x3c
|
||||
#define PHY_EEE_LP_ABILITY 0x3d
|
||||
#define PHY_EEE_ADV2 0x3e
|
||||
#define PHY_EEE_LP_ABILITY2 0x3f
|
||||
|
||||
// Register bits for EEE capabilities at a given speed
|
||||
// PHY_EEE_ADV2
|
||||
#define PHY_EEE_BIT_2G5 0x01
|
||||
#define PHY_EEE_BIT_5G 0x02
|
||||
// PHY_EEE_ADV
|
||||
#define PHY_EEE_BIT_1G 0x04
|
||||
#define PHY_EEE_BIT_100M 0x02
|
||||
#define PHY_EEE_BIT_10G 0x08
|
||||
|
||||
/*
|
||||
* MMD 31 Registers
|
||||
|
||||
@@ -92,6 +92,15 @@ struct vlan_tag {
|
||||
#define CMD_HISTORY_SIZE 0x400
|
||||
#define CMD_HISTORY_MASK (CMD_HISTORY_SIZE - 1)
|
||||
|
||||
enum sfp_speeds {
|
||||
SFP_SPEED_AUTO = 0,
|
||||
SFP_SPEED_100M,
|
||||
SFP_SPEED_1G,
|
||||
SFP_SPEED_2G5,
|
||||
SFP_SPEED_5G,
|
||||
SFP_SPEED_10G
|
||||
};
|
||||
|
||||
/**
|
||||
* Representation of a 48-bit Ethernet address.
|
||||
*/
|
||||
@@ -110,6 +119,7 @@ extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
|
||||
extern __xdata struct uip_eth_addr uip_ethaddr;
|
||||
|
||||
// Headers for calls in the common code area (HOME/BANK0)
|
||||
void print_string_no_syslog(__code char *p);
|
||||
void print_string(__code char *p);
|
||||
void print_string_x(__xdata char *p);
|
||||
void print_long(uint32_t a);
|
||||
@@ -118,6 +128,7 @@ void print_byte(uint8_t a);
|
||||
void itoa(uint8_t v);
|
||||
void print_sfr_data(void);
|
||||
void print_phy_data(void);
|
||||
void print_cmd_prompt(void);
|
||||
void phy_write_mask(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v);
|
||||
void phy_write(uint8_t phy_id, uint8_t dev_id, uint16_t reg, uint16_t v);
|
||||
void phy_read(uint8_t phy_id, uint8_t dev_id, uint16_t reg);
|
||||
@@ -130,6 +141,7 @@ void sds_read(uint8_t sds_id, uint8_t page, uint8_t reg);
|
||||
void sds_write_v(uint8_t sds_id, uint8_t page, uint8_t reg, uint16_t v);
|
||||
void delay(uint16_t t);
|
||||
void sleep(uint16_t t);
|
||||
void write_char_no_syslog(char c);
|
||||
void write_char(char c);
|
||||
void print_reg(uint16_t reg);
|
||||
uint8_t sfp_read_reg(uint8_t slot, uint8_t reg);
|
||||
@@ -157,4 +169,5 @@ void sds_read(uint8_t sds_id, uint8_t page, uint8_t reg);
|
||||
void sds_write_v(uint8_t sds_id, uint8_t page, uint8_t reg, uint16_t v);
|
||||
void sds_config_mac(uint8_t sds, uint8_t mode);
|
||||
void sds_config(uint8_t sds, uint8_t mode);
|
||||
void handle_sfp(void);
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
#ifndef _RTL837X_FLASH_H_
|
||||
#define _RTL837X_FLASH_H_
|
||||
|
||||
// SPI FLASH MEMORY PAGE SIZE.
|
||||
#define FLASH_PAGE_SIZE 0x100
|
||||
// SPI FLASH MEMORY SECTOR SIZE = ERASE SIZE.
|
||||
#define FLASH_SECTOR_SIZE 0x1000
|
||||
|
||||
#if (FLASH_SECTOR_SIZE % FLASH_PAGE_SIZE) != 0
|
||||
#error "FLASH_SECTOR_SIZE must be a multiple of FLASH_PAGE_SIZE"
|
||||
#endif
|
||||
|
||||
|
||||
void flash_init(uint8_t enable_dio);
|
||||
void flash_read_uid(void);
|
||||
void flash_write_enable(void);
|
||||
@@ -13,3 +23,4 @@ void flash_write_bytes(__xdata uint8_t *ptr);
|
||||
__code char* get_flash_size_str(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -19,14 +19,6 @@ extern __xdata struct machine_runtime machine_detected;
|
||||
*/
|
||||
void static sds_init(void)
|
||||
{
|
||||
/*
|
||||
p001e.000d:9535 R02f8-00009535 R02f4-0000953a P000001.1e00000d:953a
|
||||
p001e.000d:953a p001e.000d:953a R02f8-0000953a R02f4-00009530 P000001.1e00000d:9530
|
||||
|
||||
RTL8373:
|
||||
p001e.000d:0010 R02f8-00000010 R02f4-0000001a P000001.1e00000d:b7fe
|
||||
p001e.000d:0010 p001e.000d:0010 R02f8-00000010 R02f4-00000010 P000001.1e00000d:b7fe
|
||||
*/
|
||||
phy_read(0, PHY_MMD30, 0xd);
|
||||
uint16_t pval = SFR_DATA_U16;
|
||||
|
||||
@@ -55,6 +47,8 @@ void static sds_init(void)
|
||||
uint16_t pval;
|
||||
|
||||
print_string(" N-settings");
|
||||
if (machine.n_10g)
|
||||
print_string(" - 10g");
|
||||
// Serdes 0 RX PN swap for 64B/66B
|
||||
sds_read(1, 6, 2);
|
||||
pval = SFR_DATA_U16;
|
||||
@@ -70,19 +64,30 @@ void static sds_init(void)
|
||||
pval = SFR_DATA_U16;
|
||||
sds_write_v(0, 6, 2, pval | 0x2000);
|
||||
|
||||
if (machine_detected.isRTL8373) {
|
||||
// RTL8224: Serdes 0 RX PN swap for 64B/66B
|
||||
// We assume that RTL8373N always paired with RTL8224N.
|
||||
// This sds register value is 0x0000 at reset.
|
||||
// So only write to it.
|
||||
RTL8224_SDS_WRITE(0, 6, 2, 0x2000);
|
||||
} else {
|
||||
// Serdes 0 RX PN swap for 8B/10B
|
||||
sds_read(0, 0, 0);
|
||||
pval = SFR_DATA_U16;
|
||||
sds_write_v(0, 0, 0, pval | 0x200);
|
||||
if (!machine.n_10g) {
|
||||
if (machine_detected.isRTL8373) {
|
||||
// RTL8224: Serdes 0 RX PN swap for 64B/66B
|
||||
// We assume that RTL8373N always paired with RTL8224N.
|
||||
// This sds register value is 0x0000 at reset.
|
||||
// So only write to it.
|
||||
RTL8224_SDS_WRITE(0, 6, 2, 0x2000);
|
||||
} else {
|
||||
// Serdes 0 RX PN swap for 8B/10B
|
||||
sds_read(0, 0, 0);
|
||||
pval = SFR_DATA_U16;
|
||||
sds_write_v(0, 0, 0, pval | 0x200);
|
||||
}
|
||||
} else if (machine.n_10g == 1) {
|
||||
reg_read_m(RTL837X_CFG_PHY_MDI_REVERSE);
|
||||
sfr_mask_data(0, 0x0f,0x0c);
|
||||
reg_write_m(RTL837X_CFG_PHY_MDI_REVERSE);
|
||||
REG_SET(RTL837X_CFG_PHY_TX_POLARITY_SWAP, 0x0000596a);
|
||||
} else if (machine.n_10g == 2) {
|
||||
REG_SET(RTL837X_CFG_PHY_MDI_REVERSE, 0xc);
|
||||
REG_SET(RTL837X_CFG_PHY_TX_POLARITY_SWAP, 0x0000596a);
|
||||
}
|
||||
}
|
||||
print_string("\nsds_init done\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +114,7 @@ void rtl8373_init(void) __banked
|
||||
phy_config_8224();
|
||||
sds_config_mac(1, SDS_OFF); // Off for now until SFP+ port used
|
||||
sds_config_mac(2, SDS_SGMII); // For RTL8224
|
||||
sds_config(0, SDS_QXGMII);
|
||||
sds_config(0, SDS_QXGMII); // For RTL8224
|
||||
|
||||
// SDS 1 setup
|
||||
// q012100:4902 Q012100:4906 q013605:0000 Q013605:4000 Q011f02:001f q011f15:0086
|
||||
@@ -163,7 +168,7 @@ void rtl8373_init(void) __banked
|
||||
|
||||
reg_bit_set(RTL837X_REG_HW_CONF, 0);
|
||||
|
||||
// enable EEE for all ports at 2.5G and 10G, but don't reset the PHYs
|
||||
// enable EEE for all ports at 2.5G, but don't reset the PHYs
|
||||
port_eee_enable_all(EEE_2G5 | EEE_NORESET);
|
||||
|
||||
// TODO: patch the PHYs
|
||||
@@ -188,14 +193,26 @@ void rtl8372_init(void) __banked
|
||||
print_string("\nrtl8372_init called\n");
|
||||
|
||||
sds_init();
|
||||
phy_config(8); // PHY configuration: External 8221B?
|
||||
phy_config(3); // PHY configuration: all internal PHYs?
|
||||
if (machine.n_10g != 2)
|
||||
phy_config(8); // PHY configuration: External 8221B?
|
||||
if (machine.n_10g)
|
||||
phy_config_8261(3, 0);
|
||||
if (machine.n_10g == 2)
|
||||
phy_config_8261(8, 1);
|
||||
else
|
||||
phy_config(3); // PHY configuration: all internal PHYs?
|
||||
// Set the MAC SerDes Modes Bits 0-4: SDS 0 = 0x2 (0x2), Bits 5-9: SDS 1: 1f (off)
|
||||
// r7b20:00000bff R7b20-00000bff r7b20:00000bff R7b20-00000bff r7b20:00000bff R7b20-000003ff r7b20:000003ff R7b20-000003e2 r7b20:000003e2 R7b20-000003e2
|
||||
reg_read_m(RTL837X_REG_SDS_MODES);
|
||||
sfr_mask_data(1, 0, 0x03);
|
||||
sfr_mask_data(0, 0, 0xe2);
|
||||
reg_write_m(RTL837X_REG_SDS_MODES);
|
||||
if (machine.n_10g == 1) {
|
||||
REG_SET(RTL837X_REG_SDS_MODES, 0x3ed); // Disable SFP for now, set RTL8261BE SDS 0 to 0xd
|
||||
} else if(machine.n_10g == 2) {
|
||||
REG_SET(RTL837X_REG_SDS_MODES, 0x1ad); // Both 10g ports use SDS_QXGMII
|
||||
} else {
|
||||
reg_read_m(RTL837X_REG_SDS_MODES);
|
||||
sfr_mask_data(1, 0, 0x03);
|
||||
sfr_mask_data(0, 0, 0xe2);
|
||||
reg_write_m(RTL837X_REG_SDS_MODES);
|
||||
}
|
||||
|
||||
// r0a90:000000f3 R0a90-000000fc
|
||||
reg_read_m(RTL837X_CFG_PHY_MDI_REVERSE);
|
||||
@@ -229,7 +246,7 @@ void rtl8372_init(void) __banked
|
||||
|
||||
|
||||
// enable EEE for all ports at 2.5G and 10G, but don't reset the PHYs
|
||||
port_eee_enable_all(EEE_2G5 | EEE_NORESET);
|
||||
port_eee_enable_all(EEE_10G | EEE_NORESET);
|
||||
|
||||
// TODO: patch the PHYs
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ void leds_dump(void) __banked
|
||||
print_string("RTL837X_REG_LED1_0_SET2: "); print_reg(RTL837X_REG_LED1_0_SET2); write_char('\n');
|
||||
print_string("RTL837X_REG_LED3_2_SET2: "); print_reg(RTL837X_REG_LED3_2_SET2); write_char('\n');
|
||||
print_string("RTL837X_REG_LED1_0_SET3: "); print_reg(RTL837X_REG_LED1_0_SET3); write_char('\n');
|
||||
print_string("RTL837X_REG_LED3_2_SET3: "); print_reg(RTL837X_REG_LED3_2_SET3); write_char('\n');
|
||||
print_string("RTL837X_REG_LED3_0_SET1: "); print_reg(RTL837X_REG_LED3_0_SET1); write_char('\n');
|
||||
print_string("RTL837X_REG_LED3_0_SET3: "); print_reg(RTL837X_REG_LED3_0_SET3); write_char('\n');
|
||||
print_string("RTL837X_LED_PORT_SET_SEL: "); print_reg(RTL837X_LED_PORT_SET_SEL); write_char('\n');
|
||||
@@ -45,6 +46,7 @@ void leds_dump(void) __banked
|
||||
print_string("RTL837X_REG_LED_GLB_MUX_5: "); print_reg(RTL837X_REG_LED_GLB_MUX_5); write_char('\n');
|
||||
print_string("RTL837X_REG_LED_GLB_MUX_6: "); print_reg(RTL837X_REG_LED_GLB_MUX_6); write_char('\n');
|
||||
print_string("RTL837X_REG_LED_GLB_ACTIVE: "); print_reg(RTL837X_REG_LED_GLB_ACTIVE); write_char('\n');
|
||||
print_string("RTL837X_REG_LED_MODE: "); print_reg(RTL837X_REG_LED_MODE); write_char('\n');
|
||||
print_string("LED pad Configuration:\n");
|
||||
for (uint8_t i = 0; i < 28; i++) {
|
||||
print_byte(i);
|
||||
|
||||
@@ -86,6 +86,76 @@ void rtl8224_phy_enable(void) __banked
|
||||
}
|
||||
|
||||
|
||||
void phy_config_8261(uint8_t phy, uint8_t sds) __banked
|
||||
{
|
||||
print_string("phy_config_8261: phy "); print_byte(phy);
|
||||
print_string(" sds "); print_byte(sds); write_char('\n');
|
||||
phy_write(phy, PHY_MMD30, 0x141, 0x80aa); // P000008.1e000141:80aa P000008.1e000143:8c07 p031e.0143:0c07
|
||||
phy_write(phy, PHY_MMD30, 0x143, 0x8c07);
|
||||
phy_read(phy, PHY_MMD30, 0x143);
|
||||
print_phy_data();
|
||||
phy_write(phy, PHY_MMD30, 0x141, 0x5078); // P000008.1e000141:5078 P000008.1e000143:8c86 p031e.0143:0c86
|
||||
phy_write(phy, PHY_MMD30, 0x143, 0x8c86);
|
||||
phy_read(phy, PHY_MMD30, 0x143);
|
||||
print_phy_data();
|
||||
phy_read(phy, PHY_MMD30, 0x105);
|
||||
print_phy_data(); // p031e.0105:0000
|
||||
|
||||
phy_write(phy, PHY_MMD30, 0xe1, 0x00); // P000008.1e0000e1:0000
|
||||
phy_write(phy, PHY_MMD30, 0xe3, 0x00); // P000008.1e0000e3:0000
|
||||
phy_write(phy, PHY_MMD30, 0xe4, 0x01); // P000008.1e0000e4:0001
|
||||
phy_write(phy, PHY_MMD30, 0xe0, 0x2f); // P000008.1e0000e0:002f
|
||||
|
||||
// The following are actually bit-ops:
|
||||
phy_write(phy, PHY_MMD31, 0xa442, 0x8418); // p031f.a442:0418 P000008.1f00a442:8418
|
||||
phy_write(phy, PHY_MMD31, 0xa448, 0x07a0); // p031f.a448:07a0 P000008.1f00a448:07a0
|
||||
phy_write(phy, PHY_MMD31, 0xa43a, 0x003f); // p031f.a43a:0030 P000008.1e0000e2:003f
|
||||
|
||||
phy_write(phy, PHY_MMD31, 0xc800, 0x5a02); // P000008.1f00c800:5a02
|
||||
|
||||
phy_write(phy, PHY_MMD30, 0x01ee, 0x5a02); // p031e.01ee:5a00 P000008.1e0001ee:5a02
|
||||
phy_write(phy, PHY_MMD30, 0x0230, 0x0002); // p031e.0230:0000 P000008.1e000230:0002
|
||||
phy_write(phy, PHY_MMD31, 0xc802, 0x0073); // p031f.c802:0000 P000008.1f00c802:0073
|
||||
phy_write(phy, PHY_MMD30, 0x01ef, 0xe004); // p031e.01ef:0004 P000008.1e0001ef:e004
|
||||
delay(20);
|
||||
phy_write(phy, PHY_MMD30, 0x01ef, 0x0004); // p031e.01ef:e004 P000008.1e0001ef:0004
|
||||
delay(20);
|
||||
phy_write(phy, PHY_MMD30, 0x0230, 0x01c2); // p031e.0230:01c2 P000008.1e000230:0002
|
||||
|
||||
phy_read(phy, PHY_MMD30, 0x103);
|
||||
print_phy_data(); // p031e.0103:8261
|
||||
|
||||
phy_write(phy, PHY_MMD30, 0x01c8, 0x0104); // p031e.01c8:0104 P000008.1e0001c8:0104
|
||||
phy_write(phy, PHY_MMD30, 0x01c9, 0x8080); // p031e.01c9:8080 P000008.1e0001c9:8080
|
||||
phy_write(phy, PHY_MMD30, 0x01ca, 0x2020); // p031e.01ca:2020 P000008.1e0001ca:2020
|
||||
phy_write(phy, PHY_MMD30, 0x0105, 0x0000); // p031e.0105:0000 P000008.1e000105:0000
|
||||
phy_write(phy, PHY_MMD30, 0x00c2, 0x880d); // p031e.00c2:880d P000008.1e0000c2:880d
|
||||
phy_write(phy, PHY_MMD30, 0x03f1, 0x0072); // p031e.03f1:0072 P000008.1e0003f1:0072
|
||||
phy_write(phy, PHY_MMD30, 0x02a2, 0x0010); // p031e.02a2:0010 P000008.1e0002a2:0010
|
||||
phy_write(phy, PHY_MMD30, 0x00c1, 0x0127); // p031e.00c1:0127 P000008.1e0000c1:0127
|
||||
phy_write(phy, PHY_MMD30, 0x00c1, 0x0167); // p031e.00c1:0127 P000008.1e0000c1:0167
|
||||
|
||||
sds_write_v(sds, 0x21, 0x00, 0x4096); // Q002100:4906
|
||||
sds_write_v(sds, 0x36, 0x05, 0x4000); // Q003605:4000
|
||||
sds_write_v(sds, 0x1f, 0x02, 0x001f); // Q001f02:001f
|
||||
|
||||
phy_read(phy, 0x01, 0x0000);
|
||||
print_phy_data(); // p0301.0000:2040
|
||||
|
||||
phy_write(phy, 0x01, 0x0000, 0x2040); // P000008.01000000:2040
|
||||
delay(20);
|
||||
|
||||
sds_write_v(sds, 0, 0, 0x1603); // Q000000:1603
|
||||
delay(20);
|
||||
sds_write_v(sds, 0, 0, 0x1601); // Q000000:1601
|
||||
delay(20);
|
||||
sds_write_v(sds, 0, 0, 0x1603); //Q000000:1603
|
||||
delay(20);
|
||||
// r6330:00005555 R6330-00005555 r7b20:000003ed R7b20-000003ed
|
||||
print_string("\r\nphy_config_8261 done\n");
|
||||
}
|
||||
|
||||
|
||||
void phy_config(uint8_t phy) __banked
|
||||
{
|
||||
print_string("\r\nphy_config: ");
|
||||
@@ -193,6 +263,10 @@ void phy_set_speed(void) __banked
|
||||
uint16_t v;
|
||||
|
||||
print_string("Setting port "); write_char(machine.log_to_phys_port[phy_settings.port] + '0');
|
||||
if (machine.n_10g && phy_settings.port == 3)
|
||||
phy_settings.is10g_port = 1;
|
||||
if (machine.n_10g == 2 && phy_settings.port == 8)
|
||||
phy_settings.is10g_port = 1;
|
||||
if (phy_settings.speed == PHY_OFF) {
|
||||
print_string(" to disabled");
|
||||
} else {
|
||||
@@ -200,6 +274,8 @@ void phy_set_speed(void) __banked
|
||||
switch(phy_settings.speed) {
|
||||
case PHY_SPEED_AUTO:
|
||||
print_string("auto");
|
||||
if (phy_settings.is10g_port)
|
||||
print_string (" (10g)");
|
||||
break;
|
||||
case PHY_SPEED_10M:
|
||||
print_string("10M");
|
||||
@@ -246,7 +322,10 @@ void phy_set_speed(void) __banked
|
||||
// bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD
|
||||
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081);
|
||||
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
|
||||
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200); // Loop timing enabled
|
||||
if (phy_settings.is10g_port)
|
||||
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0e00);
|
||||
else
|
||||
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200);
|
||||
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x3200); // Restart AN
|
||||
} else {
|
||||
// AN Control Register (MMD 7.0x0000)
|
||||
@@ -285,6 +364,12 @@ void phy_set_speed(void) __banked
|
||||
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081);
|
||||
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
|
||||
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
|
||||
} else if (phy_settings.speed == PHY_SPEED_5G) {
|
||||
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081);
|
||||
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0400, 0x0000);
|
||||
} else if (phy_settings.speed == PHY_SPEED_10G) {
|
||||
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081);
|
||||
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0800, 0x0000);
|
||||
}
|
||||
}
|
||||
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x3000); // Enable AN
|
||||
@@ -442,6 +527,10 @@ void phy_show(uint8_t port) __banked
|
||||
v = SFR_DATA_U16;
|
||||
if (v & 0x0080)
|
||||
print_string(" 2500BaseN-Full");
|
||||
if (v & 0x0100)
|
||||
print_string(" 5000BaseN-Full");
|
||||
if (v & 0x1000)
|
||||
print_string(" 10GBaseN-Full");
|
||||
}
|
||||
phy_read(port, PHY_MMD_AN, PHY_ANEG_LP_ABILITY);
|
||||
v = SFR_DATA_U16;
|
||||
|
||||
@@ -14,6 +14,7 @@ struct phy_settings {
|
||||
uint8_t duplex;
|
||||
uint8_t port;
|
||||
uint8_t speed;
|
||||
uint8_t is10g_port;
|
||||
};
|
||||
|
||||
extern __xdata struct phy_settings phy_settings;
|
||||
@@ -28,6 +29,7 @@ void phy_reset(uint8_t port) __banked;
|
||||
void rtl8224_read_reg_u16(uint16_t reg) __banked;
|
||||
void rtl8224_write_reg_u16(uint16_t reg, uint16_t val) __banked;
|
||||
void rtl8224_sds_write(uint16_t sds_cmd, uint16_t val) __banked;
|
||||
void phy_config_8261(uint8_t phy, uint8_t sds) __banked;
|
||||
|
||||
#define RTL8224_SDS_WRITE(sds_id, page, reg, v) uint16_t _sdscmd = (uint16_t)(sds_id & 0x01) | (1 << 14) | (1 << 15); \
|
||||
_sdscmd |= (page & 0x3F) << 1; \
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
#include "rtl837x_common.h"
|
||||
#include "rtl837x_regs.h"
|
||||
|
||||
uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin) {
|
||||
#pragma codeseg BANK2
|
||||
#pragma constseg BANK2
|
||||
|
||||
uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin) __banked {
|
||||
switch (sda_pin) {
|
||||
case GPIO47_I2C_SDA0:
|
||||
return 0;
|
||||
@@ -19,7 +22,7 @@ uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin) {
|
||||
uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin) __banked{
|
||||
switch (scl_pin) {
|
||||
case GPIO46_I2C_SCL0:
|
||||
return 0;
|
||||
@@ -35,18 +38,18 @@ uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin) {
|
||||
}
|
||||
|
||||
/* Returns RTL837X_REG_GPIO_XX_OUTPUT register address */
|
||||
static uint16_t gpio_output_reg(uint8_t pin) {
|
||||
static uint16_t gpio_output_reg(uint8_t pin) __banked{
|
||||
return pin < 32 ? RTL837X_REG_GPIO_00_31_OUTPUT : RTL837X_REG_GPIO_32_63_OUTPUT;
|
||||
}
|
||||
|
||||
/* Returns RTL837X_REG_GPIO_XX_DIRECTION register address */
|
||||
static uint16_t gpio_direction_reg(uint8_t pin) {
|
||||
static uint16_t gpio_direction_reg(uint8_t pin) __banked {
|
||||
return pin < 32 ? RTL837X_REG_GPIO_00_31_DIRECTION : RTL837X_REG_GPIO_32_63_DIRECTION;
|
||||
}
|
||||
|
||||
|
||||
/* Enable GPIO functions for pin */
|
||||
static void gpio_mux_setup(uint8_t pin)
|
||||
static void gpio_mux_setup(uint8_t pin) __banked
|
||||
{
|
||||
// Some GPIOs require setting MUX registers to enable GPIO
|
||||
switch (pin) {
|
||||
@@ -94,7 +97,7 @@ static void gpio_mux_setup(uint8_t pin)
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_input_setup(uint8_t pin) {
|
||||
void gpio_input_setup(uint8_t pin) __banked {
|
||||
if (pin == GPIO_NA) {
|
||||
return;
|
||||
}
|
||||
@@ -103,7 +106,7 @@ void gpio_input_setup(uint8_t pin) {
|
||||
reg_bit_clear(gpio_direction_reg(pin), (pin % 32));
|
||||
}
|
||||
|
||||
void gpio_output_setup(uint8_t pin, __xdata uint8_t initial_val) {
|
||||
void gpio_output_setup(uint8_t pin, __xdata uint8_t initial_val) __banked{
|
||||
if (pin == GPIO_NA) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -72,22 +72,22 @@
|
||||
#define GPIO_NA 0xFF
|
||||
|
||||
/* Convert SDA PIN GPIO to I2C bus number */
|
||||
uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin);
|
||||
uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin) __banked;
|
||||
|
||||
/* Convert SCL PIN GPIO to I2C bus number */
|
||||
uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin);
|
||||
uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin) __banked;
|
||||
|
||||
/*
|
||||
* Setup a GPIO pin as input
|
||||
* pin: GPIO pin number 0-63
|
||||
*/
|
||||
void gpio_input_setup(uint8_t pin);
|
||||
void gpio_input_setup(uint8_t pin) __banked;
|
||||
|
||||
/*
|
||||
* Setup a GPIO pin as output
|
||||
* pin: GPIO pin number 0-63
|
||||
* initial_val: 1 for bit set in RTL837X_REG_GPIO_xx_OUTPUT, 0 for bit not set
|
||||
*/
|
||||
void gpio_output_setup(uint8_t pin, __xdata uint8_t initial_val);
|
||||
void gpio_output_setup(uint8_t pin, __xdata uint8_t initial_val) __banked;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -116,11 +116,45 @@ uint16_t port_pvid_get(uint8_t port) __banked
|
||||
void vlan_delete(uint16_t vlan) __banked
|
||||
{
|
||||
print_string("\nvlan_delete called \n"); print_short(vlan);
|
||||
vlan_name_remove(vlan);
|
||||
REG_WRITE(RTL837x_TBL_DATA_IN_A, 0, 0, 0, 0);
|
||||
REG_WRITE(RTL837X_TBL_CTRL, vlan >> 8, vlan, TBL_VLAN, TBL_WRITE | TBL_EXECUTE);
|
||||
}
|
||||
|
||||
|
||||
void vlan_name_remove(uint16_t vlan) __banked
|
||||
{
|
||||
static __xdata uint16_t name_pos;
|
||||
static __xdata uint16_t entry_start;
|
||||
static __xdata uint16_t pos;
|
||||
static __xdata uint16_t entry_len;
|
||||
static __xdata uint16_t move_count;
|
||||
static __xdata uint16_t j;
|
||||
|
||||
name_pos = vlan_name(vlan);
|
||||
if (name_pos == 0xffff)
|
||||
return;
|
||||
|
||||
entry_start = name_pos - 3;
|
||||
pos = entry_start;
|
||||
|
||||
while (pos < vlan_ptr && vlan_names[pos] != ' ')
|
||||
pos++;
|
||||
if (pos >= vlan_ptr)
|
||||
return;
|
||||
pos++;
|
||||
|
||||
entry_len = pos - entry_start;
|
||||
move_count = vlan_ptr - pos;
|
||||
|
||||
for (j = 0; j < move_count; j++)
|
||||
vlan_names[entry_start + j] = vlan_names[pos + j];
|
||||
|
||||
vlan_ptr -= entry_len;
|
||||
vlan_names[vlan_ptr] = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reads VLAN information from VLAN table
|
||||
* Returns data in sfr_data
|
||||
@@ -387,7 +421,7 @@ void port_l2_setup(void) __banked
|
||||
|
||||
void port_stats_print(void) __banked
|
||||
{
|
||||
print_string("\n Port\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n");
|
||||
print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n");
|
||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||
write_char('0' + machine.log_to_phys_port[i]); write_char('\t');
|
||||
|
||||
@@ -440,6 +474,9 @@ void port_stats_print(void) __banked
|
||||
case 5:
|
||||
print_string("2.5G\t");
|
||||
break;
|
||||
case 6:
|
||||
print_string("5G\t");
|
||||
break;
|
||||
case 99:
|
||||
print_string("Down\t");
|
||||
break;
|
||||
@@ -489,20 +526,19 @@ void port_eee_enable(__xdata uint8_t port,__xdata uint8_t speed) __banked
|
||||
return;
|
||||
}
|
||||
|
||||
REG_SET(RTL837X_EEE_CTRL_BASE + (port << 8), EEE_RX_ENABLE | EEE_TX_ENABLE);
|
||||
print_string("EEE on for "); print_byte(port); print_string(" speed ");
|
||||
// Enable all speeds up to the specified speed
|
||||
if ((speed & (EEE_100 | EEE_1000 | EEE_2G5)) == EEE_100) {
|
||||
if (speed & EEE_100) {
|
||||
print_string("100m\n");
|
||||
REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100);
|
||||
// Enable EEE advertisement for 100BASE-T via EEE Advertisement Reg
|
||||
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_100M);
|
||||
if (!(speed & EEE_NORESET))
|
||||
phy_reset(port);
|
||||
return;
|
||||
}
|
||||
if ((speed & (EEE_100 | EEE_1000 | EEE_2G5)) == EEE_1000) {
|
||||
if (speed & EEE_1000) {
|
||||
print_string("1g\n");
|
||||
REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000);
|
||||
// Disable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
|
||||
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, 0);
|
||||
// Enable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg
|
||||
@@ -511,9 +547,8 @@ void port_eee_enable(__xdata uint8_t port,__xdata uint8_t speed) __banked
|
||||
phy_reset(port);
|
||||
return;
|
||||
}
|
||||
if ((speed & (EEE_100 | EEE_1000 | EEE_2G5)) == EEE_2G5) {
|
||||
if (speed & EEE_2G5) {
|
||||
print_string("2g5\n");
|
||||
REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000 | EEE_2G5);
|
||||
// Enable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg
|
||||
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_1G | PHY_EEE_BIT_100M);
|
||||
// Enable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
|
||||
@@ -522,6 +557,26 @@ void port_eee_enable(__xdata uint8_t port,__xdata uint8_t speed) __banked
|
||||
phy_reset(port);
|
||||
return;
|
||||
}
|
||||
if (speed & EEE_5G) {
|
||||
print_string("5g\n");
|
||||
// Enable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg
|
||||
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_1G | PHY_EEE_BIT_100M);
|
||||
// Enable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
|
||||
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, PHY_EEE_BIT_2G5 | PHY_EEE_BIT_5G);
|
||||
if (!(speed & EEE_NORESET))
|
||||
phy_reset(port);
|
||||
return;
|
||||
}
|
||||
if (speed & EEE_10G) {
|
||||
print_string("10g\n");
|
||||
// Enable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg
|
||||
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_10G | PHY_EEE_BIT_1G | PHY_EEE_BIT_100M);
|
||||
// Enable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
|
||||
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, PHY_EEE_BIT_2G5 | PHY_EEE_BIT_5G);
|
||||
if (!(speed & EEE_NORESET))
|
||||
phy_reset(port);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -532,7 +587,7 @@ void port_eee_disable(uint8_t port) __banked
|
||||
return;
|
||||
|
||||
print_string("EEE off for "); print_byte(port); write_char('\n');
|
||||
REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), 0);
|
||||
REG_SET(RTL837X_EEE_CTRL_BASE + (port << 8), 0);
|
||||
// Disable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg
|
||||
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, 0);
|
||||
// Disable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
|
||||
@@ -552,8 +607,24 @@ void port_eee_status(uint8_t port) __banked
|
||||
|
||||
uint16_t v;
|
||||
print_string("Advertising: ");
|
||||
|
||||
if (machine.n_10g) {
|
||||
phy_read(port, PHY_MMD_AN, PHY_EEE_ADV);
|
||||
v = SFR_DATA_U16;
|
||||
if (v & PHY_EEE_BIT_10G)
|
||||
print_string(" 10G");
|
||||
else
|
||||
print_string(" ");
|
||||
}
|
||||
phy_read(port, PHY_MMD_AN, PHY_EEE_ADV2);
|
||||
v = SFR_DATA_U16;
|
||||
if (machine.n_10g) {
|
||||
if (v & PHY_EEE_BIT_5G)
|
||||
print_string(" 5G");
|
||||
else
|
||||
print_string(" ");
|
||||
}
|
||||
v = SFR_DATA_U16;
|
||||
if (v & PHY_EEE_BIT_2G5)
|
||||
print_string(" 2.5G");
|
||||
else
|
||||
@@ -570,8 +641,22 @@ void port_eee_status(uint8_t port) __banked
|
||||
print_string(" ");
|
||||
|
||||
print_string(" Link Partner: ");
|
||||
if (machine.n_10g) {
|
||||
phy_read(port, PHY_MMD_AN, PHY_EEE_LP_ABILITY);
|
||||
v = SFR_DATA_U16;
|
||||
if (v & PHY_EEE_BIT_10G)
|
||||
print_string(" 10G");
|
||||
else
|
||||
print_string(" ");
|
||||
}
|
||||
phy_read(port, PHY_MMD_AN, PHY_EEE_LP_ABILITY2);
|
||||
v = SFR_DATA_U16;
|
||||
if (machine.n_10g) {
|
||||
if (v & PHY_EEE_BIT_5G)
|
||||
print_string(" 5G");
|
||||
else
|
||||
print_string(" ");
|
||||
}
|
||||
if (v & PHY_EEE_BIT_2G5)
|
||||
print_string(" 2.5G");
|
||||
else
|
||||
@@ -599,7 +684,16 @@ 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++) {
|
||||
port_eee_enable(i, speed);
|
||||
if (i == 3 && machine.n_10g) {
|
||||
port_eee_enable(i, speed);
|
||||
} else if (i == 8 && machine.n_10g == 2) {
|
||||
port_eee_enable(i, speed);
|
||||
} else {
|
||||
if (speed & EEE_10G)
|
||||
port_eee_enable(i, speed & EEE_NORESET | EEE_2G5);
|
||||
else
|
||||
port_eee_enable(i, speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,16 @@ struct vlan_settings {
|
||||
uint16_t tagged;
|
||||
};
|
||||
|
||||
/*
|
||||
* Port EEE settings
|
||||
*/
|
||||
#define EEE_100 0x01
|
||||
#define EEE_1000 0x04
|
||||
#define EEE_2G5 0x10
|
||||
#define EEE_5G 0x20
|
||||
#define EEE_10G 0x40
|
||||
#define EEE_NORESET 0x80
|
||||
|
||||
extern __xdata struct vlan_settings vlan_settings;
|
||||
|
||||
uint8_t port_l2_forget(void) __banked;
|
||||
@@ -40,6 +50,7 @@ void port_l2_learned(void) __banked;
|
||||
void port_stats_print(void) __banked;
|
||||
int8_t vlan_get(register uint16_t vlan) __banked;
|
||||
__xdata uint16_t vlan_name(register uint16_t vlan) __banked;
|
||||
void vlan_name_remove(uint16_t vlan) __banked;
|
||||
void vlan_setup(void) __banked;
|
||||
void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked;
|
||||
uint16_t port_pvid_get(uint8_t port) __banked;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define RTL837X_REG_LED_GLB_IO_EN 0x65DC
|
||||
#define RTL837X_REG_LED3_0_SET3 0x6524
|
||||
#define RTL837X_REG_LED3_0_SET1 0x6528
|
||||
#define RTL837X_REG_LED3_2_SET3 0x652C
|
||||
#define RTL837X_REG_LED1_0_SET3 0x6530
|
||||
#define RTL837X_REG_LED3_2_SET2 0x6534
|
||||
#define RTL837X_REG_LED1_0_SET2 0x6538
|
||||
@@ -72,6 +73,7 @@
|
||||
*/
|
||||
#define SDS_SGMII 0x02
|
||||
#define SDS_1000BX_FIBER 0x04
|
||||
#define SDS_100FX 0x05
|
||||
#define SDS_QXGMII 0x0d
|
||||
#define SDS_HISGMII 0x12
|
||||
#define SDS_HSG 0x16
|
||||
@@ -268,14 +270,11 @@
|
||||
/*
|
||||
* EEE
|
||||
*/
|
||||
#define RTL837X_EEE_STATUS 0x125C
|
||||
#define RTL837X_EEE_CTRL_BASE 0x125C
|
||||
#define EEE_RX_ENABLE 0x01
|
||||
#define EEE_TX_ENABLE 0x02
|
||||
#define RTL837X_MAC_EEE_ABLTY 0x6404
|
||||
#define RTL8373_PHY_EEE_ABLTY 0x642C
|
||||
#define RTL8373_EEE_CTRL_BASE 0x606c
|
||||
#define EEE_100 0x01
|
||||
#define EEE_1000 0x04
|
||||
#define EEE_2G5 0x10
|
||||
#define EEE_NORESET 0x80
|
||||
|
||||
/*
|
||||
* RANDOM
|
||||
|
||||
@@ -136,7 +136,7 @@ void stp_in(void) __banked
|
||||
// print_string("Flags: "); print_byte(STP_I->flags); write_char('\n');
|
||||
print_string("Check new Root\n");
|
||||
if (STP_I->root.prio < root_bridge.prio
|
||||
|| ((STP_I->root.prio == root_bridge.prio) && cmpMAC(STP_I->root.mac, STP_I->root.mac) < 0)) {
|
||||
|| ((STP_I->root.prio == root_bridge.prio) && cmpMAC(STP_I->root.mac, root_bridge.mac) < 0)) {
|
||||
print_string("Updating Root bridge\n");
|
||||
root_bridge.prio = STP_I->root.prio;
|
||||
memcpy(root_bridge.mac, STP_I->root.mac, 6);
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
#include "uip/uip_arp.h"
|
||||
#include "machine.h"
|
||||
#include "phy.h"
|
||||
#include "syslog.h"
|
||||
|
||||
extern __code const struct machine machine;
|
||||
extern __xdata uint32_t flash_size;
|
||||
extern __xdata uint8_t err_status;
|
||||
|
||||
extern __xdata uint16_t crc_value;
|
||||
__xdata struct machine_runtime machine_detected;
|
||||
@@ -137,6 +137,7 @@ __xdata char sfp_module_vendor[2][17];
|
||||
__xdata char sfp_module_model[2][17];
|
||||
__xdata char sfp_module_serial[2][17];
|
||||
__xdata uint8_t sfp_options[2];
|
||||
__xdata uint8_t sfp_speed[2];
|
||||
__xdata bool button_last;
|
||||
__xdata uint8_t button_sec_counter_last;
|
||||
volatile __bit tx_buf_empty;
|
||||
@@ -216,7 +217,7 @@ void isr_serial(void) __interrupt(4)
|
||||
}
|
||||
|
||||
|
||||
void write_char(char c)
|
||||
void write_char_no_syslog(char c)
|
||||
{
|
||||
do {
|
||||
} while (tx_buf_empty == 0);
|
||||
@@ -230,6 +231,17 @@ void write_char(char c)
|
||||
SBUF = c;
|
||||
}
|
||||
|
||||
void write_char(char c)
|
||||
{
|
||||
write_char_no_syslog(c);
|
||||
|
||||
if (syslog_state.enabled) {
|
||||
logbuf[syslog_state.writeptr++] = c;
|
||||
syslog_state.writeptr &= (LOGBUF_SIZE - 1);
|
||||
if (c == '\n')
|
||||
syslog_state.line_available = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void itoa(uint8_t v)
|
||||
{
|
||||
@@ -253,6 +265,12 @@ void print_string(__code char *p)
|
||||
write_char(*p++);
|
||||
}
|
||||
|
||||
void print_string_no_syslog(__code char *p)
|
||||
{
|
||||
while (*p)
|
||||
write_char_no_syslog(*p++);
|
||||
}
|
||||
|
||||
void print_string_x(__xdata char *p)
|
||||
{
|
||||
while (*p)
|
||||
@@ -350,6 +368,11 @@ void print_byte(uint8_t a)
|
||||
write_char(low);
|
||||
}
|
||||
|
||||
void print_cmd_prompt(void)
|
||||
{
|
||||
print_string_no_syslog("\n> ");
|
||||
}
|
||||
|
||||
/*
|
||||
* External IRQ 0 Service Routine: Called on link change?
|
||||
* Note that all registers are being put on the STACK because of calling a subroutine
|
||||
@@ -867,13 +890,14 @@ void early_boot_handle_button(void)
|
||||
* to connect to an SFP module or a PHY
|
||||
* Valid modes are SDS_10GR, SDS_QXGMII, SDS_HISGMII, SDS_HSG, SDS_SGMII and SDS_1000BX_FIBER
|
||||
* The SerDes ID may be 0 or 1 for RTL8272 and 0-2 for RTL8373
|
||||
* SDS_QXGMII is used for 10G Fiber, RTL8224 and RTL8261BE
|
||||
*/
|
||||
void sds_config(uint8_t sds, uint8_t mode)
|
||||
{
|
||||
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) // 10G Fiber, 10G connection to RTL8224
|
||||
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
|
||||
@@ -903,13 +927,17 @@ void sds_config(uint8_t sds, uint8_t mode)
|
||||
v = 0x0200;
|
||||
page = 0x2e;
|
||||
break;
|
||||
case SDS_100FX:
|
||||
v = 0x0200;
|
||||
page = 0x26;
|
||||
break;
|
||||
default:
|
||||
print_string("Error in SDS Mode\n");
|
||||
return;
|
||||
}
|
||||
sds_write_v(sds, 0x36, 0x10, v); // Q003610:0200
|
||||
|
||||
if (page == 0x2e) { // 10G Fiber
|
||||
if (page == 0x2e) { // 10G Fiber / SDS_QXGMII
|
||||
sds_write_v(sds, page, 0x04, 0x0080); // Q012e04:0080
|
||||
sds_write_v(sds, page, 0x06, 0x0408); // Q012e06:0408
|
||||
sds_write_v(sds, page, 0x07, 0x020d); // Q012e07:020d
|
||||
@@ -938,6 +966,30 @@ void sds_config(uint8_t sds, uint8_t mode)
|
||||
sds_write_v(sds, 0x07, 0x0c, 0x9401); // Q00070c:9401
|
||||
sds_write_v(sds, 0x1f, 0x0b, 0x0003); // Q001f0b:0003
|
||||
sds_write_v(sds, 0x06, 0x03, 0xc45c); // Q000603:c45c
|
||||
|
||||
// RTL8261BE
|
||||
if (machine.n_10g && mode == SDS_QXGMII) {
|
||||
sds_write_v(sds, 0x06, 0x1f, 0x2100); // Q00061f:2100
|
||||
sds_write_v(sds, 0x07, 0x11, 0x054f); // Q000711:054f
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0030); // Q002000:0030
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0050); // Q002000:0050
|
||||
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0cd0); // Q002000:0cd0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x04d0); // Q002000:04d0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x04d0); // Q002000:04d0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0cd0); // Q002000:0cd0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0050); // Q002000:0050
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0030); // Q002000:0030
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0000); // Q002000:0000
|
||||
sds_write_v(sds, 0x1f, 0x00, 0x000b); // Q001f00:000b
|
||||
sds_write_v(sds, 0x1f, 0x00, 0x0000); // Q001f00:0000
|
||||
return;
|
||||
}
|
||||
if (mode != SDS_QXGMII)
|
||||
sds_write_v(sds, 0x06, 0x1f, 0x2100); // Q00061f:2100
|
||||
|
||||
@@ -1122,11 +1174,13 @@ void handle_tx(void)
|
||||
|
||||
static inline uint8_t sfp_rate_to_sds_config(register uint8_t rate)
|
||||
{
|
||||
if (rate == 0x1 || rate == 0x2)
|
||||
return SDS_100FX;
|
||||
if (rate == 0xc || rate == 0xd)
|
||||
return SDS_1000BX_FIBER;
|
||||
if (rate >= 0x19 && rate <= 0x20) // Ethernet 2.5 GBit
|
||||
return SDS_HSG;
|
||||
if (rate > 0x65 && rate < 0x70)
|
||||
if (rate >= 0x63 && rate < 0x70)
|
||||
return SDS_10GR;
|
||||
return 0xff;
|
||||
}
|
||||
@@ -1187,6 +1241,14 @@ void handle_sfp(void)
|
||||
// Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit
|
||||
delay(100); // Delay, because some modules need time to wake up
|
||||
uint8_t rate = sfp_read_reg(sfp, 12);
|
||||
if (sfp_speed[sfp] == SFP_SPEED_100M)
|
||||
rate = 0x1;
|
||||
else if (sfp_speed[sfp] == SFP_SPEED_1G)
|
||||
rate = 0xc;
|
||||
else if (sfp_speed[sfp] == SFP_SPEED_2G5)
|
||||
rate = 0x19;
|
||||
else if (sfp_speed[sfp] == SFP_SPEED_10G)
|
||||
rate = 0x69;
|
||||
print_string(" Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored?
|
||||
print_string(" Encoding: "); print_byte(sfp_read_reg(sfp, 11));
|
||||
print_string(" Module: "); sfp_print_info(sfp);
|
||||
@@ -1342,13 +1404,17 @@ void idle(void)
|
||||
uint8_t p5 = sfr_data[2] >> 4;
|
||||
uint8_t p5_last = linkbits_last[2] >> 4;
|
||||
cpy_4(linkbits_last, sfr_data);
|
||||
// Handle link change of the RTL8221 PHY, adjust SDS mode
|
||||
if (p5_last != p5) {
|
||||
// Handle link change of the RTL8221 PHY, adjust SDS mode, RTL8261BE always uses SDS_QXGMII
|
||||
if (!machine.n_10g && p5_last != p5) {
|
||||
if (p5 == 0x5) // 2.5GBit Mode
|
||||
sds_config(0, SDS_HISGMII);
|
||||
else if (p5 == 0x2) // 1GBit
|
||||
sds_config(0, SDS_SGMII);
|
||||
}
|
||||
if (machine.n_10g)
|
||||
sds_config(0, SDS_QXGMII);
|
||||
if (machine.n_10g == 2)
|
||||
sds_config(1, SDS_QXGMII);
|
||||
} else {
|
||||
cpy_4(linkbits_last, sfr_data);
|
||||
}
|
||||
@@ -1376,7 +1442,7 @@ void idle(void)
|
||||
cmd_tokenize();
|
||||
if (err_status == ERR_OK)
|
||||
cmd_parser();
|
||||
print_string("\n> ");
|
||||
print_cmd_prompt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1637,7 +1703,11 @@ void init_smi(void)
|
||||
/* Set the SMI(i.e.I2C) type for PHY polling, 0b01 is 2.5/10G PHY. Disable (0b00) for the SFP-ports
|
||||
* which are at port 8 and additionally at port 3 for a dual SFP device
|
||||
*/
|
||||
REG_SET(RTL837X_REG_SMI_MAC_TYPE, machine.n_sfp == 2 ? 0x00005515 : 0x00005555);
|
||||
if (machine.n_10g == 2) {
|
||||
REG_SET(RTL837X_REG_SMI_MAC_TYPE, 0x00015555);
|
||||
} else {
|
||||
REG_SET(RTL837X_REG_SMI_MAC_TYPE, machine.n_sfp == 2 ? 0x00005515 : 0x00005555);
|
||||
}
|
||||
|
||||
// Configure polling of all PHYs by the MAC to detect link-state changes
|
||||
if (machine_detected.isRTL8373) {
|
||||
@@ -1664,6 +1734,11 @@ void init_smi(void)
|
||||
sfr_mask_data(1, 0x80, 0);
|
||||
reg_write_m(RTL837X_REG_SMI_PORT0_5_ADDR);
|
||||
}
|
||||
|
||||
if (machine.n_10g == 2) {
|
||||
// Set address of second external PHY on port 8
|
||||
REG_SET(RTL837X_REG_SMI_PORT6_9_ADDR, 0x000040e6);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1936,6 +2011,8 @@ void main(void)
|
||||
// Print SW version
|
||||
print_sw_version();
|
||||
|
||||
// Set AUTONEG for SFP ports
|
||||
sfp_speed[0] = sfp_speed[1] = SFP_SPEED_AUTO;
|
||||
// Reset NIC
|
||||
reg_bit_set(RTL837X_REG_RESET, RESET_NIC_BIT);
|
||||
do {
|
||||
@@ -1985,6 +2062,8 @@ void main(void)
|
||||
|
||||
check_and_flash_update_image();
|
||||
|
||||
syslog_init();
|
||||
|
||||
#ifdef DEBUG
|
||||
// This register seems to work on the RTL8373 only if also the SDS
|
||||
// Is correctly configured. Therefore, we can test it, here...
|
||||
@@ -2016,7 +2095,6 @@ void main(void)
|
||||
|
||||
setup_i2c();
|
||||
setup_sfp_gpio();
|
||||
|
||||
print_string(greeting);
|
||||
|
||||
print_string("\nClock register: ");
|
||||
@@ -2031,12 +2109,13 @@ void main(void)
|
||||
early_boot_handle_button();
|
||||
|
||||
execute_config();
|
||||
print_string("\n> ");
|
||||
print_cmd_prompt();
|
||||
idle_ready = 1;
|
||||
|
||||
set_sys_led_state(SYS_LED_ON);
|
||||
|
||||
cmd_editor_init();
|
||||
|
||||
while (1) {
|
||||
cmd_edit();
|
||||
idle(); // Enter Idle mode until interrupt occurs
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
#include "machine.h"
|
||||
#include "syslog.h"
|
||||
#include "uip/uip.h"
|
||||
#include "rtl837x_common.h"
|
||||
|
||||
#pragma codeseg BANK2
|
||||
#pragma constseg BANK2
|
||||
|
||||
#define SYSLOG_P ((__xdata uint8_t *)uip_appdata)
|
||||
|
||||
__xdata char logbuf[LOGBUF_SIZE];
|
||||
__xdata struct syslog_state syslog_state;
|
||||
__xdata uip_ipaddr_t server_ip;
|
||||
|
||||
#define state syslog_state
|
||||
|
||||
void syslog_init(void) __banked
|
||||
{
|
||||
state.enabled = 0;
|
||||
state.syslog_conn = 0;
|
||||
state.writeptr = 0;
|
||||
state.readptr = 0;
|
||||
state.line_available = 0;
|
||||
state.server_ip[0] = 0; state.server_ip[1] = 0; state.server_ip[2] = 0; state.server_ip[3] = 0;// Default to 0.0.0.0
|
||||
}
|
||||
|
||||
void syslog_start(void) __banked
|
||||
{
|
||||
if (state.syslog_conn == 0) {
|
||||
uip_ipaddr(server_ip, state.server_ip[0], state.server_ip[1], state.server_ip[2], state.server_ip[3]);
|
||||
state.syslog_conn = uip_udp_new(&server_ip, HTONS(514));
|
||||
if (state.syslog_conn == 0) {
|
||||
print_string_no_syslog("Failed to create a new UDP client\n");
|
||||
return;
|
||||
}
|
||||
print_string_no_syslog("Started syslog to IP ");
|
||||
itoa(state.server_ip[0]); write_char('.'); itoa(state.server_ip[1]); write_char('.');
|
||||
itoa(state.server_ip[2]); write_char('.'); itoa(state.server_ip[3]); write_char('\n');
|
||||
state.enabled = 1;
|
||||
}
|
||||
else {
|
||||
print_string_no_syslog("Syslog is already running\n");
|
||||
}
|
||||
}
|
||||
|
||||
void syslog_stop(void) __banked
|
||||
{
|
||||
state.enabled = 0;
|
||||
if (state.syslog_conn != 0) {
|
||||
uip_udp_remove(state.syslog_conn);
|
||||
state.syslog_conn = 0;
|
||||
print_string_no_syslog("Stopped syslog\n");
|
||||
} else {
|
||||
print_string_no_syslog("Syslog is not running\n");
|
||||
}
|
||||
}
|
||||
|
||||
void syslog_callback(uint16_t lport) __banked
|
||||
{
|
||||
if (lport != state.syslog_conn->lport)
|
||||
return;
|
||||
|
||||
if ((state.readptr != state.writeptr) && state.line_available)
|
||||
{
|
||||
int16_t log_size = state.writeptr - state.readptr;
|
||||
if (log_size < 0)
|
||||
log_size += LOGBUF_SIZE;
|
||||
|
||||
// Skipping linefeeds at the start of the log line
|
||||
uint16_t log_start = state.readptr;
|
||||
while (log_size > 0 && logbuf[log_start] == '\n') {
|
||||
log_start = (log_start + 1) & (LOGBUF_SIZE - 1);
|
||||
log_size--;
|
||||
}
|
||||
|
||||
// Skipping linefeeds and whitespaces at the end of the log line
|
||||
uint16_t log_end = state.writeptr;
|
||||
while ( (log_size > 0) &&
|
||||
((logbuf[(log_end-1) & (LOGBUF_SIZE - 1)] == '\n') ||
|
||||
(logbuf[(log_end-1) & (LOGBUF_SIZE - 1)] == ' ')))
|
||||
{
|
||||
log_end = (log_end - 1) & (LOGBUF_SIZE - 1);
|
||||
log_size--;
|
||||
}
|
||||
|
||||
if (log_size == 0) {
|
||||
state.readptr = state.writeptr;
|
||||
state.line_available = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpyc(SYSLOG_P, "<14>", 4); // Syslog priority prefix
|
||||
|
||||
if (log_end < log_start) {
|
||||
memcpy(SYSLOG_P + 4, logbuf + log_start, LOGBUF_SIZE - log_start);
|
||||
memcpy(SYSLOG_P + 4 + LOGBUF_SIZE - log_start, logbuf, log_end);
|
||||
} else {
|
||||
memcpy(SYSLOG_P + 4, logbuf + log_start, log_end - log_start);
|
||||
}
|
||||
|
||||
uip_udp_send(log_size+4);
|
||||
state.readptr = state.writeptr;
|
||||
state.line_available = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef _SYSLOG_H_
|
||||
#define _SYSLOG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define LOGBUF_SIZE 512
|
||||
|
||||
struct syslog_state {
|
||||
uint8_t enabled;
|
||||
uint8_t line_available;
|
||||
uint16_t writeptr ;
|
||||
uint16_t readptr;
|
||||
uint8_t server_ip[4];
|
||||
|
||||
struct uip_udp_conn *syslog_conn;
|
||||
};
|
||||
|
||||
extern __xdata struct syslog_state syslog_state;
|
||||
extern __xdata char logbuf[LOGBUF_SIZE];
|
||||
|
||||
void syslog_init(void) __banked;
|
||||
void syslog_start(void) __banked;
|
||||
void syslog_stop(void) __banked;
|
||||
void syslog_callback(uint16_t lport) __banked;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
#include "uip/uip.h"
|
||||
#include "udp_apps.h"
|
||||
|
||||
void udp_callbacks(void)
|
||||
{
|
||||
dhcp_callback(uip_udp_conn->lport); // let the application decide if this is for it or not
|
||||
syslog_callback(uip_udp_conn->lport); // let the application decide if this is for it or not
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef _UDPAPPS_H_
|
||||
#define _UDPAPPS_H_
|
||||
|
||||
#include "dhcp.h"
|
||||
#include "syslog.h"
|
||||
|
||||
void udp_callbacks(void);
|
||||
|
||||
#ifndef UIP_UDP_APPCALL
|
||||
#define UIP_UDP_APPCALL udp_callbacks
|
||||
#endif /* UIP_UDP_APPCALL */
|
||||
|
||||
#endif
|
||||
@@ -153,7 +153,7 @@ typedef unsigned short uip_stats_t;
|
||||
our project. */
|
||||
/*#include "smtp.h"*/
|
||||
#include "httpd.h"
|
||||
#include "dhcp.h"
|
||||
#include "udp_apps.h"
|
||||
/*#include "telnetd.h"*/
|
||||
/*#include "webserver.h" */
|
||||
/*#include "dhcpc.h"*/
|
||||
|
||||