Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
855d587243 | ||
|
|
aa12adc098 | ||
|
|
4db49b2ee5 | ||
|
|
294174d152 | ||
|
|
19bcf86e80 | ||
|
|
8d467b2099 | ||
|
|
a45d0f659f | ||
|
|
820477cd27 | ||
|
|
e9171d7d22 | ||
|
|
dd0ecc5438 | ||
|
|
5e1ea935a7 | ||
|
|
57e7d7dd2a | ||
|
|
855383052b | ||
|
|
acaa80b732 | ||
|
|
233ff5a728 | ||
|
|
c2f5a91763 | ||
|
|
ed8dc0f43c | ||
|
|
7949975191 | ||
|
|
1374272db6 | ||
|
|
20fb626cc1 | ||
|
|
31a488e4e9 | ||
|
|
14bc823024 | ||
|
|
87c161dc70 | ||
|
|
04ab083652 | ||
|
|
1836c7dcb6 | ||
|
|
e33cd9d0c5 | ||
|
|
71880a95f5 | ||
|
|
494320b191 | ||
|
|
eb13d4ab04 | ||
|
|
a15500c493 | ||
|
|
a89467febc | ||
|
|
706abcf78d | ||
|
|
c868482669 | ||
|
|
9bd2d446d7 | ||
|
|
c3a6a46852 | ||
|
|
7a0f248424 | ||
|
|
23e2f5a99e | ||
|
|
81a7393a81 | ||
|
|
dc16b25d62 | ||
|
|
ffbd2c512d | ||
|
|
ba18fa19b0 | ||
|
|
70127018da | ||
|
|
e26a9e3db9 | ||
|
|
d29d7dcf98 | ||
|
|
734cce381a | ||
|
|
dfc96761b3 | ||
|
|
94d4ace88b | ||
|
|
284b2b003d | ||
|
|
68a8a9ee92 | ||
|
|
0045a74df0 | ||
|
|
0bdb238c0a | ||
|
|
033616ef63 | ||
|
|
a57aeda053 | ||
|
|
556899d346 | ||
|
|
cc734ecac2 | ||
|
|
e5d23f11de | ||
|
|
3c648d5936 | ||
|
|
4658667459 | ||
|
|
e966b153af | ||
|
|
5ecd0e6a32 | ||
|
|
d8b52d50de | ||
|
|
1f6f7fbcd4 | ||
|
|
c7ea28393a | ||
|
|
2f787feebf | ||
|
|
4c1266dca9 | ||
|
|
4d11d70356 | ||
|
|
ff94e383aa | ||
|
|
9f7e10fe7c | ||
|
|
b67e3eb602 | ||
|
|
5d731393f1 | ||
|
|
0e2a5fb7bc | ||
|
|
79c9d0deab | ||
|
|
73c56ecfe5 | ||
|
|
5e9f3324d5 | ||
|
|
94739644b7 | ||
|
|
257d8aac4f | ||
|
|
d5019b41df | ||
|
|
eae7f10d7a | ||
|
|
1b43addb11 | ||
|
|
f8c1ab4198 | ||
|
|
11a5feb49d | ||
|
|
1e7e1f42cc | ||
|
|
ea37126e87 | ||
|
|
670e0f02ec | ||
|
|
b4e7865bb7 | ||
|
|
15b0bf9664 | ||
|
|
8bd07ee649 | ||
|
|
3e1031b0f0 | ||
|
|
9918a6267c | ||
|
|
bea162962e | ||
|
|
a2ce5550fc | ||
|
|
1d91c1bf2c | ||
|
|
9d8d6f03cc | ||
|
|
98f3f15e7e | ||
|
|
6f223d3f66 | ||
|
|
fe1df83a88 | ||
|
|
e7b7cb0253 | ||
|
|
4a3cd7b73c | ||
|
|
f538a9344b | ||
|
|
f2b81af702 | ||
|
|
651bdb6489 | ||
|
|
841e1bf95e | ||
|
|
7e652f3fb7 | ||
|
|
90be2f47a3 | ||
|
|
859a50bd82 | ||
|
|
75b06ac90a | ||
|
|
d2edb92ddf | ||
|
|
0099c2a03a | ||
|
|
d29adafe3c | ||
|
|
59894e68cb | ||
|
|
6af072eb2c | ||
|
|
8cae3f1212 | ||
|
|
9aaddcd9b9 | ||
|
|
196e430ec6 | ||
|
|
9424aa3a3b | ||
|
|
7a57416e4c | ||
|
|
fc53003022 | ||
|
|
47878ac580 | ||
|
|
d83f91f9e8 | ||
|
|
708b6b7f28 | ||
|
|
9d07416641 | ||
|
|
4747eac9bf | ||
|
|
ecf152990f | ||
|
|
d4ed753715 | ||
|
|
ea230615f9 | ||
|
|
8f3cabdaff | ||
|
|
eafe2e96e8 | ||
|
|
c4dc930ca8 | ||
|
|
180de32060 | ||
|
|
68fd5d41a7 | ||
|
|
6263b7e4c6 | ||
|
|
ee190a86a1 | ||
|
|
97b46071e0 | ||
|
|
ed37d75aba | ||
|
|
3496d12111 | ||
|
|
cfb7a589a8 | ||
|
|
5391d3ec32 | ||
|
|
f6e4f13ebd | ||
|
|
55fd2d5fb6 | ||
|
|
5662285a3e | ||
|
|
b5c249995f | ||
|
|
a528436572 |
@@ -18,4 +18,4 @@ jobs:
|
|||||||
apt update
|
apt update
|
||||||
apt install make gcc sdcc xxd python-is-python3 libjson-c-dev -y
|
apt install make gcc sdcc xxd python-is-python3 libjson-c-dev -y
|
||||||
- name: Make project
|
- name: Make project
|
||||||
run: make
|
run: make MACHINE="KP_9000_6XHML_X2"
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
BOOTLOADER_ADDRESS=0x100
|
|
||||||
|
|
||||||
VERSION=0.1.0
|
VERSION=0.1.0
|
||||||
IMAGESIZE = 524288
|
IMAGESIZE = 524288
|
||||||
|
DEFAULT_CONFIG_LOCATION = 454656
|
||||||
CONFIG_LOCATION = 458752
|
CONFIG_LOCATION = 458752
|
||||||
HTML_LOCATION = 262144
|
HTML_LOCATION = 262144
|
||||||
|
|
||||||
@@ -16,14 +15,20 @@ SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS))
|
|||||||
BUILDDIR = output/
|
BUILDDIR = output/
|
||||||
VERSION_HEADER := version.h
|
VERSION_HEADER := version.h
|
||||||
|
|
||||||
|
ifeq ($(MACHINE),)
|
||||||
|
else
|
||||||
|
CC_FLAGS += -DMACHINE_$(MACHINE)
|
||||||
|
endif
|
||||||
|
|
||||||
all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)rtlplayground.bin
|
all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)rtlplayground.bin
|
||||||
|
|
||||||
create_build_dir:
|
create_build_dir:
|
||||||
mkdir -p $(BUILDDIR)
|
mkdir -p $(BUILDDIR)
|
||||||
|
|
||||||
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_leds.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c
|
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_leds.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c \
|
||||||
|
rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c cmd_editor.c rtl837x_bandwidth.c
|
||||||
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
|
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
|
||||||
OBJS += uip/$(BUILDDIR)/timer.rel uip/$(BUILDDIR)/uip-fw.rel uip/$(BUILDDIR)/uip-neighbor.rel uip/$(BUILDDIR)/uip-split.rel uip/$(BUILDDIR)/uip.rel uip/$(BUILDDIR)/uip_arp.rel uip/$(BUILDDIR)/uiplib.rel httpd/$(BUILDDIR)/httpd.rel httpd/$(BUILDDIR)/page_impl.rel
|
OBJS += uip/$(BUILDDIR)/timer.rel uip/$(BUILDDIR)/uip-fw.rel uip/$(BUILDDIR)/uip-split.rel uip/$(BUILDDIR)/uip.rel uip/$(BUILDDIR)/uip_arp.rel uip/$(BUILDDIR)/uiplib.rel httpd/$(BUILDDIR)/httpd.rel httpd/$(BUILDDIR)/page_impl.rel
|
||||||
|
|
||||||
html_data.c html_data.h: html tools
|
html_data.c html_data.h: html tools
|
||||||
tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -d html -p html_data
|
tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -d html -p html_data
|
||||||
@@ -32,6 +37,7 @@ $(VERSION_HEADER):
|
|||||||
@echo "#ifndef VERSION_H" > $(VERSION_HEADER)
|
@echo "#ifndef VERSION_H" > $(VERSION_HEADER)
|
||||||
@echo "#define 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 \"v$(VERSION)-g$(shell git rev-parse --short HEAD)\"" >> $(VERSION_HEADER)
|
||||||
|
@echo "#define BUILD_DATE \"$(shell date +"%Y-%m-%d %H:%M:%S")\"" >> $(VERSION_HEADER)
|
||||||
@echo "#endif" >> $(VERSION_HEADER)
|
@echo "#endif" >> $(VERSION_HEADER)
|
||||||
|
|
||||||
httpd: html_data.h
|
httpd: html_data.h
|
||||||
@@ -58,8 +64,8 @@ $(BUILDDIR)%.rel: $(BUILDDIR)%.asm
|
|||||||
${ASM} ${AFLAGS} -o $@ $<
|
${ASM} ${AFLAGS} -o $@ $<
|
||||||
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
|
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
|
||||||
|
|
||||||
$(BUILDDIR)rtlplayground.ihx: $(BUILDDIR)crtstart.rel $(OBJS) $(BUILDDIR)crc16.rel
|
$(BUILDDIR)rtlplayground.ihx: $(OBJS) $(BUILDDIR)crtstart.rel $(BUILDDIR)crc16.rel
|
||||||
$(CC) $(CC_FLAGS) -Wl-bHOME=${BOOTLOADER_ADDRESS} -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-r -o $@ $^
|
$(CC) $(CC_FLAGS) -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-r -o $@ $^
|
||||||
|
|
||||||
$(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx
|
$(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx
|
||||||
objcopy --input-target=ihex -O binary $< $@
|
objcopy --input-target=ihex -O binary $< $@
|
||||||
@@ -67,6 +73,7 @@ $(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx
|
|||||||
$(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlplayground.img
|
$(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlplayground.img
|
||||||
if [ -e $@ ]; then rm $@; fi
|
if [ -e $@ ]; then rm $@; fi
|
||||||
tools/$(BUILDDIR)imagebuilder -i $^ $@
|
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 $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
|
||||||
tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -d html -p html_data $@
|
tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -d html -p html_data $@
|
||||||
tools/$(BUILDDIR)crc_calculator -u $@
|
tools/$(BUILDDIR)crc_calculator -u $@
|
||||||
|
|||||||
@@ -56,20 +56,12 @@ device simulator is provided, which runs entirely under Linux as a local webserv
|
|||||||
Install the following particular build requisites (Debian 12/13), note that Ubuntu 24.04
|
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:
|
still has an older version of sdcc, but you will need sdcc version 4.5 for the code to compile:
|
||||||
```
|
```
|
||||||
sudo apt install sdcc xxd python-is-python3 libjson-c-dev
|
sudo apt install make gcc sdcc xxd python-is-python3 libjson-c-dev
|
||||||
```
|
```
|
||||||
|
Edit machine.h with an editor like vi or nano. Select the correct machine the firmware should build for.
|
||||||
Now, building the firmware image should work:
|
Now, building the firmware image should work:
|
||||||
```
|
```
|
||||||
$ make
|
make
|
||||||
sdas8051 -plosgff crtstart.asm
|
|
||||||
sdcc -mmcs51 -c rtlplayground.c
|
|
||||||
sdcc -mmcs51 -c rtl837x_flash.c
|
|
||||||
sdcc -mmcs51 -Wl-bHOME=0x100 -o rtlplayground.ihx crtstart.rel rtlplayground.rel rtl837x_flash.rel
|
|
||||||
objcopy --input-target=ihex -O binary rtlplayground.ihx rtlplayground.img
|
|
||||||
if [ -e rtlplayground.bin ]; then rm rtlplayground.bin; fi
|
|
||||||
echo "0000000: 00 40" | xxd -r - rtlplayground.bin
|
|
||||||
cat rtlplayground.img >> rtlplayground.bin
|
|
||||||
```
|
```
|
||||||
Note, that the image generated ends in .bin, not .img, in order to make
|
Note, that the image generated ends in .bin, not .img, in order to make
|
||||||
IMSProg happy.
|
IMSProg happy.
|
||||||
|
|||||||
@@ -0,0 +1,208 @@
|
|||||||
|
#include "cmd_parser.h"
|
||||||
|
#include "machine.h"
|
||||||
|
|
||||||
|
#pragma codeseg BANK2
|
||||||
|
#pragma constseg BANK2
|
||||||
|
|
||||||
|
// Position in the serial buffer
|
||||||
|
__xdata uint8_t l;
|
||||||
|
// Properties of currently edited command line in cmd_buffer[CMD_BUF_SIZE]
|
||||||
|
__xdata uint8_t cursor;
|
||||||
|
__xdata uint8_t cmd_line_len;
|
||||||
|
__xdata uint8_t current_cmdline[CMD_BUF_SIZE];
|
||||||
|
__xdata uint16_t history_editptr;
|
||||||
|
|
||||||
|
|
||||||
|
extern __xdata uint8_t cmd_history[CMD_HISTORY_SIZE];
|
||||||
|
extern __xdata uint16_t cmd_history_ptr;
|
||||||
|
|
||||||
|
void cmd_editor_init(void) __banked
|
||||||
|
{
|
||||||
|
l = sbuf_ptr; // We have printed out entered characters until l
|
||||||
|
cursor = 0;
|
||||||
|
cmd_line_len = 0;
|
||||||
|
cmd_available = 0;
|
||||||
|
history_editptr = 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allows editing the current command line held in cmd_buffer[CMD_BUF_SIZE] by
|
||||||
|
* identifying new characters typed or up to 4-byte escape sequences in the
|
||||||
|
* serial buffer ring sbuf[SBUF_SIZE].
|
||||||
|
* Upon detecting new characters or escape sequences, the cmd_buffer and the
|
||||||
|
* representation of the command line in the terminal are updated.
|
||||||
|
* To debug, the easist is to interpose a tty-interceptor between the physical
|
||||||
|
* serial device and a logical one created by interceptty:
|
||||||
|
* sudo interceptty -s 'ispeed 115200 ospeed 115200' /dev/ttyUSB0 /dev/tmpS
|
||||||
|
* picocom -b 115200 /dev/tmpS
|
||||||
|
*/
|
||||||
|
void cmd_edit(void) __banked
|
||||||
|
{
|
||||||
|
while (l != sbuf_ptr) {
|
||||||
|
if (sbuf[l] >= ' ' && sbuf[l] < 127) { // A printable character, copy to command line
|
||||||
|
if (cmd_line_len >= CMD_BUF_SIZE)
|
||||||
|
continue;
|
||||||
|
write_char(sbuf[l]);
|
||||||
|
// Shift buffer to right
|
||||||
|
for (uint8_t i = cmd_line_len; i > cursor; i--)
|
||||||
|
cmd_buffer[i] = cmd_buffer[i-1];
|
||||||
|
// Insert char in comand buffer
|
||||||
|
cmd_buffer[cursor++] = sbuf[l];
|
||||||
|
cmd_line_len++;
|
||||||
|
// Print rest of line
|
||||||
|
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
||||||
|
write_char(cmd_buffer[i]);
|
||||||
|
// Move backwards
|
||||||
|
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
||||||
|
write_char('\010'); // BS works like cursor-left
|
||||||
|
} else if (sbuf[l] == '\033') { // ESC-Sequence
|
||||||
|
// Wait until we have at least 3 characters including the ESC character in the serial buffer
|
||||||
|
if (((sbuf_ptr + SBUF_SIZE - l) & SBUF_MASK) < 3)
|
||||||
|
continue;
|
||||||
|
if (((sbuf_ptr > l ? sbuf_ptr - l : SBUF_SIZE + sbuf_ptr - l) >= 4)
|
||||||
|
&& sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == '3' && sbuf[(l + 3) & SBUF_MASK] == '~') { // DEL
|
||||||
|
if (cursor < cmd_line_len) {
|
||||||
|
write_char('\033'); write_char('['); write_char('1'); write_char('P'); // Delete to end of line
|
||||||
|
cmd_line_len--;
|
||||||
|
for (uint8_t i = cursor; i < cmd_line_len; i++) {
|
||||||
|
cmd_buffer[i] = cmd_buffer[i+1];
|
||||||
|
write_char(cmd_buffer[i]);
|
||||||
|
}
|
||||||
|
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
||||||
|
write_char('\010');
|
||||||
|
}
|
||||||
|
l += 4;
|
||||||
|
l &= SBUF_MASK;
|
||||||
|
continue;
|
||||||
|
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'D') { // <CURSOR-LEFT>
|
||||||
|
if (cursor) {
|
||||||
|
write_char('\010'); // BS works like cursor-left
|
||||||
|
cursor--;
|
||||||
|
}
|
||||||
|
l += 3;
|
||||||
|
l &= SBUF_MASK;
|
||||||
|
continue;
|
||||||
|
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'C') { // <CURSOR-RIGHT>
|
||||||
|
if (cursor < cmd_line_len) {
|
||||||
|
write_char('\033'); write_char('['); write_char('C');
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
l += 3;
|
||||||
|
l &= SBUF_MASK;
|
||||||
|
continue;
|
||||||
|
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'A') { // <CURSOR-UP>
|
||||||
|
for (uint8_t i = 0; i < cmd_line_len; i++)
|
||||||
|
current_cmdline[i] = cmd_buffer[i];
|
||||||
|
current_cmdline[cmd_line_len] = 0;
|
||||||
|
__xdata uint16_t p;
|
||||||
|
if (history_editptr == 0xffff)
|
||||||
|
p = (cmd_history_ptr - 2) & CMD_HISTORY_MASK;
|
||||||
|
else
|
||||||
|
p = history_editptr;
|
||||||
|
// Move cursor to beginning of line
|
||||||
|
write_char('\033'); write_char('['); itoa(cursor + 2); write_char('D');
|
||||||
|
cursor = 0;
|
||||||
|
while (cmd_history[p] && cmd_history[p] != '\n') {
|
||||||
|
cursor++;
|
||||||
|
p--;
|
||||||
|
p &= CMD_HISTORY_MASK;
|
||||||
|
}
|
||||||
|
history_editptr = (p - 1) & CMD_HISTORY_MASK;
|
||||||
|
p = (p + 1) & CMD_HISTORY_MASK;
|
||||||
|
if (cursor) {
|
||||||
|
print_string("\033[2K> "); // Clear entire line: ^[[2K and print new prompt
|
||||||
|
for (uint8_t i = 0; i < cursor; i++) {
|
||||||
|
cmd_buffer[i] = cmd_history[p];
|
||||||
|
write_char(cmd_buffer[i]);
|
||||||
|
p = (p+1) & CMD_HISTORY_MASK;
|
||||||
|
}
|
||||||
|
cmd_line_len = cursor;
|
||||||
|
} else {
|
||||||
|
print_string("\033[2C"); // Move 2 right to start of editing space
|
||||||
|
}
|
||||||
|
l += 3;
|
||||||
|
l &= SBUF_MASK;
|
||||||
|
continue;
|
||||||
|
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'B') { // <CURSOR-DOWN>
|
||||||
|
if (history_editptr != 0xffff) {
|
||||||
|
__xdata uint16_t p = (history_editptr + 2) & CMD_HISTORY_MASK;
|
||||||
|
// Move cursor to beginning of line
|
||||||
|
write_char('\033'); write_char('['); itoa(cursor + 2); write_char('D');
|
||||||
|
print_string("\033[2K> "); // Clear entire line: ^[[2K and print new prompt
|
||||||
|
uint8_t i = 0;
|
||||||
|
while (cmd_history[p] && cmd_history[p] != '\n') {
|
||||||
|
p = (p + 1) & CMD_HISTORY_MASK;
|
||||||
|
}
|
||||||
|
p = (p + 1) & CMD_HISTORY_MASK;
|
||||||
|
while (cmd_history[p] && cmd_history[p] != '\n') {
|
||||||
|
cmd_buffer[i] = cmd_history[p];
|
||||||
|
write_char(cmd_buffer[i++]);
|
||||||
|
p = (p + 1) & CMD_HISTORY_MASK;
|
||||||
|
}
|
||||||
|
history_editptr = (p - 1) & CMD_HISTORY_MASK;
|
||||||
|
if (!i) {
|
||||||
|
if (current_cmdline[i]) {
|
||||||
|
while (current_cmdline[i]) {
|
||||||
|
cmd_buffer[i] = current_cmdline[i];
|
||||||
|
write_char(cmd_buffer[i++]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
write_char('\033'); write_char('['); write_char('C');
|
||||||
|
}
|
||||||
|
history_editptr = 0xffff;
|
||||||
|
// Move cursor right
|
||||||
|
}
|
||||||
|
cmd_line_len = i;
|
||||||
|
cursor = 0;
|
||||||
|
// Move cursor again to beginning of line
|
||||||
|
write_char('\033'); write_char('['); itoa(i); write_char('D');
|
||||||
|
} else {
|
||||||
|
// If we are at the last entry of the history, just move the cursor to the end of the line
|
||||||
|
if (cursor < cmd_line_len) {
|
||||||
|
write_char('\033'); write_char('['); itoa(cmd_line_len - cursor); write_char('C');
|
||||||
|
}
|
||||||
|
cursor = cmd_line_len;
|
||||||
|
}
|
||||||
|
l += 3;
|
||||||
|
l &= SBUF_MASK;
|
||||||
|
continue;
|
||||||
|
} else { // An unknown or not yet complete Escape sequence: wait
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (sbuf[l] == 127) { // Backspace
|
||||||
|
if (cursor > 0) {
|
||||||
|
write_char('\010');
|
||||||
|
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
||||||
|
write_char(cmd_buffer[i]);
|
||||||
|
write_char(' '); // Overwrite end of line
|
||||||
|
// Move backwards n steps:
|
||||||
|
for (uint8_t i = cursor; i <= cmd_line_len; i++)
|
||||||
|
write_char('\010');
|
||||||
|
cursor--;
|
||||||
|
for (uint8_t i = cursor; i <= cmd_line_len; i++)
|
||||||
|
cmd_buffer[i] = cmd_buffer[i+1];
|
||||||
|
cmd_line_len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the command buffer is currently in use, we cannot copy to it
|
||||||
|
if (cmd_available)
|
||||||
|
break;
|
||||||
|
// Check whether return was pressed:
|
||||||
|
if (sbuf[l] == '\n' || sbuf[l] == '\r') {
|
||||||
|
write_char('\n');
|
||||||
|
cmd_buffer[cmd_line_len] = '\0';
|
||||||
|
// write_char('>'); print_string_x(cmd_buffer); write_char('<');
|
||||||
|
// If there is a command we print the prompt after execution
|
||||||
|
// otherwise immediately because there is nothing to execute
|
||||||
|
if (cmd_line_len)
|
||||||
|
cmd_available = 1;
|
||||||
|
else
|
||||||
|
print_string("\n> ");
|
||||||
|
cursor = 0;
|
||||||
|
cmd_line_len = 0;
|
||||||
|
history_editptr = 0xffff;
|
||||||
|
}
|
||||||
|
l++;
|
||||||
|
l &= SBUF_MASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _CMD_EDITOR_H_
|
||||||
|
#define _CMD_EDITOR_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void cmd_editor_init(void) __banked;
|
||||||
|
void cmd_edit(void) __banked;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "rtl837x_sfr.h"
|
#include "rtl837x_sfr.h"
|
||||||
#include "rtl837x_stp.h"
|
#include "rtl837x_stp.h"
|
||||||
#include "rtl837x_igmp.h"
|
#include "rtl837x_igmp.h"
|
||||||
|
#include "rtl837x_bandwidth.h"
|
||||||
#include "dhcp.h"
|
#include "dhcp.h"
|
||||||
#include "uip/uip.h"
|
#include "uip/uip.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
@@ -33,7 +34,7 @@ extern volatile __xdata uint8_t sfr_data[4];
|
|||||||
extern __code uint8_t * __code greeting;
|
extern __code uint8_t * __code greeting;
|
||||||
extern __code uint8_t * __code hex;
|
extern __code uint8_t * __code hex;
|
||||||
|
|
||||||
extern __xdata uint8_t flash_buf[512];
|
extern __xdata uint8_t flash_buf[FLASH_BUF_SIZE];
|
||||||
extern __xdata struct flash_region_t flash_region;
|
extern __xdata struct flash_region_t flash_region;
|
||||||
|
|
||||||
extern __xdata char passwd[21];
|
extern __xdata char passwd[21];
|
||||||
@@ -43,6 +44,7 @@ extern __xdata struct dhcp_state dhcp_state;
|
|||||||
__xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
|
__xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
|
||||||
__xdata uint16_t vlan_ptr;
|
__xdata uint16_t vlan_ptr;
|
||||||
extern __xdata uint16_t management_vlan;
|
extern __xdata uint16_t management_vlan;
|
||||||
|
extern __xdata uint16_t dhcpd_vlan;
|
||||||
__xdata uint8_t gpio_last_value[8] = { 0 };
|
__xdata uint8_t gpio_last_value[8] = { 0 };
|
||||||
|
|
||||||
// Temporatly for str to hex convertion value.
|
// Temporatly for str to hex convertion value.
|
||||||
@@ -51,17 +53,16 @@ __xdata uint8_t hexvalue[4] = { 0 };
|
|||||||
|
|
||||||
|
|
||||||
// Buffer for writing to flash 0x1fd000, copy to 0x1fe000
|
// Buffer for writing to flash 0x1fd000, copy to 0x1fe000
|
||||||
__xdata uint8_t cmd_buffer[SBUF_SIZE];
|
__xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
|
||||||
__xdata uint8_t cmd_available;
|
__xdata uint8_t cmd_available;
|
||||||
|
|
||||||
__xdata uint8_t l;
|
|
||||||
__xdata uint8_t line_ptr;
|
__xdata uint8_t line_ptr;
|
||||||
__xdata char is_white;
|
__xdata char is_white;
|
||||||
__xdata char save_cmd;
|
__xdata char save_cmd;
|
||||||
|
|
||||||
__xdata uint8_t ip[4];
|
__xdata uint8_t ip[4];
|
||||||
|
|
||||||
#define N_WORDS SBUF_SIZE
|
#define N_WORDS CMD_BUF_SIZE
|
||||||
__xdata signed char cmd_words_b[N_WORDS];
|
__xdata signed char cmd_words_b[N_WORDS];
|
||||||
|
|
||||||
__xdata uint8_t cmd_history[CMD_HISTORY_SIZE];
|
__xdata uint8_t cmd_history[CMD_HISTORY_SIZE];
|
||||||
@@ -93,7 +94,7 @@ uint8_t cmd_compare(uint8_t start, uint8_t * __code cmd)
|
|||||||
signed char j = 0;
|
signed char j = 0;
|
||||||
|
|
||||||
for (i = cmd_words_b[start]; i != cmd_words_b[start + 1] && cmd_buffer[i] != ' '; i++) {
|
for (i = cmd_words_b[start]; i != cmd_words_b[start + 1] && cmd_buffer[i] != ' '; i++) {
|
||||||
i &= SBUF_SIZE - 1;
|
i &= CMD_BUF_SIZE - 1;
|
||||||
// print_byte(i); write_char(':'); print_byte(j); write_char('#'); print_string("\n");
|
// print_byte(i); write_char(':'); print_byte(j); write_char('#'); print_string("\n");
|
||||||
// write_char('>'); write_char(cmd[j]); write_char('-'); write_char(cmd_buffer[i]); print_string("\n");
|
// write_char('>'); write_char(cmd[j]); write_char('-'); write_char(cmd_buffer[i]); print_string("\n");
|
||||||
if (!cmd[j] && !isletter(cmd_buffer[i]))
|
if (!cmd[j] && !isletter(cmd_buffer[i]))
|
||||||
@@ -150,6 +151,14 @@ uint8_t atoi_hex(uint8_t idx)
|
|||||||
h_idx++;
|
h_idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (h_idx & 1) {
|
||||||
|
hexvalue[h_idx >> 1] <<= 4;
|
||||||
|
hexvalue[3] = hexvalue[3] >> 4 | (hexvalue[2] << 4);
|
||||||
|
hexvalue[2] = hexvalue[2] >> 4 | (hexvalue[1] << 4);
|
||||||
|
hexvalue[1] = hexvalue[1] >> 4 | (hexvalue[0] << 4);
|
||||||
|
hexvalue[0] >>= 4;
|
||||||
|
}
|
||||||
|
|
||||||
return ((h_idx + 1) >> 1);
|
return ((h_idx + 1) >> 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,17 +291,17 @@ void parse_lag_hash(void)
|
|||||||
|
|
||||||
void parse_vlan(void)
|
void parse_vlan(void)
|
||||||
{
|
{
|
||||||
__xdata uint16_t vlan;
|
vlan_settings.vlan = 0;
|
||||||
__xdata uint16_t members = 0;
|
vlan_settings.members = 0;
|
||||||
__xdata uint16_t tagged = 0;
|
vlan_settings.tagged = 0;
|
||||||
if (!atoi_short(&vlan, cmd_words_b[1])) {
|
if (!atoi_short(&vlan_settings.vlan, cmd_words_b[1])) {
|
||||||
if (cmd_words_b[2] > 0 && cmd_buffer[cmd_words_b[2]] == 'd' && cmd_words_b[3] < 0) {
|
if (cmd_words_b[2] > 0 && cmd_buffer[cmd_words_b[2]] == 'd' && cmd_words_b[3] < 0) {
|
||||||
vlan_delete(vlan);
|
vlan_delete(vlan_settings.vlan);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cmd_words_b[2] > 0 && cmd_compare(2, "mgmt")) {
|
if (cmd_words_b[2] > 0 && cmd_compare(2, "mgmt")) {
|
||||||
management_vlan = vlan;
|
management_vlan = vlan_settings.vlan;
|
||||||
if (!vlan)
|
if (!vlan_settings.vlan)
|
||||||
print_string("Management VLAN disabled\n");
|
print_string("Management VLAN disabled\n");
|
||||||
else
|
else
|
||||||
print_string("Management VLAN set to "); print_short(management_vlan); write_char('\n');
|
print_string("Management VLAN set to "); print_short(management_vlan); write_char('\n');
|
||||||
@@ -301,9 +310,9 @@ void parse_vlan(void)
|
|||||||
uint8_t w = 2;
|
uint8_t w = 2;
|
||||||
if (cmd_words_b[w] > 0 && isletter(cmd_buffer[cmd_words_b[w]])) {
|
if (cmd_words_b[w] > 0 && isletter(cmd_buffer[cmd_words_b[w]])) {
|
||||||
register uint8_t i = 0;
|
register uint8_t i = 0;
|
||||||
vlan_names[vlan_ptr++] = hex[(vlan >> 8) & 0xf];
|
vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 8) & 0xf];
|
||||||
vlan_names[vlan_ptr++] = hex[(vlan >> 4) & 0xf] ;
|
vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 4) & 0xf] ;
|
||||||
vlan_names[vlan_ptr++] = hex[vlan & 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] != ' ') {
|
||||||
write_char(cmd_buffer[cmd_words_b[w] + i]);
|
write_char(cmd_buffer[cmd_words_b[w] + i]);
|
||||||
vlan_names[vlan_ptr++] = cmd_buffer[cmd_words_b[w] + i++];
|
vlan_names[vlan_ptr++] = cmd_buffer[cmd_words_b[w] + i++];
|
||||||
@@ -313,25 +322,25 @@ void parse_vlan(void)
|
|||||||
print_string("<\n");
|
print_string("<\n");
|
||||||
}
|
}
|
||||||
while (cmd_words_b[w] > 0) {
|
while (cmd_words_b[w] > 0) {
|
||||||
uint8_t port;
|
__xdata uint8_t port;
|
||||||
if (isnumber(cmd_buffer[cmd_words_b[w]])) {
|
if (isnumber(cmd_buffer[cmd_words_b[w]])) {
|
||||||
port = cmd_buffer[cmd_words_b[w]] - '1';
|
port = cmd_buffer[cmd_words_b[w]] - '1';
|
||||||
if (isnumber(cmd_buffer[cmd_words_b[w] + 1])) {
|
if (isnumber(cmd_buffer[cmd_words_b[w] + 1])) {
|
||||||
port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1';
|
port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1';
|
||||||
if (cmd_buffer[cmd_words_b[w] + 2] == 't')
|
if (cmd_buffer[cmd_words_b[w] + 2] == 't')
|
||||||
tagged |= ((uint16_t)1) << port;
|
vlan_settings.tagged |= ((uint16_t)1) << port;
|
||||||
} else {
|
} else {
|
||||||
port = machine.phys_to_log_port[port];
|
port = machine.phys_to_log_port[port];
|
||||||
if (cmd_buffer[cmd_words_b[w] + 1] == 't')
|
if (cmd_buffer[cmd_words_b[w] + 1] == 't')
|
||||||
tagged |= ((uint16_t)1) << port;
|
vlan_settings.tagged |= ((uint16_t)1) << port;
|
||||||
}
|
}
|
||||||
if (port > machine.max_port)
|
if (port > machine.max_port)
|
||||||
goto err;
|
goto err;
|
||||||
members |= ((uint16_t)1) << port;
|
vlan_settings.members |= ((uint16_t)1) << port;
|
||||||
}
|
}
|
||||||
w++;
|
w++;
|
||||||
}
|
}
|
||||||
vlan_create(vlan, members, tagged);
|
vlan_create();
|
||||||
}
|
}
|
||||||
if (cmd_words_b[2] > 0 && isletter(cmd_buffer[cmd_words_b[2]])) {
|
if (cmd_words_b[2] > 0 && isletter(cmd_buffer[cmd_words_b[2]])) {
|
||||||
print_string("vlan_ptr "); print_short(vlan_ptr); write_char(':');
|
print_string("vlan_ptr "); print_short(vlan_ptr); write_char(':');
|
||||||
@@ -422,10 +431,10 @@ void parse_mirror(void)
|
|||||||
void parse_port(void)
|
void parse_port(void)
|
||||||
{
|
{
|
||||||
print_string("\nPORT ");
|
print_string("\nPORT ");
|
||||||
uint8_t p = cmd_buffer[cmd_words_b[1]] - '1';
|
phy_settings.port = cmd_buffer[cmd_words_b[1]] - '1';
|
||||||
p = machine.phys_to_log_port[p];
|
phy_settings.port = machine.phys_to_log_port[phy_settings.port];
|
||||||
print_byte(p);
|
print_byte(phy_settings.port);
|
||||||
if (machine.is_sfp[p]) {
|
if (machine.is_sfp[phy_settings.port]) {
|
||||||
print_string(" is SFP no PHY information available.\n");
|
print_string(" is SFP no PHY information available.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -433,46 +442,53 @@ void parse_port(void)
|
|||||||
print_string("\nport <port> [show|on|off|10m|100m|1g|2g5] [half|full]");
|
print_string("\nport <port> [show|on|off|10m|100m|1g|2g5] [half|full]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
phy_settings.duplex = PHY_DUPLEX_BOTH;
|
||||||
if (cmd_compare(2, "10m")) {
|
if (cmd_compare(2, "10m")) {
|
||||||
print_string(" 10M\n");
|
print_string(" 10M\n");
|
||||||
|
phy_settings.speed = PHY_SPEED_10M;
|
||||||
if (cmd_words_b[3] > 0 && cmd_compare(3, "half"))
|
if (cmd_words_b[3] > 0 && cmd_compare(3, "half"))
|
||||||
phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_HALF);
|
phy_settings.duplex = PHY_DUPLEX_HALF;
|
||||||
else if (cmd_words_b[3] > 0 && cmd_compare(3, "full"))
|
else if (cmd_words_b[3] > 0 && cmd_compare(3, "full"))
|
||||||
phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_FULL);
|
phy_settings.duplex = PHY_DUPLEX_FULL;
|
||||||
else
|
phy_set_speed();
|
||||||
phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_BOTH);
|
|
||||||
} else if (cmd_compare(2, "100m")) {
|
} else if (cmd_compare(2, "100m")) {
|
||||||
print_string(" 100M\n");
|
print_string(" 100M\n");
|
||||||
|
phy_settings.speed = PHY_SPEED_100M;
|
||||||
if (cmd_words_b[3] > 0 && cmd_compare(3, "half"))
|
if (cmd_words_b[3] > 0 && cmd_compare(3, "half"))
|
||||||
phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_HALF);
|
phy_settings.duplex = PHY_DUPLEX_HALF;
|
||||||
else if (cmd_words_b[3] > 0 && cmd_compare(3, "full"))
|
else if (cmd_words_b[3] > 0 && cmd_compare(3, "full"))
|
||||||
phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_FULL);
|
phy_settings.duplex = PHY_DUPLEX_FULL;
|
||||||
else
|
phy_set_speed();
|
||||||
phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_BOTH);
|
|
||||||
} else if (cmd_compare(2, "2g5")) {
|
} else if (cmd_compare(2, "2g5")) {
|
||||||
print_string(" 2.5G\n");
|
print_string(" 2.5G\n");
|
||||||
phy_set_speed(p, PHY_SPEED_2G5, PHY_DUPLEX_BOTH);
|
phy_settings.speed = PHY_SPEED_2G5;
|
||||||
|
phy_set_speed();
|
||||||
} else if (cmd_compare(2, "1g")) {
|
} else if (cmd_compare(2, "1g")) {
|
||||||
print_string(" 1G\n");
|
print_string(" 1G\n");
|
||||||
phy_set_speed(p, PHY_SPEED_1G, PHY_DUPLEX_BOTH);
|
phy_settings.speed = PHY_SPEED_1G;
|
||||||
|
phy_set_speed();
|
||||||
} else if (cmd_compare(2, "auto")) {
|
} else if (cmd_compare(2, "auto")) {
|
||||||
print_string(" AUTO\n");
|
print_string(" AUTO\n");
|
||||||
phy_set_speed(p, PHY_SPEED_AUTO, PHY_DUPLEX_BOTH);
|
phy_settings.speed = PHY_SPEED_AUTO;
|
||||||
|
phy_set_speed();
|
||||||
} else if (cmd_compare(2, "off")) {
|
} else if (cmd_compare(2, "off")) {
|
||||||
print_string(" OFF\n");
|
print_string(" OFF\n");
|
||||||
phy_set_speed(p, PHY_OFF, PHY_DUPLEX_BOTH);
|
phy_settings.speed = PHY_OFF;
|
||||||
|
phy_set_speed();
|
||||||
} else if (cmd_compare(2, "on")) {
|
} else if (cmd_compare(2, "on")) {
|
||||||
print_string(" ON\n");
|
print_string(" ON\n");
|
||||||
phy_set_speed(p, PHY_SPEED_AUTO, PHY_DUPLEX_BOTH);
|
phy_settings.speed = PHY_SPEED_AUTO;
|
||||||
|
phy_set_speed();
|
||||||
} else if (cmd_compare(2, "duplex")) {
|
} else if (cmd_compare(2, "duplex")) {
|
||||||
print_string(" DUPLEX\n");
|
print_string(" DUPLEX\n");
|
||||||
if (cmd_words_b[3] > 0 && cmd_compare(3, "full"))
|
if (cmd_words_b[3] > 0 && cmd_compare(3, "full"))
|
||||||
phy_set_duplex(p, PHY_DUPLEX_FULL);
|
phy_settings.speed = PHY_DUPLEX_FULL;
|
||||||
else
|
else
|
||||||
phy_set_duplex(p, PHY_DUPLEX_HALF);
|
phy_settings.speed = PHY_DUPLEX_HALF;
|
||||||
|
phy_set_duplex();
|
||||||
}
|
}
|
||||||
if (cmd_words_b[2] > 0 && cmd_compare(2, "show")) {
|
if (cmd_words_b[2] > 0 && cmd_compare(2, "show")) {
|
||||||
phy_show(p);
|
phy_show(phy_settings.port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,6 +649,137 @@ void parse_passwd(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void parse_eee(void)
|
||||||
|
{
|
||||||
|
__xdata int8_t port = -1;
|
||||||
|
__xdata uint8_t speed = EEE_2G5;
|
||||||
|
__xdata uint8_t speed_word = 0;
|
||||||
|
// Check if word 2 is a speed (contains 'g' or 'm') or a port number
|
||||||
|
if (cmd_words_b[3] > 0) {
|
||||||
|
uint8_t idx = cmd_words_b[2];
|
||||||
|
// Skip digits to check if there's a letter after
|
||||||
|
while (isnumber(cmd_buffer[idx]))
|
||||||
|
idx++;
|
||||||
|
if (cmd_buffer[idx] == 'g' || cmd_buffer[idx] == 'm') {
|
||||||
|
// Word 2 is a speed (e.g., "2g5", "100m", "1g")
|
||||||
|
speed_word = 2;
|
||||||
|
} else if (cmd_buffer[idx] == ' ' || cmd_buffer[idx] == '\0') {
|
||||||
|
// Word 2 is a port number
|
||||||
|
port = cmd_buffer[cmd_words_b[2]] - '1';
|
||||||
|
port = machine.phys_to_log_port[port];
|
||||||
|
// Check if word 3 is a speed
|
||||||
|
if (cmd_words_b[4] > 0)
|
||||||
|
speed_word = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Parse speed if found
|
||||||
|
if (speed_word > 0) {
|
||||||
|
if (cmd_compare(speed_word, "100m"))
|
||||||
|
speed = EEE_100;
|
||||||
|
else if (cmd_compare(speed_word, "1g"))
|
||||||
|
speed = EEE_1000;
|
||||||
|
else if (cmd_compare(speed_word, "2g5"))
|
||||||
|
speed = EEE_2G5;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print_string("Speed word invalid, use: [100m|1g|2g5]\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
|
||||||
|
if (port >= 0)
|
||||||
|
port_eee_enable(port, speed);
|
||||||
|
else
|
||||||
|
port_eee_enable_all(speed);
|
||||||
|
} else if (cmd_words_b[1] > 0 && cmd_compare(1, "off")) {
|
||||||
|
if (port >= 0)
|
||||||
|
port_eee_disable(port);
|
||||||
|
else
|
||||||
|
port_eee_disable_all();
|
||||||
|
} else if (cmd_words_b[1] > 0 && cmd_compare(1, "status")) {
|
||||||
|
if (port >= 0)
|
||||||
|
port_eee_status(port);
|
||||||
|
else
|
||||||
|
port_eee_status_all();
|
||||||
|
} else {
|
||||||
|
print_string("eee [on|off|status] [port] [100m|1g|2g5]\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void parse_bw(void)
|
||||||
|
{
|
||||||
|
__xdata uint8_t port;
|
||||||
|
__xdata uint32_t bw = 0;
|
||||||
|
|
||||||
|
if (cmd_words_b[3] < 0) // Check for at least 2 arguments
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
port = cmd_buffer[cmd_words_b[2]] - '1';
|
||||||
|
if (port > 9)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
port = machine.phys_to_log_port[port];
|
||||||
|
|
||||||
|
if (cmd_compare(1, "status")) {
|
||||||
|
bandwidth_status(port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd_words_b[4] < 0) // Check for at least 3 arguments
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (cmd_compare(3, "drop")) {
|
||||||
|
if (cmd_compare(1, "in")) {
|
||||||
|
bandwidth_ingress_drop(port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd_compare(3, "fc")) {
|
||||||
|
if (cmd_compare(1, "in")) {
|
||||||
|
bandwidth_ingress_fc(port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd_compare(3, "off")) {
|
||||||
|
if (cmd_compare(1, "in")) {
|
||||||
|
bandwidth_ingress_disable(port);
|
||||||
|
return;
|
||||||
|
} else if (cmd_compare(1, "out")) {
|
||||||
|
bandwidth_egress_disable(port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t hex_size = atoi_hex(cmd_words_b[3]);
|
||||||
|
if (hex_size == 0 || hex_size > 4) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
uint8_t i = 0;
|
||||||
|
while (hex_size) {
|
||||||
|
hex_size--;
|
||||||
|
*(((uint8_t *) &bw) + hex_size) = hexvalue[i++];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd_compare(1, "in")) {
|
||||||
|
bandwidth_ingress_set(port, bw);
|
||||||
|
} else if (cmd_compare(1, "out")) {
|
||||||
|
bandwidth_egress_set(port, bw);
|
||||||
|
} else {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
err:
|
||||||
|
print_string("usage: bw [in|out|status] <port> [<hexvalue>|off|drop|fc]\n");
|
||||||
|
}
|
||||||
|
|
||||||
// Parse command into words
|
// Parse command into words
|
||||||
uint8_t cmd_tokenize(void) __banked
|
uint8_t cmd_tokenize(void) __banked
|
||||||
{
|
{
|
||||||
@@ -645,7 +792,7 @@ uint8_t cmd_tokenize(void) __banked
|
|||||||
is_white = 1;
|
is_white = 1;
|
||||||
uint8_t word = 0;
|
uint8_t word = 0;
|
||||||
cmd_words_b[0] = -1;
|
cmd_words_b[0] = -1;
|
||||||
while (cmd_buffer[line_ptr] && line_ptr < SBUF_SIZE - 1) {
|
while (cmd_buffer[line_ptr] && line_ptr < CMD_BUF_SIZE - 1) {
|
||||||
if (is_white && cmd_buffer[line_ptr] != ' ') {
|
if (is_white && cmd_buffer[line_ptr] != ' ') {
|
||||||
is_white = 0;
|
is_white = 0;
|
||||||
cmd_words_b[word++] = line_ptr;
|
cmd_words_b[word++] = line_ptr;
|
||||||
@@ -658,7 +805,7 @@ uint8_t cmd_tokenize(void) __banked
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (line_ptr == SBUF_SIZE - 1)
|
if (line_ptr == CMD_BUF_SIZE - 1)
|
||||||
return 1;
|
return 1;
|
||||||
cmd_words_b[word++] = line_ptr;
|
cmd_words_b[word++] = line_ptr;
|
||||||
cmd_words_b[word++] = -1;
|
cmd_words_b[word++] = -1;
|
||||||
@@ -695,9 +842,8 @@ void print_gpio_status(void) {
|
|||||||
|
|
||||||
// Show software version
|
// Show software version
|
||||||
void print_sw_version(void) __banked {
|
void print_sw_version(void) __banked {
|
||||||
print_string("Software version: ");
|
print_string("Software version: " VERSION_SW);
|
||||||
print_string(VERSION_SW);
|
print_string("\nBuild date: " BUILD_DATE);
|
||||||
print_string("\nBuild: " __DATE__ " " __TIME__);
|
|
||||||
print_string("\nHardware: ");
|
print_string("\nHardware: ");
|
||||||
print_string(machine.machine_name);
|
print_string(machine.machine_name);
|
||||||
write_char('\n');
|
write_char('\n');
|
||||||
@@ -740,47 +886,27 @@ void cmd_parser(void) __banked
|
|||||||
}
|
}
|
||||||
} else if (cmd_compare(0, "stat")) {
|
} else if (cmd_compare(0, "stat")) {
|
||||||
port_stats_print();
|
port_stats_print();
|
||||||
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') {
|
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 's') {
|
||||||
print_string("\nPRINT SECURITY REGISTERS\n");
|
print_string("\nSECURITY REGISTERS\n");
|
||||||
// The following will only show something else than 0xff if it was programmed for a managed switch
|
// The following will only show something else than 0xff if it was programmed for a managed switch
|
||||||
|
print_string("Region 1: ");
|
||||||
flash_region.addr = 0x0001000;
|
flash_region.addr = 0x0001000;
|
||||||
flash_region.len = 40;
|
flash_region.len = 40;
|
||||||
flash_read_security();
|
flash_read_security();
|
||||||
|
print_string("\nRegion 2: ");
|
||||||
flash_region.addr = 0x0002000;
|
flash_region.addr = 0x0002000;
|
||||||
flash_region.len = 40;
|
flash_region.len = 40;
|
||||||
flash_read_security();
|
flash_read_security();
|
||||||
|
print_string("\nRegion 3: ");
|
||||||
flash_region.addr = 0x0003000;
|
flash_region.addr = 0x0003000;
|
||||||
flash_region.len = 40;
|
flash_region.len = 40;
|
||||||
flash_read_security();
|
flash_read_security();
|
||||||
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'd') {
|
|
||||||
print_string("\nDUMPING FLASH\n");
|
|
||||||
flash_region.addr = 0;
|
|
||||||
flash_region.len = 255;
|
|
||||||
flash_dump(255);
|
|
||||||
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') {
|
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') {
|
||||||
print_string("\nJEDEC ID\n");
|
print_string("\nJEDEC ID\n");
|
||||||
flash_read_jedecid();
|
flash_read_jedecid();
|
||||||
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'u') {
|
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'u') {
|
||||||
print_string("\nUNIQUE ID\n");
|
print_string("\nUNIQUE ID (note: only 4 bytes are likely correct here!)\n");
|
||||||
flash_read_uid();
|
flash_read_uid();
|
||||||
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 's') {
|
|
||||||
print_string("\nFLASH FAST MODE\n"); // Switch to flash 62.5 MHz mode
|
|
||||||
flash_init(1);
|
|
||||||
print_string("\nNow dumping flash\n");
|
|
||||||
flash_region.addr = 0;
|
|
||||||
flash_region.len = 255;
|
|
||||||
flash_dump(255);
|
|
||||||
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'e') {
|
|
||||||
print_string("\nFLASH erase\n");
|
|
||||||
flash_region.addr = 0x20000;
|
|
||||||
flash_sector_erase();
|
|
||||||
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'w') {
|
|
||||||
print_string("\nFLASH write\n");
|
|
||||||
for (uint8_t i = 0; i < 20; i++)
|
|
||||||
flash_buf[i] = greeting[i];
|
|
||||||
flash_region.addr = 0x200000;
|
|
||||||
flash_region.len = 20;
|
|
||||||
flash_write_bytes(flash_buf);
|
|
||||||
} else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) {
|
} else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) {
|
||||||
parse_port();
|
parse_port();
|
||||||
} else if (cmd_compare(0, "mtu") && cmd_words_b[1] > 0) {
|
} else if (cmd_compare(0, "mtu") && cmd_words_b[1] > 0) {
|
||||||
@@ -867,6 +993,24 @@ void cmd_parser(void) __banked
|
|||||||
stp_off();
|
stp_off();
|
||||||
stpEnabled = 0;
|
stpEnabled = 0;
|
||||||
}
|
}
|
||||||
|
} else if (cmd_compare(0, "dhcp")) {
|
||||||
|
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
|
||||||
|
dhcp_start();
|
||||||
|
} else {
|
||||||
|
print_string("DHCP disabled\n");
|
||||||
|
dhcp_stop();
|
||||||
|
}
|
||||||
|
} else if (cmd_compare(0, "dhcpd")) {
|
||||||
|
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
|
||||||
|
if (cmd_words_b[2] > 0)
|
||||||
|
atoi_short(&dhcpd_vlan, cmd_words_b[2]);
|
||||||
|
else
|
||||||
|
dhcpd_vlan = 0;
|
||||||
|
dhcpd_start();
|
||||||
|
} else {
|
||||||
|
print_string("DHCP Server disabled\n");
|
||||||
|
dhcpd_stop();
|
||||||
|
}
|
||||||
} else if (cmd_compare(0, "pvid") && cmd_words_b[1] > 0 && cmd_words_b[2] > 0) {
|
} else if (cmd_compare(0, "pvid") && cmd_words_b[1] > 0 && cmd_words_b[2] > 0) {
|
||||||
__xdata uint16_t pvid;
|
__xdata uint16_t pvid;
|
||||||
uint8_t port;
|
uint8_t port;
|
||||||
@@ -895,27 +1039,9 @@ void cmd_parser(void) __banked
|
|||||||
} else if (cmd_compare(0, "passwd")) {
|
} else if (cmd_compare(0, "passwd")) {
|
||||||
parse_passwd();
|
parse_passwd();
|
||||||
} else if (cmd_compare(0, "eee")) {
|
} else if (cmd_compare(0, "eee")) {
|
||||||
int8_t port = -1;
|
parse_eee();
|
||||||
if (cmd_words_b[3] > 0) {
|
} else if (cmd_compare(0, "bw")) {
|
||||||
port = cmd_buffer[cmd_words_b[2]] - '1';
|
parse_bw();
|
||||||
port = machine.phys_to_log_port[port];
|
|
||||||
}
|
|
||||||
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
|
|
||||||
if (port >= 0)
|
|
||||||
port_eee_enable(port);
|
|
||||||
else
|
|
||||||
port_eee_enable_all();
|
|
||||||
} else if (cmd_words_b[1] > 0 && cmd_compare(1, "off")) {
|
|
||||||
if (port >= 0)
|
|
||||||
port_eee_disable(port);
|
|
||||||
else
|
|
||||||
port_eee_disable_all();
|
|
||||||
} else if (cmd_words_b[1] > 0 && cmd_compare(1, "status")) {
|
|
||||||
if (port >= 0)
|
|
||||||
port_eee_status(port);
|
|
||||||
else
|
|
||||||
port_eee_status_all();
|
|
||||||
}
|
|
||||||
} else if (cmd_compare(0, "version")) {
|
} else if (cmd_compare(0, "version")) {
|
||||||
print_sw_version();
|
print_sw_version();
|
||||||
} else if (cmd_compare(0, "time")) {
|
} else if (cmd_compare(0, "time")) {
|
||||||
@@ -957,6 +1083,16 @@ void cmd_parser(void) __banked
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void clear_command_history(void) __banked
|
||||||
|
{
|
||||||
|
for (cmd_history_ptr = 0; cmd_history_ptr < CMD_HISTORY_SIZE; cmd_history_ptr++)
|
||||||
|
cmd_history[cmd_history_ptr] = 0;
|
||||||
|
cmd_history_ptr = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define FLASH_READ_BURST_SIZE 0x100
|
#define FLASH_READ_BURST_SIZE 0x100
|
||||||
#define PASSWORD "1234"
|
#define PASSWORD "1234"
|
||||||
void execute_config(void) __banked
|
void execute_config(void) __banked
|
||||||
@@ -976,7 +1112,7 @@ void execute_config(void) __banked
|
|||||||
__xdata uint8_t cfg_idx = 0;
|
__xdata uint8_t cfg_idx = 0;
|
||||||
uint8_t c = 0;
|
uint8_t c = 0;
|
||||||
do {
|
do {
|
||||||
for (uint8_t cmd_idx = 0; cmd_idx < (SBUF_SIZE - 1); cmd_idx++) {
|
for (uint8_t cmd_idx = 0; cmd_idx < (CMD_BUF_SIZE - 1); cmd_idx++) {
|
||||||
c = flash_buf[cfg_idx++];
|
c = flash_buf[cfg_idx++];
|
||||||
if (c == 0 || c == '\n') {
|
if (c == 0 || c == '\n') {
|
||||||
cmd_buffer[cmd_idx] = '\0';
|
cmd_buffer[cmd_idx] = '\0';
|
||||||
@@ -997,8 +1133,6 @@ void execute_config(void) __banked
|
|||||||
|
|
||||||
config_done:
|
config_done:
|
||||||
// Start saving commands to cmd_history
|
// Start saving commands to cmd_history
|
||||||
|
clear_command_history();
|
||||||
save_cmd = 1;
|
save_cmd = 1;
|
||||||
for (cmd_history_ptr = 0; cmd_history_ptr < CMD_HISTORY_SIZE; cmd_history_ptr++)
|
|
||||||
cmd_history[cmd_history_ptr] = 0;
|
|
||||||
cmd_history_ptr = 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
|
|
||||||
#include "rtl837x_common.h"
|
#include "rtl837x_common.h"
|
||||||
|
|
||||||
extern __xdata uint8_t cmd_buffer[SBUF_SIZE];
|
extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
|
||||||
extern __xdata uint8_t cmd_available;
|
extern __xdata uint8_t cmd_available;
|
||||||
|
|
||||||
uint8_t cmd_tokenize(void) __banked;
|
uint8_t cmd_tokenize(void) __banked;
|
||||||
void cmd_parser(void) __banked;
|
void cmd_parser(void) __banked;
|
||||||
void execute_config(void) __banked;
|
void execute_config(void) __banked;
|
||||||
void print_sw_version(void) __banked;
|
void print_sw_version(void) __banked;
|
||||||
|
void clear_command_history(void) __banked;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,44 +1,4 @@
|
|||||||
.globl __start__stack
|
|
||||||
;--------------------------------------------------------
|
|
||||||
; Stack segment in internal ram
|
|
||||||
;--------------------------------------------------------
|
|
||||||
.area SSEG (DATA)
|
|
||||||
__start__stack:
|
|
||||||
.ds 1
|
|
||||||
|
|
||||||
.area VECTOR (CODE)
|
|
||||||
.globl __interrupt_vect
|
|
||||||
__interrupt_vect:
|
|
||||||
ljmp __sdcc_gsinit_startup
|
|
||||||
ljmp _isr_ext0 ; 0x03
|
|
||||||
.ds 5
|
|
||||||
ljmp _isr_timer0 ; 0x0b
|
|
||||||
.ds 5
|
|
||||||
ljmp _isr_ext1 ; 0x13
|
|
||||||
.ds 5
|
|
||||||
reti ; 0x1b TIMER 1 IRQ
|
|
||||||
.ds 7
|
|
||||||
ljmp _isr_serial ; 0x23
|
|
||||||
.ds 5
|
|
||||||
ljmp _isr_timer2 ; 0x2b TIMER 2 IRQ
|
|
||||||
.ds 5
|
|
||||||
reti ; 0x33 NOT used by DW8051
|
|
||||||
.ds 7
|
|
||||||
reti ; 0x3b Serial port 1 RX/TX IRQ
|
|
||||||
.ds 7
|
|
||||||
ljmp _isr_ext2 ; 0x43
|
|
||||||
.ds 5
|
|
||||||
ljmp _isr_ext3 ; 0x4b
|
|
||||||
|
|
||||||
.globl __start__stack
|
|
||||||
|
|
||||||
.area GSINIT0 (CODE)
|
|
||||||
|
|
||||||
__sdcc_gsinit_startup::
|
|
||||||
mov sp,#__start__stack - 1
|
|
||||||
|
|
||||||
.area GSFINAL (CODE)
|
.area GSFINAL (CODE)
|
||||||
ljmp _bootloader
|
|
||||||
|
|
||||||
__sdcc_banked_call::
|
__sdcc_banked_call::
|
||||||
push _PSBANK
|
push _PSBANK
|
||||||
|
|||||||
@@ -12,10 +12,12 @@
|
|||||||
#include "uip.h"
|
#include "uip.h"
|
||||||
#include "uip/uip.h"
|
#include "uip/uip.h"
|
||||||
|
|
||||||
extern __code struct uip_eth_addr uip_ethaddr;
|
|
||||||
__xdata struct dhcp_state dhcp_state;
|
__xdata struct dhcp_state dhcp_state;
|
||||||
__xdata uip_ipaddr_t server;
|
__xdata uip_ipaddr_t server;
|
||||||
|
|
||||||
|
#define BOOTP_REQUEST 1
|
||||||
|
#define BOOTP_REPY 2
|
||||||
|
|
||||||
#define DHCP_HW_TYPE_ETH 1
|
#define DHCP_HW_TYPE_ETH 1
|
||||||
|
|
||||||
#define DHCP_SUBNET_MASK 1
|
#define DHCP_SUBNET_MASK 1
|
||||||
@@ -33,6 +35,7 @@ __xdata uip_ipaddr_t server;
|
|||||||
#define DHCP_MESSAGE_DISCOVER 1
|
#define DHCP_MESSAGE_DISCOVER 1
|
||||||
#define DHCP_MESSAGE_OFFER 2
|
#define DHCP_MESSAGE_OFFER 2
|
||||||
#define DHCP_MESSAGE_REQUEST 3
|
#define DHCP_MESSAGE_REQUEST 3
|
||||||
|
#define DHCP_MESSAGE_NACK 4
|
||||||
#define DHCP_MESSAGE_ACK 5
|
#define DHCP_MESSAGE_ACK 5
|
||||||
#define DHCP_LEASE 51
|
#define DHCP_LEASE 51
|
||||||
#define DHCP_LEASE_LEN 4
|
#define DHCP_LEASE_LEN 4
|
||||||
@@ -44,15 +47,23 @@ __xdata uip_ipaddr_t server;
|
|||||||
#define DHCP_CLIENT_ID_LEN 7
|
#define DHCP_CLIENT_ID_LEN 7
|
||||||
#define DHCP_REQUEST_IP 50
|
#define DHCP_REQUEST_IP 50
|
||||||
#define DHCP_REQUEST_IP_LEN 4
|
#define DHCP_REQUEST_IP_LEN 4
|
||||||
|
#define DHCP_CLIENT_NAME 12
|
||||||
#define DHCP_PARAMS 55
|
#define DHCP_PARAMS 55
|
||||||
|
#define DHCP_VENDOR_ID 60
|
||||||
|
#define DHCP_CLIENT_ID 61
|
||||||
#define DHCP_PARAM_SUBNET 1
|
#define DHCP_PARAM_SUBNET 1
|
||||||
#define DHCP_PARAM_ROUTER 3
|
#define DHCP_PARAM_ROUTER 3
|
||||||
#define DHCP_PARAM_DNS 6
|
#define DHCP_PARAM_DNS 6
|
||||||
#define DHCP_END 255
|
#define DHCP_END 255
|
||||||
|
|
||||||
|
#define LEASE_TIME 43200
|
||||||
|
#define RENEWAL_TIME 21600
|
||||||
|
#define REBIND_TIME 21600
|
||||||
|
|
||||||
#pragma codeseg BANK2
|
#pragma codeseg BANK2
|
||||||
#pragma constseg BANK2
|
#pragma constseg BANK2
|
||||||
|
|
||||||
|
|
||||||
struct dhcp_pkt {
|
struct dhcp_pkt {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t hw;
|
uint8_t hw;
|
||||||
@@ -72,16 +83,13 @@ struct dhcp_pkt {
|
|||||||
uint8_t cookie[4];
|
uint8_t cookie[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
#define DHCP_P ((__xdata struct dhcp_pkt *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE])
|
|
||||||
#define DHCP_OPT ((__xdata uint8_t *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE + sizeof (struct dhcp_pkt)])
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define DHCP_P ((__xdata struct dhcp_pkt *)uip_appdata)
|
#define DHCP_P ((__xdata struct dhcp_pkt *)uip_appdata)
|
||||||
#define DHCP_OPT ((__xdata uint8_t *)(uip_appdata) + sizeof (struct dhcp_pkt))
|
#define DHCP_OPT ((__xdata uint8_t *)(uip_appdata) + sizeof (struct dhcp_pkt))
|
||||||
|
|
||||||
__xdata uint32_t long_value;
|
__xdata uint32_t long_value;
|
||||||
|
__xdata struct dhcpd_cstate cstates[DHCPD_MAX_CLIENTS];
|
||||||
|
__xdata uint8_t client_idx;
|
||||||
|
__xdata uint16_t dhcpd_vlan;
|
||||||
|
|
||||||
void dhcp_print_ip(uint8_t *a)
|
void dhcp_print_ip(uint8_t *a)
|
||||||
{
|
{
|
||||||
@@ -92,19 +100,19 @@ void dhcp_print_ip(uint8_t *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void dhcp_prepare_request(void)
|
void dhcp_prepare_msg(void)
|
||||||
{
|
{
|
||||||
DHCP_P->type = 1;
|
DHCP_P->type = BOOTP_REQUEST;
|
||||||
DHCP_P->hw = DHCP_HW_TYPE_ETH;
|
DHCP_P->hw = DHCP_HW_TYPE_ETH;
|
||||||
DHCP_P->hw_len = 6;
|
DHCP_P->hw_len = 6;
|
||||||
DHCP_P->hops = 0;
|
DHCP_P->hops = 0;
|
||||||
|
|
||||||
DHCP_P->tid = HTONS(dhcp_state.transaction_id);
|
DHCP_P->tid = dhcp_state.transaction_id; // In network byte order
|
||||||
DHCP_P->delay = HTONS(0);
|
DHCP_P->delay = HTONS(0);
|
||||||
DHCP_P->flags = 0;
|
DHCP_P->flags = 0;
|
||||||
// Clear fields client_ip to bootp_file
|
// Clear fields client_ip to bootp_file
|
||||||
memset(DHCP_P->client_ip, 0, 224);
|
memset(DHCP_P->client_ip, 0, 224);
|
||||||
memcpyc(DHCP_P->client_addr, uip_ethaddr.addr, 6);
|
memcpy(DHCP_P->client_addr, uip_ethaddr.addr, 6);
|
||||||
DHCP_P->cookie[0] = 0x63;
|
DHCP_P->cookie[0] = 0x63;
|
||||||
DHCP_P->cookie[1] = 0x82;
|
DHCP_P->cookie[1] = 0x82;
|
||||||
DHCP_P->cookie[2] = 0x53;
|
DHCP_P->cookie[2] = 0x53;
|
||||||
@@ -117,7 +125,7 @@ void dhcp_addopt_client_id(void)
|
|||||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID;
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID;
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID_LEN;
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID_LEN;
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_HW_TYPE_ETH;
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_HW_TYPE_ETH;
|
||||||
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 6);
|
memcpy(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 6);
|
||||||
dhcp_state.opt_ptr += 6;
|
dhcp_state.opt_ptr += 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +138,6 @@ void dhcp_addopt_request_ip(void)
|
|||||||
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[1];
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[1];
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[2];
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[2];
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[3];
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[3];
|
||||||
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -142,14 +149,68 @@ void dhcp_addopt_server_id(void)
|
|||||||
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[1];
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[1];
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[2];
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[2];
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[3];
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[3];
|
||||||
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dhcp_addopt_subnet(void)
|
||||||
|
{
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_SUBNET_MASK;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_SUBNET_MASK_LEN;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.subnet[0];
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.subnet[1];
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.subnet[2];
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.subnet[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dhcp_addopt_router(void)
|
||||||
|
{
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_ROUTER;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_ROUTER_LEN;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.router[0];
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.router[1];
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.router[2];
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.router[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dhcp_addopt_lease(void)
|
||||||
|
{
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_LEASE;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_LEASE_LEN;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = LEASE_TIME >> 8;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = LEASE_TIME & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dhcp_addopt_renewal(void)
|
||||||
|
{
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_RENEWAL;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_RENEWAL_LEN;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = RENEWAL_TIME >> 8;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = RENEWAL_TIME & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dhcp_addopt_rebind(void)
|
||||||
|
{
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REBIND;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REBIND_LEN;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = REBIND_TIME >> 8;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = REBIND_TIME & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void dhcp_send_discover(void)
|
void dhcp_send_discover(void)
|
||||||
{
|
{
|
||||||
print_string("dhcp_send_discover called\n");
|
print_string("dhcp_send_discover called\n");
|
||||||
dhcp_prepare_request();
|
dhcp_prepare_msg();
|
||||||
|
|
||||||
dhcp_state.opt_ptr = 0;
|
dhcp_state.opt_ptr = 0;
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
|
||||||
@@ -184,7 +245,7 @@ void dhcp_send_discover(void)
|
|||||||
void dhcp_send_request(void)
|
void dhcp_send_request(void)
|
||||||
{
|
{
|
||||||
print_string("dhcp_send_request called\n");
|
print_string("dhcp_send_request called\n");
|
||||||
dhcp_prepare_request();
|
dhcp_prepare_msg();
|
||||||
|
|
||||||
dhcp_state.opt_ptr = 0;
|
dhcp_state.opt_ptr = 0;
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
|
||||||
@@ -217,6 +278,41 @@ void dhcp_send_request(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dhcp_send_reply(uint8_t rtype)
|
||||||
|
{
|
||||||
|
print_string("dhcp_send_reply called\n");
|
||||||
|
dhcp_prepare_msg();
|
||||||
|
DHCP_P->type = BOOTP_REPY;
|
||||||
|
DHCP_P->client_addr[0] = cstates[client_idx].mac[0]; DHCP_P->client_addr[1] = cstates[client_idx].mac[1];
|
||||||
|
DHCP_P->client_addr[2] = cstates[client_idx].mac[2]; DHCP_P->client_addr[3] = cstates[client_idx].mac[3];
|
||||||
|
DHCP_P->client_addr[4] = cstates[client_idx].mac[4]; DHCP_P->client_addr[5] = cstates[client_idx].mac[5];
|
||||||
|
|
||||||
|
if (rtype != DHCP_MESSAGE_NACK) {
|
||||||
|
DHCP_P->your_ip[0] = dhcp_state.server[0];
|
||||||
|
DHCP_P->your_ip[1] = dhcp_state.server[1];
|
||||||
|
DHCP_P->your_ip[2] = dhcp_state.server[2];
|
||||||
|
DHCP_P->your_ip[3] = DHCPD_START_IP + client_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
dhcp_state.opt_ptr = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE_LEN;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = rtype;
|
||||||
|
|
||||||
|
if (rtype != DHCP_MESSAGE_NACK) {
|
||||||
|
dhcp_addopt_subnet();
|
||||||
|
dhcp_addopt_router();
|
||||||
|
dhcp_addopt_server_id();
|
||||||
|
dhcp_addopt_rebind();
|
||||||
|
dhcp_addopt_lease();
|
||||||
|
dhcp_addopt_renewal();
|
||||||
|
}
|
||||||
|
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_END;
|
||||||
|
uip_udp_send(sizeof(struct dhcp_pkt) + dhcp_state.opt_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ip_opt(uint8_t * __xdata ip)
|
void ip_opt(uint8_t * __xdata ip)
|
||||||
{
|
{
|
||||||
dhcp_state.opt_ptr++;
|
dhcp_state.opt_ptr++;
|
||||||
@@ -244,6 +340,22 @@ void long_opt(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void print_txt_opt(void)
|
||||||
|
{
|
||||||
|
dhcp_state.opt_ptr++;
|
||||||
|
for (uint8_t l = DHCP_OPT[dhcp_state.opt_ptr++]; l ; l--)
|
||||||
|
write_char(DHCP_OPT[dhcp_state.opt_ptr++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void print_eth_opt(void)
|
||||||
|
{
|
||||||
|
dhcp_state.opt_ptr++;
|
||||||
|
for (uint8_t l = DHCP_OPT[dhcp_state.opt_ptr++]; l ; l--)
|
||||||
|
print_byte(DHCP_OPT[dhcp_state.opt_ptr++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void parse_opts(void)
|
void parse_opts(void)
|
||||||
{
|
{
|
||||||
while (DHCP_OPT[dhcp_state.opt_ptr] && DHCP_OPT[dhcp_state.opt_ptr] != DHCP_END) {
|
while (DHCP_OPT[dhcp_state.opt_ptr] && DHCP_OPT[dhcp_state.opt_ptr] != DHCP_END) {
|
||||||
@@ -263,6 +375,9 @@ void parse_opts(void)
|
|||||||
case DHCP_BROADCAST:
|
case DHCP_BROADCAST:
|
||||||
ip_opt(&dhcp_state.broadcast[0]);
|
ip_opt(&dhcp_state.broadcast[0]);
|
||||||
break;
|
break;
|
||||||
|
case DHCP_REQUEST_IP:
|
||||||
|
ip_opt(&dhcp_state.current_ip[0]);
|
||||||
|
break;
|
||||||
case DHCP_LEASE:
|
case DHCP_LEASE:
|
||||||
long_opt();
|
long_opt();
|
||||||
dhcp_state.lease = long_value;
|
dhcp_state.lease = long_value;
|
||||||
@@ -275,6 +390,27 @@ void parse_opts(void)
|
|||||||
long_opt();
|
long_opt();
|
||||||
dhcp_state.renewal = long_value;
|
dhcp_state.renewal = long_value;
|
||||||
break;
|
break;
|
||||||
|
case DHCP_CLIENT_NAME:
|
||||||
|
print_string("Client name: ");
|
||||||
|
print_txt_opt();
|
||||||
|
write_char('\n');
|
||||||
|
break;
|
||||||
|
case DHCP_VENDOR_ID:
|
||||||
|
print_string("Vendor ID: ");
|
||||||
|
print_txt_opt();
|
||||||
|
write_char('\n');
|
||||||
|
break;
|
||||||
|
case DHCP_CLIENT_ID:
|
||||||
|
print_string("Client ID: ");
|
||||||
|
print_eth_opt();
|
||||||
|
write_char('\n');
|
||||||
|
break;
|
||||||
|
case DHCP_PARAMS:
|
||||||
|
print_string("PARAMS request (ignored)\n");
|
||||||
|
dhcp_state.opt_ptr++;
|
||||||
|
dhcp_state.opt_ptr += DHCP_OPT[dhcp_state.opt_ptr];
|
||||||
|
dhcp_state.opt_ptr++;
|
||||||
|
break;
|
||||||
case DHCP_END:
|
case DHCP_END:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -287,9 +423,39 @@ void parse_opts(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void parse_dhcp(void)
|
void find_client(void)
|
||||||
{
|
{
|
||||||
if (!DHCP_P->tid == HTONS(dhcp_state.transaction_id))
|
uint8_t i;
|
||||||
|
for (i = 0; i < DHCPD_MAX_CLIENTS; i++) {
|
||||||
|
if (cstates[i].mac[0] == DHCP_P->client_addr[0] && cstates[i].mac[1] == DHCP_P->client_addr[1]
|
||||||
|
&& cstates[i].mac[2] == DHCP_P->client_addr[2] && cstates[i].mac[3] == DHCP_P->client_addr[3]
|
||||||
|
&& cstates[i].mac[4] == DHCP_P->client_addr[4] && cstates[i].mac[5] == DHCP_P->client_addr[5]
|
||||||
|
)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i < DHCPD_MAX_CLIENTS) {
|
||||||
|
client_idx = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
client_idx = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void find_slot(void)
|
||||||
|
{
|
||||||
|
for (client_idx = 0; client_idx < DHCPD_MAX_CLIENTS; client_idx++) {
|
||||||
|
if (!cstates[client_idx].cstate)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
client_idx = 255;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void parse_dhcp_response(void)
|
||||||
|
{
|
||||||
|
if (!DHCP_P->tid == dhcp_state.transaction_id)
|
||||||
return;
|
return;
|
||||||
if (DHCP_P->cookie[0] != 0x63 || DHCP_P->cookie[1] != 0x82 || DHCP_P->cookie[2] != 0x53 || DHCP_P->cookie[3] != 0x63)
|
if (DHCP_P->cookie[0] != 0x63 || DHCP_P->cookie[1] != 0x82 || DHCP_P->cookie[2] != 0x53 || DHCP_P->cookie[3] != 0x63)
|
||||||
return;
|
return;
|
||||||
@@ -328,13 +494,50 @@ void parse_dhcp(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void parse_dhcp_request(void)
|
||||||
|
{
|
||||||
|
print_string("parse_dhcp_request called\n");
|
||||||
|
if (DHCP_P->cookie[0] != 0x63 || DHCP_P->cookie[1] != 0x82 || DHCP_P->cookie[2] != 0x53 || DHCP_P->cookie[3] != 0x63)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dhcp_state.opt_ptr = 0;
|
||||||
|
if (DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE || DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE_LEN)
|
||||||
|
return;
|
||||||
|
if (DHCP_OPT[dhcp_state.opt_ptr] == DHCP_MESSAGE_DISCOVER) {
|
||||||
|
dhcp_state.opt_ptr++;
|
||||||
|
find_client();
|
||||||
|
if (client_idx == 255)
|
||||||
|
find_slot();
|
||||||
|
// If there is no empty slot, we play possum and do not answer to the request
|
||||||
|
if (client_idx == 255)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cstates[client_idx].cstate = CSTATE_OFFERED;
|
||||||
|
cstates[client_idx].mac[0] = DHCP_P->client_addr[0]; cstates[client_idx].mac[1] = DHCP_P->client_addr[1];
|
||||||
|
cstates[client_idx].mac[2] = DHCP_P->client_addr[2]; cstates[client_idx].mac[3] = DHCP_P->client_addr[3];
|
||||||
|
cstates[client_idx].mac[4] = DHCP_P->client_addr[4]; cstates[client_idx].mac[5] = DHCP_P->client_addr[5];
|
||||||
|
dhcp_state.transaction_id = DHCP_P->tid;
|
||||||
|
parse_opts();
|
||||||
|
dhcp_send_reply(DHCP_MESSAGE_OFFER);
|
||||||
|
} else if (DHCP_OPT[dhcp_state.opt_ptr++] == DHCP_MESSAGE_REQUEST) {
|
||||||
|
find_client();
|
||||||
|
if (client_idx == 255) {
|
||||||
|
dhcp_send_reply(DHCP_MESSAGE_NACK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parse_opts();
|
||||||
|
dhcp_send_reply(DHCP_MESSAGE_ACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dhcp_start(void) __banked
|
void dhcp_start(void) __banked
|
||||||
{
|
{
|
||||||
uip_ipaddr(server, 255,255,255,255);
|
uip_ipaddr(server, 255,255,255,255);
|
||||||
dhcp_state.conn = uip_udp_new(&server, HTONS(DHCPC_SERVER_PORT));
|
dhcp_state.conn = uip_udp_new(&server, HTONS(DHCP_SERVER_PORT));
|
||||||
dhcp_state.current_ip[0] = dhcp_state.current_ip[1] = dhcp_state.current_ip[2] = dhcp_state.current_ip[3] = 0;
|
dhcp_state.current_ip[0] = dhcp_state.current_ip[1] = dhcp_state.current_ip[2] = dhcp_state.current_ip[3] = 0;
|
||||||
if(dhcp_state.conn) {
|
if(dhcp_state.conn) {
|
||||||
uip_udp_bind(dhcp_state.conn, HTONS(DHCPC_CLIENT_PORT));
|
uip_udp_bind(dhcp_state.conn, HTONS(DHCP_CLIENT_PORT));
|
||||||
} else {
|
} else {
|
||||||
print_string("dhcp_start failed to set up socket\n");
|
print_string("dhcp_start failed to set up socket\n");
|
||||||
return;
|
return;
|
||||||
@@ -346,6 +549,43 @@ void dhcp_start(void) __banked
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dhcpd_start(void) __banked
|
||||||
|
{
|
||||||
|
memset(&cstates[0], 0, sizeof (struct dhcpd_cstate) * DHCPD_MAX_CLIENTS);
|
||||||
|
dhcp_state.conn = uip_udp_new(0, 0);
|
||||||
|
if(dhcp_state.conn) {
|
||||||
|
uip_udp_bind(dhcp_state.conn, HTONS(DHCP_SERVER_PORT));
|
||||||
|
} else {
|
||||||
|
print_string("dhcpd_start failed to set up socket\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!dhcpd_vlan)
|
||||||
|
print_string("dhcpd: enabling for all VLANs\n");
|
||||||
|
else
|
||||||
|
print_string("dhcpd: enabling for VLAN "); print_short(dhcpd_vlan); write_char('\n');
|
||||||
|
dhcp_state.state = DHCP_SERVER;
|
||||||
|
|
||||||
|
dhcp_state.server[1] = uip_hostaddr[0] >> 8; dhcp_state.server[0] = uip_hostaddr[0] & 0xff;
|
||||||
|
dhcp_state.server[3] = uip_hostaddr[1] >> 8; dhcp_state.server[2] = uip_hostaddr[1] & 0xff;
|
||||||
|
|
||||||
|
dhcp_state.router[1] = uip_draddr[0] >> 8; dhcp_state.router[0] = uip_draddr[0] & 0xff;
|
||||||
|
dhcp_state.router[3] = uip_draddr[1] >> 8; dhcp_state.router[2] = uip_draddr[1] & 0xff;
|
||||||
|
|
||||||
|
dhcp_state.subnet[1] = uip_netmask[0] >> 8; dhcp_state.subnet[0] = uip_netmask[0] & 0xff;
|
||||||
|
dhcp_state.subnet[3] = uip_netmask[1] >> 8; dhcp_state.subnet[2] = uip_netmask[1] & 0xff;
|
||||||
|
|
||||||
|
dhcp_state.broadcast[0] = dhcp_state.router[0]; dhcp_state.broadcast[1] = dhcp_state.router[1];
|
||||||
|
dhcp_state.broadcast[2] = dhcp_state.router[2]; dhcp_state.broadcast[3] = 0xff;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < DHCPD_MAX_CLIENTS; i++) {
|
||||||
|
cstates[i].cstate = CSTATE_NONE;
|
||||||
|
}
|
||||||
|
// TODO: DNS, correct broadcast address
|
||||||
|
|
||||||
|
print_string("dhcpd_start done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dhcp_stop(void) __banked
|
void dhcp_stop(void) __banked
|
||||||
{
|
{
|
||||||
print_string("dhcp_stop called\n");
|
print_string("dhcp_stop called\n");
|
||||||
@@ -353,6 +593,13 @@ void dhcp_stop(void) __banked
|
|||||||
dhcp_state.state = DHCP_OFF;
|
dhcp_state.state = DHCP_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dhcpd_stop(void) __banked
|
||||||
|
{
|
||||||
|
print_string("dhcpd_stop called\n");
|
||||||
|
uip_udp_remove(dhcp_state.conn);
|
||||||
|
dhcp_state.state = DHCP_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dhcp_callback(void) __banked
|
void dhcp_callback(void) __banked
|
||||||
{
|
{
|
||||||
@@ -361,8 +608,10 @@ void dhcp_callback(void) __banked
|
|||||||
if (uip_closed()) {
|
if (uip_closed()) {
|
||||||
print_string("Closed\n");
|
print_string("Closed\n");
|
||||||
return;
|
return;
|
||||||
|
} else if (dhcp_state.state == DHCP_SERVER && uip_newdata()) {
|
||||||
|
parse_dhcp_request();
|
||||||
} else if (uip_newdata()) {
|
} else if (uip_newdata()) {
|
||||||
parse_dhcp();
|
parse_dhcp_response();
|
||||||
} else {
|
} else {
|
||||||
if (dhcp_state.state == DHCP_START) {
|
if (dhcp_state.state == DHCP_START) {
|
||||||
dhcp_send_discover();
|
dhcp_send_discover();
|
||||||
@@ -385,7 +634,4 @@ void dhcp_callback(void) __banked
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// By default we do not send anything out
|
|
||||||
uip_len = 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,22 +3,27 @@
|
|||||||
|
|
||||||
#include "uipopt.h"
|
#include "uipopt.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#define DHCPD_MAX_CLIENTS 20
|
||||||
|
#define DHCPD_START_IP 100
|
||||||
|
|
||||||
#define DHCPC_SERVER_PORT 67
|
#define DHCP_SERVER_PORT 67
|
||||||
#define DHCPC_CLIENT_PORT 68
|
#define DHCP_CLIENT_PORT 68
|
||||||
|
|
||||||
#define DHCP_OFF 0
|
#define DHCP_OFF 0
|
||||||
#define DHCP_START 1
|
#define DHCP_START 1
|
||||||
#define DHCP_DISCOVER_SENT 2
|
#define DHCP_DISCOVER_SENT 2
|
||||||
#define DHCP_REQUEST_SENT 3
|
#define DHCP_REQUEST_SENT 3
|
||||||
#define DHCP_LEASING 4
|
#define DHCP_LEASING 4
|
||||||
|
#define DHCP_SERVER 5
|
||||||
|
|
||||||
|
#define CSTATE_NONE 0
|
||||||
|
#define CSTATE_OFFERED 1
|
||||||
|
#define CSTATE_LEASED 2
|
||||||
|
|
||||||
void dhcp_start(void) __banked;
|
void dhcp_start(void) __banked;
|
||||||
void dhcp_stop(void) __banked;
|
void dhcp_stop(void) __banked;
|
||||||
// void dhcp_periodic(void) __banked;
|
|
||||||
void dhcp_callback(void) __banked;
|
void dhcp_callback(void) __banked;
|
||||||
|
|
||||||
|
|
||||||
struct dhcp_state {
|
struct dhcp_state {
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
uint32_t transaction_id;
|
uint32_t transaction_id;
|
||||||
@@ -38,6 +43,18 @@ struct dhcp_state {
|
|||||||
struct uip_udp_conn *conn;
|
struct uip_udp_conn *conn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dhcpd_cstate {
|
||||||
|
uint8_t cstate;
|
||||||
|
uint16_t timer;
|
||||||
|
uint32_t transaction_id;
|
||||||
|
uint8_t mac[6];
|
||||||
|
uint8_t ip[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void dhcpd_start(void) __banked;
|
||||||
|
void dhcpd_stop(void) __banked;
|
||||||
|
|
||||||
typedef struct dhcp_state uip_udp_appstate_t;
|
typedef struct dhcp_state uip_udp_appstate_t;
|
||||||
|
|
||||||
/* Finally we define the application function to be called by uIP. */
|
/* Finally we define the application function to be called by uIP. */
|
||||||
|
|||||||
@@ -0,0 +1,238 @@
|
|||||||
|
# Egress and Ingress Bandwidth Control
|
||||||
|
The RTL8372/3 allows to control the bandwidth of data transmitted (egress) and/or
|
||||||
|
admitted (ingress) at any given port. Once admitted, packets are internally switched
|
||||||
|
at wire-speed, since the backplane of the devices has a bandwidth of 60GBit/s.
|
||||||
|
|
||||||
|
The devices schedules transmission of packets by assigning packets to 8 queues
|
||||||
|
implemented in hardware per port, which share a total of 8Mbit of memory internal
|
||||||
|
to the switching part of the SoCs. Packets are assigned to the respective queues
|
||||||
|
based on the priority assigned to a packet, which can be based on various
|
||||||
|
properties of a packet such as IEEE 802.1P priority, DSCP value, physical port
|
||||||
|
number, destination or source MAC, Ether-Type-based, CVID, SVID, IPv4 source or
|
||||||
|
destination IP, IPv4/IPv6 TOS field, IPv6 Flow Label and even TCP/UDP
|
||||||
|
source/destination port. Once in a queue, packets are scheduled for egress
|
||||||
|
based on differnent configurable algorithms.
|
||||||
|
|
||||||
|
RTLPlayground currently allows only to control the bandwidth at ingress at a port
|
||||||
|
or just before packets leave a port. There is no control of the priority assignment
|
||||||
|
or queue scheduling mechanisms. The bandwidth can be controlled in steps of 16Kbit/s
|
||||||
|
from 16Kbit/s to 10Gbp/s.
|
||||||
|
|
||||||
|
The bandwidth control as currently implemented allows e.g. to assign a certain
|
||||||
|
share of bandwidth to an attached device (e.g. to share an uplink), or simulate
|
||||||
|
connections with low bandwidth and even bad connectivity with packet drops when
|
||||||
|
ingress is not controlled by Flow Control but by simply droping packets.
|
||||||
|
|
||||||
|
## Ingress/Egress control
|
||||||
|
The relevant registers for controlling Ingress and Egress at a port are:
|
||||||
|
```
|
||||||
|
#define RTL837X_IGBW_CTRL 0x4c10
|
||||||
|
#define IGBW_INC_BYPASS_PKT 0x100
|
||||||
|
#define IGBW_INC_IFG 0x80
|
||||||
|
#define IGBW_ADM_DHCP 0x20
|
||||||
|
#define IGBW_ADM_ARPREQ 0x10
|
||||||
|
#define IGBW_ADM_RMA 0x08
|
||||||
|
#define IGBW_ADM_BPDU 0x04
|
||||||
|
#define IGBW_ADM_RTKPKT 0x02
|
||||||
|
#define IGBW_ADM_IGMP 0x01
|
||||||
|
#define RTL837X_IGBW_PORT_CTRL 0x4C18
|
||||||
|
#define RTL837X_IGBW_PORT_FC_CTRL 0x4C8C
|
||||||
|
#define RTL837X_EGBW_PORT_CTRL 0x1c34
|
||||||
|
#define RTL837X_EGBW_CTRL 0x447c
|
||||||
|
#define EGBW_INC_IFG 0x02
|
||||||
|
#define EGBW_CPUMODE 0x01
|
||||||
|
```
|
||||||
|
`RTL837X_IGBW_CTRL/RTL837X_EGBW_CTRL` control the behaviour of the bandwidth control
|
||||||
|
at ingress and egress. The flags such as `IGBW_ADM_DHCP`control whether certain types
|
||||||
|
of packets such as DHCP are exempt from being ingress controlled. The
|
||||||
|
`IGBW_INC_IFG/EGBW_INC_IFG` flags control whether the Inter Frame Gaps are part of
|
||||||
|
the bandwidth being controlled. `EGBW_CPUMODE` controls whether packets generated
|
||||||
|
by the internal CPU are subject to egress control.
|
||||||
|
|
||||||
|
`RTL837X_IGBW_PORT_CTRL/RTL837X_EGBW_PORT_CTRL` configure the bandwidth for ingress
|
||||||
|
and egress at a port.
|
||||||
|
|
||||||
|
`RTL837X_IGBW_PORT_FC_CTRL` configures whether packets are bandwidth-controlled using
|
||||||
|
Flow Control (port-bit set), or simply dropped (port-bit clear).
|
||||||
|
|
||||||
|
## Ingress/Egress bandwidth API
|
||||||
|
The code currently provides the following functions:
|
||||||
|
```
|
||||||
|
void bandwidth_setup(void) __banked;
|
||||||
|
void bandwidth_ingress_set(uint8_t port, __xdata uint32_t bw) __banked;
|
||||||
|
void bandwidth_ingress_disable(uint8_t port) __banked;
|
||||||
|
void bandwidth_ingress_drop(uint8_t port) __banked;
|
||||||
|
void bandwidth_egress_set(uint8_t port, __xdata uint32_t bw) __banked;
|
||||||
|
void bandwidth_egress_disable(uint8_t port) __banked;
|
||||||
|
void bandwidth_status(uint8_t port) __banked;
|
||||||
|
```c
|
||||||
|
|
||||||
|
`bandwidth_setup()` is called at boot-time and configures excluding all special packets
|
||||||
|
that may be for the CPU and packets outgoing from the CPU to be excluded from bandwidth
|
||||||
|
control. IFG is not part of the bandwidth calculation.
|
||||||
|
|
||||||
|
`bandwidth_ingress_set()` enables ingress bandwidth control for a particular port given
|
||||||
|
the specified bandwidth. This also enabled Flow Control at a port.
|
||||||
|
|
||||||
|
`bandwidth_ingress_set()` enables egress bandwidth control for a particular port given
|
||||||
|
the specified bandwidth
|
||||||
|
|
||||||
|
`bandwidth_ingress_disable() / bandwidth_egress_disable()` disable ingress and egress
|
||||||
|
bandwidth control at a given port
|
||||||
|
|
||||||
|
`bandwidth_ingress_drop(port)` configures packets exceeding bandwidth limitations to
|
||||||
|
simply be dropped
|
||||||
|
|
||||||
|
`bandwidth_status(port)` shows the current bandwidth control status for a given port
|
||||||
|
|
||||||
|
## Bandwidth control configuration on the Serial Console
|
||||||
|
The following commands are provided on the serial console:
|
||||||
|
```
|
||||||
|
> bw [in|out|status] <port> [<hexvalue>|off|drop]
|
||||||
|
Configures or shows the status of bandwidth control
|
||||||
|
```
|
||||||
|
The bandwidth is given as the `<hexvalue>` in Kbit/s. Note that the control is only
|
||||||
|
possible at a granularity of 16 Kbit/s and the minimum value is also 16 Kbit/s. The
|
||||||
|
hexadecimal numbers must be given in full bytes, i.e. have an even number of digits.
|
||||||
|
|
||||||
|
To enable bandwidth control of ingress for physical port 2 to be set to 256 Kbit/s
|
||||||
|
do:
|
||||||
|
```
|
||||||
|
> bw in 2 0100
|
||||||
|
```
|
||||||
|
|
||||||
|
To drop packets when the bandwidth is exceeeded at port 2 do:
|
||||||
|
```
|
||||||
|
> bw in 2 drop
|
||||||
|
```
|
||||||
|
|
||||||
|
To disable bandwidth control for incoming packets on port 2 do:
|
||||||
|
```
|
||||||
|
> bw in 2 off
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bandwidth configuration via the Web Interface
|
||||||
|
Not implemented, yet!
|
||||||
|
|
||||||
|
## A Test using iperf3
|
||||||
|
The following is and example how to test bandwidth control with a signle Linux device using
|
||||||
|
network namespaces to route packets between a client and a server on the same Linux device
|
||||||
|
through an external switch.
|
||||||
|
|
||||||
|
You will need 2 network intefaces on the linux device, say, 2 USB-Ethernet controllers called
|
||||||
|
eth0 and eth1:
|
||||||
|
```
|
||||||
|
$ sudo ip netns add client
|
||||||
|
$ sudo ip netns add server
|
||||||
|
|
||||||
|
$ sudo ip link set dev eth0 netns client
|
||||||
|
$ sudo ip link set dev eth1 netns server
|
||||||
|
|
||||||
|
$ sudo ip netns exec client ip link set dev eth0 up
|
||||||
|
$ sudo ip netns exec server ip link set dev eth1 up
|
||||||
|
|
||||||
|
$ sudo ip netns exec client ip addr add dev eth0 192.168.99.1/24
|
||||||
|
$ sudo ip netns exec server ip addr add dev eth1 192.168.99.2/24
|
||||||
|
|
||||||
|
$ sudo ip netns exec server iperf3 -s
|
||||||
|
```
|
||||||
|
This will start an iper3 server in the above shell.
|
||||||
|
|
||||||
|
In a different shell you can now run the iperf3 client against your server:
|
||||||
|
```
|
||||||
|
$ sudo ip netns exec client iperf -c 192.168.99.2
|
||||||
|
```
|
||||||
|
The LEDs on your switch where your network adapters are connected should start to flicker.
|
||||||
|
On a 1GBit connection, you should see:
|
||||||
|
```
|
||||||
|
$ sudo ip netns exec client iperf3 -c 192.168.99.2
|
||||||
|
Connecting to host 192.168.99.2, port 5201
|
||||||
|
[ 5] local 192.168.99.1 port 46776 connected to 192.168.99.2 port 5201
|
||||||
|
[ ID] Interval Transfer Bitrate Retr Cwnd
|
||||||
|
[ 5] 0.00-1.00 sec 114 MBytes 952 Mbits/sec 0 339 KBytes
|
||||||
|
[ 5] 1.00-2.00 sec 113 MBytes 946 Mbits/sec 0 356 KBytes
|
||||||
|
[ 5] 2.00-3.00 sec 112 MBytes 937 Mbits/sec 0 390 KBytes
|
||||||
|
[ 5] 3.00-4.00 sec 112 MBytes 942 Mbits/sec 0 390 KBytes
|
||||||
|
[ 5] 4.00-5.00 sec 112 MBytes 943 Mbits/sec 0 390 KBytes
|
||||||
|
[ 5] 5.00-6.00 sec 112 MBytes 944 Mbits/sec 0 390 KBytes
|
||||||
|
[ 5] 6.00-7.00 sec 112 MBytes 938 Mbits/sec 0 390 KBytes
|
||||||
|
[ 5] 7.00-8.00 sec 112 MBytes 942 Mbits/sec 0 410 KBytes
|
||||||
|
[ 5] 8.00-9.00 sec 113 MBytes 947 Mbits/sec 0 410 KBytes
|
||||||
|
[ 5] 9.00-10.00 sec 112 MBytes 940 Mbits/sec 0 410 KBytes
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
[ ID] Interval Transfer Bitrate Retr
|
||||||
|
[ 5] 0.00-10.00 sec 1.10 GBytes 943 Mbits/sec 0 sender
|
||||||
|
[ 5] 0.00-10.00 sec 1.10 GBytes 941 Mbits/sec receiver
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, we limit ingress on port 1 (connected to eth0) to 4 MBit/s:
|
||||||
|
```> bw in 1 1000
|
||||||
|
bandwidth_ingress_set called, port 04
|
||||||
|
RTL837X_IGBW_PORT_CTRL:0x00100100
|
||||||
|
RTL837X_IGBW_PORT_FC_CTRL:0x00000010
|
||||||
|
```
|
||||||
|
|
||||||
|
We now get:
|
||||||
|
```
|
||||||
|
$ sudo ip netns exec client iperf3 -c 192.168.99.2
|
||||||
|
[ 5] local 192.168.99.1 port 43324 connected to 192.168.99.2 port 5201
|
||||||
|
[ ID] Interval Transfer Bitrate Retr Cwnd
|
||||||
|
[ 5] 0.00-1.00 sec 1.12 MBytes 9.43 Mbits/sec 0 160 KBytes
|
||||||
|
[ 5] 1.00-2.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
|
||||||
|
[ 5] 2.00-3.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes
|
||||||
|
[ 5] 3.00-4.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes
|
||||||
|
[ 5] 4.00-5.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
|
||||||
|
[ 5] 5.00-6.00 sec 256 KBytes 2.10 Mbits/sec 0 160 KBytes
|
||||||
|
[ 5] 6.00-7.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
|
||||||
|
[ 5] 7.00-8.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes
|
||||||
|
[ 5] 8.00-9.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
|
||||||
|
[ 5] 9.00-10.00 sec 256 KBytes 2.10 Mbits/sec 0 160 KBytes
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
[ ID] Interval Transfer Bitrate Retr
|
||||||
|
[ 5] 0.00-10.00 sec 5.25 MBytes 4.40 Mbits/sec 0 sender
|
||||||
|
[ 5] 0.00-10.16 sec 4.75 MBytes 3.92 Mbits/sec receiver
|
||||||
|
|
||||||
|
iperf Done.
|
||||||
|
```
|
||||||
|
Which is the 4Mbit/s we configured. There are no packet drops (retries) because
|
||||||
|
Flow Control is used to signal the Ethernet adapter on the incoming interface
|
||||||
|
(port 1 of the router) to slow down.
|
||||||
|
|
||||||
|
We can also configure a mere 256KBit/s and packet drop to simulate a bad connection:
|
||||||
|
```
|
||||||
|
> bw in 1 0100
|
||||||
|
bandwidth_ingress_set called, port 04
|
||||||
|
RTL837X_IGBW_PORT_CTRL:0x00100010
|
||||||
|
RTL837X_IGBW_PORT_FC_CTRL:0x00000010
|
||||||
|
|
||||||
|
> bw in 1 drop
|
||||||
|
RTL837X_IGBW_PORT_FC_CTRL:0x00000000
|
||||||
|
```
|
||||||
|
|
||||||
|
We now get:
|
||||||
|
```
|
||||||
|
$ sudo ip netns exec client iperf3 -c 192.168.99.2
|
||||||
|
Connecting to host 192.168.99.2, port 5201
|
||||||
|
[ 5] local 192.168.99.1 port 46060 connected to 192.168.99.2 port 5201
|
||||||
|
[ ID] Interval Transfer Bitrate Retr Cwnd
|
||||||
|
[ 5] 0.00-1.00 sec 384 KBytes 3.14 Mbits/sec 2 1.41 KBytes
|
||||||
|
[ 5] 1.00-2.00 sec 0.00 Bytes 0.00 bits/sec 54 1.41 KBytes
|
||||||
|
[ 5] 2.00-3.00 sec 0.00 Bytes 0.00 bits/sec 31 29.7 KBytes
|
||||||
|
[ 5] 3.00-4.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes
|
||||||
|
[ 5] 4.00-5.00 sec 0.00 Bytes 0.00 bits/sec 23 1.41 KBytes
|
||||||
|
[ 5] 5.00-6.00 sec 128 KBytes 1.05 Mbits/sec 16 14.1 KBytes
|
||||||
|
[ 5] 6.00-7.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes
|
||||||
|
[ 5] 7.00-8.00 sec 0.00 Bytes 0.00 bits/sec 11 1.41 KBytes
|
||||||
|
[ 5] 8.00-9.00 sec 128 KBytes 1.05 Mbits/sec 9 8.48 KBytes
|
||||||
|
[ 5] 9.00-10.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
[ ID] Interval Transfer Bitrate Retr
|
||||||
|
[ 5] 0.00-10.00 sec 640 KBytes 524 Kbits/sec 152 sender
|
||||||
|
[ 5] 0.00-10.00 sec 256 KBytes 210 Kbits/sec receiver
|
||||||
|
|
||||||
|
iperf Done.
|
||||||
|
```
|
||||||
|
Which shows a large number of retries due to dropped packets and an average number
|
||||||
|
of received packets (the client sends the packets to the server, and they are sent
|
||||||
|
back to the client by the server) of 210 KBit/s, the number is higher for the transmitted
|
||||||
|
packets, because they may include dropped packets.
|
||||||
@@ -5,13 +5,30 @@
|
|||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| keepLINK | KP-9000-9XHML-X | Yes| 2M-PCB23-V3.1 | 2M| 8273N + 8224N |
|
| keepLINK | KP-9000-9XHML-X | Yes| 2M-PCB23-V3.1 | 2M| 8273N + 8224N |
|
||||||
|
|
||||||
|
## PCB
|
||||||
|
|
||||||
|
<img src="photos/2M-PCB23-V3.1-managed/2M-PCB23-V3.1-top.jpeg" width="300" />
|
||||||
|
|
||||||
|
## Port overview
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ ┌──────────┐ │
|
||||||
|
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ SFP (J4) │ │
|
||||||
|
│ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ PORT 9 │ │
|
||||||
|
│ │ PORT 1 │ │ PORT 2 │ │ PORT 3 │ │ PORT 4 │ │ PORT 5 │ │ PORT 6 │ │ PORT 7 │ │ PORT 8 │ │ MAC 8 │ O (PWR) │
|
||||||
|
│ O │ MAC 0 │ │ MAC 1 │ │ MAC 2 │ │ MAC 3 │ │ MAC 4 │ │ MAC 5 │ │ MAC 6 │ │ MAC 7 │ │ SerDes 1 │ O (SFP) │
|
||||||
|
│ RST └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
# Connectors
|
# Connectors
|
||||||
|`J4` SFP PINs | Signal | Component | GPIO | Notes |
|
|`J4` SFP PINs | Signal | Component | GPIO | Notes |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
|2| TX_FAULT | | --- | |
|
|2| TX_FAULT | | --- | |
|
||||||
|3| TX_DISABLE | | --- | Pull down - 0R |
|
|3| TX_DISABLE | | --- | Pull down - 0R |
|
||||||
|4| MODDEF2 – SDA | b-r273 | GPIO39 | |
|
|4| MODDEF2 – SDA | b-r273 | GPIO39-SDA4 | |
|
||||||
|5| MODDEF1 – SCL | b-r274 | GPIO40 | |
|
|5| MODDEF1 – SCL | b-r274 | GPIO40-SCL3 | |
|
||||||
|6| MODDEF0 – PRESENT | B-R275 | GPIO38 | |
|
|6| MODDEF0 – PRESENT | B-R275 | GPIO38 | |
|
||||||
|7| RATE SEL | | --- | |
|
|7| RATE SEL | | --- | |
|
||||||
|8| LOS | B-R276 | GPIO38 | |
|
|8| LOS | B-R276 | GPIO38 | |
|
||||||
@@ -31,15 +48,26 @@ Note: component numbering `<L>-<REFDES>-<SIDE>`
|
|||||||
| 3 | GPIO32 | U0RXD (Input) |
|
| 3 | GPIO32 | U0RXD (Input) |
|
||||||
| 4 | 3V3 | PWR |
|
| 4 | 3V3 | PWR |
|
||||||
|
|
||||||
### T7
|
### T7, Slave Interface
|
||||||
|`T7` pin|what|Signal|
|
|`T7` pin|what|Signal|Components|
|
||||||
|---|---|---|
|
|---|---|---|---|
|
||||||
| 1 | GPIO | |
|
| 1 | Slave Interface | Slave SCK/SCL/MDC/EE_SCL | U7-6 |
|
||||||
| 2 | GND | |
|
| 2 | GND | | |
|
||||||
| 3 | GPIO | |
|
| 3 | Slave Interface | Slave SDI/SDA/MDIO/EE_SDA | U7-5 |
|
||||||
| 4 | 3V3 | |
|
| 4 | 3V3 | | |
|
||||||
| 5 | GPIO | |
|
| 5 | GPIO? | | |
|
||||||
| 6 | GPIO | |
|
| 6 | GPIO? | | |
|
||||||
|
|
||||||
|
`U7` can be a standard I2C eeprom memory, like `24LC32`.
|
||||||
|
|
||||||
|
The Slave Interface allows an extenal host to controll the SOC even if the internal MCU is used.
|
||||||
|
Depending on the `IF_SEL` bootstrap resistors, this can me `I2C`, `SPI` or `SMI`.
|
||||||
|
On this device it is `I2C` on address `0b1011100` or `0x5c` (7-bit notation).
|
||||||
|
|
||||||
|
* I2c Read: must be a write_read opperation `<Dev-ADDR><RegAddr15:8><RegAddr7:0>` `<DevAddr><Data7:0><Data15:8><Data23:16><Data31:24>`.
|
||||||
|
* I2c Write: `<Dev-ADDR><RegAddr15:8><RegAddr7:0><DevAddr><Data7:0><Data15:8><Data23:16><Data31:24>`.
|
||||||
|
|
||||||
|
Example register `0x0004` return chip id `0x00, 0x00, 0x72, 0x83` = `0x83720000`.
|
||||||
|
|
||||||
### T9
|
### T9
|
||||||
|`T9` SMI | Signal | Component | GPIO | Notes |
|
|`T9` SMI | Signal | Component | GPIO | Notes |
|
||||||
@@ -67,23 +95,23 @@ Reset-line found at `T-D6-L`, `T-R83`, `T-R97`, `T-R94`, `T-R93` active-low.
|
|||||||
| HEX VAL. | GPIO | Component | What | | GPIO | Component | What |
|
| HEX VAL. | GPIO | Component | What | | GPIO | Component | What |
|
||||||
| -------- | ------ | ---- | ---- | ---- | ---- | ---- | ---- |
|
| -------- | ------ | ---- | ---- | ---- | ---- | ---- | ---- |
|
||||||
| 00000001 | GPIO00 | T-R34-R, P1-LED-YL |? | | GPIO32 | B-r126-r | U0RXD |
|
| 00000001 | GPIO00 | T-R34-R, P1-LED-YL |? | | GPIO32 | B-r126-r | U0RXD |
|
||||||
| 00000002 | GPIO01 | T-R99-R, P1-LED-GR |? | | GPIO33 | | |
|
| 00000002 | GPIO01 | T-R99-R, P1-LED-GR |? | | GPIO33 | | |
|
||||||
| 00000004 | GPIO02 | |? | | GPIO34 | B-R172, To RTL8225 | Already driver HIGH INT? |
|
| 00000004 | GPIO02 | |? | | GPIO34 | B-R172, To RTL8224 | SMI-MDC0 |
|
||||||
| 00000008 | GPIO03 | T-R113-R, P2-LED-GR |? | | GPIO35 | B-R173, To RTL8225 | Easy to pulldown Reset? |
|
| 00000008 | GPIO03 | T-R113-R, P2-LED-GR |? | | GPIO35 | B-R173, To RTL8224 | SMI-MDIO0 |
|
||||||
| 00000010 | GPIO04 | T-R115-R, P3-LED-YL |? | | GPIO36 || | |
|
| 00000010 | GPIO04 | T-R115-R, P3-LED-YL |? | | GPIO36 | | | |
|
||||||
| 00000020 | GPIO05 | T-R117-R, P3-LED-GR |? | | GPIO37 | To RTL8225 | Already driver low I2C-SCL? | |
|
| 00000020 | GPIO05 | T-R117-R, P3-LED-GR |? | | GPIO37 | To RTL8224 ?? | Already driver low | |
|
||||||
| 00000040 | GPIO06 | |? | | GPIO38 | sfp-6 via B-R275, sfp-8 via B-R276 | |
|
| 00000040 | GPIO06 | |? | | GPIO38 | sfp-6 via B-R275, sfp-8 via B-R276 | SFP-PRESENT |
|
||||||
| 00000080 | GPIO07 | |? | | GPIO39 | sfp-4, b-r273, B-r143 | |
|
| 00000080 | GPIO07 | |? | | GPIO39 | sfp-4, b-r273, B-r143 | I2C4-SDA |
|
||||||
| 00000100 | GPIO08 | | | | GPIO40 | T9-2, sfp-5 b-r274, B-r146 | SMI-MDC |
|
| 00000100 | GPIO08 | | | | GPIO40 | T9-2, sfp-5 b-r274, B-r146 | I2C3-SCL |
|
||||||
| 00000200 | GPIO09 | |LEDx[^1] | | GPIO41 | T9-1, | SMI-MDO , B-r143 |
|
| 00000200 | GPIO09 | |LEDx[^1] | | GPIO41 | T9-1, B-r143 | | I2C3-SDA (Unused) |
|
||||||
| 00000400 | GPIO10 | | | | GPIO42 | U6?8?-P6, T-R | SPI-MEMORY, CLK |
|
| 00000400 | GPIO10 | | | | GPIO42 | U6?8?-P6, T-R | SPI-MEMORY, CLK |
|
||||||
| 00000800 | GPIO11 | |LEDx[^1] | | GPIO43 | U6?8?-P5, T-R | SPI-MEMORY, DI,IO0 |
|
| 00000800 | GPIO11 | |LEDx[^1] | | GPIO43 | U6?8?-P5, T-R | SPI-MEMORY, DI,IO0 |
|
||||||
| 00001000 | GPIO12 | |LEDx[^1] | | GPIO44 | U6?8?-P2, T-R | SPI-MEMORY, DO,IO1 |
|
| 00001000 | GPIO12 | |LEDx[^1] | | GPIO44 | U6?8?-P2, T-R | SPI-MEMORY, DO,IO1 |
|
||||||
| 00002000 | GPIO13 | |LEDx[^1] | | GPIO45 | U6?8?-P1, T-R | SPI-MEMORY, CS |
|
| 00002000 | GPIO13 | |LEDx[^1] | | GPIO45 | U6?8?-P1, T-R | SPI-MEMORY, CS |
|
||||||
| 00004000 | GPIO14 | |LEDx[^1] | | GPIO46 | T10-6 | |
|
| 00004000 | GPIO14 | |LEDx[^1] | | GPIO46 | T10-6 | SPI0-SCK |
|
||||||
| 00008000 | GPIO15 | |LEDx[^1] | | GPIO47 | T10-2 | |
|
| 00008000 | GPIO15 | |LEDx[^1] | | GPIO47 | T10-2 | SPI0-SDA |
|
||||||
| 00010000 | GPIO16 | |LEDx[^1] | | GPIO48 | T10-4, J6 (BUTTON RESET) | |
|
| 00010000 | GPIO16 | |LEDx[^1] | | GPIO48 | T10-4, J6 (BUTTON RESET) | SPI1-SCK |
|
||||||
| 00020000 | GPIO17 | |LEDx[^1] | | GPIO49 | T10-1 | |
|
| 00020000 | GPIO17 | |LEDx[^1] | | GPIO49 | T10-1 | SPI1-SDA |
|
||||||
| 00040000 | GPIO18 | |LEDx[^1] | | GPIO50 | | |
|
| 00040000 | GPIO18 | |LEDx[^1] | | GPIO50 | | |
|
||||||
| 00080000 | GPIO19 | |LEDx[^1] | | GPIO51 | | |
|
| 00080000 | GPIO19 | |LEDx[^1] | | GPIO51 | | |
|
||||||
| 00100000 | GPIO20 | |LEDx[^1] | | GPIO52 | | |
|
| 00100000 | GPIO20 | |LEDx[^1] | | GPIO52 | | |
|
||||||
@@ -96,8 +124,8 @@ Reset-line found at `T-D6-L`, `T-R83`, `T-R97`, `T-R94`, `T-R93` active-low.
|
|||||||
| 08000000 | GPIO27 | |? | | GPIO59 | | |
|
| 08000000 | GPIO27 | |? | | GPIO59 | | |
|
||||||
| 10000000 | GPIO28 | | | | GPIO60 | | |
|
| 10000000 | GPIO28 | | | | GPIO60 | | |
|
||||||
| 20000000 | GPIO29 | | | | GPIO61 | | |
|
| 20000000 | GPIO29 | | | | GPIO61 | | |
|
||||||
| 40000000 | GPIO30 | |SFP-DETE | | GPIO62 | To RTL8225 | Already driver INT? | |
|
| 40000000 | GPIO30 | RTL8224N Reset |RTL8224 | | GPIO62 | To RTL8224 | Already driver | |
|
||||||
| 80000000 | GPIO31 | B-r129-r? |U0TXD | | GPIO63 | | |
|
| 80000000 | GPIO31 | B-r129-r? |U0TXD | | GPIO63 | | |
|
||||||
|
|
||||||
## GPIO Register Input value
|
## GPIO Register Input value
|
||||||
|
|
||||||
@@ -130,4 +158,4 @@ Chip can deliver up to 5A and the sweetspot is at 2A.
|
|||||||
So higher power SFP-modules should work.
|
So higher power SFP-modules should work.
|
||||||
|
|
||||||
|
|
||||||
[^1]: LEDs are found by just plugin a RJ45 connector and see with cmd `gpio` the status change. But the bit pattern for port 1,2 are diffrent from port 3,4.
|
[^1]: LEDs are found by just plugin a RJ45 connector and see with cmd `gpio` the status change. But the bit pattern for port 1,2 are diffrent from port 3,4.
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# 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,54 @@
|
|||||||
|
# SWTG018AS-A V2.0
|
||||||
|
|
||||||
|
The following is a documentation for the unmanaged switch marked as `SWTG018AS-A V2.0`.
|
||||||
|
It is e.g. sold under the Ampcom brand, but no branh-markings are found on the device.
|
||||||
|
|
||||||
|
The original software is running UART on 9600 baud rate.
|
||||||
|
|
||||||
|
Using a SOIC clamp in-board is the only method for initial installation.
|
||||||
|
|
||||||
|
The board has a single flash chips `BS` with 4M-bit size. The front switch, switches between the two flash chips.
|
||||||
|
These can be programed independently by using said switch - so it is e.g. possible to run the original and new firmware in parallel.
|
||||||
|
|
||||||
|
### Label specifications
|
||||||
|
|
||||||
|
- **Name**: 9-Ports 2.5G Ethernet Switch
|
||||||
|
- **Ports**:
|
||||||
|
- 8 × RJ45: 10/100/1000/2500 Mbps
|
||||||
|
- 1 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||||
|
- **Power**: 12V DC, 1A barrel connector
|
||||||
|
|
||||||
|
<img src="photos/SWTG018AS_A_V_2_0/label.jpg" width="300" />
|
||||||
|
|
||||||
|
### What works
|
||||||
|
The device is fully supported:
|
||||||
|
- All 8 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||||
|
- The SFP+ port supports 1G, 2.5G and 10G modules
|
||||||
|
- LEDs work with the same indiciations as the OEM firmware
|
||||||
|
|
||||||
|
### PCB overview
|
||||||
|
|
||||||
|
**Board markings**
|
||||||
|
- Top silkscreen: SWTG018AS-A-V2.0.1_19649
|
||||||
|
|
||||||
|
Top side
|
||||||
|
|
||||||
|
<img src="photos/SWTG018AS_A_V_2_0/pcb_top.jpg" width="300" />
|
||||||
|
|
||||||
|
Bottom
|
||||||
|
|
||||||
|
<img src="photos/SWTG018AS_A_V_2_0/pcb_bottom.jpg" width="300" />
|
||||||
|
|
||||||
|
### J1, serial console
|
||||||
|
|
||||||
|
| `J1` pin | Signal |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| 1 | 3V3 |
|
||||||
|
| 2 | GND |
|
||||||
|
| 3 | RX (Input) |
|
||||||
|
| 4 | TX (Output) |
|
||||||
|
|
||||||
|
|
||||||
|
## Power supply
|
||||||
|
|
||||||
|
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
### ZX-SWTGW218AS
|
||||||
|
|
||||||
|
## Brands
|
||||||
|
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| Mokerlink | ZX-SWTGW218AS | Yes| SWTG118AS-V2.0-16029 | 2MB (FM25Q16A)| 8273N + 8224N |
|
||||||
|
| Sodola | | | | | |
|
||||||
|
| Horaco | | | | | |
|
||||||
|
|
||||||
|
|
||||||
|
## Photos
|
||||||
|
|
||||||
|
<img src="photos/SWTGW218AS-managed/front.png" width="800" />
|
||||||
|
|
||||||
|
<img src="photos/SWTGW218AS-managed/label.jpg" width="800" />
|
||||||
|
|
||||||
|
## PCB
|
||||||
|
|
||||||
|
See up'n'atom's Repo:
|
||||||
|
|
||||||
|
https://github.com/up-n-atom/SWTG118AS/blob/main/photos/SWTG118AS-v2.0/SWTG118AS-v2.0-pcb-top.JPG
|
||||||
|
|
||||||
|
https://github.com/up-n-atom/SWTG118AS/blob/main/photos/SWTG118AS-v2.0/SWTG118AS-v2.0-pcb-bottom.JPG
|
||||||
|
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
# TrendNet TEG-S562
|
||||||
|
|
||||||
|
Following is documentation for unmanaged switch marked as `TEG-S563/EU H/W: V1.0R`.
|
||||||
|
|
||||||
|
Original software is running UART on 57600 baud rate. The software does not allow to
|
||||||
|
do anything fancy via serial. There is `IP` configuration which can be printed as well.
|
||||||
|
There might be also some flash upload procedure, but using SPI clamp in-board seems to
|
||||||
|
be easier method.
|
||||||
|
|
||||||
|
The memory chip is `Winbond W25Q16JV` with 16M-bit size.
|
||||||
|
|
||||||
|
## What does work
|
||||||
|
|
||||||
|
1. 2.5G ports on all advertised speeds.
|
||||||
|
2. SFP+ communication.
|
||||||
|
3. Serial, Web UI.
|
||||||
|
|
||||||
|
## Known issues
|
||||||
|
|
||||||
|
1. LEDs are not initialized properly.
|
||||||
|
|
||||||
|
## PCB
|
||||||
|
|
||||||
|
Manufacturer information be found [on the product page](https://www.trendnet.com/support/support-detail.asp?prod=105_TEG-S562).
|
||||||
|
|
||||||
|
Top side
|
||||||
|
|
||||||
|
<img src="photos/TEG-S562/TEG-S562-v1.0R-top.jpg" width="300" />
|
||||||
|
|
||||||
|
Bottom
|
||||||
|
|
||||||
|
<img src="photos/TEG-S562/TEG-S562-v1.0R-bottom.jpg" width="300" />
|
||||||
|
|
||||||
|
## Connectors
|
||||||
|
|
||||||
|
### Port overview
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ ┌──────────┐ ┌──────────┐ │
|
||||||
|
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ SFP │ │ SFP │ │
|
||||||
|
│ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ PORT 5 │ │ PORT 6 │ │
|
||||||
|
│ │ PORT 1 │ │ PORT 2 │ │ PORT 3 │ │ PORT 4 │ │ MAC ? │ │ MAC ? │ │
|
||||||
|
│ │ MAC 4 │ │ MAC 5 │ │ MAC 6 │ │ MAC 7 │ │ SerDes ? │ │ SerDes ? │ │
|
||||||
|
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘ └──────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### J2, serial console
|
||||||
|
|
||||||
|
| `J2` pin | Signal |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| 1 | 3V3 |
|
||||||
|
| 2 | TX (Output) |
|
||||||
|
| 3 | RX (Input) |
|
||||||
|
| 4 | GND |
|
||||||
|
|
||||||
|
Note: 1 pin is square shaped, towards the power input.
|
||||||
|
|
||||||
|
### J5, power pass-thru
|
||||||
|
|
||||||
|
| `J5` pin | Signal |
|
||||||
|
| -------- | ------ |
|
||||||
|
| 1 | 12V |
|
||||||
|
| 2 | 12V |
|
||||||
|
| 3 | GND |
|
||||||
|
| 4 | GND |
|
||||||
|
|
||||||
|
Note: 1 pin is square shaped.
|
||||||
|
|
||||||
|
### U5, I2C eeprom placeholder
|
||||||
|
|
||||||
|
| `J5` pin | Signal |
|
||||||
|
| -------- | ------------- |
|
||||||
|
| 1 | GND |
|
||||||
|
| 2 | GND |
|
||||||
|
| 3 | GND |
|
||||||
|
| 4 | GND |
|
||||||
|
| 5 | 3V3 |
|
||||||
|
| 6 | ??? Logic Low |
|
||||||
|
| 7 | SCL |
|
||||||
|
| 8 | SDA |
|
||||||
|
|
||||||
|
SOC I2C address is 0x5c.
|
||||||
|
|
||||||
|
### SW1 GPIO switch?
|
||||||
|
|
||||||
|
Not populated but looks like a switch for selecting
|
||||||
|
GPIO level. Missing resistors in place.
|
||||||
|
|
||||||
|
GPIO mapping unknown.
|
||||||
|
|
||||||
|
### S2 Reset ciruit
|
||||||
|
|
||||||
|
Not populated but looks like a button can be added on `S2` connector,
|
||||||
|
requires additional `R571` resistor which will pull signal to ground.
|
||||||
|
|
||||||
|
GPIO mapping unknown.
|
||||||
|
|
||||||
|
### GPIO
|
||||||
|
|
||||||
|
| HEX VAL. | GPIO | When | GPIO | When |
|
||||||
|
| -------- | ------ | ----------------| ------ | -----------------------|
|
||||||
|
| 00000001 | GPIO00 | | GPIO32 | |
|
||||||
|
| 00000002 | GPIO01 | | GPIO33 | |
|
||||||
|
| 00000004 | GPIO02 | | GPIO34 | Random changes |
|
||||||
|
| 00000008 | GPIO03 | | GPIO35 | |
|
||||||
|
| 00000010 | GPIO04 | | GPIO36 | SFP1 Present |
|
||||||
|
| 00000020 | GPIO05 | | GPIO37 | SFP1 RX Los |
|
||||||
|
| 00000040 | GPIO06 | | GPIO38 | SFP2 Present |
|
||||||
|
| 00000080 | GPIO07 | | GPIO39 | |
|
||||||
|
| 00000100 | GPIO08 | | GPIO40 | |
|
||||||
|
| 00000200 | GPIO09 | | GPIO41 | |
|
||||||
|
| 00000400 | GPIO10 | | GPIO42 | Random changes |
|
||||||
|
| 00000800 | GPIO11 | | GPIO43 | |
|
||||||
|
| 00001000 | GPIO12 | PORT1 Link | GPIO44 | |
|
||||||
|
| 00002000 | GPIO13 | PORT1-LED-GREEN | GPIO45 | |
|
||||||
|
| 00004000 | GPIO14 | PORT1-LED-AMBER | GPIO46 | SFP1 I2C CLK |
|
||||||
|
| 00008000 | GPIO15 | PORT2 Link | GPIO47 | SFP1 I2C SDA |
|
||||||
|
| 00010000 | GPIO16 | PORT2-LED-GREEN | GPIO48 | SFP2 I2C CLK |
|
||||||
|
| 00020000 | GPIO17 | PORT2-LED-AMBER | GPIO49 | SFP2 I2C SDA |
|
||||||
|
| 00040000 | GPIO18 | PORT3 Link | GPIO50 | SFP2 Rx LOS |
|
||||||
|
| 00080000 | GPIO19 | PORT3-LED-GREEN | GPIO51 | SFP1 TX Disable |
|
||||||
|
| 00100000 | GPIO20 | PORT4-LED-AMBER | GPIO52 | |
|
||||||
|
| 00200000 | GPIO21 | PORT4 Link | GPIO53 | |
|
||||||
|
| 00400000 | GPIO22 | PORT4-LED-GREEN | GPIO54 | SFP2 TX Disable |
|
||||||
|
| 00800000 | GPIO23 | PORT4-LED-AMBER | GPIO55 | |
|
||||||
|
| 01000000 | GPIO24 | | GPIO56 | |
|
||||||
|
| 02000000 | GPIO25 | | GPIO57 | |
|
||||||
|
| 04000000 | GPIO26 | | GPIO58 | |
|
||||||
|
| 08000000 | GPIO27 | | GPIO59 | |
|
||||||
|
| 10000000 | GPIO28 | | GPIO60 | |
|
||||||
|
| 20000000 | GPIO29 | | GPIO61 | |
|
||||||
|
| 40000000 | GPIO30 | | GPIO62 | |
|
||||||
|
| 80000000 | GPIO31 | | GPIO63 | |
|
||||||
|
|
||||||
|
## LEDs
|
||||||
|
|
||||||
|
Leds are not yet working as in stock firmware. This will be handled later.
|
||||||
|
|
||||||
|
Ports 1-4 are amber for 100M/1G links, Green for 2.5G.
|
||||||
|
Port 5-6 are green for 10G/1G link. Both should flash on activity.
|
||||||
|
|
||||||
|
| NAME | When active |
|
||||||
|
| ---------------- | ---------------|
|
||||||
|
| PWR | 3V3 |
|
||||||
|
| SFP1 | |
|
||||||
|
| SFP2 | |
|
||||||
|
| PORT1-LED-GREEN | - |
|
||||||
|
| PORT2-LED-GREEN | PORT2 2.5G |
|
||||||
|
| PORT3-LED-GREEN | PORT3 2.5G |
|
||||||
|
| PORT4-LED-GREEN | PORT4 2.5G |
|
||||||
|
| PORT1-LED-AMBER | PORT1 1GB/100M |
|
||||||
|
| PORT2-LED-AMBER | PORT2 1GB/100M |
|
||||||
|
| PORT3-LED-AMBER | PORT3 1GB/100M |
|
||||||
|
| PORT4-LED-AMBER | PORT4 1GB/100M |
|
||||||
|
|
||||||
|
## Power supply
|
||||||
|
|
||||||
|
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||||
|
Board has two supply rails. `0.95` and `3.3` volt.
|
||||||
|
|
||||||
|
### `0.95` Core Voltage
|
||||||
|
|
||||||
|
Voltage is made by a `APW8713` (U3).
|
||||||
|
|
||||||
|
### `3.3` Voltage
|
||||||
|
|
||||||
|
Voltage is crated regulated by chip marke as `GoIAT` (U2).
|
||||||
|
|
||||||
|
## SFP SPI
|
||||||
|
|
||||||
|
There is separate clock and data lines for both SFP modules. MSDA/MSCK 0 and 1 need to be enabled.
|
||||||
|
|
||||||
|
SFP1 slot is connected to SPI0. SFP2 slot is connected to SPI1.
|
||||||
|
After Width: | Height: | Size: 754 KiB |
|
After Width: | Height: | Size: 521 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 3.1 MiB |
|
After Width: | Height: | Size: 2.8 MiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 876 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 558 KiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 2.6 MiB |
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## SPI-Flash Memory
|
## SPI-Flash Memory
|
||||||
|
|
||||||
SPI-Flash memory can be replaced with an other type. Because the chip is defect, like #69 & #70 or you have an unmanaged-switch with a small flash size, and want to convert it to a managed-variant to run `RTLPlayground` software on it. Currently `RTLPlayground`-firmware expects `8 MBit / 2 MiB`.
|
SPI-Flash memory can be replaced with an other type. Because the chip is defect, like #69 & #70 or you have an unmanaged-switch with a small flash size, and want to convert it to a managed-variant to run `RTLPlayground` software on it. Currently `RTLPlayground`-firmware expects `8 MBit / 1 MiB`.
|
||||||
|
|
||||||
### Size
|
### Size
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ Most use package are `SO8`-type may also called `SOIC8`-type. Which can also hav
|
|||||||
|
|
||||||
### Specification
|
### Specification
|
||||||
|
|
||||||
1. Size: At least `16 MBit / 4 MiB` (theoretic max. `128 MBit / 32 MiB`, but is not *tested*!)
|
1. Size: At least `8 MBit / 1 MiB` (theoretic max. `128 MBit / 16 MiB`, but is not *tested*!)
|
||||||
2. Speed: `62.5 MHz` or better.
|
2. Speed: `62.5 MHz` or better.
|
||||||
3. Support for `DUAL SPI operation`.
|
3. Support for `DUAL SPI operation`.
|
||||||
Device need support for command `BBh`, `Dual I/O Fast Read` or `Fast Read Dual I/O`.
|
Device need support for command `BBh`, `Dual I/O Fast Read` or `Fast Read Dual I/O`.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ The following devices have been tested and are fully working:
|
|||||||
- Lianguo LG-SWTGW218AS (RTL8373 + RTL8224 PHY: 8x 2.5GBit + 1x 10GBit SFP+)
|
- Lianguo LG-SWTGW218AS (RTL8373 + RTL8224 PHY: 8x 2.5GBit + 1x 10GBit SFP+)
|
||||||
- No-Name ZX-SWTGW215AS, managed version of kp-9000-6hx-x, ordered on
|
- No-Name ZX-SWTGW215AS, managed version of kp-9000-6hx-x, ordered on
|
||||||
AliExpress as keepLINK 5+1 port managed
|
AliExpress as keepLINK 5+1 port managed
|
||||||
|
- TrendNet TEG-S562 (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]
|
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)
|
(https://github.com/up-n-atom/SWTG118AS)
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<script src="/main.js"></script>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<title>Ingress and Egress Bandwidth</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav id="sidebar"></nav>
|
||||||
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<div id="ports"></div>
|
||||||
|
<h1>Ingress and Egress Bandwidth</h1>
|
||||||
|
<table id="bwtable">
|
||||||
|
<tr> <th> </th> <th colspan="3"> Ingress </th> <th colspan="2">Egress</th> <th></th></tr>
|
||||||
|
<tr> <th>Port</th> <th>Limit</th> <th>Bandwidth [kBit/s]</th> <th>Flow Control</th> <th>Limit</th> <th>Bandwidth [kBit/s]</th> <th>Apply</th></tr>
|
||||||
|
</table>
|
||||||
|
<script src="/bandwidth.js"></script>
|
||||||
|
</div>
|
||||||
|
<script src="/navigation.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
const iLayout = '" type="number" maxlength="10" size="10" onfocus="inputFocus(';
|
||||||
|
function createBW() {
|
||||||
|
var tbl = document.getElementById('bwtable');
|
||||||
|
const limit = '<input type="checkbox" id="limit_port" onchange="exec();">'
|
||||||
|
if (tbl.rows.length <= 2 && numPorts) {
|
||||||
|
clearInterval(createBWInterval);
|
||||||
|
console.log("CREATING TABLE ", tbl.rows.length);
|
||||||
|
for (let i = 2; i < 2 + numPorts; i++) {
|
||||||
|
const tr = tbl.insertRow();
|
||||||
|
let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i-1}`));
|
||||||
|
td = tr.insertCell();
|
||||||
|
td.innerHTML = limit.replaceAll("limit_port", "ilimit_port_" + i).replace("exec()", "iClicked(" + i + ")");
|
||||||
|
td = tr.insertCell();
|
||||||
|
td.innerHTML = 'UNLIMITED';
|
||||||
|
td = tr.insertCell();
|
||||||
|
td.innerHTML = limit.replaceAll("limit_port", "fc_port_" + i).replace("exec()", "document.getElementById('bwapply_" + i + "').disabled=false;");
|
||||||
|
td = tr.insertCell();
|
||||||
|
td.innerHTML = limit.replaceAll("limit_port", "elimit_port_" + i).replace("exec()", "eClicked(" + i + ")");
|
||||||
|
td = tr.insertCell();
|
||||||
|
td.innerHTML = 'UNLIMITED';
|
||||||
|
var button = '<button type="button" id="bwapply_' + i + '" style="margin: 0 0 0 24px" onclick="applyBandwidth(' + i + ');">Apply</button>';
|
||||||
|
td = tr.insertCell();
|
||||||
|
td.innerHTML = button;
|
||||||
|
document.getElementById("bwapply_" + i).disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function iClicked(i)
|
||||||
|
{
|
||||||
|
document.getElementById("bwapply_" + i).disabled=false;
|
||||||
|
var tbl = document.getElementById('bwtable');
|
||||||
|
var tr = tbl.rows[i];
|
||||||
|
if (!document.getElementById("ilimit_port_" + i).checked) {
|
||||||
|
tr.cells[2].innerHTML = "UNLIMITED";
|
||||||
|
document.getElementById("fc_port_" + i).disabled = true;
|
||||||
|
document.getElementById("fc_port_" + i).checked = true;
|
||||||
|
} else {
|
||||||
|
tr.cells[2].innerHTML = '<input id="ibw_' + i + iLayout + i + ')" value="0"/>';
|
||||||
|
document.getElementById("fc_port_" + i).disabled = false;
|
||||||
|
document.getElementById("fc_port_" + i).checked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function eClicked(i)
|
||||||
|
{
|
||||||
|
document.getElementById("bwapply_" + i).disabled=false;
|
||||||
|
var tbl = document.getElementById('bwtable');
|
||||||
|
var tr = tbl.rows[i];
|
||||||
|
if (!document.getElementById("elimit_port_" + i).checked) {
|
||||||
|
tr.cells[5].innerHTML = "UNLIMITED";
|
||||||
|
} else {
|
||||||
|
tr.cells[5].innerHTML = '<input id="ebw_' + i + iLayout + i + ')" value="0"/>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function inputFocus(i)
|
||||||
|
{
|
||||||
|
document.getElementById("bwapply_" + i).disabled=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doCMD(cmd)
|
||||||
|
{
|
||||||
|
console.log("Sending >" + cmd + "<");
|
||||||
|
try {
|
||||||
|
const response = await fetch('/cmd', {
|
||||||
|
method: 'POST',
|
||||||
|
body: cmd
|
||||||
|
});
|
||||||
|
console.log('Completed!', response);
|
||||||
|
} catch(err) {
|
||||||
|
console.error(`Error: ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function applyBandwidth(i) {
|
||||||
|
var tbl = document.getElementById('bwtable');
|
||||||
|
var tr = tbl.rows[i];
|
||||||
|
var cmd = "bw in " + (i-1) + " off";
|
||||||
|
if (document.getElementById("ilimit_port_" + i).checked)
|
||||||
|
cmd = 'bw in ' + (i-1) + ' ' + parseInt(document.getElementById("ibw_" + i).value).toString(16).padStart(4, "0");;
|
||||||
|
doCMD(cmd);
|
||||||
|
if (document.getElementById("ilimit_port_" + i).checked) {
|
||||||
|
if (!document.getElementById("fc_port_" + i).checked)
|
||||||
|
cmd = "bw in " + (i-1) + " drop";
|
||||||
|
doCMD(cmd);
|
||||||
|
}
|
||||||
|
var cmd = "bw out " + (i-1) + " off";
|
||||||
|
if (document.getElementById("elimit_port_" + i).checked)
|
||||||
|
cmd = 'bw out ' + (i-1) + ' ' + parseInt(document.getElementById("ebw_" + i).value).toString(16).padStart(4, "0");;
|
||||||
|
doCMD(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBW() {
|
||||||
|
var xhttp = new XMLHttpRequest();
|
||||||
|
xhttp.onreadystatechange = function() {
|
||||||
|
if (this.readyState == 4 && this.status == 200) {
|
||||||
|
const s = JSON.parse(xhttp.responseText);
|
||||||
|
console.log("BW: ", JSON.stringify(s));
|
||||||
|
var tbl = document.getElementById('bwtable');
|
||||||
|
if (tbl.rows.length > 2 && numPorts) {
|
||||||
|
for (let i = 2; i < 2 + numPorts; i++) {
|
||||||
|
p = s[i-2];
|
||||||
|
let n = p.portNum;
|
||||||
|
let tr = tbl.rows[n+1];
|
||||||
|
if (!document.getElementById("bwapply_" + (n+1)).disabled)
|
||||||
|
continue;
|
||||||
|
console.log("Table Update row: " + i + " portNum is " + n + ", pState is " + pState[i-2] + ", row number is " + (n+1));
|
||||||
|
let iBW = parseInt(p.iBW,16) * 16; let eBW = parseInt(p.eBW,16) * 16;
|
||||||
|
document.getElementById("ilimit_port_" + (n+1)).checked = p.iLimited;
|
||||||
|
document.getElementById("elimit_port_" + (n+1)).checked = p.eLimited;
|
||||||
|
if (!p.iLimited) {
|
||||||
|
tr.cells[2].innerHTML = "UNLIMITED";
|
||||||
|
} else {
|
||||||
|
tr.cells[2].innerHTML = '<input id="ibw_' + (n+1) + iLayout + (n+1) + ')" value="' + iBW +'"/>';
|
||||||
|
}
|
||||||
|
if (!p.eLimited) {
|
||||||
|
tr.cells[5].innerHTML = "UNLIMITED";
|
||||||
|
} else {
|
||||||
|
tr.cells[5].innerHTML = '<input id="ebw_' + (n+1) + iLayout + (n+1) + ')" value="' + eBW +'"/>';
|
||||||
|
}
|
||||||
|
document.getElementById("fc_port_" + (n+1)).checked = p.iFC==1?true:false;
|
||||||
|
document.getElementById("fc_port_" + (n+1)).disabled = p.iLimited==1?false:true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhttp.open("GET", "/bandwidth.json", true);
|
||||||
|
xhttp.timeout = 1500; xhttp.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("load", function() {
|
||||||
|
getBW();
|
||||||
|
const iCount = setInterval(getBW, 2000);
|
||||||
|
});
|
||||||
|
const createBWInterval = setInterval(createBW, 1010);
|
||||||
@@ -1 +0,0 @@
|
|||||||
../config.txt
|
|
||||||
@@ -49,7 +49,8 @@ async function fetchCmdLog() {
|
|||||||
console.log("CMD-Log: ", response);
|
console.log("CMD-Log: ", response);
|
||||||
const t = await response.text();
|
const t = await response.text();
|
||||||
return t;
|
return t;
|
||||||
} catch(error) {
|
} catch(err) {
|
||||||
console.error("Error: ", err);
|
console.error("Error: ", err);
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ var txG = new BigInt64Array(10);
|
|||||||
var txB = new BigInt64Array(10);
|
var txB = new BigInt64Array(10);
|
||||||
var rxG = new BigInt64Array(10);
|
var rxG = new BigInt64Array(10);
|
||||||
var rxB = new BigInt64Array(10);
|
var rxB = new BigInt64Array(10);
|
||||||
const linkS = ["Disabled", "No Link", "100M", "1000M", "500M", "10G", "2.5G", "5G"];
|
const linkS = ["Disabled", "Down", "10M", "100M", "1000M", "500M", "10G", "2.5G", "5G"];
|
||||||
var pState = new Int8Array(10);
|
var pState = new Int8Array(10);
|
||||||
var pIsSFP = new Int8Array(10);
|
var pIsSFP = new Int8Array(10);
|
||||||
var pAdvertised = new Int8Array(10);
|
var pAdvertised = new Int8Array(10);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ function fetchMirror() {
|
|||||||
for (let i = 1; i <= numPorts; i++) {
|
for (let i = 1; i <= numPorts; i++) {
|
||||||
let p = i - 1;
|
let p = i - 1;
|
||||||
if (numPorts < 9)
|
if (numPorts < 9)
|
||||||
p = physToLogPort[p];members & (1<<p)
|
p = physToLogPort[p];
|
||||||
setM("mPortsTX"+i, m_tx&(1<<p)); setM("mPortsRX"+i, m_rx&(1<<p));
|
setM("mPortsTX"+i, m_tx&(1<<p)); setM("mPortsRX"+i, m_rx&(1<<p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,6 @@ document.getElementById('sidebar').innerHTML =
|
|||||||
+ "<li><a href='mirror.html'>Mirroring</a></li>"
|
+ "<li><a href='mirror.html'>Mirroring</a></li>"
|
||||||
+ "<li><a href='lag.html'>Link Aggregation</a></li>"
|
+ "<li><a href='lag.html'>Link Aggregation</a></li>"
|
||||||
+ "<li><a href='eee.html'>EEE</a></li>"
|
+ "<li><a href='eee.html'>EEE</a></li>"
|
||||||
|
+ "<li><a href='bandwidth.html'>Bandwidth Limits</a></li>"
|
||||||
+ "<li><a href='system.html'>System Settings</a></li>"
|
+ "<li><a href='system.html'>System Settings</a></li>"
|
||||||
+ "<li><a href='update.html'>Firmware Update</a></li></ul>";
|
+ "<li><a href='update.html'>Firmware Update</a></li></ul>";
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ ul {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 12%;
|
width: 12%;
|
||||||
height: 100%;
|
height: calc(100% - 50px);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
top: 50px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,28 +3,69 @@
|
|||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>System Settings</title>
|
<title>System Settings</title>
|
||||||
|
<style>
|
||||||
|
.tab-bar { display: flex; border-bottom: 2px solid #226; margin-bottom: 0; margin-left: 16%; padding: 1px 16px; padding-bottom: 0; }
|
||||||
|
.tab-btn { padding: 10px 20px; background-color: #ddf; border: none; cursor: pointer; font-size: 1em; border-radius: 8px 8px 0 0; margin-right: 4px; }
|
||||||
|
.tab-btn:hover { background-color: #aaf; }
|
||||||
|
.tab-btn.active { background-color: #aaf; font-weight: bold; border-bottom: 2px solid #aaf; margin-bottom: -2px; }
|
||||||
|
.tab-content { display: none; }
|
||||||
|
.tab-content.active { display: block; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
<h1>System Settings</h1>
|
|
||||||
<div class="row">
|
<div id="system-tab" class="tab-content active">
|
||||||
<div class="lcol"> <label for="ip">IP address:</label></div>
|
<h1>System Settings</h1>
|
||||||
<div class="rcol"> <input id="ip" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
<label class="dhcpon">DHCP client endabled: <input id="dhcp" type="checkbox" onchange="dhcpClicked(this)"></label><br/><br/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="ip">IP address:</label></div>
|
||||||
|
<div class="rcol"> <input id="ip" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="netmask">Netmask:</label></div>
|
||||||
|
<div class="rcol"><input id="netmask" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="gw">Gateway:</label></div>
|
||||||
|
<div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
When updating the above settings, remember to point your browser to the new IP afterwards:<br/>
|
||||||
|
<input style="width:40%;" class="action" id="ip_sub" onclick="ipSub();" type="button" value="Update Settings"><br/>
|
||||||
|
<br/>
|
||||||
|
Save all current settings to Flash:<br/>
|
||||||
|
<input style="width:40%;" class="action" id="flash_sub" onclick="flashSave();" type="button" value="Save Settings to Flash">
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
|
||||||
<div class="lcol"> <label for="netmask">Netmask:</label></div>
|
<div id="advanced-tab" class="tab-content">
|
||||||
<div class="rcol"><input id="netmask" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
<h1>Advanced Settings</h1>
|
||||||
|
<div class="lcol"> <label for="config_display">Startup configuration:</label></div>
|
||||||
|
<textarea id="config_display" rows="8" cols="60"></textarea>
|
||||||
|
<br/><br/>
|
||||||
|
Be careful when saving the directly edited startup configuration, you can lock yourself out:<br/>
|
||||||
|
<input style="width:40%;" class="action" id="clear_config" onclick="clearConfig();" type="button" value="Clear Startup Config">
|
||||||
|
<br/>
|
||||||
|
<input style="width:40%;" class="action" id="flash_startup_sub" onclick="flashStartupSave();" type="button" value="Save Startup Settings to Flash">
|
||||||
|
<br/>
|
||||||
|
<input style="width:40%;" class="action" id="switch_reset" onclick="resetSwitch();" type="button" value="Reset Switch">
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="lcol"> <label for="gw">Gateway:</label></div>
|
<div class="lcol"> <label for="gw">Gateway:</label></div>
|
||||||
<div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
<div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
||||||
</div>
|
</div><br/>
|
||||||
<br/><br/>
|
|
||||||
When updating the above settings, remember to point your browser to the new IP afterwards:<br/>
|
When updating the above settings, remember to point your browser to the new IP afterwards:<br/>
|
||||||
<input style="width:40%;" class="action" id="ip_sub" onclick="ipSub();" type="button" value="Update Settings"><br/>
|
<input style="width:40%;" class="action" id="ip_sub" onclick="ipSub();" type="button" value="Update Settings"><br/>
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
|
<label class="dhcpdon">Enable DHCP Server: <input id="dhcpd" type="checkbox"></label><br/><br/>
|
||||||
|
<label class="dhcpdvlan">Limit DHCP Server to VLAN (0: serve all VLANs): <input type="number" min="0" max="2047" value="0" id="dhcpd_vid" name="dhcpd_vid"></label><br/>
|
||||||
|
<input style="width:40%;" class="action" id="dhcpd_sub" onclick="dhcpdSub();" type="button" value="Change DHCPD State"><br/><br/><br/>
|
||||||
Save all current settings to Flash:<br/>
|
Save all current settings to Flash:<br/>
|
||||||
<input style="width:40%;" class="action" id="flash_sub" onclick="flashSave();" type="button" value="Save Settings to Flash">
|
<input style="width:40%;" class="action" id="flash_sub" onclick="flashSave();" type="button" value="Save Settings to Flash">
|
||||||
|
|
||||||
@@ -32,5 +73,13 @@
|
|||||||
<script src="/config.js"></script>
|
<script src="/config.js"></script>
|
||||||
<script src="/system.js"></script>
|
<script src="/system.js"></script>
|
||||||
<script src="/navigation.js"></script>
|
<script src="/navigation.js"></script>
|
||||||
|
<script>
|
||||||
|
function openTab(evt, tabId) {
|
||||||
|
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
|
||||||
|
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
||||||
|
document.getElementById(tabId).classList.add('active');
|
||||||
|
evt.currentTarget.classList.add('active');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -8,6 +8,20 @@ function checkIp(ip) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function ipSub() {
|
async function ipSub() {
|
||||||
|
if (document.getElementById('dhcp').checked) {
|
||||||
|
var cmd = "ip dhcp";
|
||||||
|
try {
|
||||||
|
const response = await fetch('/cmd', {
|
||||||
|
method: 'POST',
|
||||||
|
body: cmd
|
||||||
|
});
|
||||||
|
console.log('Completed!', response);
|
||||||
|
systemInterval = setInterval(fetchIP, 10000);
|
||||||
|
} catch(err) {
|
||||||
|
console.error(`Error: ${err}`);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (let i=0;i<3;i++) {
|
for (let i=0;i<3;i++) {
|
||||||
if (!checkIp(document.getElementById(ips[i]).value))
|
if (!checkIp(document.getElementById(ips[i]).value))
|
||||||
return;
|
return;
|
||||||
@@ -26,7 +40,39 @@ async function ipSub() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async function dhcpdSub() {
|
||||||
|
var dhcpd_cmd = "dhcpd off";
|
||||||
|
if (document.getElementById('dhcpd').checked) {
|
||||||
|
dhcpd_cmd = "dhcpd on";
|
||||||
|
var v=document.getElementById('dhcpd_vid').value
|
||||||
|
if (v && v!= 0)
|
||||||
|
dhcpd_cmd = dhcpd_cmd + " " + v;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
console.log("Sending: ", dhcpd_cmd);
|
||||||
|
const response = await fetch('/cmd', {
|
||||||
|
method: 'POST',
|
||||||
|
body: dhcpd_cmd
|
||||||
|
});
|
||||||
|
console.log('Completed!', response);
|
||||||
|
} catch(err) {
|
||||||
|
console.error(`Error: ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function dhcpClicked(e)
|
||||||
|
{
|
||||||
|
console.log("dhcpClicked called");
|
||||||
|
if (e.checked) {
|
||||||
|
for (let i=0; i<3;i++)
|
||||||
|
document.getElementById(ips[i]).disabled = true;
|
||||||
|
document.getElementById('dhcpd').disabled = true;
|
||||||
|
} else {
|
||||||
|
console.log("dhcpClicked off");
|
||||||
|
for (let i=0; i<3;i++)
|
||||||
|
document.getElementById(ips[i]).disabled = false;
|
||||||
|
document.getElementById('dhcpd').disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
async function sendConfig(c) {
|
async function sendConfig(c) {
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
form.append("MAX_FILE_SIZE", "4096");
|
form.append("MAX_FILE_SIZE", "4096");
|
||||||
@@ -42,6 +88,7 @@ async function sendConfig(c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function flashSave() {
|
async function flashSave() {
|
||||||
fetchConfig().then((s) => {
|
fetchConfig().then((s) => {
|
||||||
parseConf(s);
|
parseConf(s);
|
||||||
@@ -53,6 +100,39 @@ async function flashSave() {
|
|||||||
sendConfig(body);
|
sendConfig(body);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
fetchIP();
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function flashStartupSave() {
|
||||||
|
var configContent = document.getElementById("config_display").value;
|
||||||
|
console.log("CONFIGURATION to save: ", configContent);
|
||||||
|
sendConfig(configContent);
|
||||||
|
// Clear the command log 1 second after initiating the config save
|
||||||
|
setTimeout(() => {
|
||||||
|
fetch('/cmd_log_clear', { method: 'GET' })
|
||||||
|
.then(response => console.log('Command log cleared', response))
|
||||||
|
.catch(err => console.error('Error clearing command log:', err));
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearConfig() {
|
||||||
|
document.getElementById("config_display").value = "";
|
||||||
|
|
||||||
|
// Validate and populate with current IP settings
|
||||||
|
for (let i=0; i<3; i++) {
|
||||||
|
if (!checkIp(document.getElementById(ips[i]).value))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var configLines = "";
|
||||||
|
for (let i=0; i<3; i++){
|
||||||
|
var cmd = ips[i]+' '+document.getElementById(ips[i]).value;
|
||||||
|
configLines += cmd + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("config_display").value = configLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchIP() {
|
function fetchIP() {
|
||||||
@@ -64,13 +144,35 @@ function fetchIP() {
|
|||||||
document.getElementById("ip").value=s.ip_address;
|
document.getElementById("ip").value=s.ip_address;
|
||||||
document.getElementById("netmask").value=s.ip_netmask;
|
document.getElementById("netmask").value=s.ip_netmask;
|
||||||
document.getElementById("gw").value=s.ip_gateway;
|
document.getElementById("gw").value=s.ip_gateway;
|
||||||
|
document.getElementById('dhcp').checked = s.dhcp_client;
|
||||||
|
document.getElementById('dhcpd').checked = s.dhcp_server;
|
||||||
clearInterval(systemInterval);
|
clearInterval(systemInterval);
|
||||||
|
// Fetch and populate the config textbox
|
||||||
|
fetchConfig().then((configText) => {
|
||||||
|
let fullConfig = configText;
|
||||||
|
// Fetch and append cmd_log
|
||||||
|
//return fetchCmdLog().then((cmdLogText) => {
|
||||||
|
// if (cmdLogText) {
|
||||||
|
// fullConfig = fullConfig + cmdLogText;
|
||||||
|
// }
|
||||||
|
document.getElementById("config_display").value = fullConfig;
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
xhttp.open("GET", `/information.json`, true);
|
xhttp.open("GET", `/information.json`, true);
|
||||||
xhttp.send();
|
xhttp.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetSwitch() {
|
||||||
|
if (!confirm('Are you sure you want to reset the switch?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fetch('/reset', { method: 'GET' }).catch(() => {});
|
||||||
|
setTimeout(() => {
|
||||||
|
alert('Switch is resetting. Please wait and refresh the page.');
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
window.addEventListener("load", function() {
|
||||||
systemInterval = setInterval(fetchIP, 1000);
|
systemInterval = setInterval(fetchIP, 1000);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,9 +14,6 @@
|
|||||||
#define SESSION_ID_LENGTH 12
|
#define SESSION_ID_LENGTH 12
|
||||||
#define SESSION_TIMEOUT 200
|
#define SESSION_TIMEOUT 200
|
||||||
|
|
||||||
// Upload Firmware to 1M
|
|
||||||
#define FIRMWARE_UPLOAD_START 0x100000
|
|
||||||
|
|
||||||
// SPI FLASH MEMORY PAGE SIZE.
|
// SPI FLASH MEMORY PAGE SIZE.
|
||||||
#define FLASHMEM_PAGE_SIZE 0x100
|
#define FLASHMEM_PAGE_SIZE 0x100
|
||||||
|
|
||||||
@@ -30,9 +27,10 @@ extern __code uint8_t * __code hex;
|
|||||||
extern __code struct f_data f_data[];
|
extern __code struct f_data f_data[];
|
||||||
extern __code char * __code mime_strings[];
|
extern __code char * __code mime_strings[];
|
||||||
extern __xdata struct flash_region_t flash_region;
|
extern __xdata struct flash_region_t flash_region;
|
||||||
|
extern __xdata uint32_t flash_size;
|
||||||
|
|
||||||
// Flash buffer to optimize flash writing speed, write_len is the current filling position
|
// Flash buffer to optimize flash writing speed, write_len is the current filling position
|
||||||
extern __xdata uint8_t flash_buf[512];
|
extern __xdata uint8_t flash_buf[FLASH_BUF_SIZE];
|
||||||
__xdata uint32_t uptr; // Current flash write position
|
__xdata uint32_t uptr; // Current flash write position
|
||||||
__xdata uint16_t write_len;
|
__xdata uint16_t write_len;
|
||||||
|
|
||||||
@@ -301,6 +299,8 @@ uint8_t stream_upload(uint16_t bptr)
|
|||||||
print_string("Checksum incorrect!");
|
print_string("Checksum incorrect!");
|
||||||
}
|
}
|
||||||
print_string("\nUpload to flash done, will reset!\n");
|
print_string("\nUpload to flash done, will reset!\n");
|
||||||
|
// close connection to avoid retries by browser
|
||||||
|
uip_close();
|
||||||
reset_chip();
|
reset_chip();
|
||||||
}
|
}
|
||||||
// Make sure there is a 0 at the end of the uploaded data
|
// Make sure there is a 0 at the end of the uploaded data
|
||||||
@@ -310,6 +310,9 @@ uint8_t stream_upload(uint16_t bptr)
|
|||||||
flash_write_bytes(flash_buf);
|
flash_write_bytes(flash_buf);
|
||||||
if (bptr >= uip_len)
|
if (bptr >= uip_len)
|
||||||
return 0;
|
return 0;
|
||||||
|
if(!verify_crc)
|
||||||
|
//ugly hack to signal connection finished after config upload.
|
||||||
|
uip_close();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (p[bptr] == boundary[bindex]) {
|
if (p[bptr] == boundary[bindex]) {
|
||||||
@@ -424,6 +427,12 @@ void handle_post(void)
|
|||||||
p += 4; // Skip \r\n\r\n sequence at end of preamble of part
|
p += 4; // Skip \r\n\r\n sequence at end of preamble of part
|
||||||
|
|
||||||
if (is_word(request_path, "upload")) {
|
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.");
|
print_string("Firmware upload started.");
|
||||||
uptr = FIRMWARE_UPLOAD_START;
|
uptr = FIRMWARE_UPLOAD_START;
|
||||||
verify_crc = 1;
|
verify_crc = 1;
|
||||||
@@ -577,6 +586,8 @@ void httpd_appcall(void)
|
|||||||
send_counters(q[20]-'0');
|
send_counters(q[20]-'0');
|
||||||
} else if (is_word(q, "/eee.json")) {
|
} else if (is_word(q, "/eee.json")) {
|
||||||
send_eee();
|
send_eee();
|
||||||
|
} else if (is_word(q, "/bandwidth.json")) {
|
||||||
|
send_bandwidth();
|
||||||
} else if (is_word(q, "/l2.json")) {
|
} else if (is_word(q, "/l2.json")) {
|
||||||
parse_short(q + 13); // e.g.: /l2.json?idx=10
|
parse_short(q + 13); // e.g.: /l2.json?idx=10
|
||||||
send_l2(short_parsed);
|
send_l2(short_parsed);
|
||||||
@@ -593,6 +604,13 @@ void httpd_appcall(void)
|
|||||||
send_config();
|
send_config();
|
||||||
} else if (is_word(q, "/cmd_log")) {
|
} else if (is_word(q, "/cmd_log")) {
|
||||||
send_cmd_log();
|
send_cmd_log();
|
||||||
|
} else if (is_word(q, "/cmd_log_clear")) {
|
||||||
|
clear_command_history();
|
||||||
|
send_mtu(); // dummy response
|
||||||
|
} else if (is_word(q, "/reset")) {
|
||||||
|
uip_close();
|
||||||
|
delay(1000); //wait for the close packet to be sent, otherwise the browser will retry
|
||||||
|
reset_chip();
|
||||||
} else {
|
} else {
|
||||||
send_not_found();
|
send_not_found();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "uip.h"
|
#include "uip.h"
|
||||||
#include "html_data.h"
|
#include "html_data.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "dhcp.h"
|
||||||
#include "phy.h"
|
#include "phy.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
// #define DEBUG
|
// #define DEBUG
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
||||||
#define L2_MAX_TRANSFER 30
|
#define L2_MAX_TRANSFER 30
|
||||||
|
|
||||||
#pragma codeseg BANK1
|
#pragma codeseg BANK1
|
||||||
@@ -29,7 +31,6 @@ extern __xdata uint16_t cont_len;
|
|||||||
extern __xdata uint32_t cont_addr;
|
extern __xdata uint32_t cont_addr;
|
||||||
extern __code uint8_t * __code hex;
|
extern __code uint8_t * __code hex;
|
||||||
extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
|
extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
|
||||||
extern __code struct uip_eth_addr uip_ethaddr;
|
|
||||||
|
|
||||||
extern __xdata uint8_t sfr_data[4];
|
extern __xdata uint8_t sfr_data[4];
|
||||||
extern __xdata uint8_t sfp_pins_last;
|
extern __xdata uint8_t sfp_pins_last;
|
||||||
@@ -45,6 +46,8 @@ extern __xdata char sfp_module_model[2][17];
|
|||||||
extern __xdata char sfp_module_serial[2][17];
|
extern __xdata char sfp_module_serial[2][17];
|
||||||
extern __xdata uint8_t sfp_options[2];
|
extern __xdata uint8_t sfp_options[2];
|
||||||
|
|
||||||
|
extern __xdata struct dhcp_state dhcp_state;
|
||||||
|
|
||||||
__code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
|
__code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
|
||||||
__code uint8_t * __code HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
|
__code uint8_t * __code HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
|
||||||
|
|
||||||
@@ -97,6 +100,10 @@ void itoa_html(uint8_t v)
|
|||||||
char_to_html('0' + (v % 10));
|
char_to_html('0' + (v % 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void string_to_html(register char *s)
|
||||||
|
{
|
||||||
|
while (*s) char_to_html(*s++);
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t stat_content(void)
|
uint16_t stat_content(void)
|
||||||
{
|
{
|
||||||
@@ -231,8 +238,13 @@ void send_basic_info(void)
|
|||||||
byte_to_html(uip_ethaddr.addr[5]);
|
byte_to_html(uip_ethaddr.addr[5]);
|
||||||
slen += strtox(outbuf + slen, "\",\"sw_ver\":\"");
|
slen += strtox(outbuf + slen, "\",\"sw_ver\":\"");
|
||||||
slen += strtox(outbuf + slen, VERSION_SW);
|
slen += strtox(outbuf + slen, VERSION_SW);
|
||||||
|
slen += strtox(outbuf + slen, "\",\"build_date\":\"");
|
||||||
|
slen += strtox(outbuf + slen, BUILD_DATE);
|
||||||
slen += strtox(outbuf + slen, "\",\"hw_ver\":\"");
|
slen += strtox(outbuf + slen, "\",\"hw_ver\":\"");
|
||||||
slen += strtox(outbuf + slen, machine.machine_name);
|
slen += strtox(outbuf + slen, machine.machine_name);
|
||||||
|
slen += strtox(outbuf + slen, "\",\"flash_size\":\"");
|
||||||
|
string_to_html(get_flash_size_str());
|
||||||
|
|
||||||
slen += strtox(outbuf + slen, "\",\"sfp_slot_0\":\"");
|
slen += strtox(outbuf + slen, "\",\"sfp_slot_0\":\"");
|
||||||
send_sfp_info(0);
|
send_sfp_info(0);
|
||||||
char_to_html('"');
|
char_to_html('"');
|
||||||
@@ -241,6 +253,12 @@ void send_basic_info(void)
|
|||||||
send_sfp_info(1);
|
send_sfp_info(1);
|
||||||
char_to_html('"');
|
char_to_html('"');
|
||||||
}
|
}
|
||||||
|
if (dhcp_state.state != DHCP_OFF && dhcp_state.state != DHCP_SERVER)
|
||||||
|
slen += strtox(outbuf + slen, ",\"dhcp_client\":1,\"dhcp_server\":0");
|
||||||
|
else if (dhcp_state.state == DHCP_SERVER)
|
||||||
|
slen += strtox(outbuf + slen, ",\"dhcp_client\":0,\"dhcp_server\":1");
|
||||||
|
else
|
||||||
|
slen += strtox(outbuf + slen, ",\"dhcp_client\":0,\"dhcp_server\":0");
|
||||||
char_to_html('}');
|
char_to_html('}');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,6 +555,50 @@ void send_eee(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void send_bandwidth(void)
|
||||||
|
{
|
||||||
|
dbg_string("send_bandwidth called\n");
|
||||||
|
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||||
|
char_to_html('[');
|
||||||
|
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||||
|
slen += strtox(outbuf + slen, "{\"portNum\":");
|
||||||
|
itoa_html(machine.log_to_phys_port[i]);
|
||||||
|
slen += strtox(outbuf + slen, ",\"iLimited\":");
|
||||||
|
reg_read_m(RTL837X_IGBW_PORT_CTRL + i * 4);
|
||||||
|
if (sfr_data[1] & 0x10)
|
||||||
|
char_to_html('1');
|
||||||
|
else
|
||||||
|
char_to_html('0');
|
||||||
|
slen += strtox(outbuf + slen, ",\"iBW\":\"");
|
||||||
|
byte_to_html(sfr_data[1] & 0x0f);
|
||||||
|
byte_to_html(sfr_data[2]);
|
||||||
|
byte_to_html(sfr_data[3]);
|
||||||
|
slen += strtox(outbuf + slen, "\",\"iFC\":");
|
||||||
|
if (reg_bit_test(RTL837X_IGBW_PORT_FC_CTRL, i))
|
||||||
|
char_to_html('1');
|
||||||
|
else
|
||||||
|
char_to_html('0');
|
||||||
|
reg_read_m(RTL837X_EGBW_PORT_CTRL + i * 1024);
|
||||||
|
slen += strtox(outbuf + slen, ",\"eLimited\":");
|
||||||
|
if (sfr_data[1] & 0x10)
|
||||||
|
char_to_html('1');
|
||||||
|
else
|
||||||
|
char_to_html('0');
|
||||||
|
slen += strtox(outbuf + slen, ",\"eBW\":\"");
|
||||||
|
byte_to_html(sfr_data[1] & 0x0f);
|
||||||
|
byte_to_html(sfr_data[2]);
|
||||||
|
byte_to_html(sfr_data[3]);
|
||||||
|
char_to_html('"');
|
||||||
|
char_to_html('}');
|
||||||
|
if (i < machine.max_port)
|
||||||
|
char_to_html(',');
|
||||||
|
else
|
||||||
|
char_to_html(']');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void send_mtu(void)
|
void send_mtu(void)
|
||||||
{
|
{
|
||||||
dbg_string("send_mtu called\n");
|
dbg_string("send_mtu called\n");
|
||||||
@@ -627,13 +689,25 @@ void send_status(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
slen += strtox(outbuf + slen, ",\"link\":");
|
slen += strtox(outbuf + slen, ",\"link\":");
|
||||||
|
|
||||||
if (i < 8)
|
uint8_t b = 0;
|
||||||
reg_read_m(RTL837X_REG_LINKS);
|
// Determine link state
|
||||||
|
reg_read_m(RTL837X_REG_LINKS_STS);
|
||||||
|
if(!((sfr_data[(i / 8) + 1] >> (i % 8 ) & 1)))
|
||||||
|
{
|
||||||
|
b = 0; //link down
|
||||||
|
}
|
||||||
else
|
else
|
||||||
reg_read_m(RTL837X_REG_LINKS_89);
|
{
|
||||||
uint8_t b = sfr_data[3 - ((i & 7) >> 1)];
|
//Determine link speed
|
||||||
b = (i & 1) ? b >> 4 : b & 0xf;
|
if (i < 8)
|
||||||
|
reg_read_m(RTL837X_REG_LINKS);
|
||||||
|
else
|
||||||
|
reg_read_m(RTL837X_REG_LINKS_89);
|
||||||
|
|
||||||
|
b = sfr_data[3 - ((i & 7) >> 1)];
|
||||||
|
b = ((i & 1) ? b >> 4 : b & 0xf) + 1;
|
||||||
|
}
|
||||||
char_to_html('0' + b);
|
char_to_html('0' + b);
|
||||||
|
|
||||||
STAT_GET(STAT_COUNTER_TX_PKTS, i);
|
STAT_GET(STAT_COUNTER_TX_PKTS, i);
|
||||||
@@ -665,26 +739,45 @@ void send_status(void)
|
|||||||
void send_config(void)
|
void send_config(void)
|
||||||
{
|
{
|
||||||
dbg_string("send_config called\n");
|
dbg_string("send_config called\n");
|
||||||
__xdata uint32_t pos = CONFIG_START; // 70000 , 6c000 / 0xc000 = 9
|
__xdata uint32_t pos = CONFIG_START;
|
||||||
|
__xdata uint16_t valid_len = 0;
|
||||||
extern __xdata uint16_t len_left = CONFIG_LEN;
|
__xdata uint16_t len_left = CONFIG_LEN;
|
||||||
|
__xdata uint8_t flash_buf[256];
|
||||||
|
|
||||||
slen = strtox(outbuf, HTTP_RESPONCE_TXT);
|
slen = strtox(outbuf, HTTP_RESPONCE_TXT);
|
||||||
while (read_flash((CONFIG_START-CODE0_SIZE) / CODE_BANK_SIZE + 1,
|
|
||||||
(__code uint8_t *) (((CONFIG_START + len_left - CODE0_SIZE) % CODE_BANK_SIZE) + CODE0_SIZE + len_left)) == 0xff) {
|
// Scan through config to find the end of valid data (null terminator)
|
||||||
dbg_short(len_left);
|
do {
|
||||||
len_left--;
|
flash_region.addr = pos;
|
||||||
}
|
flash_region.len = (len_left > 256) ? 256 : len_left;
|
||||||
len_left++;
|
flash_read_bulk(flash_buf);
|
||||||
|
|
||||||
if (len_left > (TCP_OUTBUF_SIZE - slen)) {
|
// Look for null terminator in this chunk
|
||||||
cont_len = len_left - (TCP_OUTBUF_SIZE - slen);
|
for (uint16_t i = 0; i < flash_region.len; i++) {
|
||||||
len_left = TCP_OUTBUF_SIZE - slen;
|
if (flash_buf[i] == 0) {
|
||||||
cont_addr = len_left;
|
// Found end of valid data
|
||||||
|
valid_len += i;
|
||||||
|
goto found_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_len += flash_region.len;
|
||||||
|
len_left -= flash_region.len;
|
||||||
|
pos += flash_region.len;
|
||||||
|
} while (len_left > 0);
|
||||||
|
|
||||||
|
found_end:
|
||||||
|
// Now send the valid data
|
||||||
|
if (valid_len > (TCP_OUTBUF_SIZE - slen)) {
|
||||||
|
cont_len = valid_len - (TCP_OUTBUF_SIZE - slen);
|
||||||
|
valid_len = TCP_OUTBUF_SIZE - slen;
|
||||||
|
cont_addr = valid_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
flash_region.addr = CONFIG_START;
|
flash_region.addr = CONFIG_START;
|
||||||
flash_region.len = len_left;
|
flash_region.len = valid_len;
|
||||||
flash_read_bulk(outbuf + slen);
|
flash_read_bulk(outbuf + slen);
|
||||||
slen += len_left;
|
slen += valid_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_cmd_log(void)
|
void send_cmd_log(void)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ void send_counters(char port);
|
|||||||
void send_status(void);
|
void send_status(void);
|
||||||
void send_vlan(uint16_t vlan);
|
void send_vlan(uint16_t vlan);
|
||||||
void send_basic_info(void);
|
void send_basic_info(void);
|
||||||
|
void send_bandwidth(void);
|
||||||
void send_eee(void);
|
void send_eee(void);
|
||||||
void send_l2(uint16_t idx);
|
void send_l2(uint16_t idx);
|
||||||
void l2_delete(uint16_t idx);
|
void l2_delete(uint16_t idx);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "rtl837x_pins.h"
|
#include "rtl837x_pins.h"
|
||||||
#include "rtl837x_leds.h"
|
#include "rtl837x_leds.h"
|
||||||
|
#include "rtl837x_regs.h"
|
||||||
|
#include "rtl837x_common.h"
|
||||||
|
|
||||||
#ifdef MACHINE_KP_9000_6XHML_X2
|
#ifdef MACHINE_KP_9000_6XHML_X2
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
@@ -11,18 +13,20 @@ __code const struct machine machine = {
|
|||||||
.n_sfp = 2,
|
.n_sfp = 2,
|
||||||
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
|
.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},
|
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
|
||||||
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
|
.is_sfp = {0, 0, 0, 1, 0, 0, 0, 0, 2},
|
||||||
|
// Left SFP port (5)
|
||||||
.sfp_port[0].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
|
.sfp_port[0].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
|
||||||
.sfp_port[0].pin_los = GPIO10_LED10,
|
.sfp_port[0].pin_los = GPIO10_LED10,
|
||||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||||
.sfp_port[0].sds = 0,
|
.sfp_port[0].sds = 0,
|
||||||
.sfp_port[0].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 },
|
.sfp_port[0].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
|
// Right SFP port (6)
|
||||||
.sfp_port[1].pin_detect = GPIO30_ACL_BIT3_EN,
|
.sfp_port[1].pin_detect = GPIO30_ACL_BIT3_EN,
|
||||||
.sfp_port[1].pin_los = GPIO37,
|
.sfp_port[1].pin_los = GPIO37,
|
||||||
.sfp_port[1].pin_tx_disable = GPIO_NA,
|
.sfp_port[1].pin_tx_disable = GPIO_NA,
|
||||||
.sfp_port[1].sds = 1,
|
.sfp_port[1].sds = 1,
|
||||||
.sfp_port[1].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
.sfp_port[1].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
.reset_pin = GPIO46_I2C_SCL0,
|
.reset_pin = GPIO54_ACL_BIT2_EN,
|
||||||
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 },
|
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 },
|
||||||
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
/* Conditions for LED on:
|
/* Conditions for LED on:
|
||||||
@@ -35,14 +39,10 @@ __code const struct machine machine = {
|
|||||||
LEDS_1G | LEDS_LINK,
|
LEDS_1G | LEDS_LINK,
|
||||||
0 },
|
0 },
|
||||||
},
|
},
|
||||||
.led_mux_custom = 0,
|
|
||||||
// LED0 LED1 LED2 LED3 LED4 LED5 LED6 LED7 LED8 LED9 LED10 LED11 LED12 LED13 LED14 LED15
|
|
||||||
// L-SFP R-SFP | PORT 1
|
|
||||||
// LED16 LED17 LED18 LED19 LED20 LED21 LED22 LED23 LED24 LED25 LED26 LED27
|
|
||||||
// | PORT 2 | PORT 3 | PORT 4
|
|
||||||
// .led_mux = { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x0f, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14,
|
|
||||||
// 0x15, 0x16, 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23 },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void machine_custom_init(void) { }
|
||||||
|
|
||||||
#elif defined MACHINE_KP_9000_6XH_X
|
#elif defined MACHINE_KP_9000_6XH_X
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "keepLink KP-9000-6XH-X",
|
.machine_name = "keepLink KP-9000-6XH-X",
|
||||||
@@ -57,7 +57,6 @@ __code const struct machine machine = {
|
|||||||
.sfp_port[0].pin_los = GPIO37,
|
.sfp_port[0].pin_los = GPIO37,
|
||||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||||
.sfp_port[0].sds = 1,
|
.sfp_port[0].sds = 1,
|
||||||
.sfp_port[0].i2c_bus = { .sda = 4, .scl = 3 },
|
|
||||||
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
.reset_pin = GPIO_NA,
|
.reset_pin = GPIO_NA,
|
||||||
/* Conditions for LED on:
|
/* Conditions for LED on:
|
||||||
@@ -71,9 +70,12 @@ __code const struct machine machine = {
|
|||||||
0 },
|
0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void machine_custom_init(void) { }
|
||||||
|
|
||||||
#elif defined MACHINE_KP_9000_9XH_X_EU
|
#elif defined MACHINE_KP_9000_9XH_X_EU
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "keepLink KP-9000-6XH-X-EU",
|
.machine_name = "keepLink KP-9000-9XH-X-EU",
|
||||||
.isRTL8373 = 1,
|
.isRTL8373 = 1,
|
||||||
.min_port = 0,
|
.min_port = 0,
|
||||||
.max_port = 8,
|
.max_port = 8,
|
||||||
@@ -96,6 +98,45 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void machine_custom_init(void) { }
|
||||||
|
|
||||||
|
#elif defined MACHINE_KP_9000_9XHML_X
|
||||||
|
__code const struct machine machine = {
|
||||||
|
.machine_name = "keepLink KP-9000-9XHML-X",
|
||||||
|
.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 = 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 },
|
||||||
|
.reset_pin = GPIO48_I2C_SCL1,
|
||||||
|
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 },
|
||||||
|
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
.led_sets = {
|
||||||
|
{ /* RJ45: First LED, yellow, second LED: green */
|
||||||
|
LEDS_2G5 | LEDS_LINK,
|
||||||
|
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
}, { /* SFP PORT, SINGLE GREEN LED */
|
||||||
|
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
}},
|
||||||
|
.led_mux_custom = 1,
|
||||||
|
.led_mux = {0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0c, 0x09, 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) { }
|
||||||
|
|
||||||
#elif defined MACHINE_SWGT024_V2_0
|
#elif defined MACHINE_SWGT024_V2_0
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "SWGT024 V2.0",
|
.machine_name = "SWGT024 V2.0",
|
||||||
@@ -133,6 +174,49 @@ __code const struct machine machine = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void machine_custom_init(void) { }
|
||||||
|
|
||||||
|
#elif defined MACHINE_SWTG018AS_A_V_2_0
|
||||||
|
__code const struct machine machine = {
|
||||||
|
.machine_name = "SWTG018AS-A V2.0",
|
||||||
|
.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 = GPIO38,
|
||||||
|
.sfp_port[0].pin_los = GPIO_NA,
|
||||||
|
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||||
|
.sfp_port[0].sds = 1,
|
||||||
|
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
|
.reset_pin = GPIO_NA,
|
||||||
|
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 },
|
||||||
|
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
.led_sets = {
|
||||||
|
{ /* RJ45: First LED, yellow, second LED: green */
|
||||||
|
LEDS_2G5 | LEDS_LINK,
|
||||||
|
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
}, { /* SFP PORT, SINGLE GREEN LED */
|
||||||
|
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
}},
|
||||||
|
.led_mux_custom = 1,
|
||||||
|
.led_mux = { 0x00, 0x01, 0x04, 0x05, 0x08, // 65e0
|
||||||
|
0x09, 0x0c, 0x09, 0x0d, 0x10, // 65e4
|
||||||
|
0x11, 0x0e, 0x14, 0x11, 0x12, // 65e8
|
||||||
|
0x15, 0x15, 0x16, 0x18, 0x19, // 65ec
|
||||||
|
0x1a, 0x19, 0x1d, 0x1e, 0x1c, // 65f0
|
||||||
|
0x1d, 0x20, 0x21 },
|
||||||
|
};
|
||||||
|
|
||||||
|
void machine_custom_init(void) { }
|
||||||
|
|
||||||
#elif defined MACHINE_HG0402XG_V1_1
|
#elif defined MACHINE_HG0402XG_V1_1
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "HG0402XG V1.1",
|
.machine_name = "HG0402XG V1.1",
|
||||||
@@ -170,48 +254,44 @@ __code const struct machine machine = {
|
|||||||
0 },
|
0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
#elif defined MACHINE_ZX_SWTGW215AS_HASIVO
|
|
||||||
|
void machine_custom_init(void) { }
|
||||||
|
|
||||||
|
#elif defined MACHINE_SWTGW218AS
|
||||||
|
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "ZX-SWTGW215AS HASIVO",
|
.machine_name = "SWTGW218AS 8+1 Managed Switch",
|
||||||
.isRTL8373 = 0,
|
.isRTL8373 = 1,
|
||||||
.min_port = 3,
|
.min_port = 0,
|
||||||
.max_port = 8,
|
.max_port = 8,
|
||||||
.n_sfp = 1,
|
.n_sfp = 1,
|
||||||
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
|
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||||
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
|
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
|
||||||
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
|
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
|
||||||
.sfp_port[0].pin_los = GPIO37,
|
.sfp_port[0].pin_los = GPIO37,
|
||||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||||
.sfp_port[0].sds = 1,
|
.sfp_port[0].sds = 1,
|
||||||
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
.sfp_port[1].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
|
||||||
.reset_pin = GPIO54_ACL_BIT2_EN,
|
.reset_pin = GPIO54_ACL_BIT2_EN,
|
||||||
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 },
|
.high_leds = { .mux = LED_27 | LED_28 | LED_29, .enable = LED_28 | LED_29 },
|
||||||
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
.led_sets = {
|
.led_sets = { { LEDS_2G5 | LEDS_LINK | LEDS_ACT, // Green LED (right)
|
||||||
/* The Ethernet ports have 1 amber LED (bi-color left) and 2 green LED (left/right)
|
0, // unused
|
||||||
* The SFP port has 1 green LED
|
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // Amber LED (left)
|
||||||
* Ethernet ports use LED-set 0, SFP port uses LED-set 1
|
0
|
||||||
* Amber-LED: ledid0 & ledid1 & !ledid2
|
}, // unused
|
||||||
* Left-Green: ledid-2
|
{ LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT, // SFP LED
|
||||||
* Right-Green: ledid-0
|
0, // unused
|
||||||
* ledid3 is not used
|
0, // unused
|
||||||
*/
|
0
|
||||||
{ LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
|
}, // unused },
|
||||||
LEDS_2G5 | LEDS_LINK | LEDS_10G,
|
},
|
||||||
LEDS_1G | LEDS_LINK,
|
|
||||||
0 },
|
|
||||||
{
|
|
||||||
LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5,
|
|
||||||
LEDS_1G | LEDS_LINK,
|
|
||||||
LEDS_2G5 | LEDS_LINK,
|
|
||||||
LEDS_COL | LEDS_DUPLEX,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.led_mux_custom = 0,
|
|
||||||
};
|
};
|
||||||
#elif defined DEFAULT_8C_1SFP
|
|
||||||
|
void machine_custom_init(void) { }
|
||||||
|
|
||||||
|
#elif defined MACHINE_DEFAULT_8C_1SFP
|
||||||
__code const struct machine machine = {
|
__code const struct machine machine = {
|
||||||
.machine_name = "8+1 SFP Port Switch",
|
.machine_name = "8+1 SFP Port Switch",
|
||||||
.isRTL8373 = 1,
|
.isRTL8373 = 1,
|
||||||
@@ -235,4 +315,83 @@ __code const struct machine machine = {
|
|||||||
LEDS_2G5 | LEDS_LINK | LEDS_ACT },
|
LEDS_2G5 | LEDS_LINK | LEDS_ACT },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void machine_custom_init(void) { }
|
||||||
|
|
||||||
|
#elif defined MACHINE_TRENDNET_TEG_S562
|
||||||
|
__code const struct machine machine = {
|
||||||
|
.machine_name = "Trendnet TEG-S562",
|
||||||
|
.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, 3, 8, 0, 0, 0},
|
||||||
|
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
|
||||||
|
.sfp_port[0].pin_detect = GPIO36_PWM_OUT,
|
||||||
|
.sfp_port[0].pin_los = GPIO37,
|
||||||
|
.sfp_port[0].pin_tx_disable = GPIO51_I2C_SDA2_UART1_RX,
|
||||||
|
.sfp_port[0].sds = 0,
|
||||||
|
.sfp_port[0].i2c = { .sda = GPIO47_I2C_SDA0, .scl = GPIO46_I2C_SCL0 },
|
||||||
|
.sfp_port[1].pin_detect = GPIO38,
|
||||||
|
.sfp_port[1].pin_los = GPIO50_I2C_SCL2_UART1_TX,
|
||||||
|
.sfp_port[1].pin_tx_disable = GPIO54_ACL_BIT2_EN,
|
||||||
|
.sfp_port[1].sds = 1,
|
||||||
|
.sfp_port[1].i2c = { .sda = GPIO49_I2C_SDA1, .scl = GPIO48_I2C_SCL1 },
|
||||||
|
.reset_pin = GPIO_NA,
|
||||||
|
};
|
||||||
|
|
||||||
|
void machine_custom_init(void) { }
|
||||||
|
|
||||||
|
#elif defined MACHINE_HI_K0402WS
|
||||||
|
__code const struct machine machine = {
|
||||||
|
.machine_name = "HiSource HI-K0402WS",
|
||||||
|
.isRTL8373 = 0,
|
||||||
|
.min_port = 3,
|
||||||
|
.max_port = 8,
|
||||||
|
.n_sfp = 2,
|
||||||
|
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
|
||||||
|
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
|
||||||
|
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
|
||||||
|
|
||||||
|
// Left SFP port
|
||||||
|
.sfp_port[0].pin_detect = GPIO38,
|
||||||
|
.sfp_port[0].pin_los = GPIO_NA,
|
||||||
|
.sfp_port[0].sds = 1,
|
||||||
|
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
|
|
||||||
|
// Right SFP port
|
||||||
|
.sfp_port[1].pin_detect = GPIO37,
|
||||||
|
.sfp_port[1].pin_los = GPIO_NA,
|
||||||
|
.sfp_port[1].sds = 0,
|
||||||
|
.sfp_port[1].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 },
|
||||||
|
|
||||||
|
.reset_pin = GPIO_NA,
|
||||||
|
.high_leds = { .mux = LED_28 | LED_29, .enable = LED_27 | LED_28 | LED_29 },
|
||||||
|
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
|
||||||
|
.led_sets = {
|
||||||
|
{
|
||||||
|
LEDS_2G5 | LEDS_LINK | LEDS_10M | LEDS_ACT,
|
||||||
|
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
|
||||||
|
LEDS_1G | LEDS_LINK,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK,
|
||||||
|
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_ACT,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error "Please select a machine type in machine.h"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,13 +9,15 @@
|
|||||||
// #define MACHINE_KP_9000_6XHML_X2
|
// #define MACHINE_KP_9000_6XHML_X2
|
||||||
// #define MACHINE_KP_9000_6XH_X
|
// #define MACHINE_KP_9000_6XH_X
|
||||||
// #define MACHINE_KP_9000_9XH_X_EU
|
// #define MACHINE_KP_9000_9XH_X_EU
|
||||||
|
// #define MACHINE_KP_9000_9XHML_X
|
||||||
// #define MACHINE_SWGT024_V2_0
|
// #define MACHINE_SWGT024_V2_0
|
||||||
// #define MACHINE_HORACO_ZX_SG4T2
|
// #define MACHINE_HORACO_ZX_SG4T2
|
||||||
|
// #define MACHINE_TRENDNET_TEG_S562
|
||||||
// #define MACHINE_HG0402XG_V1_1
|
// #define MACHINE_HG0402XG_V1_1
|
||||||
#define MACHINE_ZX_SWTGW215AS_HASIVO
|
// #define MACHINE_SWTG018AS_A_V_2_0
|
||||||
// #define DEFAULT_8C_1SFP
|
// #define MACHINE_SWTGW218AS
|
||||||
|
// #define MACHINE_HI_K0402WS
|
||||||
// #define DEFAULT_5C_1SFP
|
// #define MACHINE_DEFAULT_8C_1SFP
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// GPIO pins for SDA/SCL
|
// GPIO pins for SDA/SCL
|
||||||
@@ -55,7 +57,7 @@ typedef struct machine {
|
|||||||
uint8_t is_sfp[9]; // 0 for non-SFP ports 1 or 2 for the I2C port number
|
uint8_t is_sfp[9]; // 0 for non-SFP ports 1 or 2 for the I2C port number
|
||||||
// sfp_port[0] is the first SFP-port from the left on the device, sfp_port[1] the next if present
|
// sfp_port[0] is the first SFP-port from the left on the device, sfp_port[1] the next if present
|
||||||
struct sfp_port sfp_port[2];
|
struct sfp_port sfp_port[2];
|
||||||
int8_t reset_pin;
|
uint8_t reset_pin;
|
||||||
struct high_leds high_leds;
|
struct high_leds high_leds;
|
||||||
uint8_t port_led_set[9];
|
uint8_t port_led_set[9];
|
||||||
uint32_t led_sets[4][4];
|
uint32_t led_sets[4][4];
|
||||||
@@ -69,4 +71,6 @@ typedef struct machine_runtime
|
|||||||
uint8_t isN : 1;
|
uint8_t isN : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void machine_custom_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
// #define REGDBG
|
||||||
|
// #define DEBUG
|
||||||
|
|
||||||
|
#include "rtl837x_common.h"
|
||||||
|
#include "rtl837x_sfr.h"
|
||||||
|
#include "rtl837x_regs.h"
|
||||||
|
#include "rtl837x_bandwidth.h"
|
||||||
|
#include "machine.h"
|
||||||
|
|
||||||
|
#pragma codeseg BANK2
|
||||||
|
#pragma constseg BANK2
|
||||||
|
|
||||||
|
extern __xdata uint8_t sfr_data[4];
|
||||||
|
|
||||||
|
void bandwidth_setup(void) __banked
|
||||||
|
{
|
||||||
|
print_string("bandwidth_setup called\n");
|
||||||
|
// Exclude all packets possibly for the CPU port, but do not include bypassed packets or Inter-Frame-Gap into bandwidth
|
||||||
|
REG_SET(RTL837X_IGBW_CTRL, IGBW_ADM_DHCP | IGBW_ADM_ARPREQ | IGBW_ADM_RMA | IGBW_ADM_BPDU | IGBW_ADM_RTKPKT | IGBW_ADM_IGMP);
|
||||||
|
|
||||||
|
// We do not count IFG for Egress and allways allow CPU-traffic
|
||||||
|
REG_SET(RTL837X_EGBW_CTRL, EGBW_CPUMODE);
|
||||||
|
|
||||||
|
print_string("RTL837X_IGBW_CTRL: "); print_reg(RTL837X_IGBW_CTRL); write_char('\n');
|
||||||
|
print_string("RTL837X_EGBW_CTRL: "); print_reg(RTL837X_EGBW_CTRL); write_char('\n');
|
||||||
|
print_string("bandwidth_setup done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the ingress bandwidth
|
||||||
|
* bw: Bandwidth in kb
|
||||||
|
*/
|
||||||
|
void bandwidth_ingress_set(uint8_t port, __xdata uint32_t bw) __banked
|
||||||
|
{
|
||||||
|
__xdata uint8_t * __xdata bwptr = &bw;
|
||||||
|
|
||||||
|
print_string("bandwidth_ingress_set called, port "); print_byte(port); write_char('\n');
|
||||||
|
sfr_data[0] = 0;
|
||||||
|
sfr_data[1] = 0x10 | (*(bwptr + 2) >> 4); // Set bit 20 to enable ingress bandwidth control
|
||||||
|
sfr_data[2] = (*(bwptr + 2) << 4) | (*(bwptr + 1) >> 4);
|
||||||
|
sfr_data[3] = (*(bwptr) >> 4) | (*(bwptr + 1) << 4);
|
||||||
|
reg_write_m(RTL837X_IGBW_PORT_CTRL + port * 4);
|
||||||
|
|
||||||
|
// We enable Flow Control instead of just dropping packets
|
||||||
|
reg_bit_set(RTL837X_IGBW_PORT_FC_CTRL, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bandwidth_ingress_drop(uint8_t port) __banked
|
||||||
|
{
|
||||||
|
reg_bit_clear(RTL837X_IGBW_PORT_FC_CTRL, port);
|
||||||
|
print_string("RTL837X_IGBW_PORT_FC_CTRL:"); print_reg(RTL837X_IGBW_PORT_FC_CTRL); write_char('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bandwidth_ingress_fc(uint8_t port) __banked
|
||||||
|
{
|
||||||
|
reg_bit_set(RTL837X_IGBW_PORT_FC_CTRL, port);
|
||||||
|
print_string("RTL837X_IGBW_PORT_FC_CTRL:"); print_reg(RTL837X_IGBW_PORT_FC_CTRL); write_char('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bandwidth_ingress_disable(uint8_t port) __banked
|
||||||
|
{
|
||||||
|
print_string("Ingress bandwidth limit disabled, port "); print_byte(port); write_char('\n');
|
||||||
|
REG_SET(RTL837X_IGBW_PORT_CTRL + port * 4, 0x0fffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bandwidth_egress_set(uint8_t port, __xdata uint32_t bw) __banked
|
||||||
|
{
|
||||||
|
__xdata uint8_t * __xdata bwptr = &bw;
|
||||||
|
|
||||||
|
print_string("bandwidth_egress_set called, port "); print_byte(port); write_char('\n');
|
||||||
|
sfr_data[0] = 0;
|
||||||
|
sfr_data[1] = 0x10 | (*(bwptr + 2) >> 4); // Set bit 20 to enable egress bandwidth control
|
||||||
|
sfr_data[2] = (*(bwptr + 2) << 4) | (*(bwptr + 1) >> 4);
|
||||||
|
sfr_data[3] = (*(bwptr) >> 4) | (*(bwptr + 1) << 4);
|
||||||
|
reg_write_m(RTL837X_EGBW_PORT_CTRL + port * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bandwidth_egress_disable(uint8_t port) __banked
|
||||||
|
{
|
||||||
|
print_string("Egress bandwidth limit disabled, port "); print_byte(port); write_char('\n');
|
||||||
|
REG_SET(RTL837X_EGBW_PORT_CTRL + port * 1024, 0x0fffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bandwidth_status(uint8_t port) __banked
|
||||||
|
{
|
||||||
|
print_string("ingress: ");
|
||||||
|
reg_read_m(RTL837X_IGBW_PORT_CTRL + port * 4);
|
||||||
|
if (sfr_data[1] & 0x10) {
|
||||||
|
print_string("enabled: ");
|
||||||
|
sfr_data[1] &= 0xef;
|
||||||
|
print_string("0x");
|
||||||
|
print_byte(sfr_data[1]);
|
||||||
|
print_byte(sfr_data[2]);
|
||||||
|
print_byte(sfr_data[3]);
|
||||||
|
write_char('0');
|
||||||
|
write_char('\n');
|
||||||
|
} else {
|
||||||
|
print_string("disabled\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
print_string("egress: ");
|
||||||
|
reg_read_m(RTL837X_EGBW_PORT_CTRL + port * 1024);
|
||||||
|
if (sfr_data[1] & 0x10) {
|
||||||
|
print_string("enabled: ");
|
||||||
|
sfr_data[1] &= 0xef;
|
||||||
|
print_string("0x");
|
||||||
|
print_byte(sfr_data[1]);
|
||||||
|
print_byte(sfr_data[2]);
|
||||||
|
print_byte(sfr_data[3]);
|
||||||
|
write_char('0');
|
||||||
|
write_char('\n');
|
||||||
|
} else {
|
||||||
|
print_string("disabled\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef _RTL837X_BANDWIDTH_H_
|
||||||
|
#define _RTL837X_BANDWIDTH_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void bandwidth_setup(void) __banked;
|
||||||
|
void bandwidth_ingress_set(uint8_t port, __xdata uint32_t bw) __banked;
|
||||||
|
void bandwidth_ingress_disable(uint8_t port) __banked;
|
||||||
|
void bandwidth_ingress_drop(uint8_t port) __banked;
|
||||||
|
void bandwidth_ingress_fc(uint8_t port) __banked;
|
||||||
|
void bandwidth_egress_set(uint8_t port, __xdata uint32_t bw) __banked;
|
||||||
|
void bandwidth_egress_disable(uint8_t port) __banked;
|
||||||
|
void bandwidth_status(uint8_t port) __banked;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -19,9 +19,19 @@
|
|||||||
#define LOOKUP_MISS_DROP_9 0x00015555
|
#define LOOKUP_MISS_DROP_9 0x00015555
|
||||||
#define LOOKUP_MISS_FLOOD 0x00000000
|
#define LOOKUP_MISS_FLOOD 0x00000000
|
||||||
|
|
||||||
// The serial buffer. Defines the command line size
|
/* Buffer for serial input, SBUF_SIZE must be power of 2 < 256
|
||||||
// Must be 2^x and <= 128
|
* Writing to this buffer is under the sole control of the serial ISR
|
||||||
#define SBUF_SIZE 128
|
* Note that key-presses such as <cursor-left> can create multiple
|
||||||
|
* keys (3 to 4) being sent via the serial line, so this must be
|
||||||
|
* sufficiently large */
|
||||||
|
#define SBUF_SIZE 16
|
||||||
|
#define SBUF_MASK (SBUF_SIZE - 1)
|
||||||
|
|
||||||
|
extern __xdata volatile uint8_t sbuf_ptr;
|
||||||
|
extern __xdata uint8_t sbuf[SBUF_SIZE];
|
||||||
|
|
||||||
|
// Define the command buffer size, Must be 2^x and <= 128
|
||||||
|
#define CMD_BUF_SIZE 128
|
||||||
|
|
||||||
// Size of the TCP Output buffer
|
// Size of the TCP Output buffer
|
||||||
#define TCP_OUTBUF_SIZE 2500
|
#define TCP_OUTBUF_SIZE 2500
|
||||||
@@ -29,6 +39,9 @@
|
|||||||
// Size of the memory area dedicated to VLAN-names
|
// Size of the memory area dedicated to VLAN-names
|
||||||
#define VLAN_NAMES_SIZE 1024
|
#define VLAN_NAMES_SIZE 1024
|
||||||
|
|
||||||
|
// Size of the flash buffer used for writing to flash, must be a multiple of the flash page size (0x100)
|
||||||
|
#define FLASH_BUF_SIZE 512
|
||||||
|
|
||||||
// For RX data, a propriatary RTL FRAME is inserted. Instead of 0x0800 for IPv4,
|
// For RX data, a propriatary RTL FRAME is inserted. Instead of 0x0800 for IPv4,
|
||||||
// the RTL_FRAME_TAG_ID is used as part of an 8-byte tag. When VLAN is activated,
|
// the RTL_FRAME_TAG_ID is used as part of an 8-byte tag. When VLAN is activated,
|
||||||
// the VLAN tag is inserted after the RTL tag
|
// the VLAN tag is inserted after the RTL tag
|
||||||
@@ -57,11 +70,15 @@ struct vlan_tag {
|
|||||||
// This is the standard size of an Ethernet frame header
|
// This is the standard size of an Ethernet frame header
|
||||||
#define ETHER_HEADER_SIZE 14
|
#define ETHER_HEADER_SIZE 14
|
||||||
|
|
||||||
|
#define DEFAULT_CONFIG_START 0x6f000
|
||||||
#define CONFIG_START 0x70000
|
#define CONFIG_START 0x70000
|
||||||
#define CONFIG_LEN 0x1000
|
#define CONFIG_LEN 0x1000
|
||||||
#define CODE0_SIZE 0x4000
|
#define CODE0_SIZE 0x4000
|
||||||
#define CODE_BANK_SIZE 0xc000
|
#define CODE_BANK_SIZE 0xc000
|
||||||
|
|
||||||
|
// Store update image after running image
|
||||||
|
#define FIRMWARE_UPLOAD_START 0x80000
|
||||||
|
|
||||||
// Constants for the circular command buffer, the size must be 2^n
|
// Constants for the circular command buffer, the size must be 2^n
|
||||||
#define CMD_HISTORY_SIZE 0x400
|
#define CMD_HISTORY_SIZE 0x400
|
||||||
#define CMD_HISTORY_MASK (CMD_HISTORY_SIZE - 1)
|
#define CMD_HISTORY_MASK (CMD_HISTORY_SIZE - 1)
|
||||||
@@ -79,10 +96,14 @@ struct flash_region_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
|
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
|
||||||
|
extern __xdata struct uip_eth_addr uip_ethaddr;
|
||||||
|
extern __xdata uint16_t rx_packet_vlan;
|
||||||
|
extern __xdata uint16_t dhcpd_vlan;
|
||||||
|
|
||||||
// Headers for calls in the common code area (HOME/BANK0)
|
// Headers for calls in the common code area (HOME/BANK0)
|
||||||
void print_string(__code char *p);
|
void print_string(__code char *p);
|
||||||
void print_long(__xdata uint32_t a);
|
void print_string_x(__xdata char *p);
|
||||||
|
void print_long(uint32_t a);
|
||||||
void print_short(uint16_t a);
|
void print_short(uint16_t a);
|
||||||
void print_byte(uint8_t a);
|
void print_byte(uint8_t a);
|
||||||
void itoa(uint8_t v);
|
void itoa(uint8_t v);
|
||||||
@@ -103,6 +124,7 @@ void print_reg(uint16_t reg);
|
|||||||
uint8_t sfp_read_reg(uint8_t slot, uint8_t reg);
|
uint8_t sfp_read_reg(uint8_t slot, uint8_t reg);
|
||||||
void reg_bit_set(uint16_t reg_addr, char bit);
|
void reg_bit_set(uint16_t reg_addr, char bit);
|
||||||
void reg_bit_clear(uint16_t reg_addr, char bit);
|
void reg_bit_clear(uint16_t reg_addr, char bit);
|
||||||
|
uint8_t reg_bit_test(uint16_t reg_addr, char bit);
|
||||||
void sfr_mask_data(uint8_t n, uint8_t mask, uint8_t set);
|
void sfr_mask_data(uint8_t n, uint8_t mask, uint8_t set);
|
||||||
void sfr_set_zero(void);
|
void sfr_set_zero(void);
|
||||||
void reset_chip(void);
|
void reset_chip(void);
|
||||||
@@ -112,8 +134,8 @@ void memset(register __xdata uint8_t *dst, register __xdata uint8_t v, register
|
|||||||
uint16_t strlen(register __code const char *s);
|
uint16_t strlen(register __code const char *s);
|
||||||
uint16_t strlen_x(register __xdata const char *s);
|
uint16_t strlen_x(register __xdata const char *s);
|
||||||
uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s);
|
uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s);
|
||||||
|
uint16_t strcpy(register __xdata uint8_t *dst, register const char *s);
|
||||||
void tcpip_output(void);
|
void tcpip_output(void);
|
||||||
void print_string_x(__xdata char *p);
|
|
||||||
uint8_t read_flash(uint8_t bank, __code uint8_t *addr);
|
uint8_t read_flash(uint8_t bank, __code uint8_t *addr);
|
||||||
void get_random_32(void);
|
void get_random_32(void);
|
||||||
void read_reg_timer(uint32_t * tmr);
|
void read_reg_timer(uint32_t * tmr);
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
__xdata uint8_t dio_enabled;
|
__xdata uint8_t dio_enabled;
|
||||||
__xdata struct flash_region_t flash_region;
|
__xdata struct flash_region_t flash_region;
|
||||||
|
|
||||||
|
__xdata uint32_t flash_size;
|
||||||
|
__xdata uint8_t flash_capacity_code;
|
||||||
|
|
||||||
// For the flash commands, see e.g. Windbond W25Q32JV datasheet
|
// For the flash commands, see e.g. Windbond W25Q32JV datasheet
|
||||||
#define CMD_WRITE_STATUS 0x01
|
#define CMD_WRITE_STATUS 0x01
|
||||||
@@ -17,8 +19,9 @@ __xdata struct flash_region_t flash_region;
|
|||||||
// Don't use command `READ 0x03`, because on many device this command can't run at maximum SPI-clock speed.
|
// Don't use command `READ 0x03`, because on many device this command can't run at maximum SPI-clock speed.
|
||||||
// Use `Fast READ 0x0b` instead!
|
// Use `Fast READ 0x0b` instead!
|
||||||
//#define CMD_READ 0x03
|
//#define CMD_READ 0x03
|
||||||
|
#define CMD_READ_STATUS 0x05
|
||||||
#define CMD_WRITE_ENABLE 0x06
|
#define CMD_WRITE_ENABLE 0x06
|
||||||
#define CMD_FREAD 0x0b
|
#define CMD_FREAD 0x0b
|
||||||
#define CMD_SECTOR_ERASE 0x20
|
#define CMD_SECTOR_ERASE 0x20
|
||||||
#define CMD_READ_SECURITY_REGS 0x48
|
#define CMD_READ_SECURITY_REGS 0x48
|
||||||
#define CMD_READ_UNIQUE_ID 0x4b
|
#define CMD_READ_UNIQUE_ID 0x4b
|
||||||
@@ -87,7 +90,7 @@ uint8_t flash_read_status(void)
|
|||||||
|
|
||||||
// setup status read command
|
// setup status read command
|
||||||
SFR_FLASH_TCONF = 0x11;
|
SFR_FLASH_TCONF = 0x11;
|
||||||
SFR_FLASH_CMD_R = 5;
|
SFR_FLASH_CMD_R = CMD_READ_STATUS;
|
||||||
|
|
||||||
// execute and wait for controller done
|
// execute and wait for controller done
|
||||||
SFR_FLASH_EXEC_GO = 1;
|
SFR_FLASH_EXEC_GO = 1;
|
||||||
@@ -119,9 +122,10 @@ void flash_read_uid(void)
|
|||||||
print_byte(SFR_FLASH_DATA8);
|
print_byte(SFR_FLASH_DATA8);
|
||||||
print_byte(SFR_FLASH_DATA16);
|
print_byte(SFR_FLASH_DATA16);
|
||||||
print_byte(SFR_FLASH_DATA24);
|
print_byte(SFR_FLASH_DATA24);
|
||||||
|
write_char(' ');
|
||||||
|
|
||||||
|
SFR_FLASH_DUMMYCYCLES = 24; // Doesn't seem to work; we get the same data as for the first transfer
|
||||||
SFR_FLASH_EXEC_GO = 1;
|
SFR_FLASH_EXEC_GO = 1;
|
||||||
SFR_FLASH_DUMMYCYCLES = 24;
|
|
||||||
while(SFR_FLASH_EXEC_BUSY);
|
while(SFR_FLASH_EXEC_BUSY);
|
||||||
|
|
||||||
print_byte(SFR_FLASH_DATA0);
|
print_byte(SFR_FLASH_DATA0);
|
||||||
@@ -132,6 +136,19 @@ void flash_read_uid(void)
|
|||||||
flash_configure_mmio();
|
flash_configure_mmio();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__code char* get_flash_size_str(void)
|
||||||
|
{
|
||||||
|
switch (flash_capacity_code) {
|
||||||
|
case 0x12: return "256 KB";
|
||||||
|
case 0x13: return "512 KB";
|
||||||
|
case 0x14: return "1 MB";
|
||||||
|
case 0x15: return "2 MB";
|
||||||
|
case 0x16: return "4 MB";
|
||||||
|
case 0x17: return "8 MB";
|
||||||
|
case 0x18: return "16 MB";
|
||||||
|
default: return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void flash_read_jedecid(void)
|
void flash_read_jedecid(void)
|
||||||
{
|
{
|
||||||
@@ -148,15 +165,16 @@ void flash_read_jedecid(void)
|
|||||||
SFR_FLASH_EXEC_GO = 1;
|
SFR_FLASH_EXEC_GO = 1;
|
||||||
while(SFR_FLASH_EXEC_BUSY);
|
while(SFR_FLASH_EXEC_BUSY);
|
||||||
|
|
||||||
|
print_string("Flash information:\n");
|
||||||
|
print_string(" Manufacturer ID: 0x");
|
||||||
print_byte(SFR_FLASH_DATA0);
|
print_byte(SFR_FLASH_DATA0);
|
||||||
|
print_string("\n Memory Type: 0x");
|
||||||
print_byte(SFR_FLASH_DATA8);
|
print_byte(SFR_FLASH_DATA8);
|
||||||
print_byte(SFR_FLASH_DATA16);
|
print_string("\n Capacity: 0x");
|
||||||
print_byte(SFR_FLASH_DATA24);
|
flash_capacity_code = SFR_FLASH_DATA16;
|
||||||
|
flash_size = 1UL << flash_capacity_code;
|
||||||
// Reset slow read mode
|
print_byte(flash_capacity_code);
|
||||||
SFR_FLASH_MODEB = 0x0;
|
print_string(" = "); print_string(get_flash_size_str()); write_char('\n');
|
||||||
SFR_FLASH_CMD_R = CMD_FREAD;
|
|
||||||
SFR_FLASH_DUMMYCYCLES = 8;
|
|
||||||
|
|
||||||
flash_configure_mmio();
|
flash_configure_mmio();
|
||||||
}
|
}
|
||||||
@@ -188,51 +206,6 @@ void flash_write_enable(void)
|
|||||||
} while (!(status & 0x2));
|
} while (!(status & 0x2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void flash_dump(uint8_t len)
|
|
||||||
{
|
|
||||||
short status;
|
|
||||||
do {
|
|
||||||
status = flash_read_status();
|
|
||||||
print_short(status);
|
|
||||||
} while (status & 0x1);
|
|
||||||
|
|
||||||
// Set fast read mode
|
|
||||||
if (dio_enabled) {
|
|
||||||
SFR_FLASH_MODEB = 0x18;
|
|
||||||
SFR_FLASH_CMD_R = CMD_FREAD_DIO;
|
|
||||||
SFR_FLASH_DUMMYCYCLES = 4;
|
|
||||||
} else {
|
|
||||||
SFR_FLASH_MODEB = 0x0;
|
|
||||||
SFR_FLASH_CMD_R = CMD_FREAD; // Fast read
|
|
||||||
SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks after read?
|
|
||||||
}
|
|
||||||
// Read 4 bytes
|
|
||||||
SFR_FLASH_TCONF = 4;
|
|
||||||
while (len) {
|
|
||||||
SFR_FLASH_ADDR16 = flash_region.addr >> 16;
|
|
||||||
SFR_FLASH_ADDR8 = flash_region.addr >> 8;
|
|
||||||
SFR_FLASH_ADDR0 = flash_region.addr;
|
|
||||||
flash_region.addr += 4;
|
|
||||||
|
|
||||||
SFR_FLASH_EXEC_GO = 1;
|
|
||||||
while(SFR_FLASH_EXEC_BUSY);
|
|
||||||
|
|
||||||
print_short(SFR_FLASH_DATA0);
|
|
||||||
if (len == 1)
|
|
||||||
return;
|
|
||||||
print_short(SFR_FLASH_DATA8);
|
|
||||||
if (len == 2)
|
|
||||||
return;
|
|
||||||
print_short(SFR_FLASH_DATA16);
|
|
||||||
if (len == 3)
|
|
||||||
return;
|
|
||||||
print_short(SFR_FLASH_DATA24);
|
|
||||||
|
|
||||||
len -= 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads bulk data of length len from the flash memory starging at address src
|
* Reads bulk data of length len from the flash memory starging at address src
|
||||||
* and writes the data into a buffer pointed to by dst in XMEM
|
* and writes the data into a buffer pointed to by dst in XMEM
|
||||||
@@ -315,7 +288,7 @@ void flash_read_security(void)
|
|||||||
if (flash_region.len == 3)
|
if (flash_region.len == 3)
|
||||||
break;
|
break;
|
||||||
print_byte(SFR_FLASH_DATA24);
|
print_byte(SFR_FLASH_DATA24);
|
||||||
|
write_char(' ');
|
||||||
flash_region.len -= 4;
|
flash_region.len -= 4;
|
||||||
} while(flash_region.len);
|
} while(flash_region.len);
|
||||||
|
|
||||||
|
|||||||
@@ -10,4 +10,6 @@ void flash_read_security(void);
|
|||||||
void flash_sector_erase(void);
|
void flash_sector_erase(void);
|
||||||
void flash_read_bulk(__xdata uint8_t *dst);
|
void flash_read_bulk(__xdata uint8_t *dst);
|
||||||
void flash_write_bytes(__xdata uint8_t *ptr);
|
void flash_write_bytes(__xdata uint8_t *ptr);
|
||||||
|
__code char* get_flash_size_str(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ extern __code uint16_t bit_mask[16];
|
|||||||
extern __code const struct machine machine;
|
extern __code const struct machine machine;
|
||||||
extern __xdata struct machine_runtime machine_detected;
|
extern __xdata struct machine_runtime machine_detected;
|
||||||
|
|
||||||
|
__xdata struct phy_settings phy_settings;
|
||||||
|
|
||||||
// SDS-settings for RTL8224 first SerDes which is connected to the RTL837x-SOC.
|
// SDS-settings for RTL8224 first SerDes which is connected to the RTL837x-SOC.
|
||||||
// Array contrains register-value, and SDS-CMD, which already encodes (sds_index, page, reg).
|
// Array contrains register-value, and SDS-CMD, which already encodes (sds_index, page, reg).
|
||||||
// This array is used in phy_config_8224().
|
// This array is used in phy_config_8224().
|
||||||
@@ -186,106 +188,151 @@ void phy_config_8224(void) __banked
|
|||||||
* See e.g. RTL8221B datasheet
|
* See e.g. RTL8221B datasheet
|
||||||
* duplex: 0: half, 1: full, 2: both
|
* duplex: 0: half, 1: full, 2: both
|
||||||
*/
|
*/
|
||||||
void phy_set_speed(uint8_t port, uint8_t speed, uint8_t duplex) __banked
|
void phy_set_speed(void) __banked
|
||||||
{
|
{
|
||||||
uint16_t v;
|
uint16_t v;
|
||||||
phy_read(port, PHY_MMD31, 0xa610);
|
|
||||||
|
print_string("Setting port "); write_char(machine.log_to_phys_port[phy_settings.port] + '0');
|
||||||
|
if (phy_settings.speed == PHY_OFF) {
|
||||||
|
print_string(" to disabled");
|
||||||
|
} else {
|
||||||
|
print_string(" to speed ");
|
||||||
|
switch(phy_settings.speed) {
|
||||||
|
case PHY_SPEED_AUTO:
|
||||||
|
print_string("auto");
|
||||||
|
break;
|
||||||
|
case PHY_SPEED_10M:
|
||||||
|
print_string("10M");
|
||||||
|
if (phy_settings.duplex)
|
||||||
|
print_string(" full duplex");
|
||||||
|
else
|
||||||
|
print_string(" half duplex");
|
||||||
|
break;
|
||||||
|
case PHY_SPEED_100M:
|
||||||
|
print_string("100M");
|
||||||
|
if (phy_settings.duplex)
|
||||||
|
print_string(" full duplex");
|
||||||
|
else
|
||||||
|
print_string(" half duplex");
|
||||||
|
break;
|
||||||
|
case PHY_SPEED_1G:
|
||||||
|
print_string("1G");
|
||||||
|
break;
|
||||||
|
case PHY_SPEED_2G5:
|
||||||
|
print_string("2G5");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print_string("UNKNOWN");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write_char('\n');
|
||||||
|
|
||||||
|
phy_read(phy_settings.port, PHY_MMD31, 0xa610);
|
||||||
v = SFR_DATA_U16;
|
v = SFR_DATA_U16;
|
||||||
if (speed == PHY_OFF) {
|
if (phy_settings.speed == PHY_OFF) {
|
||||||
phy_write(port, PHY_MMD31, 0xa610, v | 0x0800);
|
phy_write(phy_settings.port, PHY_MMD31, 0xa610, v | 0x0800);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Port is on, make sure of it:
|
// Port is on, make sure of it:
|
||||||
if (v & 0x0800)
|
if (v & 0x0800)
|
||||||
phy_write(port, PHY_MMD31, 0xa610, v & 0xf7ff);
|
phy_write(phy_settings.port, PHY_MMD31, 0xa610, v & 0xf7ff);
|
||||||
|
|
||||||
if (speed == PHY_SPEED_AUTO) {
|
if (phy_settings.speed == PHY_SPEED_AUTO) {
|
||||||
// AN Advertisement Register (MMD 7.0x0010)
|
// AN Advertisement Register (MMD 7.0x0010)
|
||||||
// bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
|
// bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x15e1);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x15e1);
|
||||||
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
|
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
|
||||||
// bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD
|
// bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081);
|
||||||
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
|
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
|
||||||
phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200); // Loop timing enabled
|
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200); // Loop timing enabled
|
||||||
phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x3200); // Restart AN
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x3200); // Restart AN
|
||||||
} else {
|
} else {
|
||||||
// AN Control Register (MMD 7.0x0000)
|
// AN Control Register (MMD 7.0x0000)
|
||||||
phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13)
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13)
|
||||||
if (speed == PHY_SPEED_10M) {
|
if (phy_settings.speed == PHY_SPEED_10M) {
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001);
|
||||||
if (!duplex)
|
if (!phy_settings.duplex)
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1421);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1421);
|
||||||
else if (duplex == 1)
|
else if (phy_settings.duplex == 1)
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1441);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1441);
|
||||||
else
|
else
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1461);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1461);
|
||||||
phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
|
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
|
||||||
} else if (speed == PHY_SPEED_100M) {
|
} else if (phy_settings.speed == PHY_SPEED_100M) {
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001);
|
||||||
if (!duplex)
|
if (!phy_settings.duplex)
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1481);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1481);
|
||||||
if (duplex == 1)
|
if (phy_settings.duplex == 1)
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1501);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1501);
|
||||||
else
|
else
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1581);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1581);
|
||||||
phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
|
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
|
||||||
} else {
|
} else {
|
||||||
// AN Advertisement Register (MMD 7.0x0010)
|
// AN Advertisement Register (MMD 7.0x0010)
|
||||||
// bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
|
// bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1001);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1001);
|
||||||
if (speed == PHY_SPEED_1G) {
|
if (phy_settings.speed == PHY_SPEED_1G) {
|
||||||
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
|
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
|
||||||
// bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed
|
// bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001);
|
||||||
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
|
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
|
||||||
phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200);
|
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200);
|
||||||
} else if (speed == PHY_SPEED_2G5) {
|
} else if (phy_settings.speed == PHY_SPEED_2G5) {
|
||||||
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
|
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
|
||||||
// bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed
|
// bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed
|
||||||
phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081);
|
||||||
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
|
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
|
||||||
phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
|
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x3000); // Enable AN
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x3000); // Enable AN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void phy_set_duplex(uint8_t port, uint8_t fullduplex) __banked
|
void phy_set_duplex(void) __banked
|
||||||
{
|
{
|
||||||
uint16_t v;
|
uint16_t v;
|
||||||
phy_read(port, PHY_MMD31, PHY_ANEG_CTRL);
|
|
||||||
|
print_string("Setting port "); write_char(machine.log_to_phys_port[phy_settings.port] + '0');
|
||||||
|
if (phy_settings.duplex)
|
||||||
|
print_string(" to full duplex");
|
||||||
|
else
|
||||||
|
print_string(" to half duplex");
|
||||||
|
write_char('\n');
|
||||||
|
|
||||||
|
phy_read(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL);
|
||||||
v = SFR_DATA_U16;
|
v = SFR_DATA_U16;
|
||||||
if (!(v & 0x1000)) { // AN disabled, we are in forced mode
|
if (!(v & 0x1000)) { // AN disabled, we are in forced mode
|
||||||
phy_read(port, PHY_MMD31, PHY_MMD31_FEDCR);
|
phy_read(phy_settings.port, PHY_MMD31, PHY_MMD31_FEDCR);
|
||||||
v = SFR_DATA_U16;
|
v = SFR_DATA_U16;
|
||||||
if (fullduplex)
|
if (phy_settings.duplex)
|
||||||
v |= 0x0100;
|
v |= 0x0100;
|
||||||
else
|
else
|
||||||
v &= 0xfeff;
|
v &= 0xfeff;
|
||||||
phy_write(port, PHY_MMD31, PHY_MMD31_FEDCR, v);
|
phy_write(phy_settings.port, PHY_MMD31, PHY_MMD31_FEDCR, v);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Disable AN
|
// Disable AN
|
||||||
phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x2000);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x2000);
|
||||||
phy_read(port, PHY_MMD_AN, PHY_ANEG_ADV);
|
phy_read(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV);
|
||||||
v = SFR_DATA_U16;
|
v = SFR_DATA_U16;
|
||||||
if (v & 0x0060) {
|
if (v & 0x0060) {
|
||||||
if (fullduplex)
|
if (phy_settings.duplex)
|
||||||
phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffbf, 0x0040);
|
phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffbf, 0x0040);
|
||||||
else
|
else
|
||||||
phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffdf, 0x0020);
|
phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffdf, 0x0020);
|
||||||
}
|
}
|
||||||
if (v & 0x0180) {
|
if (v & 0x0180) {
|
||||||
if (fullduplex)
|
if (phy_settings.duplex)
|
||||||
phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xfeff, 0x0100);
|
phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xfeff, 0x0100);
|
||||||
else
|
else
|
||||||
phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xff7f, 0x0080);
|
phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xff7f, 0x0080);
|
||||||
}
|
}
|
||||||
// Restart AN
|
// Restart AN
|
||||||
phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x3000);
|
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -327,7 +374,7 @@ void phy_show(uint8_t port) __banked
|
|||||||
else
|
else
|
||||||
print_string(" half duplex");
|
print_string(" half duplex");
|
||||||
|
|
||||||
phy_read(port, PHY_MMD31, PHY_ANEG_CTRL);
|
phy_read(port, PHY_MMD_AN, PHY_ANEG_CTRL);
|
||||||
v = SFR_DATA_U16;
|
v = SFR_DATA_U16;
|
||||||
if (!(v & 0x1000)) { // AN disabled, we are in forced mode
|
if (!(v & 0x1000)) { // AN disabled, we are in forced mode
|
||||||
phy_read(port, PHY_MMD_PMAPMD, 0);
|
phy_read(port, PHY_MMD_PMAPMD, 0);
|
||||||
|
|||||||
@@ -10,11 +10,19 @@
|
|||||||
#define PHY_SPEED_AUTO 0x10
|
#define PHY_SPEED_AUTO 0x10
|
||||||
#define PHY_OFF 0xff
|
#define PHY_OFF 0xff
|
||||||
|
|
||||||
|
struct phy_settings {
|
||||||
|
uint8_t duplex;
|
||||||
|
uint8_t port;
|
||||||
|
uint8_t speed;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern __xdata struct phy_settings phy_settings;
|
||||||
|
|
||||||
void rtl8224_phy_enable(void) __banked;
|
void rtl8224_phy_enable(void) __banked;
|
||||||
void phy_config(uint8_t phy) __banked;
|
void phy_config(uint8_t phy) __banked;
|
||||||
void phy_config_8224(void) __banked;
|
void phy_config_8224(void) __banked;
|
||||||
void phy_set_speed(uint8_t port, uint8_t speed, uint8_t duplex) __banked;
|
void phy_set_speed(void) __banked;
|
||||||
void phy_set_duplex(uint8_t port, uint8_t fullduplex) __banked;
|
void phy_set_duplex(void) __banked;
|
||||||
void phy_show(uint8_t port) __banked;
|
void phy_show(uint8_t port) __banked;
|
||||||
void phy_reset(uint8_t port) __banked;
|
void phy_reset(uint8_t port) __banked;
|
||||||
void rtl8224_read_reg_u16(uint16_t reg) __banked;
|
void rtl8224_read_reg_u16(uint16_t reg) __banked;
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ extern __xdata struct machine_runtime machine_detected;
|
|||||||
|
|
||||||
__xdata uint32_t l2_head;
|
__xdata uint32_t l2_head;
|
||||||
|
|
||||||
|
__xdata struct vlan_settings vlan_settings;
|
||||||
|
|
||||||
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked
|
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked
|
||||||
{
|
{
|
||||||
print_string("\nport_mirror_set called \n");
|
print_string("\nport_mirror_set called \n");
|
||||||
@@ -46,7 +48,7 @@ void port_mirror_del(void) __banked
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void port_ingress_filter(register uint8_t port, uint8_t type) __banked
|
void port_ingress_filter(__xdata uint8_t port, __xdata uint8_t type) __banked
|
||||||
{
|
{
|
||||||
if (type & 0x1)
|
if (type & 0x1)
|
||||||
reg_bit_set(RTL837x_REG_INGRESS, port << 1);
|
reg_bit_set(RTL837x_REG_INGRESS, port << 1);
|
||||||
@@ -121,27 +123,31 @@ __xdata uint16_t vlan_name(register uint16_t vlan) __banked
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* Create a VLAN
|
||||||
|
* The arguments are passed in global structure vlan_settings
|
||||||
* A member that is not tagged, is untagged
|
* A member that is not tagged, is untagged
|
||||||
*/
|
*/
|
||||||
void vlan_create(register uint16_t vlan, register uint16_t members, register uint16_t tagged) __banked
|
void vlan_create(void) __banked
|
||||||
{
|
{
|
||||||
// For now, the CPU-port is always a tagged member:
|
// For now, the CPU-port is always a tagged member:
|
||||||
members |= 0x0200; // Set 10th bit
|
vlan_settings.members |= 0x0200; // Set 10th bit
|
||||||
tagged |= 0x0200;
|
vlan_settings.tagged |= 0x0200;
|
||||||
print_string("\nvlan_create called\nvlan: "); print_short(vlan);
|
|
||||||
print_string(", members: "); print_short(members);
|
print_string("\nvlan_create called\nvlan: "); print_short(vlan_settings.vlan);
|
||||||
print_string(", tagged: "); print_short(tagged); write_char('\n');
|
print_string(", members: "); print_short(vlan_settings.members);
|
||||||
|
print_string(", tagged: "); print_short(vlan_settings.tagged); write_char('\n');
|
||||||
|
|
||||||
|
uint16_t a = (~vlan_settings.members) ^ vlan_settings.tagged ^ vlan_settings.members;
|
||||||
|
|
||||||
uint16_t a = (~members) ^ tagged ^ members;
|
|
||||||
// On RTL8372, port-bits 0-2 must be 0, although they are not members
|
// On RTL8372, port-bits 0-2 must be 0, although they are not members
|
||||||
if (!machine_detected.isRTL8373) {
|
if (!machine_detected.isRTL8373) {
|
||||||
a &= 0x1f8;
|
a &= 0x1f8;
|
||||||
tagged &= 0x3f8;
|
vlan_settings.tagged &= 0x3f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize VLAN table with VLAN 1
|
// Initialize VLAN table with VLAN 1
|
||||||
REG_WRITE(RTL837x_TBL_DATA_IN_A, 0x02, (a >> 6) & 0x0f, (a << 2) | (members >> 8), members);
|
REG_WRITE(RTL837x_TBL_DATA_IN_A, 0x02, (a >> 6) & 0x0f, (a << 2) | (vlan_settings.members >> 8), vlan_settings.members);
|
||||||
REG_WRITE(RTL837X_TBL_CTRL, vlan >> 8, vlan, TBL_VLAN, TBL_WRITE | TBL_EXECUTE);
|
REG_WRITE(RTL837X_TBL_CTRL, vlan_settings.vlan >> 8, vlan_settings.vlan, TBL_VLAN, TBL_WRITE | TBL_EXECUTE);
|
||||||
do {
|
do {
|
||||||
reg_read_m(RTL837X_TBL_CTRL);
|
reg_read_m(RTL837X_TBL_CTRL);
|
||||||
} while (sfr_data[3] & TBL_EXECUTE);
|
} while (sfr_data[3] & TBL_EXECUTE);
|
||||||
@@ -363,15 +369,28 @@ void port_stats_print(void) __banked
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < 8)
|
uint8_t b = 0;
|
||||||
reg_read_m(RTL837X_REG_LINKS);
|
|
||||||
|
// Determine link state
|
||||||
|
reg_read_m(RTL837X_REG_LINKS_STS);
|
||||||
|
if(!((sfr_data[(i / 8) + 1] >> ( i % 8 ) & 1)))
|
||||||
|
{
|
||||||
|
b = 99;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
reg_read_m(RTL837X_REG_LINKS_89);
|
{
|
||||||
uint8_t b = sfr_data[3 - ((i & 7) >> 1)];
|
if (i < 8)
|
||||||
b = (i & 1) ? b >> 4 : b & 0xf;
|
reg_read_m(RTL837X_REG_LINKS);
|
||||||
|
else
|
||||||
|
reg_read_m(RTL837X_REG_LINKS_89);
|
||||||
|
|
||||||
|
b = sfr_data[3 - ((i & 7) >> 1)];
|
||||||
|
b = (i & 1) ? b >> 4 : b & 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
switch (b) {
|
switch (b) {
|
||||||
case 0:
|
case 0:
|
||||||
print_string("Down\t");
|
print_string("10M\t");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
print_string("100M\t");
|
print_string("100M\t");
|
||||||
@@ -385,6 +404,9 @@ void port_stats_print(void) __banked
|
|||||||
case 5:
|
case 5:
|
||||||
print_string("2.5G\t");
|
print_string("2.5G\t");
|
||||||
break;
|
break;
|
||||||
|
case 99:
|
||||||
|
print_string("Down\t");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
print_string("Up\t");
|
print_string("Up\t");
|
||||||
break;
|
break;
|
||||||
@@ -422,17 +444,49 @@ uint16_t port_isolation_get(register uint8_t port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void port_eee_enable(uint8_t port) __banked
|
void port_eee_enable(__xdata uint8_t port,__xdata uint8_t speed) __banked
|
||||||
{
|
{
|
||||||
if (machine.is_sfp[port])
|
|
||||||
return;
|
|
||||||
|
|
||||||
REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000 | EEE_2G5);
|
if (machine.is_sfp[port])
|
||||||
// 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);
|
print_string("EEE can't be enabled for SFP port "); print_byte(port); print_string("\n");
|
||||||
// Enable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
|
return;
|
||||||
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, PHY_EEE_BIT_2G5);
|
}
|
||||||
phy_reset(port);
|
|
||||||
|
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) {
|
||||||
|
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) {
|
||||||
|
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
|
||||||
|
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_1G | PHY_EEE_BIT_100M);
|
||||||
|
if (!(speed & EEE_NORESET))
|
||||||
|
phy_reset(port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((speed & (EEE_100 | EEE_1000 | EEE_2G5)) == 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
|
||||||
|
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, PHY_EEE_BIT_2G5);
|
||||||
|
if (!(speed & EEE_NORESET))
|
||||||
|
phy_reset(port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -506,10 +560,10 @@ void port_eee_status(uint8_t port) __banked
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void port_eee_enable_all(void) __banked
|
void port_eee_enable_all(__xdata uint8_t speed) __banked
|
||||||
{
|
{
|
||||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||||
port_eee_enable(i);
|
port_eee_enable(i, speed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,14 @@
|
|||||||
reg_read_m(RTL837X_STAT_GET); \
|
reg_read_m(RTL837X_STAT_GET); \
|
||||||
} while (sfr_data[3] & 0x1);
|
} while (sfr_data[3] & 0x1);
|
||||||
|
|
||||||
|
struct vlan_settings {
|
||||||
|
uint16_t vlan;
|
||||||
|
uint16_t members;
|
||||||
|
uint16_t tagged;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern __xdata struct vlan_settings vlan_settings;
|
||||||
|
|
||||||
uint8_t port_l2_forget(void) __banked;
|
uint8_t port_l2_forget(void) __banked;
|
||||||
void port_l2_learned(void) __banked;
|
void port_l2_learned(void) __banked;
|
||||||
void port_stats_print(void) __banked;
|
void port_stats_print(void) __banked;
|
||||||
@@ -20,18 +28,18 @@ int8_t vlan_get(register uint16_t vlan) __banked;
|
|||||||
__xdata uint16_t vlan_name(register uint16_t vlan) __banked;
|
__xdata uint16_t vlan_name(register uint16_t vlan) __banked;
|
||||||
void vlan_setup(void) __banked;
|
void vlan_setup(void) __banked;
|
||||||
void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked;
|
void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked;
|
||||||
void vlan_create(register uint16_t vlan, register uint16_t members, register uint16_t tagged) __banked;
|
void vlan_create(void) __banked;
|
||||||
void vlan_delete(uint16_t vlan) __banked;
|
void vlan_delete(uint16_t vlan) __banked;
|
||||||
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked;
|
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked;
|
||||||
void port_mirror_del(void) __banked;
|
void port_mirror_del(void) __banked;
|
||||||
void port_ingress_filter(register uint8_t port, uint8_t type) __banked;
|
void port_ingress_filter(__xdata uint8_t port, __xdata uint8_t type) __banked;
|
||||||
void port_l2_setup(void) __banked;
|
void port_l2_setup(void) __banked;
|
||||||
void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked;
|
void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked;
|
||||||
void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash) __banked;
|
void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash) __banked;
|
||||||
void port_eee_enable_all(void) __banked;
|
void port_eee_enable_all(__xdata uint8_t speed) __banked;
|
||||||
void port_eee_disable_all(void) __banked;
|
void port_eee_disable_all(void) __banked;
|
||||||
void port_eee_status_all(void) __banked;
|
void port_eee_status_all(void) __banked;
|
||||||
void port_eee_enable(uint8_t port) __banked;
|
void port_eee_enable(__xdata uint8_t port, __xdata uint8_t speed) __banked;
|
||||||
void port_eee_disable(uint8_t port) __banked;
|
void port_eee_disable(uint8_t port) __banked;
|
||||||
void port_eee_status(uint8_t port) __banked;
|
void port_eee_status(uint8_t port) __banked;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
#define _RTL837X_REGS_H_
|
#define _RTL837X_REGS_H_
|
||||||
|
|
||||||
#define RTL837X_REG_CHIP_ID 0x0004
|
#define RTL837X_REG_CHIP_ID 0x0004
|
||||||
#define RTL837X_REG_CHIP_INFO 0x000c
|
#define RTL837X_REG_CHIP_INFO 0x000c
|
||||||
|
#define RTL837X_REG_CHIP_UUID 0x0010
|
||||||
|
#define RTL837X_REG_CHIP_LOT_NO 0x0014
|
||||||
#define RTL837X_REG_RESET 0x0024
|
#define RTL837X_REG_RESET 0x0024
|
||||||
#define RESET_SOC_BIT 0
|
#define RESET_SOC_BIT 0
|
||||||
#define RESET_NIC_BIT 2
|
#define RESET_NIC_BIT 2
|
||||||
@@ -78,6 +80,8 @@
|
|||||||
|
|
||||||
#define RTL837X_REG_LINKS 0x63f0
|
#define RTL837X_REG_LINKS 0x63f0
|
||||||
#define RTL837X_REG_LINKS_89 0x63f4
|
#define RTL837X_REG_LINKS_89 0x63f4
|
||||||
|
#define RTL837X_REG_LINKS_STS 0x63E8
|
||||||
|
|
||||||
/* Each nibble encodes the link state of a port.
|
/* Each nibble encodes the link state of a port.
|
||||||
Port 0 appears to be the CPU port
|
Port 0 appears to be the CPU port
|
||||||
The RTL8372 serves ports 4-7, port 3 is the RTL8221
|
The RTL8372 serves ports 4-7, port 3 is the RTL8221
|
||||||
@@ -271,6 +275,7 @@
|
|||||||
#define EEE_100 0x01
|
#define EEE_100 0x01
|
||||||
#define EEE_1000 0x04
|
#define EEE_1000 0x04
|
||||||
#define EEE_2G5 0x10
|
#define EEE_2G5 0x10
|
||||||
|
#define EEE_NORESET 0x80
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RANDOM
|
* RANDOM
|
||||||
@@ -280,6 +285,25 @@
|
|||||||
#define RTL837X_RAND_NUM0 0x107C
|
#define RTL837X_RAND_NUM0 0x107C
|
||||||
#define RTL837X_RAND_NUM1 0x1080
|
#define RTL837X_RAND_NUM1 0x1080
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bandwidth control
|
||||||
|
*/
|
||||||
|
#define RTL837X_IGBW_CTRL 0x4c10
|
||||||
|
#define IGBW_INC_BYPASS_PKT 0x100
|
||||||
|
#define IGBW_INC_IFG 0x80
|
||||||
|
#define IGBW_ADM_DHCP 0x20
|
||||||
|
#define IGBW_ADM_ARPREQ 0x10
|
||||||
|
#define IGBW_ADM_RMA 0x08
|
||||||
|
#define IGBW_ADM_BPDU 0x04
|
||||||
|
#define IGBW_ADM_RTKPKT 0x02
|
||||||
|
#define IGBW_ADM_IGMP 0x01
|
||||||
|
#define RTL837X_IGBW_PORT_CTRL 0x4C18
|
||||||
|
#define RTL837X_IGBW_PORT_FC_CTRL 0x4C8C
|
||||||
|
#define RTL837X_EGBW_PORT_CTRL 0x1c34
|
||||||
|
#define RTL837X_EGBW_CTRL 0x447c
|
||||||
|
#define EGBW_INC_IFG 0x02
|
||||||
|
#define EGBW_CPUMODE 0x01
|
||||||
|
|
||||||
#ifdef REGDBG
|
#ifdef REGDBG
|
||||||
|
|
||||||
#define REG_SET(r, v) SFR_DATA_24 = (((uint32_t)v) >> 24) & 0xff; \
|
#define REG_SET(r, v) SFR_DATA_24 = (((uint32_t)v) >> 24) & 0xff; \
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ __sfr __at(0x91) EXIF;
|
|||||||
__sfr __at(0xf8) EIP;
|
__sfr __at(0xf8) EIP;
|
||||||
__sbit __at(0xf9) PX3;
|
__sbit __at(0xf9) PX3;
|
||||||
|
|
||||||
|
/* MPAGE page (sdcc _XPAGE) register for "movx @Ri" */
|
||||||
|
__sfr __at(0x92) _XPAGE; /* _XPAGE is used by sdcc in xstack mode */
|
||||||
|
__sfr __at(0x92) MPAGE;
|
||||||
/* SFR Bank control register: 0x0-3f. A value of 0 is bank 1 */
|
/* SFR Bank control register: 0x0-3f. A value of 0 is bank 1 */
|
||||||
__sfr __at(0x96) PSBANK;
|
__sfr __at(0x96) PSBANK;
|
||||||
// SFR used to store return bank for trampoline
|
// SFR used to store return bank for trampoline
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
extern __code struct machine machine;
|
extern __code struct machine machine;
|
||||||
extern __xdata uint8_t sfr_data[4];
|
extern __xdata uint8_t sfr_data[4];
|
||||||
|
|
||||||
extern __code struct uip_eth_addr uip_ethaddr;
|
extern __xdata struct uip_eth_addr uip_ethaddr;
|
||||||
|
|
||||||
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2];
|
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2];
|
||||||
|
|
||||||
@@ -164,9 +164,9 @@ void stp_cnf_send(uint8_t port)
|
|||||||
STP_O->bpdu_type = 0x00; // Config
|
STP_O->bpdu_type = 0x00; // Config
|
||||||
STP_O->flags = 0x81;
|
STP_O->flags = 0x81;
|
||||||
|
|
||||||
memcpyc(STP_O->src_addr, uip_ethaddr.addr, 6);
|
memcpy(STP_O->src_addr, uip_ethaddr.addr, 6);
|
||||||
memcpy(STP_O->root.mac, root_bridge.mac, 6);
|
memcpy(STP_O->root.mac, root_bridge.mac, 6);
|
||||||
memcpyc(STP_O->bridge.mac, uip_ethaddr.addr, 6);
|
memcpy(STP_O->bridge.mac, uip_ethaddr.addr, 6);
|
||||||
|
|
||||||
STP_O->root.prio = root_bridge.prio;
|
STP_O->root.prio = root_bridge.prio;
|
||||||
STP_O->root.ext = 0x00;
|
STP_O->root.ext = 0x00;
|
||||||
@@ -221,7 +221,7 @@ void stp_setup(void) __banked
|
|||||||
|
|
||||||
root_bridge.prio = 0x80; // This corresponds to 32768
|
root_bridge.prio = 0x80; // This corresponds to 32768
|
||||||
root_bridge.ext = 0x00;
|
root_bridge.ext = 0x00;
|
||||||
memcpyc(root_bridge.mac, uip_ethaddr.addr, 6);
|
memcpy(root_bridge.mac, uip_ethaddr.addr, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,25 +14,23 @@
|
|||||||
#include "rtl837x_stp.h"
|
#include "rtl837x_stp.h"
|
||||||
#include "rtl837x_igmp.h"
|
#include "rtl837x_igmp.h"
|
||||||
#include "rtl837x_leds.h"
|
#include "rtl837x_leds.h"
|
||||||
|
#include "rtl837x_bandwidth.h"
|
||||||
#include "dhcp.h"
|
#include "dhcp.h"
|
||||||
#include "cmd_parser.h"
|
#include "cmd_parser.h"
|
||||||
|
#include "cmd_editor.h"
|
||||||
#include "uip/uipopt.h"
|
#include "uip/uipopt.h"
|
||||||
#include "uip/uip.h"
|
#include "uip/uip.h"
|
||||||
#include "uip/uip_arp.h"
|
#include "uip/uip_arp.h"
|
||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "phy.h"
|
#include "phy.h"
|
||||||
|
|
||||||
|
|
||||||
extern __code const struct machine machine;
|
extern __code const struct machine machine;
|
||||||
|
extern __xdata uint32_t flash_size;
|
||||||
|
|
||||||
extern __xdata uint16_t crc_value;
|
extern __xdata uint16_t crc_value;
|
||||||
__xdata uint8_t crc_testbytes[10];
|
|
||||||
__xdata struct machine_runtime machine_detected;
|
__xdata struct machine_runtime machine_detected;
|
||||||
void crc16(__xdata uint8_t *v) __naked;
|
void crc16(__xdata uint8_t *v) __naked;
|
||||||
|
|
||||||
// Upload Firmware to 1M
|
|
||||||
#define FIRMWARE_UPLOAD_START 0x100000
|
|
||||||
|
|
||||||
// See setup_serial_timer1() for valid baudrate settings!
|
// See setup_serial_timer1() for valid baudrate settings!
|
||||||
#define SERIAL_BAUD_RATE 115200
|
#define SERIAL_BAUD_RATE 115200
|
||||||
|
|
||||||
@@ -77,10 +75,11 @@ void crc16(__xdata uint8_t *v) __naked;
|
|||||||
__xdata uint8_t idle_ready;
|
__xdata uint8_t idle_ready;
|
||||||
|
|
||||||
__code uint8_t ownIP[] = { 192, 168, 2, 2 };
|
__code uint8_t ownIP[] = { 192, 168, 2, 2 };
|
||||||
__code struct uip_eth_addr uip_ethaddr = {{ 0x1c, 0x2a, 0xa3, 0x23, 0x00, 0x02 }};
|
|
||||||
__code uint8_t gatewayIP[] = { 192, 168, 2, 22};
|
__code uint8_t gatewayIP[] = { 192, 168, 2, 22};
|
||||||
__code uint8_t netmask[] = { 255, 255, 255, 0};
|
__code uint8_t netmask[] = { 255, 255, 255, 0};
|
||||||
|
|
||||||
|
__xdata struct uip_eth_addr uip_ethaddr;
|
||||||
|
|
||||||
volatile __xdata uint32_t ticks;
|
volatile __xdata uint32_t ticks;
|
||||||
volatile __xdata uint8_t sec_counter;
|
volatile __xdata uint8_t sec_counter;
|
||||||
volatile __xdata uint16_t sleep_ticks;
|
volatile __xdata uint16_t sleep_ticks;
|
||||||
@@ -89,10 +88,13 @@ extern __xdata struct dhcp_state dhcp_state;
|
|||||||
|
|
||||||
#define STP_TICK_DIVIDER 3
|
#define STP_TICK_DIVIDER 3
|
||||||
|
|
||||||
|
/* Buffer for serial input, SBUF_SIZE must be power of 2 < 256
|
||||||
// Buffer for serial input, SBUF_SIZE must be power of 2 < 256
|
* Writing to this buffer is under the sole control of the serial ISR
|
||||||
|
* Note that key-presses such as <cursor-left> can create multiple
|
||||||
|
* keys being sent via the serial line */
|
||||||
__xdata volatile uint8_t sbuf_ptr;
|
__xdata volatile uint8_t sbuf_ptr;
|
||||||
__xdata uint8_t sbuf[SBUF_SIZE];
|
__xdata uint8_t sbuf[SBUF_SIZE];
|
||||||
|
|
||||||
__xdata uint8_t sfr_data[4];
|
__xdata uint8_t sfr_data[4];
|
||||||
|
|
||||||
extern __xdata uint8_t gpio_last_value[8];
|
extern __xdata uint8_t gpio_last_value[8];
|
||||||
@@ -102,7 +104,7 @@ extern __xdata struct flash_region_t flash_region;
|
|||||||
__code uint8_t * __code greeting = "\nA minimal prompt to explore the RTL8372:\n";
|
__code uint8_t * __code greeting = "\nA minimal prompt to explore the RTL8372:\n";
|
||||||
__code uint8_t * __code hex = "0123456789abcdef";
|
__code uint8_t * __code hex = "0123456789abcdef";
|
||||||
|
|
||||||
__xdata uint8_t flash_buf[512];
|
__xdata uint8_t flash_buf[FLASH_BUF_SIZE];
|
||||||
|
|
||||||
// NIC buffers for packet RX/TX
|
// NIC buffers for packet RX/TX
|
||||||
__xdata uint8_t rx_headers[16]; // Packet header(s) on RX
|
__xdata uint8_t rx_headers[16]; // Packet header(s) on RX
|
||||||
@@ -127,6 +129,8 @@ __xdata char sfp_module_vendor[2][17];
|
|||||||
__xdata char sfp_module_model[2][17];
|
__xdata char sfp_module_model[2][17];
|
||||||
__xdata char sfp_module_serial[2][17];
|
__xdata char sfp_module_serial[2][17];
|
||||||
__xdata uint8_t sfp_options[2];
|
__xdata uint8_t sfp_options[2];
|
||||||
|
__xdata bool button_last;
|
||||||
|
__xdata uint8_t button_sec_counter_last;
|
||||||
__sbit tx_buf_empty;
|
__sbit tx_buf_empty;
|
||||||
|
|
||||||
#define ETHERTYPE_OFFSET (12 + VLAN_TAG_SIZE + RTL_TAG_SIZE)
|
#define ETHERTYPE_OFFSET (12 + VLAN_TAG_SIZE + RTL_TAG_SIZE)
|
||||||
@@ -237,6 +241,7 @@ uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s)
|
|||||||
return dst - b;
|
return dst - b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t strlen(register __code const char *s)
|
uint16_t strlen(register __code const char *s)
|
||||||
{
|
{
|
||||||
uint16_t l = 0;
|
uint16_t l = 0;
|
||||||
@@ -257,27 +262,44 @@ uint16_t strlen_x(register __xdata const char *s)
|
|||||||
|
|
||||||
void print_short(uint16_t a)
|
void print_short(uint16_t a)
|
||||||
{
|
{
|
||||||
|
// allocating the registers first improves the sdcc code here
|
||||||
|
uint8_t h = a >> 8;
|
||||||
|
uint8_t l = a;
|
||||||
|
|
||||||
print_string("0x");
|
print_string("0x");
|
||||||
for (signed char i = 12; i >= 0; i -= 4) {
|
print_byte(h);
|
||||||
write_char(hex[(a >> i) & 0xf]);
|
print_byte(l);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_long(uint32_t a)
|
||||||
void print_long(__xdata uint32_t a)
|
|
||||||
{
|
{
|
||||||
|
// allocating the registers first improves the sdcc code here
|
||||||
|
uint8_t a24 = a >> 24;
|
||||||
|
uint8_t a16 = a >> 16;
|
||||||
|
uint8_t a8 = a >> 8;
|
||||||
|
uint8_t a0 = a;
|
||||||
|
|
||||||
print_string("0x");
|
print_string("0x");
|
||||||
for (signed char i = 28; i >= 0; i -= 4) {
|
print_byte(a24);
|
||||||
write_char(hex[(a >> i) & 0xf]);
|
print_byte(a16);
|
||||||
}
|
print_byte(a8);
|
||||||
|
print_byte(a0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_byte(uint8_t a)
|
void print_byte(uint8_t a)
|
||||||
{
|
{
|
||||||
write_char(hex[(a >> 4) & 0xf]);
|
char high = (a >> 4) + '0';
|
||||||
write_char(hex[a & 0xf]);
|
if (high > '9') {
|
||||||
}
|
high += 'a' - ('0' + 10);
|
||||||
|
}
|
||||||
|
write_char(high);
|
||||||
|
|
||||||
|
char low = (a & 0xf) + '0';
|
||||||
|
if (low > '9') {
|
||||||
|
low += 'a' - ('0' + 10);
|
||||||
|
}
|
||||||
|
write_char(low);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* External IRQ 0 Service Routine: Called on link change?
|
* External IRQ 0 Service Routine: Called on link change?
|
||||||
@@ -435,6 +457,23 @@ void reg_bit_clear(uint16_t reg_addr, char bit)
|
|||||||
reg_write_m(reg_addr);
|
reg_write_m(reg_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This sets a bit in the 32bit wide switch register reg_addr
|
||||||
|
*/
|
||||||
|
uint8_t reg_bit_test(uint16_t reg_addr, char bit)
|
||||||
|
{
|
||||||
|
uint8_t bit_mask = 1 << (bit & 0x7);
|
||||||
|
|
||||||
|
bit >>= 3;
|
||||||
|
reg_read_m(reg_addr);
|
||||||
|
bit_mask = bit_mask;
|
||||||
|
if (sfr_data[3-bit] & bit_mask)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This masks the sfr data fields, first &-ing with ~mask, then setting the bits in set
|
* This masks the sfr data fields, first &-ing with ~mask, then setting the bits in set
|
||||||
*/
|
*/
|
||||||
@@ -545,16 +584,6 @@ uint8_t read_flash(uint8_t bank, __code uint8_t *addr)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void print_long_x(__xdata uint8_t v[])
|
|
||||||
{
|
|
||||||
write_char('0'); write_char('x');
|
|
||||||
for (uint8_t i=0; i < 4; i++) {
|
|
||||||
write_char(hex[v[i] >> 4]);
|
|
||||||
write_char(hex[v[i] & 0xf]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read a SerDes register in the SoC
|
* Read a SerDes register in the SoC
|
||||||
* Input must be: sds_id = 0/1, page < 128, reg <= 0xff
|
* Input must be: sds_id = 0/1, page < 128, reg <= 0xff
|
||||||
@@ -601,14 +630,10 @@ void print_sfr_data(void)
|
|||||||
{
|
{
|
||||||
write_char('0');
|
write_char('0');
|
||||||
write_char('x');
|
write_char('x');
|
||||||
write_char(hex[sfr_data[0] >> 4]);
|
print_byte(sfr_data[0]);
|
||||||
write_char(hex[sfr_data[0] & 0xf]);
|
print_byte(sfr_data[1]);
|
||||||
write_char(hex[sfr_data[1] >> 4]);
|
print_byte(sfr_data[2]);
|
||||||
write_char(hex[sfr_data[1] & 0xf]);
|
print_byte(sfr_data[3]);
|
||||||
write_char(hex[sfr_data[2] >> 4]);
|
|
||||||
write_char(hex[sfr_data[2] & 0xf]);
|
|
||||||
write_char(hex[sfr_data[3] >> 4]);
|
|
||||||
write_char(hex[sfr_data[3] & 0xf]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -616,10 +641,8 @@ void print_phy_data(void)
|
|||||||
{
|
{
|
||||||
write_char('0');
|
write_char('0');
|
||||||
write_char('x');
|
write_char('x');
|
||||||
write_char(hex[SFR_DATA_8 >> 4]);
|
print_byte(SFR_DATA_8);
|
||||||
write_char(hex[SFR_DATA_8 & 0xf]);
|
print_byte(SFR_DATA_0);
|
||||||
write_char(hex[SFR_DATA_0 >> 4]);
|
|
||||||
write_char(hex[SFR_DATA_0 & 0xf]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -926,13 +949,12 @@ void handle_rx(void)
|
|||||||
if (uip_len) {
|
if (uip_len) {
|
||||||
tcpip_output();
|
tcpip_output();
|
||||||
}
|
}
|
||||||
} else if (uip_buf[ETHERTYPE_OFFSET] == 0x08 && uip_buf[ETHERTYPE_OFFSET + 1] == 0x00) { // TCP?
|
} else if (uip_buf[ETHERTYPE_OFFSET] == 0x08 && uip_buf[ETHERTYPE_OFFSET + 1] == 0x00) { // IP packet?
|
||||||
if (!management_vlan || management_vlan == rx_packet_vlan) {
|
if (!management_vlan || management_vlan == rx_packet_vlan) {
|
||||||
uip_arp_ipin(); // Learn MAC addresses in TCP packets
|
uip_arp_ipin(); // Learn MAC addresses in TCP packets
|
||||||
uip_input();
|
uip_input();
|
||||||
if (uip_len) {
|
if (uip_len) {
|
||||||
// Add ethernet frame
|
uip_arp_out(); // Add ethernet frame
|
||||||
uip_arp_out();
|
|
||||||
tcpip_output();
|
tcpip_output();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1063,6 +1085,72 @@ void handle_sfp(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void flash_default_config(void)
|
||||||
|
{
|
||||||
|
__xdata uint32_t source = DEFAULT_CONFIG_START;
|
||||||
|
__xdata uint32_t dest = CONFIG_START;
|
||||||
|
|
||||||
|
flash_region.addr = CONFIG_START;
|
||||||
|
flash_sector_erase();
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 8; i++) // 8 * 512 Byte = 4 kByte (1 sector)
|
||||||
|
{
|
||||||
|
flash_region.addr = source;
|
||||||
|
flash_region.len = FLASH_BUF_SIZE;
|
||||||
|
flash_read_bulk(flash_buf);
|
||||||
|
flash_region.addr = dest;
|
||||||
|
flash_region.len = FLASH_BUF_SIZE;
|
||||||
|
flash_write_bytes(flash_buf);
|
||||||
|
dest += FLASH_BUF_SIZE;
|
||||||
|
source += FLASH_BUF_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_string("Written default config to flash\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_button(void)
|
||||||
|
{
|
||||||
|
if (machine.reset_pin == GPIO_NA) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool button_pressed = !gpio_pin_test(machine.reset_pin);
|
||||||
|
if (button_last != button_pressed)
|
||||||
|
{
|
||||||
|
print_string(button_pressed ? "Button pressed\n" : "Button released\n");
|
||||||
|
reg_read_m(RTL837X_REG_SEC_COUNTER);
|
||||||
|
uint8_t diff_sec_counter = sfr_data[3] - button_sec_counter_last;
|
||||||
|
button_last = button_pressed;
|
||||||
|
button_sec_counter_last = sfr_data[3];
|
||||||
|
|
||||||
|
if (!button_pressed)
|
||||||
|
{
|
||||||
|
if (diff_sec_counter > 10)
|
||||||
|
{
|
||||||
|
print_string(">10s button detected; reverting to default settings:\n");
|
||||||
|
flash_default_config();
|
||||||
|
print_string("Now resetting...\n");
|
||||||
|
reset_chip();
|
||||||
|
}
|
||||||
|
else if (diff_sec_counter > 3)
|
||||||
|
{
|
||||||
|
print_string(">3s button detected; resetting chip...\n");
|
||||||
|
reset_chip();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print_string("Short button press detected; no action.\n");
|
||||||
|
set_sys_led_state(SYS_LED_ON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Give the user feedback for button press
|
||||||
|
set_sys_led_state(SYS_LED_SLOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// An idle function that sleeps for 1 tick and does all the house-keeping
|
// An idle function that sleeps for 1 tick and does all the house-keeping
|
||||||
//
|
//
|
||||||
@@ -1095,6 +1183,10 @@ void idle(void)
|
|||||||
}
|
}
|
||||||
reg_write_m(RTL837X_REG_SEC_COUNTER);
|
reg_write_m(RTL837X_REG_SEC_COUNTER);
|
||||||
reg_read_m(RTL837X_REG_SEC_COUNTER);
|
reg_read_m(RTL837X_REG_SEC_COUNTER);
|
||||||
|
|
||||||
|
// Check for button presses once a second
|
||||||
|
handle_button();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
print_sfr_data();
|
print_sfr_data();
|
||||||
write_char('\n');
|
write_char('\n');
|
||||||
@@ -1134,11 +1226,6 @@ void idle(void)
|
|||||||
// Check for changes with SFP modules
|
// Check for changes with SFP modules
|
||||||
handle_sfp();
|
handle_sfp();
|
||||||
|
|
||||||
/* Button pressed on KL-8xhm-x2:
|
|
||||||
reg_read(RTL837X_REG_GPIO_32_63_INPUT);
|
|
||||||
if (!(sfr_data[2] & 0x40))
|
|
||||||
print_string("Button pressed\n");
|
|
||||||
*/
|
|
||||||
// Check new Packets RX
|
// Check new Packets RX
|
||||||
handle_rx();
|
handle_rx();
|
||||||
// Check UIP for packets to transmit
|
// Check UIP for packets to transmit
|
||||||
@@ -1553,6 +1640,9 @@ void rtl8373_init(void)
|
|||||||
|
|
||||||
reg_bit_set(RTL837X_REG_HW_CONF, 0);
|
reg_bit_set(RTL837X_REG_HW_CONF, 0);
|
||||||
|
|
||||||
|
// enable EEE for all ports at 2.5G and 10G, but don't reset the PHYs
|
||||||
|
port_eee_enable_all(EEE_2G5 | EEE_NORESET);
|
||||||
|
|
||||||
// TODO: patch the PHYs
|
// TODO: patch the PHYs
|
||||||
|
|
||||||
// Re-enable PHY after configuration
|
// Re-enable PHY after configuration
|
||||||
@@ -1614,6 +1704,10 @@ void rtl8372_init(void)
|
|||||||
|
|
||||||
reg_bit_set(RTL837X_REG_HW_CONF, 0);
|
reg_bit_set(RTL837X_REG_HW_CONF, 0);
|
||||||
|
|
||||||
|
|
||||||
|
// enable EEE for all ports at 2.5G and 10G, but don't reset the PHYs
|
||||||
|
port_eee_enable_all(EEE_2G5 | EEE_NORESET);
|
||||||
|
|
||||||
// TODO: patch the PHYs
|
// TODO: patch the PHYs
|
||||||
|
|
||||||
// Re-enable PHY after configuration
|
// Re-enable PHY after configuration
|
||||||
@@ -1792,7 +1886,92 @@ void setup_i2c(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void bootloader(void)
|
void check_and_flash_update_image(void)
|
||||||
|
{
|
||||||
|
flash_read_jedecid(); // This initializes also __xdata flash_size variable
|
||||||
|
|
||||||
|
print_string(get_flash_size_str()); print_string(" flash size detected. (1 MB is needed for image updating)\n");
|
||||||
|
if (flash_size < FIRMWARE_UPLOAD_START*2) {
|
||||||
|
print_string("Flash too small for updating; skipping update check\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_string("Checking for update image in flash... ");
|
||||||
|
// Check if an update image is in flash
|
||||||
|
flash_region.addr = FIRMWARE_UPLOAD_START;
|
||||||
|
flash_region.len = 0x100;
|
||||||
|
flash_read_bulk(flash_buf);
|
||||||
|
if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40)
|
||||||
|
{
|
||||||
|
// Yes, flash the new image to the start of flash and reset
|
||||||
|
__xdata uint32_t dest = 0x0;
|
||||||
|
__xdata uint32_t source = FIRMWARE_UPLOAD_START;
|
||||||
|
__xdata uint16_t i = 0;
|
||||||
|
__xdata uint16_t j = 0;
|
||||||
|
__xdata uint8_t * __xdata bptr;
|
||||||
|
print_string("found update image! Checking integrity");
|
||||||
|
flash_init(0); // Re-initialize flash for non-DIO operation, otherwise flashing will fail
|
||||||
|
set_sys_led_state(SYS_LED_FAST);
|
||||||
|
crc_value = 0x0000;
|
||||||
|
for (i = 0; i < 1024; i++) {
|
||||||
|
flash_region.addr = source;
|
||||||
|
flash_region.len = FLASH_BUF_SIZE;
|
||||||
|
flash_read_bulk(flash_buf);
|
||||||
|
bptr = flash_buf;
|
||||||
|
for (j = 0; j < FLASH_BUF_SIZE; j++) {
|
||||||
|
crc16(bptr++);
|
||||||
|
}
|
||||||
|
source += FLASH_BUF_SIZE;
|
||||||
|
if (i%16 == 0) write_char('.');
|
||||||
|
}
|
||||||
|
if (crc_value == 0xb001) {
|
||||||
|
print_string("Checksum OK.\nUpdate in progress, moving firmware to start of flash");
|
||||||
|
source = FIRMWARE_UPLOAD_START;
|
||||||
|
// Don't copy the config area at the end of flash
|
||||||
|
for (i = 0; i < CONFIG_START/FLASH_BUF_SIZE; i++) {
|
||||||
|
flash_region.addr = source;
|
||||||
|
flash_region.len = FLASH_BUF_SIZE;
|
||||||
|
flash_read_bulk(flash_buf);
|
||||||
|
if (i%8 == 0) {
|
||||||
|
flash_region.addr = dest;
|
||||||
|
flash_sector_erase();
|
||||||
|
if (i%16 == 0) write_char('.');
|
||||||
|
}
|
||||||
|
flash_region.addr = dest;
|
||||||
|
flash_region.len = FLASH_BUF_SIZE;
|
||||||
|
flash_write_bytes(flash_buf);
|
||||||
|
dest += FLASH_BUF_SIZE;
|
||||||
|
source += FLASH_BUF_SIZE;
|
||||||
|
}
|
||||||
|
print_string("Done.\nDeleting uploaded flash image");
|
||||||
|
dest = FIRMWARE_UPLOAD_START;
|
||||||
|
for (register uint8_t i=0; i < 128; i++) // TODO: Erasing the entire 512kByte upload area is probably not necessary
|
||||||
|
{
|
||||||
|
flash_region.addr = dest;
|
||||||
|
flash_sector_erase();
|
||||||
|
dest += 0x1000;
|
||||||
|
if (i%4 == 0) write_char('.');
|
||||||
|
}
|
||||||
|
print_string("Done.\nResetting now");
|
||||||
|
delay(200);
|
||||||
|
reset_chip();
|
||||||
|
}
|
||||||
|
print_string("Checksum incorrect, please upload the image again\n");
|
||||||
|
print_string("Erasing bad uploaded flash image\n");
|
||||||
|
dest = FIRMWARE_UPLOAD_START;
|
||||||
|
for (register uint8_t i=0; i < 128; i++) {
|
||||||
|
flash_region.addr = dest;
|
||||||
|
flash_sector_erase();
|
||||||
|
dest += 0x1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print_string("no update image found.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void)
|
||||||
{
|
{
|
||||||
ticks = 0;
|
ticks = 0;
|
||||||
stp_clock = STP_TICK_DIVIDER;
|
stp_clock = STP_TICK_DIVIDER;
|
||||||
@@ -1829,6 +2008,9 @@ void bootloader(void)
|
|||||||
// We have not detected any link
|
// We have not detected any link
|
||||||
linkbits_last[0] = linkbits_last[1] = linkbits_last[2] = linkbits_last[3] = linkbits_last_p89 = 0;
|
linkbits_last[0] = linkbits_last[1] = linkbits_last[2] = linkbits_last[3] = linkbits_last_p89 = 0;
|
||||||
|
|
||||||
|
button_last = 0;
|
||||||
|
button_sec_counter_last = 0;
|
||||||
|
|
||||||
machine_detected.isRTL8373 = 0;
|
machine_detected.isRTL8373 = 0;
|
||||||
machine_detected.isN = 0;
|
machine_detected.isN = 0;
|
||||||
print_string("Detecting CPU: RTL837");
|
print_string("Detecting CPU: RTL837");
|
||||||
@@ -1865,97 +2047,44 @@ void bootloader(void)
|
|||||||
uip_ipaddr(&uip_hostaddr, ownIP[0], ownIP[1], ownIP[2], ownIP[3]);
|
uip_ipaddr(&uip_hostaddr, ownIP[0], ownIP[1], ownIP[2], ownIP[3]);
|
||||||
uip_ipaddr(&uip_draddr, gatewayIP[0], gatewayIP[1], gatewayIP[2], gatewayIP[3]);
|
uip_ipaddr(&uip_draddr, gatewayIP[0], gatewayIP[1], gatewayIP[2], gatewayIP[3]);
|
||||||
uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]);
|
uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]);
|
||||||
|
reg_read_m(RTL837X_REG_CHIP_UUID);
|
||||||
|
#ifdef DEBUG
|
||||||
|
print_string("SoC UUID: "); print_sfr_data();
|
||||||
|
#endif
|
||||||
|
uip_ethaddr.addr[0] = 0x06; // LAA prefix
|
||||||
|
uip_ethaddr.addr[3] = sfr_data[0] ^ sfr_data[3];
|
||||||
|
uip_ethaddr.addr[4] = sfr_data[1] ^ sfr_data[3];
|
||||||
|
uip_ethaddr.addr[5] = sfr_data[2] ^ sfr_data[3];
|
||||||
|
reg_read_m(RTL837X_REG_CHIP_LOT_NO);
|
||||||
|
#ifdef DEBUG
|
||||||
|
print_string(", LOT: "); print_sfr_data(); write_char(' ');
|
||||||
|
#endif
|
||||||
|
uip_ethaddr.addr[1] = sfr_data[0] ^ sfr_data[2];
|
||||||
|
uip_ethaddr.addr[2] = sfr_data[1] ^ sfr_data[3];
|
||||||
|
print_string("Setting MAC to: ");
|
||||||
|
print_byte(uip_ethaddr.addr[0]); write_char(':'); print_byte(uip_ethaddr.addr[1]); write_char(':');
|
||||||
|
print_byte(uip_ethaddr.addr[2]); write_char(':'); print_byte(uip_ethaddr.addr[3]); write_char(':');
|
||||||
|
print_byte(uip_ethaddr.addr[4]); write_char(':'); print_byte(uip_ethaddr.addr[5]); write_char('\n');
|
||||||
|
|
||||||
REG_SET(RTL837X_PIN_MUX_2, 0x0); // Disable pins for ACL
|
REG_SET(RTL837X_PIN_MUX_2, 0x0); // Disable pins for ACL
|
||||||
init_smi();
|
init_smi();
|
||||||
|
|
||||||
rtl8373_revision();
|
rtl8373_revision();
|
||||||
|
|
||||||
leds_setup();
|
leds_setup();
|
||||||
|
machine_custom_init();
|
||||||
|
|
||||||
leds_dump();
|
leds_dump();
|
||||||
|
|
||||||
|
set_sys_led_state(SYS_LED_SLOW);
|
||||||
|
|
||||||
if (machine_detected.isRTL8373)
|
if (machine_detected.isRTL8373)
|
||||||
rtl8373_init();
|
rtl8373_init();
|
||||||
else
|
else
|
||||||
rtl8372_init();
|
rtl8372_init();
|
||||||
delay(1000);
|
delay(1000);
|
||||||
|
|
||||||
// Check update in progress and move blocks
|
check_and_flash_update_image();
|
||||||
flash_region.addr = FIRMWARE_UPLOAD_START;
|
|
||||||
flash_region.len = 0x100;
|
|
||||||
flash_read_bulk(flash_buf);
|
|
||||||
#ifndef MACHINE_HG0402XG_V1_1
|
|
||||||
if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40) {
|
|
||||||
__xdata uint32_t dest = 0x0;
|
|
||||||
__xdata uint32_t source = FIRMWARE_UPLOAD_START;
|
|
||||||
__xdata uint16_t i = 0;
|
|
||||||
__xdata uint16_t j = 0;
|
|
||||||
__xdata uint8_t * __xdata bptr;
|
|
||||||
print_string("Identified update image. Checking integrity...");
|
|
||||||
|
|
||||||
flash_init(0); // Re-initialize flash for non-DIO operation, otherwise flashing will fail
|
|
||||||
set_sys_led_state(SYS_LED_FAST);
|
|
||||||
|
|
||||||
crc_value = 0x0000;
|
|
||||||
for (i = 0; i < 1024; i++) {
|
|
||||||
flash_region.addr = source;
|
|
||||||
flash_region.len = 0x200;
|
|
||||||
flash_read_bulk(flash_buf);
|
|
||||||
bptr = flash_buf;
|
|
||||||
for (j = 0; j < 0x200; j++) {
|
|
||||||
// print_byte(*bptr); write_char(' ');
|
|
||||||
crc16(bptr++);
|
|
||||||
// print_short(crc_value); write_char(':');
|
|
||||||
}
|
|
||||||
source += 0x200;
|
|
||||||
// write_char('\n'); print_short(crc_value); write_char(' ');
|
|
||||||
if (i%16 == 0)
|
|
||||||
write_char('.');
|
|
||||||
}
|
|
||||||
if (crc_value == 0xb001) {
|
|
||||||
print_string("\nChecksum OK\n");
|
|
||||||
print_string("Update in progress, moving firmware to start of FLASH.");
|
|
||||||
source = FIRMWARE_UPLOAD_START;
|
|
||||||
// A 512kByte = 4MBit Flash has 128*8=1024 512byte blocks, we copy only 896
|
|
||||||
// (don't overwrite config @ 0x700000)
|
|
||||||
for (i = 0; i < 896; i++) {
|
|
||||||
// print_string("Writing block: ");
|
|
||||||
// print_short(dest);
|
|
||||||
flash_region.addr = source;
|
|
||||||
flash_region.len = 0x200;
|
|
||||||
flash_read_bulk(flash_buf);
|
|
||||||
if (!(i & 0x7)) {
|
|
||||||
flash_region.addr = dest;
|
|
||||||
flash_sector_erase();
|
|
||||||
write_char('.');
|
|
||||||
}
|
|
||||||
flash_region.addr = dest;
|
|
||||||
flash_region.len = 0x200;
|
|
||||||
flash_write_bytes(flash_buf);
|
|
||||||
dest += 0x200;
|
|
||||||
source += 0x200;
|
|
||||||
}
|
|
||||||
print_string("\nDeleting uploaded flash image\n");
|
|
||||||
dest = FIRMWARE_UPLOAD_START;
|
|
||||||
for (register uint8_t i=0; i < 128; i++) {
|
|
||||||
flash_region.addr = dest;
|
|
||||||
flash_sector_erase();
|
|
||||||
dest += 0x1000;
|
|
||||||
}
|
|
||||||
print_string("Resetting now");
|
|
||||||
delay(200);
|
|
||||||
reset_chip();
|
|
||||||
}
|
|
||||||
print_string("Checksum incorrect, please upload the image again\n");
|
|
||||||
print_string("Erasing bad uploaded flash image\n");
|
|
||||||
dest = FIRMWARE_UPLOAD_START;
|
|
||||||
for (register uint8_t i=0; i < 128; i++) {
|
|
||||||
flash_region.addr = dest;
|
|
||||||
flash_sector_erase();
|
|
||||||
dest += 0x1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
set_sys_led_state(SYS_LED_SLOW);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// This register seems to work on the RTL8373 only if also the SDS
|
// This register seems to work on the RTL8373 only if also the SDS
|
||||||
@@ -1979,6 +2108,7 @@ void bootloader(void)
|
|||||||
vlan_setup();
|
vlan_setup();
|
||||||
port_l2_setup();
|
port_l2_setup();
|
||||||
igmp_setup();
|
igmp_setup();
|
||||||
|
bandwidth_setup();
|
||||||
uip_init();
|
uip_init();
|
||||||
uip_arp_init();
|
uip_arp_init();
|
||||||
httpd_init();
|
httpd_init();
|
||||||
@@ -1986,6 +2116,7 @@ void bootloader(void)
|
|||||||
management_vlan = 0; // Disabled
|
management_vlan = 0; // Disabled
|
||||||
|
|
||||||
setup_i2c();
|
setup_i2c();
|
||||||
|
setup_sfp_gpio();
|
||||||
|
|
||||||
print_string(greeting);
|
print_string(greeting);
|
||||||
|
|
||||||
@@ -2004,39 +2135,9 @@ void bootloader(void)
|
|||||||
|
|
||||||
set_sys_led_state(SYS_LED_ON);
|
set_sys_led_state(SYS_LED_ON);
|
||||||
|
|
||||||
// Wait for commands on serial connection
|
cmd_editor_init();
|
||||||
// sbuf_ptr is moved forward by serial interrupt, l is the position until we have already
|
|
||||||
// printed out the entered characters
|
|
||||||
__xdata uint8_t l = sbuf_ptr; // We have printed out entered characters until l
|
|
||||||
__xdata uint8_t line_start = sbuf_ptr; // This is where the current line starts
|
|
||||||
cmd_available = 0;
|
|
||||||
while (1) {
|
while (1) {
|
||||||
while (l != sbuf_ptr) {
|
cmd_edit();
|
||||||
// If the command buffer is currently in use, we cannot copy to it
|
|
||||||
if (cmd_available)
|
|
||||||
break;
|
|
||||||
write_char(sbuf[l]);
|
|
||||||
// Check whether there is a full line:
|
|
||||||
if (sbuf[l] == '\n' || sbuf[l] == '\r') {
|
|
||||||
write_char('\n');
|
|
||||||
register uint8_t i = 0;
|
|
||||||
while (line_start != l) {
|
|
||||||
cmd_buffer[i++] = sbuf[line_start++];
|
|
||||||
line_start &= (SBUF_SIZE - 1);
|
|
||||||
}
|
|
||||||
line_start++;
|
|
||||||
line_start &= (SBUF_SIZE - 1);
|
|
||||||
cmd_buffer[i] = '\0';
|
|
||||||
// If there is a command we print the prompt after execution
|
|
||||||
// otherwise immediately because there is nothing to execute
|
|
||||||
if (i)
|
|
||||||
cmd_available = 1;
|
|
||||||
else
|
|
||||||
print_string("\n> ");
|
|
||||||
}
|
|
||||||
l++;
|
|
||||||
l &= (SBUF_SIZE - 1);
|
|
||||||
}
|
|
||||||
idle(); // Enter Idle mode until interrupt occurs
|
idle(); // Enter Idle mode until interrupt occurs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#define PASSWORD "1234"
|
#define PASSWORD "1234"
|
||||||
#define SESSION_TIMEOUT 2000
|
#define SESSION_TIMEOUT 2000
|
||||||
|
|
||||||
#define PORTS 9
|
#define PORTS 6
|
||||||
#define NSFP 1
|
#define NSFP 1
|
||||||
|
|
||||||
#define N_COUNTERS 52
|
#define N_COUNTERS 52
|
||||||
@@ -121,7 +121,8 @@ void send_basic_info(int socket)
|
|||||||
{
|
{
|
||||||
char *response = "HTTP/1.1 200 OK\r\n"
|
char *response = "HTTP/1.1 200 OK\r\n"
|
||||||
"Content-Type: application/json; charset=UTF-8\r\n\r\n"
|
"Content-Type: application/json; charset=UTF-8\r\n\r\n"
|
||||||
"{\"ip_address\":\"192.168.10.247\",\"ip_gateway\":\"192.168.2.22\",\"ip_netmask\":\"255.255.255.0\",\"mac_address\":\"1c:2a:a3:23:00:02\",\"sw_ver\":\"" VERSION_SW "\",\"hw_ver\":\"SWGT024-V2.0\"}";
|
"{\"ip_address\":\"192.168.10.247\",\"ip_gateway\":\"192.168.2.22\",\"ip_netmask\":\"255.255.255.0\",\"mac_address\":\"1c:2a:a3:23:00:02\",\"sw_ver\":\"" VERSION_SW "\",\"hw_ver\":\"SWGT024-V2.0\""
|
||||||
|
",\"dhcp_client\":1,\"dhcp_server\":0}";
|
||||||
write(socket, response, strlen(response));
|
write(socket, response, strlen(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +230,7 @@ void send_status(int s)
|
|||||||
|
|
||||||
void send_counters(int s, int port)
|
void send_counters(int s, int port)
|
||||||
{
|
{
|
||||||
struct json_object *v, *counters;
|
struct json_object *counters;
|
||||||
const char *jstring;
|
const char *jstring;
|
||||||
char *header = "HTTP/1.1 200 OK\r\n"
|
char *header = "HTTP/1.1 200 OK\r\n"
|
||||||
"Cache-Control: no-cache\r\n"
|
"Cache-Control: no-cache\r\n"
|
||||||
@@ -239,7 +240,6 @@ void send_counters(int s, int port)
|
|||||||
counters = json_object_new_array_ext(N_COUNTERS);
|
counters = json_object_new_array_ext(N_COUNTERS);
|
||||||
|
|
||||||
for (int i = 0; i < N_COUNTERS; i++) {
|
for (int i = 0; i < N_COUNTERS; i++) {
|
||||||
v = json_object_new_object();
|
|
||||||
sprintf(counter_buf, "0x%016lx", 0x1234UL + i);
|
sprintf(counter_buf, "0x%016lx", 0x1234UL + i);
|
||||||
json_object_array_add(counters, json_object_new_string(counter_buf));
|
json_object_array_add(counters, json_object_new_string(counter_buf));
|
||||||
}
|
}
|
||||||
@@ -283,6 +283,56 @@ void send_eee(int s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void send_bandwidth(int s)
|
||||||
|
{
|
||||||
|
struct json_object *ports, *v;
|
||||||
|
const char *jstring;
|
||||||
|
uint32_t bw;
|
||||||
|
int limited, fcEnabled;
|
||||||
|
char *header = "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Content-Type: application/json; charset=UTF-8\r\n\r\n";
|
||||||
|
|
||||||
|
ports = json_object_new_array_ext(PORTS);
|
||||||
|
for (int i = 1; i <= PORTS; i++) {
|
||||||
|
v = json_object_new_object();
|
||||||
|
json_object_object_add(v, "portNum", json_object_new_int(i));
|
||||||
|
if (i % 2) {
|
||||||
|
limited = 1;
|
||||||
|
fcEnabled = i % 4 ? 1 : 0;
|
||||||
|
bw = 0x100;
|
||||||
|
} else {
|
||||||
|
limited = 0;
|
||||||
|
fcEnabled = 0;
|
||||||
|
bw = 0xfffff;
|
||||||
|
}
|
||||||
|
char bw_buf[20];
|
||||||
|
sprintf(bw_buf, "%08x", bw);
|
||||||
|
json_object_object_add(v, "iLimited", json_object_new_int(limited));
|
||||||
|
json_object_object_add(v, "iFC", json_object_new_int(fcEnabled));
|
||||||
|
json_object_object_add(v, "iBW", json_object_new_string(bw_buf));
|
||||||
|
|
||||||
|
if (i % 4) {
|
||||||
|
limited = 1;
|
||||||
|
bw = 0x1000;
|
||||||
|
} else {
|
||||||
|
limited = 0;
|
||||||
|
bw = 0xfffff;
|
||||||
|
}
|
||||||
|
sprintf(bw_buf, "%08x", bw);
|
||||||
|
json_object_object_add(v, "eLimited", json_object_new_int(limited));
|
||||||
|
json_object_object_add(v, "eBW", json_object_new_string(bw_buf));
|
||||||
|
|
||||||
|
json_object_array_add(ports, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(s, header, strlen(header));
|
||||||
|
|
||||||
|
jstring = json_object_to_json_string_ext(ports, JSON_C_TO_STRING_PLAIN);
|
||||||
|
write(s, jstring, strlen(jstring));
|
||||||
|
json_object_put(ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void send_mirror(int s)
|
void send_mirror(int s)
|
||||||
{
|
{
|
||||||
uint16_t mirror_tx, mirror_rx = 0;
|
uint16_t mirror_tx, mirror_rx = 0;
|
||||||
@@ -593,6 +643,13 @@ void launch(struct Server *server)
|
|||||||
else
|
else
|
||||||
send_eee(new_socket);
|
send_eee(new_socket);
|
||||||
goto done;
|
goto done;
|
||||||
|
} else if (!strncmp(&buffer[4], "/bandwidth.json", 15)) {
|
||||||
|
printf("Bandwidth request\n");
|
||||||
|
if (!authenticated)
|
||||||
|
send_unauthorized(new_socket);
|
||||||
|
else
|
||||||
|
send_bandwidth(new_socket);
|
||||||
|
goto done;
|
||||||
} else if (!strncmp(&buffer[4], "/information.json", 17)) {
|
} else if (!strncmp(&buffer[4], "/information.json", 17)) {
|
||||||
printf("Status request\n");
|
printf("Status request\n");
|
||||||
if (!authenticated)
|
if (!authenticated)
|
||||||
|
|||||||
@@ -106,6 +106,10 @@ int main(int argc, char **argv)
|
|||||||
printf("Error reading input file.\n");
|
printf("Error reading input file.\n");
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
if (buffer[0] != 2) {
|
||||||
|
printf("Expected LJMP at offset 0.\n");
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
for (int b = BANK0_SIZE; b < BANK_STRIDE + BANK0_SIZE; b ++) {
|
for (int b = BANK0_SIZE; b < BANK_STRIDE + BANK0_SIZE; b ++) {
|
||||||
if (buffer[b]) {
|
if (buffer[b]) {
|
||||||
printf("WARNING: Bank 0: code segment too large at 0x%x!\n", b);
|
printf("WARNING: Bank 0: code segment too large at 0x%x!\n", b);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ AFLAGS= -plosgff
|
|||||||
|
|
||||||
BUILDDIR = output/
|
BUILDDIR = output/
|
||||||
|
|
||||||
SRCS = timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-neighbor.c uip-split.c
|
SRCS = timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-split.c
|
||||||
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
|
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
|
||||||
|
|
||||||
all: create_build_dir $(OBJS)
|
all: create_build_dir $(OBJS)
|
||||||
|
|||||||
@@ -132,8 +132,6 @@ static __code const uip_ipaddr_t all_zeroes_addr =
|
|||||||
{0x0000,0x0000};
|
{0x0000,0x0000};
|
||||||
#endif /* UIP_CONF_IPV6 */
|
#endif /* UIP_CONF_IPV6 */
|
||||||
|
|
||||||
extern __code struct uip_eth_addr uip_ethaddr;
|
|
||||||
|
|
||||||
#ifndef UIP_CONF_EXTERNAL_BUFFER
|
#ifndef UIP_CONF_EXTERNAL_BUFFER
|
||||||
u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains
|
u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains
|
||||||
incoming packets. */
|
incoming packets. */
|
||||||
@@ -921,12 +919,12 @@ uip_process(u8_t flag) __banked
|
|||||||
|
|
||||||
/* Check if we have a DHCP packet, otherwise check if the packet is destined for our IP address. */
|
/* Check if we have a DHCP packet, otherwise check if the packet is destined for our IP address. */
|
||||||
#if !UIP_CONF_IPV6
|
#if !UIP_CONF_IPV6
|
||||||
if(!(BUF->proto == UIP_PROTO_UDP && UDPBUF->destport == HTONS(DHCPC_CLIENT_PORT))) {
|
if(!(BUF->proto == UIP_PROTO_UDP && (UDPBUF->destport == HTONS(DHCP_CLIENT_PORT) || UDPBUF->destport == HTONS(DHCP_SERVER_PORT)) )) {
|
||||||
if(!uip_ipaddr_cmpx(BUF->destipaddr, uip_hostaddr)) {
|
if(!uip_ipaddr_cmpx(BUF->destipaddr, uip_hostaddr)) {
|
||||||
UIP_STAT(++uip_stat.ip.drop);
|
UIP_STAT(++uip_stat.ip.drop);
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* UIP_CONF_IPV6 */
|
#else /* UIP_CONF_IPV6 */
|
||||||
/* For IPv6, packet reception is a little trickier as we need to
|
/* For IPv6, packet reception is a little trickier as we need to
|
||||||
make sure that we listen to certain multicast addresses (all
|
make sure that we listen to certain multicast addresses (all
|
||||||
@@ -940,7 +938,11 @@ uip_process(u8_t flag) __banked
|
|||||||
}
|
}
|
||||||
#endif /* UIP_CONF_IPV6 */
|
#endif /* UIP_CONF_IPV6 */
|
||||||
}
|
}
|
||||||
|
// If we serve only the designated DHCPD-VLAN, we drop the packet if not in that VLAN
|
||||||
|
if(BUF->proto == UIP_PROTO_UDP && dhcpd_vlan && UDPBUF->destport == HTONS(DHCP_SERVER_PORT) && dhcpd_vlan != rx_packet_vlan) {
|
||||||
|
UIP_STAT(++uip_stat.ip.drop);
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
#if !UIP_CONF_IPV6
|
#if !UIP_CONF_IPV6
|
||||||
// if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
|
// if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
|
||||||
// checksum. */
|
// checksum. */
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ struct arp_hdr_o {
|
|||||||
u16_t dipaddr[2];
|
u16_t dipaddr[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ethip_hdr {
|
struct ethip_hdr_o {
|
||||||
struct uip_eth_hdr ethhdr;
|
struct uip_eth_hdr ethhdr;
|
||||||
/* IP header. */
|
/* IP header. */
|
||||||
u8_t vhl,
|
u8_t vhl,
|
||||||
@@ -106,6 +106,24 @@ struct ethip_hdr {
|
|||||||
u16_t ipchksum;
|
u16_t ipchksum;
|
||||||
u16_t srcipaddr[2],
|
u16_t srcipaddr[2],
|
||||||
destipaddr[2];
|
destipaddr[2];
|
||||||
|
u16_t sport, dport;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ethip_hdr_i {
|
||||||
|
struct uip_eth_hdr ethhdr;
|
||||||
|
struct rtl_tag rtl_tag;
|
||||||
|
/* IP header. */
|
||||||
|
u8_t vhl,
|
||||||
|
tos,
|
||||||
|
len[2],
|
||||||
|
ipid[2],
|
||||||
|
ipoffset[2],
|
||||||
|
ttl,
|
||||||
|
proto;
|
||||||
|
u16_t ipchksum;
|
||||||
|
u16_t srcipaddr[2],
|
||||||
|
destipaddr[2];
|
||||||
|
u16_t sport, dport;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ARP_REQUEST 1
|
#define ARP_REQUEST 1
|
||||||
@@ -130,9 +148,10 @@ static __xdata u8_t i, c;
|
|||||||
static __xdata u8_t arptime;
|
static __xdata u8_t arptime;
|
||||||
static __xdata u8_t tmpage;
|
static __xdata u8_t tmpage;
|
||||||
|
|
||||||
#define BUF ((__xdata struct arp_hdr_i *)&uip_buf[0])
|
#define BUF ((__xdata struct arp_hdr_i *)&uip_buf[0])
|
||||||
#define BUF_O ((__xdata struct arp_hdr_o *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE])
|
#define BUF_O ((__xdata struct arp_hdr_o *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE])
|
||||||
#define IPBUF ((__xdata struct ethip_hdr *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE])
|
#define IPBUF_I ((__xdata struct ethip_hdr_i *)&uip_buf[0])
|
||||||
|
#define IPBUF_O ((__xdata struct ethip_hdr_o *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE])
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
* Initialize the ARP module.
|
* Initialize the ARP module.
|
||||||
@@ -238,27 +257,26 @@ uip_arp_update(__xdata u16_t *ipaddr, __xdata struct uip_eth_addr *ethaddr)
|
|||||||
* variable uip_len.
|
* variable uip_len.
|
||||||
*/
|
*/
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
#if 0
|
|
||||||
void
|
void
|
||||||
uip_arp_ipin(void)
|
uip_arp_ipin(void) __banked
|
||||||
{
|
{
|
||||||
uip_len -= sizeof(struct uip_eth_hdr);
|
uip_len -= sizeof(struct uip_eth_hdr);
|
||||||
|
|
||||||
/* Only insert/update an entry if the source IP address of the
|
/* Only insert/update an entry if the source IP address of the
|
||||||
incoming IP packet comes from a host on the local network. */
|
incoming IP packet comes from a host on the local network. */
|
||||||
if((IPBUF->srcipaddr[0] & uip_netmask[0]) !=
|
if((IPBUF_I->srcipaddr[0] & uip_netmask[0]) !=
|
||||||
(uip_hostaddr[0] & uip_netmask[0])) {
|
(uip_hostaddr[0] & uip_netmask[0])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if((IPBUF->srcipaddr[1] & uip_netmask[1]) !=
|
if((IPBUF_I->srcipaddr[1] & uip_netmask[1]) !=
|
||||||
(uip_hostaddr[1] & uip_netmask[1])) {
|
(uip_hostaddr[1] & uip_netmask[1])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
|
uip_arp_update(IPBUF_I->srcipaddr, &(IPBUF_I->ethhdr.src));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* 0 */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
* ARP processing for incoming ARP packets.
|
* ARP processing for incoming ARP packets.
|
||||||
@@ -302,12 +320,11 @@ uip_arp_arpin(void) __banked
|
|||||||
with this host in the future. */
|
with this host in the future. */
|
||||||
uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
|
uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
|
||||||
|
|
||||||
/* The reply opcode is 2. */
|
BUF_O->opcode = HTONS(ARP_REPLY);
|
||||||
BUF_O->opcode = HTONS(2);
|
|
||||||
|
|
||||||
memcpy(BUF_O->dhwaddr.addr, BUF->shwaddr.addr, 6);
|
memcpy(BUF_O->dhwaddr.addr, BUF->shwaddr.addr, 6);
|
||||||
memcpyc(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6);
|
memcpy(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6);
|
||||||
memcpyc(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
memcpy(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||||
memcpy(BUF_O->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
|
memcpy(BUF_O->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
|
||||||
|
|
||||||
BUF_O->dipaddr[0] = BUF->sipaddr[0];
|
BUF_O->dipaddr[0] = BUF->sipaddr[0];
|
||||||
@@ -371,19 +388,24 @@ uip_arp_out(void) __banked
|
|||||||
If not ARP table entry is found, we overwrite the original IP
|
If not ARP table entry is found, we overwrite the original IP
|
||||||
packet with an ARP request for the IP address. */
|
packet with an ARP request for the IP address. */
|
||||||
|
|
||||||
|
if (IPBUF_O->sport == 0x4300 && !IPBUF_O->destipaddr[0] && !IPBUF_O->destipaddr[1]) {
|
||||||
|
IPBUF_O->destipaddr[0] = 0xffff;
|
||||||
|
IPBUF_O->destipaddr[1] = 0xffff;
|
||||||
|
IPBUF_O->dport = 0x4400;
|
||||||
|
}
|
||||||
/* First check if destination is a local broadcast. */
|
/* First check if destination is a local broadcast. */
|
||||||
if(uip_ipaddr_cmpc(IPBUF->destipaddr, broadcast_ipaddr)) {
|
if(uip_ipaddr_cmpc(IPBUF_O->destipaddr, broadcast_ipaddr)) {
|
||||||
memcpyc(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
|
memcpyc(IPBUF_O->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
|
||||||
} else {
|
} else {
|
||||||
/* Check if the destination address is on the local network. */
|
/* Check if the destination address is on the local network. */
|
||||||
if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) {
|
if(!uip_ipaddr_maskcmp(IPBUF_O->destipaddr, uip_hostaddr, uip_netmask)) {
|
||||||
/* Destination address was not on the local network, so we need to
|
/* Destination address was not on the local network, so we need to
|
||||||
use the default router's IP address instead of the destination
|
use the default router's IP address instead of the destination
|
||||||
address when determining the MAC address. */
|
address when determining the MAC address. */
|
||||||
uip_ipaddr_copy(ipaddr, uip_draddr);
|
uip_ipaddr_copy(ipaddr, uip_draddr);
|
||||||
} else {
|
} else {
|
||||||
/* Else, we use the destination IP address. */
|
/* Else, we use the destination IP address. */
|
||||||
uip_ipaddr_copy(ipaddr, IPBUF->destipaddr);
|
uip_ipaddr_copy(ipaddr, IPBUF_O->destipaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||||
@@ -399,8 +421,8 @@ uip_arp_out(void) __banked
|
|||||||
|
|
||||||
memset(BUF_O->ethhdr.dest.addr, 0xff, 6);
|
memset(BUF_O->ethhdr.dest.addr, 0xff, 6);
|
||||||
memset(BUF_O->dhwaddr.addr, 0x00, 6);
|
memset(BUF_O->dhwaddr.addr, 0x00, 6);
|
||||||
memcpyc(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
memcpy(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||||
memcpyc(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6);
|
memcpy(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6);
|
||||||
|
|
||||||
uip_ipaddr_copy(BUF_O->dipaddr, ipaddr);
|
uip_ipaddr_copy(BUF_O->dipaddr, ipaddr);
|
||||||
uip_ipaddr_copy(BUF_O->sipaddr, uip_hostaddr);
|
uip_ipaddr_copy(BUF_O->sipaddr, uip_hostaddr);
|
||||||
@@ -418,11 +440,11 @@ uip_arp_out(void) __banked
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Build an ethernet header. */
|
/* Build an ethernet header. */
|
||||||
memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
|
memcpy(IPBUF_O->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
|
||||||
}
|
}
|
||||||
memcpyc(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
memcpy(IPBUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||||
|
|
||||||
IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
|
IPBUF_O->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
|
||||||
|
|
||||||
uip_len += sizeof(struct uip_eth_hdr);
|
uip_len += sizeof(struct uip_eth_hdr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,8 +55,6 @@
|
|||||||
#include "uip.h"
|
#include "uip.h"
|
||||||
#include "../rtl837x_common.h"
|
#include "../rtl837x_common.h"
|
||||||
|
|
||||||
extern __code struct uip_eth_addr uip_ethaddr;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Ethernet header.
|
* The Ethernet header.
|
||||||
*/
|
*/
|
||||||
@@ -80,8 +78,8 @@ void uip_arp_init(void) __banked;
|
|||||||
inserts a new mapping if none exists. The function assumes that an
|
inserts a new mapping if none exists. The function assumes that an
|
||||||
IP packet with an Ethernet header is present in the uip_buf buffer
|
IP packet with an Ethernet header is present in the uip_buf buffer
|
||||||
and that the length of the packet is in the uip_len variable. */
|
and that the length of the packet is in the uip_len variable. */
|
||||||
/*void uip_arp_ipin(void);*/
|
void uip_arp_ipin(void) __banked;
|
||||||
#define uip_arp_ipin()
|
// #define uip_arp_ipin()
|
||||||
|
|
||||||
/* The uip_arp_arpin() should be called when an ARP packet is received
|
/* The uip_arp_arpin() should be called when an ARP packet is received
|
||||||
by the Ethernet driver. This function also assumes that the
|
by the Ethernet driver. This function also assumes that the
|
||||||
|
|||||||