mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
Compare commits
182
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d48235f652 | ||
|
|
9c7572b289 | ||
|
|
0989b227c0 | ||
|
|
aa406e1d98 | ||
|
|
1d6f0a2163 | ||
|
|
f93cfd467f | ||
|
|
51c5bd75eb | ||
|
|
2008d490a9 | ||
|
|
5622f1c843 | ||
|
|
aa99921ea2 | ||
|
|
7d94f3d328 | ||
|
|
d0b6a73bf2 | ||
|
|
eb0e4df5ea | ||
|
|
9c062edc75 | ||
|
|
9929fcc169 | ||
|
|
e5f5955f71 | ||
|
|
ba902a68d4 | ||
|
|
03fb3fe6b4 | ||
|
|
726b421824 | ||
|
|
df1cd62518 | ||
|
|
aab4d334e5 | ||
|
|
73b8335bef | ||
|
|
0d64efacb3 | ||
|
|
f3ff8eed42 | ||
|
|
4d17d9ff00 | ||
|
|
8499e9e464 | ||
|
|
ac4f0d410f | ||
|
|
adc4bfc9a0 | ||
|
|
7546d0c685 | ||
|
|
58c21a1986 | ||
|
|
8efb9fb305 | ||
|
|
717247bc0e | ||
|
|
31c61faa60 | ||
|
|
2ff450edd4 | ||
|
|
1a0ad07367 | ||
|
|
0f48a773d9 | ||
|
|
09ba7859b6 | ||
|
|
39a22fd926 | ||
|
|
5cc90841ea | ||
|
|
e5ee4594ef | ||
|
|
0835d52fec | ||
|
|
928cf1cf58 | ||
|
|
a59f92a648 | ||
|
|
52fa41760c | ||
|
|
1bec5cdf8a | ||
|
|
884bc18a61 | ||
|
|
7a87b79871 | ||
|
|
05492e601a | ||
|
|
110c403443 | ||
|
|
6aa28b7385 | ||
|
|
f464be3368 | ||
|
|
4a4abef9fd | ||
|
|
48d57dfb0f | ||
|
|
418a1326cf | ||
|
|
2ba9675cbb | ||
|
|
815e47d5cc | ||
|
|
de1c707f74 | ||
|
|
373d723d47 | ||
|
|
2676dbd0d6 | ||
|
|
432d9d77de | ||
|
|
0ac4792dde | ||
|
|
60b854550d | ||
|
|
9f488415a8 | ||
|
|
0d1c958ed8 | ||
|
|
7dc6906458 | ||
|
|
d4ccebeaa7 | ||
|
|
d18d08287d | ||
|
|
d4e2b9872d | ||
|
|
2e52bcac8e | ||
|
|
8aaca9ae10 | ||
|
|
5fae67afbe | ||
|
|
9c41ada27f | ||
|
|
6e2b06fc27 | ||
|
|
f8657f41e4 | ||
|
|
c636ef3b8f | ||
|
|
0a1ea28691 | ||
|
|
2eb1416ada | ||
|
|
f148bdad20 | ||
|
|
8ff124af30 | ||
|
|
94ae1472c3 | ||
|
|
24f588effd | ||
|
|
18f1fb5f1a | ||
|
|
803e2caaa8 | ||
|
|
95d7901d00 | ||
|
|
9ad5fcb43e | ||
|
|
571bfef810 | ||
|
|
44298f2b71 | ||
|
|
844fe16dc3 | ||
|
|
e2afa9a61c | ||
|
|
455d2e28d6 | ||
|
|
b2f3d44f2b | ||
|
|
13bdcb0050 | ||
|
|
7f9147918a | ||
|
|
588dbf6f83 | ||
|
|
845a7f79bd | ||
|
|
f364f61c65 | ||
|
|
7a2e568fcc | ||
|
|
bde8454449 | ||
|
|
54ab915557 | ||
|
|
4cad857ad5 | ||
|
|
1b578405c0 | ||
|
|
074c89cf27 | ||
|
|
7e729c626c | ||
|
|
e0864f811f | ||
|
|
74b8280d80 | ||
|
|
f812970ca0 | ||
|
|
e6d90f7a8a | ||
|
|
0d63b08f89 | ||
|
|
8e9cababfb | ||
|
|
f481d1fbe4 | ||
|
|
8b91646b83 | ||
|
|
b85d57b32b | ||
|
|
2669262240 | ||
|
|
395f05c27d | ||
|
|
e72585865c | ||
|
|
5635ad835e | ||
|
|
e5146e0857 | ||
|
|
8765a9ba17 | ||
|
|
fa62eecb97 | ||
|
|
71eba81421 | ||
|
|
001c52ef39 | ||
|
|
c5995a4184 | ||
|
|
5316ae9495 | ||
|
|
7bc3d2cf49 | ||
|
|
3392b588b2 | ||
|
|
bcf4ae316c | ||
|
|
22dccbad8c | ||
|
|
cc132a8734 | ||
|
|
689d208ff1 | ||
|
|
d865862625 | ||
|
|
94cf079fcb | ||
|
|
b8928a8bcd | ||
|
|
9dafeab490 | ||
|
|
af0135bcce | ||
|
|
250beae09b | ||
|
|
a939e2e92b | ||
|
|
7ff028303d | ||
|
|
d6ea9be4c0 | ||
|
|
e499007666 | ||
|
|
3d80f73383 | ||
|
|
546d385bf1 | ||
|
|
829fbf707a | ||
|
|
326d94f48d | ||
|
|
83dcd22863 | ||
|
|
963d53335c | ||
|
|
739ab5ef40 | ||
|
|
a0239b72f4 | ||
|
|
e8c6492786 | ||
|
|
fab02c947e | ||
|
|
e859769e5c | ||
|
|
ef742f8f19 | ||
|
|
81b7e4fa87 | ||
|
|
0a05fe923e | ||
|
|
857a91ffc4 | ||
|
|
ae80aa1017 | ||
|
|
7968b03c57 | ||
|
|
52f8366d03 | ||
|
|
8fc4354ec4 | ||
|
|
d7667cb5b4 | ||
|
|
7b4a95b806 | ||
|
|
940ee648df | ||
|
|
e924431344 | ||
|
|
12b53c22f1 | ||
|
|
1caadbe631 | ||
|
|
53a8046874 | ||
|
|
9173d2c6c7 | ||
|
|
942de2d0df | ||
|
|
cc55131fed | ||
|
|
2241db371f | ||
|
|
4a72dfedf2 | ||
|
|
c3e0ad52bc | ||
|
|
ad53165351 | ||
|
|
74fbec1044 | ||
|
|
acba08d001 | ||
|
|
7727c1e561 | ||
|
|
41b181d9fb | ||
|
|
72d8f3639c | ||
|
|
4d45bee566 | ||
|
|
b1ac33b7fb | ||
|
|
dbd60fc810 | ||
|
|
d79ac79f2f | ||
|
|
93723b0061 |
@@ -0,0 +1,7 @@
|
||||
.gitignore
|
||||
output/
|
||||
html_data.c
|
||||
html_data.h
|
||||
tools/httpd_sim
|
||||
tools/injector
|
||||
tools/fileadder
|
||||
@@ -1,5 +1,9 @@
|
||||
BOOTLOADER_ADDRESS=0x100
|
||||
|
||||
IMAGESIZE = 524288
|
||||
CONFIG_LOCATION = 458752
|
||||
HTML_LOCATION = 262144
|
||||
|
||||
CC = sdcc
|
||||
CC_FLAGS = -mmcs51 -Ihttpd -Iuip
|
||||
ASM = sdas8051
|
||||
@@ -8,14 +12,19 @@ AFLAGS= -plosgff
|
||||
SUBDIRS := tools uip httpd
|
||||
SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS))
|
||||
|
||||
all: $(SUBDIRS) rtlplayground.bin
|
||||
BUILDDIR = output/
|
||||
|
||||
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c
|
||||
OBJS = ${SRCS:.c=.rel}
|
||||
OBJS += uip/timer.rel uip/uip-fw.rel uip/uip-neighbor.rel uip/uip-split.rel uip/uip.rel uip/uip_arp.rel uip/uiplib.rel httpd/httpd.rel httpd/page_impl.rel
|
||||
all: create_build_dir $(SUBDIRS) $(BUILDDIR)rtlplayground.bin
|
||||
|
||||
create_build_dir:
|
||||
mkdir -p $(BUILDDIR)
|
||||
|
||||
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c
|
||||
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
|
||||
|
||||
html_data.c html_data.h: html tools
|
||||
tools/fileadder -a -s -b BANK1 -d html -p html_data
|
||||
tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -d html -p html_data
|
||||
|
||||
httpd: html_data.h
|
||||
|
||||
@@ -25,33 +34,37 @@ $(SUBDIRS):
|
||||
clean:
|
||||
-make -C uip clean
|
||||
-make -C httpd clean
|
||||
-rm html_data.c html_data.c
|
||||
if [ -e rtlplayground.bin ]; then rm rtlplayground.bin; fi
|
||||
if [ -e rtlplayground.asm ]; then rm rtlplayground.asm; fi
|
||||
-rm *.ihx *.lk *.lst *.map *.mem *.rel *.rst *.sym *.bin
|
||||
-rm html_data.c html_data.h
|
||||
-rm -r $(BUILDDIR)
|
||||
|
||||
$(BUILDDIR)crtstart.rel: crtstart.asm
|
||||
$(ASM) $(AFLAGS) -o $@ $<
|
||||
|
||||
%.rel: %.c
|
||||
$(CC) $(CC_FLAGS) -c $<
|
||||
$(BUILDDIR)crc16.rel: crc16.asm
|
||||
$(ASM) $(AFLAGS) -o $@ $<
|
||||
|
||||
%.rel: %.asm
|
||||
${ASM} ${AFLAGS} $^
|
||||
$(BUILDDIR)%.rel: %.c
|
||||
$(CC) $(CC_FLAGS) -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)%.rel: $(BUILDDIR)%.asm
|
||||
${ASM} ${AFLAGS} -o $@ $<
|
||||
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
|
||||
|
||||
rtlplayground.ihx: crtstart.rel $(OBJS)
|
||||
$(BUILDDIR)rtlplayground.ihx: $(BUILDDIR)crtstart.rel $(OBJS) $(BUILDDIR)crc16.rel
|
||||
$(CC) $(CC_FLAGS) -Wl-bHOME=${BOOTLOADER_ADDRESS} -Wl-bBANK1=0x14000 -Wl-r -o $@ $^
|
||||
|
||||
%.img: %.ihx
|
||||
$(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx
|
||||
objcopy --input-target=ihex -O binary $< $@
|
||||
|
||||
%.bin: %.img
|
||||
$(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlplayground.img
|
||||
if [ -e $@ ]; then rm $@; fi
|
||||
echo "0000000: 00 40" | xxd -r - $@
|
||||
cat $< >> $@
|
||||
truncate --size=16K $@
|
||||
dd if=$< skip=80 bs=1024 >>$@
|
||||
tools/fileadder -s -d config.txt $@
|
||||
tools/fileadder -a -s -d html -p html_data $@
|
||||
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)crc_calculator -u $@
|
||||
|
||||
|
||||
.PHONY: clean all $(SUBDIRS)
|
||||
.PRECIOUS: %.rel %.ihx .img
|
||||
|
||||
@@ -52,7 +52,7 @@ devices by looking at the image using e.g. Ghidra.
|
||||
## Compiling
|
||||
Install the following particular build requisites (Debian 12, should work on Ubuntu)
|
||||
```
|
||||
sudo apt install sdcc xxd
|
||||
sudo apt install sdcc xxd python
|
||||
```
|
||||
|
||||
Now, building the firmware image should work:
|
||||
@@ -312,4 +312,4 @@ the RTL837x SoCs:
|
||||
- [Mirroring](doc/mirroring.md)
|
||||
- [SFP+ ports](doc/sfp.md)
|
||||
- [Trunking aka. port aggregation](doc/trunking.md)
|
||||
- [VLAN](doc/vlan.md)
|
||||
- [VLAN](doc/vlan.md)
|
||||
|
||||
+566
-190
@@ -3,42 +3,60 @@
|
||||
*/
|
||||
|
||||
// #define DEBUG
|
||||
// #define REGDBG 1
|
||||
|
||||
#define REGDBG 1
|
||||
#define CONFIG_START 0x70000
|
||||
#define CONFIG_LEN 0x1000
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rtl837x_common.h"
|
||||
#include "rtl837x_port.h"
|
||||
#include "rtl837x_flash.h"
|
||||
#include "rtl837x_phy.h"
|
||||
#include "rtl837x_regs.h"
|
||||
#include "rtl837x_sfr.h"
|
||||
#include "rtl837x_stp.h"
|
||||
#include "uip/uip.h"
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
extern __xdata uint8_t minPort;
|
||||
extern __xdata uint8_t maxPort;
|
||||
extern __xdata uint8_t nSFPPorts;
|
||||
extern __xdata uint8_t isRTL8373;
|
||||
extern __xdata uint16_t mpos;
|
||||
extern __xdata uint8_t stpEnabled;
|
||||
extern __code uint8_t log_to_phys_port[9];
|
||||
|
||||
extern volatile __xdata uint32_t ticks;
|
||||
extern volatile __xdata uint8_t sbuf_ptr;
|
||||
extern __xdata uint8_t sbuf[SBUF_SIZE];
|
||||
extern volatile __xdata uint8_t sfr_data[4];
|
||||
|
||||
extern __code uint8_t * __code greeting;
|
||||
extern __code uint8_t * __code hex;
|
||||
|
||||
extern __xdata uint8_t flash_buf[256];
|
||||
extern __xdata uint8_t flash_buf[512];
|
||||
extern __xdata struct flash_region_t flash_region;
|
||||
|
||||
__xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
|
||||
__xdata uint16_t vlan_ptr;
|
||||
__xdata uint8_t gpio_last_value[8] = { 0 };
|
||||
|
||||
// Temporatly for str to hex convertion value.
|
||||
// Support up to 32_bits.
|
||||
__xdata uint8_t hexvalue[4] = { 0 };
|
||||
|
||||
|
||||
// Buffer for writing to flash 0x1fd000, copy to 0x1fe000
|
||||
#define CMD_BUFFER_SIZE 1024
|
||||
__xdata uint8_t cmd_buffer[CMD_BUFFER_SIZE];
|
||||
__xdata uint16_t cmdptr;
|
||||
__xdata uint8_t cmd_buffer[SBUF_SIZE];
|
||||
__xdata uint8_t cmd_available;
|
||||
|
||||
__xdata uint8_t l;
|
||||
__xdata uint8_t line_ptr;
|
||||
__xdata char is_white;
|
||||
|
||||
#define N_WORDS 16
|
||||
__xdata uint8_t ip[4];
|
||||
|
||||
#define N_WORDS SBUF_SIZE
|
||||
__xdata signed char cmd_words_b[N_WORDS];
|
||||
|
||||
// Maps the physical port (starting from 0) to the logical port
|
||||
@@ -46,53 +64,136 @@ __code uint8_t phys_to_log_port[6] = {
|
||||
4, 5, 6, 7, 3, 8
|
||||
};
|
||||
|
||||
|
||||
inline uint8_t isletter(uint8_t l)
|
||||
{
|
||||
// return (l >= 'a' && l <= 'z') || (l >= 'A' && l <= 'Z');
|
||||
|
||||
// Make it lowercase
|
||||
l |= 0x20;
|
||||
l -= 'a';
|
||||
return (l <= ('z'-'a'));
|
||||
}
|
||||
|
||||
|
||||
inline uint8_t isnumber(uint8_t l)
|
||||
{
|
||||
// return (l >= '0' && l <= '9');
|
||||
l -= '0';
|
||||
return (l <= ('9'-'0'));
|
||||
}
|
||||
|
||||
|
||||
uint8_t cmd_compare(uint8_t start, uint8_t * __code cmd)
|
||||
{
|
||||
signed char i;
|
||||
signed char j = 0;
|
||||
|
||||
for (i = cmd_words_b[start]; i != cmd_words_b[start + 1] && sbuf[i] != ' '; i++) {
|
||||
for (i = cmd_words_b[start]; i != cmd_words_b[start + 1] && cmd_buffer[i] != ' '; i++) {
|
||||
i &= SBUF_SIZE - 1;
|
||||
// print_short(i); write_char(':'); print_short(j); write_char('#'); print_string("\n");
|
||||
// write_char('>'); write_char(cmd[j]); write_char('-'); write_char(sbuf[i]); print_string("\n");
|
||||
// write_char('>'); write_char(cmd[j]); write_char('-'); write_char(cmd_buffer[i]); print_string("\n");
|
||||
if (!cmd[j])
|
||||
return 1;
|
||||
if (sbuf[i] != cmd[j++])
|
||||
if (cmd_buffer[i] != cmd[j++])
|
||||
break;
|
||||
}
|
||||
// write_char('.'); print_short(i); write_char(':'); print_short(i);
|
||||
if (i == cmd_words_b[start + 1] || sbuf[i] == ' ')
|
||||
if (i == cmd_words_b[start + 1] || cmd_buffer[i] == ' ')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Converts ascii-hex array into value.
|
||||
returns number of hexvalue[] entries has been written.
|
||||
return value = 0 means error.
|
||||
*/
|
||||
uint8_t atoi_hex(uint8_t idx)
|
||||
{
|
||||
uint8_t h_idx = 0;
|
||||
uint8_t val = 0;
|
||||
uint8_t c;
|
||||
|
||||
while(1) {
|
||||
c = cmd_buffer[idx];
|
||||
|
||||
if (c == '\0' || c == ' ') {
|
||||
break;
|
||||
}
|
||||
|
||||
// swap hex nibbles
|
||||
val = (val >> 4) | (val << 4);
|
||||
|
||||
if (c - '0' < 10) {
|
||||
val |= c - '0';
|
||||
} else {
|
||||
c |= 0x20;
|
||||
c -= 'a';
|
||||
if (c > 5) {
|
||||
h_idx = 0;
|
||||
break;
|
||||
}
|
||||
val |= c + 10;
|
||||
}
|
||||
|
||||
idx++;
|
||||
hexvalue[h_idx >> 1] = val;
|
||||
|
||||
if (h_idx & 1 == 1) {
|
||||
val = 0;
|
||||
}
|
||||
h_idx++;
|
||||
}
|
||||
|
||||
return ((h_idx + 1) >> 1);
|
||||
}
|
||||
|
||||
uint8_t atoi_short(register uint16_t *vlan, register uint8_t idx)
|
||||
{
|
||||
uint8_t err = 1;
|
||||
*vlan = 0;
|
||||
|
||||
while (sbuf[idx] >= '0' && sbuf[idx] <= '9') {
|
||||
while (isnumber(cmd_buffer[idx])) {
|
||||
err = 0;
|
||||
*vlan = (*vlan * 10) + sbuf[idx] - '0';
|
||||
*vlan = (*vlan * 10) + cmd_buffer[idx] - '0';
|
||||
idx++;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
uint8_t parse_ip(register uint8_t idx)
|
||||
{
|
||||
__xdata uint8_t b;
|
||||
|
||||
for (b = 0; b < 4; b++) {
|
||||
ip[b] = 0;
|
||||
while (isnumber(cmd_buffer[idx])) {
|
||||
ip[b] = (ip[b] * 10) + cmd_buffer[idx] - '0';
|
||||
idx++;
|
||||
}
|
||||
if (b < 3 && cmd_buffer[idx++] != '.') {
|
||||
print_string("Error in IP format, expecting '.'\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void parse_trunk(void)
|
||||
{
|
||||
__xdata uint8_t group;
|
||||
__xdata uint16_t members = 0;
|
||||
|
||||
group = sbuf[cmd_words_b[1]] - '0';
|
||||
group = cmd_buffer[cmd_words_b[1]] - '0';
|
||||
|
||||
uint8_t w = 2;
|
||||
while (cmd_words_b[w] > 0) {
|
||||
uint8_t port;
|
||||
if (sbuf[cmd_words_b[w]] >= '0' && sbuf[cmd_words_b[w]] <= '9') {
|
||||
port = sbuf[cmd_words_b[w]] - '1';
|
||||
if (isnumber(cmd_buffer[cmd_words_b[w]])) {
|
||||
port = cmd_buffer[cmd_words_b[w]] - '1';
|
||||
if (port > maxPort)
|
||||
goto err;
|
||||
members |= ((uint16_t)1) << port;
|
||||
@@ -112,23 +213,40 @@ void parse_vlan(void)
|
||||
__xdata uint16_t members = 0;
|
||||
__xdata uint16_t tagged = 0;
|
||||
if (!atoi_short(&vlan, cmd_words_b[1])) {
|
||||
if (cmd_words_b[2] > 0 && sbuf[cmd_words_b[2]] == 'd') {
|
||||
if (cmd_words_b[2] > 0 && cmd_buffer[cmd_words_b[2]] == 'd' && cmd_words_b[3] < 0) {
|
||||
vlan_delete(vlan);
|
||||
return;
|
||||
}
|
||||
uint8_t w = 2;
|
||||
write_char('#');
|
||||
print_byte(cmd_words_b[w] );
|
||||
write_char('#'); write_char(cmd_buffer[cmd_words_b[w]]);
|
||||
if (cmd_words_b[w] > 0 && isletter(cmd_buffer[cmd_words_b[w]])) {
|
||||
register uint8_t i = 0;
|
||||
vlan_names[vlan_ptr++] = hex[(vlan >> 8) & 0xf];
|
||||
vlan_names[vlan_ptr++] = hex[(vlan >> 4) & 0xf] ;
|
||||
vlan_names[vlan_ptr++] = hex[vlan & 0xf];
|
||||
print_string("COPYING: >");
|
||||
while(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++] = ' '; vlan_names[vlan_ptr] = '\0';
|
||||
w++;
|
||||
print_string("<\n");
|
||||
}
|
||||
while (cmd_words_b[w] > 0) {
|
||||
uint8_t port;
|
||||
if (sbuf[cmd_words_b[w]] >= '0' && sbuf[cmd_words_b[w]] <= '9') {
|
||||
port = sbuf[cmd_words_b[w]] - '1';
|
||||
if (sbuf[cmd_words_b[w] + 1] >= '0' && sbuf[cmd_words_b[w] + 1] <= '9') {
|
||||
port = (port + 1) * 10 + sbuf[cmd_words_b[w] + 1] - '1';
|
||||
if (sbuf[cmd_words_b[w] + 2] == 't')
|
||||
if (isnumber(cmd_buffer[cmd_words_b[w]])) {
|
||||
port = 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';
|
||||
if (cmd_buffer[cmd_words_b[w] + 2] == 't')
|
||||
tagged |= ((uint16_t)1) << port;
|
||||
} else {
|
||||
if (!isRTL8373)
|
||||
port = phys_to_log_port[port];
|
||||
if (sbuf[cmd_words_b[w] + 1] == 't')
|
||||
if (cmd_buffer[cmd_words_b[w] + 1] == 't')
|
||||
tagged |= ((uint16_t)1) << port;
|
||||
}
|
||||
if (port > maxPort)
|
||||
@@ -139,6 +257,10 @@ void parse_vlan(void)
|
||||
}
|
||||
vlan_create(vlan, members, tagged);
|
||||
}
|
||||
if (cmd_words_b[2] > 0 && isletter(cmd_buffer[cmd_words_b[2]])) {
|
||||
print_string("vlan_ptr "); print_short(vlan_ptr); write_char(':');
|
||||
write_char('>'); print_string_x(&vlan_names[0]); write_char('<'); write_char('\n');
|
||||
}
|
||||
return;
|
||||
err:
|
||||
print_string("Error: vlan <vlan-id> [port][t/u]...");
|
||||
@@ -151,29 +273,58 @@ void parse_mirror(void)
|
||||
__xdata uint16_t rx_pmask = 0;
|
||||
__xdata uint16_t tx_pmask = 0;
|
||||
|
||||
if (sbuf[cmd_words_b[1]] < '0' || sbuf[cmd_words_b[1]] > '9') {
|
||||
print_string("Port missing: port <mirroring port> [port][t/r]...");
|
||||
if (cmd_words_b[1] > 0 && cmd_compare(1, "status")) {
|
||||
reg_read_m(RTL837x_MIRROR_CTRL);
|
||||
uint8_t mPort = sfr_data[3];
|
||||
if (mPort & 1) {
|
||||
print_string("Enabled: ");
|
||||
} else {
|
||||
print_string("NOT Enabled: ");
|
||||
}
|
||||
print_string("Mirroring port: ");
|
||||
if (!isRTL8373)
|
||||
write_char('0' + log_to_phys_port[mPort >> 1]);
|
||||
else
|
||||
write_char('0' + (mPort >> 1) + 1);
|
||||
reg_read_m(RTL837x_MIRROR_CONF);
|
||||
uint16_t m = sfr_data[0];
|
||||
m = (m << 8) | sfr_data[1];
|
||||
print_string(", Port mask RX: ");
|
||||
print_short(m);
|
||||
m = sfr_data[2];
|
||||
m = (m << 8) | sfr_data[3];
|
||||
print_string(", Port mask TX: ");
|
||||
print_short(m);
|
||||
write_char('\n');
|
||||
return;
|
||||
} else if (cmd_words_b[1] > 0 && cmd_compare(1, "off")) {
|
||||
port_mirror_del();
|
||||
return;
|
||||
}
|
||||
|
||||
mirroring_port = sbuf[cmd_words_b[1]] - '1';
|
||||
if (sbuf[cmd_words_b[1] + 1] >= '0' && sbuf[cmd_words_b[1] + 1] <= '9')
|
||||
mirroring_port = (mirroring_port + 1) * 10 + sbuf[cmd_words_b[1] + 1] - '1';
|
||||
if (!isnumber(cmd_buffer[cmd_words_b[1]])) {
|
||||
print_string("Port missing: mirror <mirroring port> [port][t/r]...");
|
||||
return;
|
||||
}
|
||||
|
||||
mirroring_port = cmd_buffer[cmd_words_b[1]] - '1';
|
||||
if (isnumber(cmd_buffer[cmd_words_b[1] + 1]))
|
||||
mirroring_port = (mirroring_port + 1) * 10 + cmd_buffer[cmd_words_b[1] + 1] - '1';
|
||||
if (!isRTL8373)
|
||||
mirroring_port = phys_to_log_port[mirroring_port];
|
||||
|
||||
uint8_t w = 2;
|
||||
while (cmd_words_b[w] > 0) {
|
||||
uint8_t port;
|
||||
if (sbuf[cmd_words_b[w]] >= '0' && sbuf[cmd_words_b[w]] <= '9') {
|
||||
port = sbuf[cmd_words_b[w]] - '1';
|
||||
if (sbuf[cmd_words_b[w] + 1] >= '0' && sbuf[cmd_words_b[w] + 1] <= '9') {
|
||||
port = (port + 1) * 10 + sbuf[cmd_words_b[w] + 1] - '1';
|
||||
if (isnumber(cmd_buffer[cmd_words_b[w]])) {
|
||||
port = 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';
|
||||
if (!isRTL8373)
|
||||
port = phys_to_log_port[port];
|
||||
if (sbuf[cmd_words_b[w] + 2] == 'r')
|
||||
if (cmd_buffer[cmd_words_b[w] + 2] == 'r')
|
||||
rx_pmask |= ((uint16_t)1) << port;
|
||||
else if (sbuf[cmd_words_b[w] + 2] == 't')
|
||||
else if (cmd_buffer[cmd_words_b[w] + 2] == 't')
|
||||
tx_pmask |= ((uint16_t)1) << port;
|
||||
else {
|
||||
rx_pmask |= ((uint16_t)1) << port;
|
||||
@@ -182,9 +333,9 @@ void parse_mirror(void)
|
||||
} else {
|
||||
if (!isRTL8373)
|
||||
port = phys_to_log_port[port];
|
||||
if (sbuf[cmd_words_b[w] + 1] == 'r')
|
||||
if (cmd_buffer[cmd_words_b[w] + 1] == 'r')
|
||||
rx_pmask |= ((uint16_t)1) << port;
|
||||
else if (sbuf[cmd_words_b[w] + 1] == 't')
|
||||
else if (cmd_buffer[cmd_words_b[w] + 1] == 't')
|
||||
tx_pmask |= ((uint16_t)1) << port;
|
||||
else {
|
||||
rx_pmask |= ((uint16_t)1) << port;
|
||||
@@ -198,168 +349,393 @@ void parse_mirror(void)
|
||||
}
|
||||
|
||||
|
||||
void cmd_parser(void) __banked
|
||||
void parse_regget(void)
|
||||
{
|
||||
while (l != sbuf_ptr) {
|
||||
write_char(sbuf[l]);
|
||||
// Check whether there is a full line:
|
||||
if (sbuf[l] == '\n' || sbuf[l] == '\r') {
|
||||
write_char('\n');
|
||||
#ifdef DEBUG
|
||||
print_long(ticks);
|
||||
#endif
|
||||
// Print line and parse command into words
|
||||
is_white = 1;
|
||||
uint8_t word = 0;
|
||||
cmd_words_b[0] = -1;
|
||||
while (line_ptr != l) {
|
||||
if (is_white && sbuf[line_ptr] != ' ') {
|
||||
is_white = 0;
|
||||
cmd_words_b[word++] = line_ptr;
|
||||
}
|
||||
if (sbuf[line_ptr] == ' ')
|
||||
is_white = 1;
|
||||
write_char(sbuf[line_ptr++]);
|
||||
line_ptr &= SBUF_SIZE - 1;
|
||||
if (word >= N_WORDS - 1) {
|
||||
print_string("\ntoo many arguments, truncated");
|
||||
line_ptr = l; // BUG: We should probably ignore the command
|
||||
break;
|
||||
}
|
||||
}
|
||||
cmd_words_b[word++] = line_ptr;
|
||||
cmd_words_b[word++] = -1;
|
||||
line_ptr = (l + 1) & (SBUF_SIZE - 1);
|
||||
uint16_t reg = 0;
|
||||
|
||||
// Identify command
|
||||
signed char i = cmd_words_b[0];
|
||||
if (i >= 0 && cmd_words_b[1] >= 0) {
|
||||
if (cmd_compare(0, "reset")) {
|
||||
print_string("\nRESET\n\n");
|
||||
reset_chip();
|
||||
}
|
||||
if (cmd_compare(0, "sfp")) {
|
||||
uint8_t rate = sfp_read_reg(0, 12);
|
||||
print_string("\nRate: "); print_byte(rate);
|
||||
print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11));
|
||||
print_string("\n");
|
||||
for (uint8_t i = 20; i < 60; i++) {
|
||||
uint8_t c = sfp_read_reg(0, i);
|
||||
if (c)
|
||||
write_char(c);
|
||||
}
|
||||
}
|
||||
if (cmd_compare(0, "stat")) {
|
||||
port_stats_print();
|
||||
}
|
||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'r') {
|
||||
print_string("\nPRINT SECURITY REGISTERS\n");
|
||||
// The following will only show something else then 0xff if it was programmed for a managed switch
|
||||
flash_read_security(0x0001000, 40);
|
||||
flash_read_security(0x0002000, 40);
|
||||
flash_read_security(0x0003000, 40);
|
||||
}
|
||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'd') {
|
||||
print_string("\nDUMPING FLASH\n");
|
||||
flash_dump(0, 255);
|
||||
}
|
||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'j') {
|
||||
print_string("\nJEDEC ID\n");
|
||||
flash_read_jedecid();
|
||||
}
|
||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'u') {
|
||||
print_string("\nUNIQUE ID\n");
|
||||
flash_read_uid();
|
||||
}
|
||||
// Switch to flash 62.5 MHz mode
|
||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 's') {
|
||||
print_string("\nFLASH FAST MODE\n");
|
||||
flash_init(1);
|
||||
print_string("\nNow dumping flash\n");
|
||||
flash_dump(0, 255);
|
||||
}
|
||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'e') {
|
||||
print_string("\nFLASH erase\n");
|
||||
flash_block_erase(0x20000);
|
||||
}
|
||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'w') {
|
||||
print_string("\nFLASH write\n");
|
||||
for (uint8_t i = 0; i < 20; i++)
|
||||
flash_buf[i] = greeting[i];
|
||||
flash_write_bytes(0x20000, flash_buf, 20);
|
||||
}
|
||||
if (cmd_compare(0, "port") && cmd_words_b[1] > 0) {
|
||||
print_string("\nPORT ");
|
||||
uint8_t p = sbuf[cmd_words_b[1]] - '1';
|
||||
print_byte(p);
|
||||
if (cmd_words_b[2] > 0 && cmd_compare(2, "2g5")) {
|
||||
print_string(" 2.5G\n");
|
||||
phy_set_mode(p, PHY_SPEED_2G5, 0, 0);
|
||||
}
|
||||
if (cmd_words_b[2] > 0 && cmd_compare(2, "1g")) {
|
||||
print_string(" 1G\n");
|
||||
phy_set_mode(p, PHY_SPEED_1G, 0, 0);
|
||||
}
|
||||
if (cmd_words_b[2] > 0 && cmd_compare(2, "auto")) {
|
||||
print_string(" AUTO\n");
|
||||
phy_set_mode(p, PHY_SPEED_AUTO, 0, 0);
|
||||
}
|
||||
if (cmd_words_b[2] > 0 && cmd_compare(2, "off")) {
|
||||
print_string(" OFF\n");
|
||||
phy_set_mode(p, PHY_OFF, 0, 0);
|
||||
}
|
||||
}
|
||||
if (cmd_compare(0, "l2")) {
|
||||
if (cmd_words_b[1] > 0 && cmd_compare(1, "forget"))
|
||||
port_l2_forget();
|
||||
else
|
||||
port_l2_learned();
|
||||
}
|
||||
if (cmd_compare(0, "pvid") && cmd_words_b[1] > 0 && cmd_words_b[2] > 0) {
|
||||
__xdata uint16_t pvid;
|
||||
uint8_t port;
|
||||
port = sbuf[cmd_words_b[1]] - '1';
|
||||
if (!isRTL8373)
|
||||
port = phys_to_log_port[port];
|
||||
if (!atoi_short(&pvid, cmd_words_b[2]))
|
||||
port_pvid_set(port, pvid);
|
||||
}
|
||||
if (cmd_compare(0, "vlan")) {
|
||||
parse_vlan();
|
||||
}
|
||||
if (cmd_compare(0, "mirror")) {
|
||||
parse_mirror();
|
||||
}
|
||||
if (cmd_compare(0, "trunk")) {
|
||||
parse_trunk();
|
||||
}
|
||||
if (cmd_compare(0, "sds")) {
|
||||
print_reg(RTL837X_REG_SDS_MODES);
|
||||
}
|
||||
}
|
||||
print_string("\n> ");
|
||||
if (cmd_words_b[1] < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
uint8_t hex_size = atoi_hex(cmd_words_b[1]);
|
||||
|
||||
if (hex_size == 0 || hex_size > 2) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
reg = hexvalue[0];
|
||||
if (hex_size == 2) {
|
||||
reg <<= 8;
|
||||
reg |= hexvalue[1];
|
||||
}
|
||||
|
||||
print_string("REGGET: ");
|
||||
print_short(reg);
|
||||
print_string(": VAL: ");
|
||||
|
||||
reg_read_m(reg);
|
||||
print_sfr_data();
|
||||
return;
|
||||
|
||||
err:
|
||||
print_string("usage: regget <hexvalue>\n\tlike: regget 0BB0 or regget 0c");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void parse_regset(void)
|
||||
{
|
||||
uint16_t reg = 0;
|
||||
|
||||
if (cmd_words_b[2] < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
uint8_t hex_size = atoi_hex(cmd_words_b[1]);
|
||||
if (hex_size == 0 || hex_size > 2) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
reg = hexvalue[0];
|
||||
if (hex_size == 2) {
|
||||
reg <<= 8;
|
||||
reg |= hexvalue[1];
|
||||
}
|
||||
|
||||
hex_size = atoi_hex(cmd_words_b[2]);
|
||||
if (hex_size == 0 || hex_size > 4) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// zero sfr memory data
|
||||
sfr_set_zero();
|
||||
|
||||
// copy data over sfr memory
|
||||
uint8_t offset = 4 - hex_size;
|
||||
while(hex_size) {
|
||||
hex_size -= 1;
|
||||
sfr_data[offset + hex_size] = hexvalue[hex_size];
|
||||
}
|
||||
print_string("REGSET: ");
|
||||
print_short(reg);
|
||||
|
||||
reg_write_m(reg);
|
||||
|
||||
print_string(": VAL: ");
|
||||
print_sfr_data();
|
||||
return;
|
||||
|
||||
err:
|
||||
print_string("usage: regset <hexvalue> <hexvalue>\n\tlike regset 0b abcd1234.");
|
||||
}
|
||||
|
||||
|
||||
// Parse command into words
|
||||
uint8_t cmd_tokenize(void) __banked
|
||||
{
|
||||
#ifdef DEBUG
|
||||
print_string("Tokenizing command\n");
|
||||
print_string_x(&cmd_buffer[0]);
|
||||
write_char('<'); write_char('\n');
|
||||
#endif
|
||||
line_ptr = 0;
|
||||
is_white = 1;
|
||||
uint8_t word = 0;
|
||||
cmd_words_b[0] = -1;
|
||||
while (cmd_buffer[line_ptr] && line_ptr < SBUF_SIZE - 1) {
|
||||
if (is_white && cmd_buffer[line_ptr] != ' ') {
|
||||
is_white = 0;
|
||||
cmd_words_b[word++] = line_ptr;
|
||||
}
|
||||
l++;
|
||||
l &= (SBUF_SIZE - 1);
|
||||
if (cmd_buffer[line_ptr] == ' ')
|
||||
is_white = 1;
|
||||
line_ptr++;
|
||||
if (word >= N_WORDS - 1) {
|
||||
print_string("\ntoo many arguments, truncated");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (line_ptr == SBUF_SIZE - 1)
|
||||
return 1;
|
||||
cmd_words_b[word++] = line_ptr;
|
||||
cmd_words_b[word++] = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Print GPIO status
|
||||
void print_gpio_status(void) {
|
||||
for (uint8_t idx = 0; idx < 2; idx++) {
|
||||
reg_read(RTL837X_REG_GPIO_00_31_INPUT + (idx * 4));
|
||||
print_string("GPIO ");
|
||||
write_char(idx + '0');
|
||||
write_char(':');
|
||||
write_char(' ');
|
||||
|
||||
print_byte(SFR_DATA_24);
|
||||
print_byte(SFR_DATA_16);
|
||||
print_byte(SFR_DATA_8);
|
||||
print_byte(SFR_DATA_0);
|
||||
|
||||
write_char(' ');
|
||||
print_byte( gpio_last_value[(idx *4)] ^ SFR_DATA_24);
|
||||
gpio_last_value[(idx *4)] = SFR_DATA_24;
|
||||
print_byte( gpio_last_value[(idx *4) + 1] ^ SFR_DATA_16);
|
||||
gpio_last_value[(idx *4) + 1] = SFR_DATA_16;
|
||||
print_byte( gpio_last_value[(idx *4) + 2] ^ SFR_DATA_8);
|
||||
gpio_last_value[(idx *4) + 2] = SFR_DATA_8;
|
||||
print_byte( gpio_last_value[(idx *4) + 3] ^ SFR_DATA_0);
|
||||
gpio_last_value[(idx *4) + 3] = SFR_DATA_0;
|
||||
write_char('\n');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void execute_config() __banked
|
||||
// Identify command
|
||||
void cmd_parser(void) __banked
|
||||
{
|
||||
flash_read_bulk(&cmd_buffer[0], 0x1fd000, CMD_BUFFER_SIZE);
|
||||
// Checks for empty flash
|
||||
if (cmd_buffer[0] == 0xff)
|
||||
return;
|
||||
#ifdef DEBUG
|
||||
print_long(ticks);
|
||||
print_string("Parsing command\n");
|
||||
print_string_x(&cmd_buffer[0]);
|
||||
write_char('<'); write_char('\n');
|
||||
print_string("CMD-words: ");
|
||||
print_byte(cmd_words_b[0]); write_char(' ');
|
||||
print_byte(cmd_words_b[1]); write_char(' ');
|
||||
print_byte(cmd_words_b[2]); write_char(' ');
|
||||
print_byte(cmd_words_b[3]); write_char(' ');
|
||||
print_byte(cmd_words_b[4]); write_char(' ');
|
||||
print_byte(cmd_words_b[5]); write_char(' ');
|
||||
print_byte(cmd_words_b[6]); write_char('\n');
|
||||
#endif
|
||||
if (cmd_words_b[0] >= 0 && cmd_words_b[1] >= 0) {
|
||||
if (cmd_compare(0, "reset")) {
|
||||
print_string("\nRESET\n\n");
|
||||
reset_chip();
|
||||
}
|
||||
if (cmd_compare(0, "sfp")) {
|
||||
uint8_t rate = sfp_read_reg(0, 12);
|
||||
print_string("\nRate: "); print_byte(rate);
|
||||
print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11));
|
||||
print_string("\n");
|
||||
for (uint8_t i = 20; i < 60; i++) {
|
||||
uint8_t c = sfp_read_reg(0, i);
|
||||
if (c)
|
||||
write_char(c);
|
||||
}
|
||||
}
|
||||
if (cmd_compare(0, "stat")) {
|
||||
port_stats_print();
|
||||
}
|
||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') {
|
||||
print_string("\nPRINT SECURITY REGISTERS\n");
|
||||
// The following will only show something else than 0xff if it was programmed for a managed switch
|
||||
flash_region.addr = 0x0001000;
|
||||
flash_region.len = 40;
|
||||
flash_read_security();
|
||||
flash_region.addr = 0x0002000;
|
||||
flash_region.len = 40;
|
||||
flash_read_security();
|
||||
flash_region.addr = 0x0003000;
|
||||
flash_region.len = 40;
|
||||
flash_read_security();
|
||||
}
|
||||
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);
|
||||
}
|
||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') {
|
||||
print_string("\nJEDEC ID\n");
|
||||
flash_read_jedecid();
|
||||
}
|
||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'u') {
|
||||
print_string("\nUNIQUE ID\n");
|
||||
flash_read_uid();
|
||||
}
|
||||
// Switch to flash 62.5 MHz mode
|
||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 's') {
|
||||
print_string("\nFLASH FAST MODE\n");
|
||||
flash_init(1);
|
||||
print_string("\nNow dumping flash\n");
|
||||
flash_region.addr = 0;
|
||||
flash_region.len = 255;
|
||||
flash_dump(255);
|
||||
}
|
||||
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();
|
||||
}
|
||||
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);
|
||||
}
|
||||
if (cmd_compare(0, "port") && cmd_words_b[1] > 0) {
|
||||
print_string("\nPORT ");
|
||||
uint8_t p = cmd_buffer[cmd_words_b[1]] - '1';
|
||||
print_byte(p);
|
||||
if (cmd_words_b[2] > 0 && cmd_compare(2, "2g5")) {
|
||||
print_string(" 2.5G\n");
|
||||
phy_set_mode(p, PHY_SPEED_2G5, 0, 0);
|
||||
}
|
||||
if (cmd_words_b[2] > 0 && cmd_compare(2, "1g")) {
|
||||
print_string(" 1G\n");
|
||||
phy_set_mode(p, PHY_SPEED_1G, 0, 0);
|
||||
}
|
||||
if (cmd_words_b[2] > 0 && cmd_compare(2, "auto")) {
|
||||
print_string(" AUTO\n");
|
||||
phy_set_mode(p, PHY_SPEED_AUTO, 0, 0);
|
||||
}
|
||||
if (cmd_words_b[2] > 0 && cmd_compare(2, "off")) {
|
||||
print_string(" OFF\n");
|
||||
phy_set_mode(p, PHY_OFF, 0, 0);
|
||||
}
|
||||
}
|
||||
if (cmd_compare(0, "ip")) {
|
||||
print_string("Got ip command: ");
|
||||
if (!parse_ip(cmd_words_b[1]))
|
||||
uip_ipaddr(&uip_hostaddr, ip[0], ip[1], ip[2], ip[3]);
|
||||
else
|
||||
print_string("Invalid IP address\n");
|
||||
print_byte(ip[0]); print_byte(ip[1]); print_byte(ip[2]); print_byte(ip[3]);
|
||||
write_char('\n');
|
||||
}
|
||||
if (cmd_compare(0, "gw")) {
|
||||
print_string("Got gw command: ");
|
||||
if (!parse_ip(cmd_words_b[1]))
|
||||
uip_ipaddr(&uip_draddr, ip[0], ip[1], ip[2], ip[3]);
|
||||
else
|
||||
print_string("Invalid IP address\n");
|
||||
print_byte(ip[0]); print_byte(ip[1]); print_byte(ip[2]); print_byte(ip[3]);
|
||||
write_char('\n');
|
||||
}
|
||||
if (cmd_compare(0, "netmask")) {
|
||||
print_string("Got netmask command: ");
|
||||
if (!parse_ip(cmd_words_b[1]))
|
||||
uip_ipaddr(&uip_netmask, ip[0], ip[1], ip[2], ip[3]);
|
||||
else
|
||||
print_string("Invalid IP address\n");
|
||||
print_byte(ip[0]);print_byte(ip[1]);print_byte(ip[2]);print_byte(ip[3]);
|
||||
write_char('\n');
|
||||
}
|
||||
if (cmd_compare(0, "l2")) {
|
||||
if (cmd_words_b[1] > 0 && cmd_compare(1, "forget"))
|
||||
port_l2_forget();
|
||||
else
|
||||
port_l2_learned();
|
||||
}
|
||||
if (cmd_compare(0, "stp")) {
|
||||
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
|
||||
print_string("STP enabled\n");
|
||||
stpEnabled = 1;
|
||||
stp_setup();
|
||||
} else {
|
||||
print_string("STP disabled\n");
|
||||
stp_off();
|
||||
stpEnabled = 0;
|
||||
}
|
||||
}
|
||||
if (cmd_compare(0, "pvid") && cmd_words_b[1] > 0 && cmd_words_b[2] > 0) {
|
||||
__xdata uint16_t pvid;
|
||||
uint8_t port;
|
||||
port = cmd_buffer[cmd_words_b[1]] - '1';
|
||||
if (!isRTL8373)
|
||||
port = phys_to_log_port[port];
|
||||
if (!atoi_short(&pvid, cmd_words_b[2]))
|
||||
port_pvid_set(port, pvid);
|
||||
}
|
||||
if (cmd_compare(0, "vlan")) {
|
||||
parse_vlan();
|
||||
}
|
||||
if (cmd_compare(0, "mirror")) {
|
||||
parse_mirror();
|
||||
}
|
||||
if (cmd_compare(0, "trunk")) {
|
||||
parse_trunk();
|
||||
}
|
||||
if (cmd_compare(0, "sds")) {
|
||||
print_reg(RTL837X_REG_SDS_MODES);
|
||||
}
|
||||
if (cmd_compare(0, "gpio")) {
|
||||
print_gpio_status();
|
||||
}
|
||||
if (cmd_compare(0, "regget")) {
|
||||
parse_regget();
|
||||
}
|
||||
if (cmd_compare(0, "regset")) {
|
||||
parse_regset();
|
||||
}
|
||||
if (cmd_compare(0, "eee")) {
|
||||
int8_t port = -1;
|
||||
if (cmd_words_b[3] > 0) {
|
||||
port = cmd_buffer[cmd_words_b[2]] - '1';
|
||||
if (!isRTL8373)
|
||||
port = 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cmd_parser_setup(void) __banked
|
||||
#define FLASH_READ_BURST_SIZE 0x100;
|
||||
void execute_config(void) __banked
|
||||
{
|
||||
l = sbuf_ptr;
|
||||
line_ptr = l;
|
||||
is_white = 1;
|
||||
cmdptr = 0;
|
||||
}
|
||||
memcpyc(flash_buf, "test", 5);
|
||||
print_string_x(flash_buf);
|
||||
|
||||
__xdata uint32_t pos = CONFIG_START;
|
||||
__xdata uint16_t len_left = CONFIG_LEN;
|
||||
do {
|
||||
flash_region.addr = pos;
|
||||
flash_region.len = FLASH_READ_BURST_SIZE;
|
||||
write_char('-'); print_long(flash_region.addr); write_char(':'); print_short(flash_region.len); write_char('\n');
|
||||
|
||||
flash_read_bulk(flash_buf);
|
||||
|
||||
uint8_t cfg_idx = 0;
|
||||
uint8_t c = 0;
|
||||
do {
|
||||
for (uint8_t cmd_idx = 0; cmd_idx < (SBUF_SIZE - 1); cmd_idx++) {
|
||||
c = flash_buf[cfg_idx++];
|
||||
print_byte(c);
|
||||
|
||||
if (c == 0 || c == '\n') {
|
||||
cmd_buffer[cmd_idx] = '\0';
|
||||
write_char('\n'); write_char('#'); print_short(cfg_idx); write_char('-'); print_short(cmd_idx); write_char('-'); print_string_x(cmd_buffer); write_char('\n');
|
||||
if (cmd_idx && !cmd_tokenize())
|
||||
cmd_parser();
|
||||
if (c == 0)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
cmd_buffer[cmd_idx] = c;
|
||||
}
|
||||
write_char('N');
|
||||
} while(cfg_idx);
|
||||
|
||||
len_left -= FLASH_READ_BURST_SIZE;
|
||||
pos += FLASH_READ_BURST_SIZE;
|
||||
} while(len_left);
|
||||
}
|
||||
|
||||
+9
-2
@@ -1,7 +1,14 @@
|
||||
#ifndef _CMD_PARSER_H_
|
||||
#define _CMD_PARSER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "rtl837x_common.h"
|
||||
|
||||
extern __xdata uint8_t cmd_buffer[SBUF_SIZE];
|
||||
extern __xdata uint8_t cmd_available;
|
||||
|
||||
uint8_t cmd_tokenize(void) __banked;
|
||||
void cmd_parser(void) __banked;
|
||||
void cmd_parser_setup(void) __banked;
|
||||
void execute_config() __banked;
|
||||
void execute_config(void) __banked;
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
ip 192.168.10.247
|
||||
gw 192.168.10.1
|
||||
netmask 255.255.255.0
|
||||
@@ -0,0 +1,121 @@
|
||||
;
|
||||
; CRC16 calculation module
|
||||
;
|
||||
.globl _crc_value
|
||||
.globl _crc16
|
||||
.equ BANK, 0x96
|
||||
; .equ DPS, 0x86
|
||||
; Variable in XMEM holding current CRC16 value, being updated
|
||||
.area XSEG (XDATA)
|
||||
_crc_value::
|
||||
.ds 2
|
||||
|
||||
;-------------------------------------------------------
|
||||
; CRC16 subroutine
|
||||
; - dptr points to byte to be CRCd in xmem
|
||||
; - algorithm uses table lookup
|
||||
;-------------------------------------------------------
|
||||
.area HOME (CODE)
|
||||
.area CSEG (CODE)
|
||||
; .area BANK1 (CODE)
|
||||
_crc16:
|
||||
mov BANK, #1
|
||||
push dph
|
||||
push dpl
|
||||
movx a, @dptr
|
||||
; inc DPS
|
||||
mov b, a
|
||||
mov dptr, #_crc_value
|
||||
movx a, @dptr
|
||||
|
||||
xrl a, b ; create index into tables
|
||||
push a ; save index
|
||||
mov dptr, #crc16_table_l ; low part of table address
|
||||
movc a, @a+dptr ; get low byte
|
||||
mov b, a
|
||||
|
||||
mov dptr, #_crc_value + 1
|
||||
movx a, @dptr
|
||||
|
||||
xrl a, b
|
||||
mov dptr, #_crc_value
|
||||
movx @dptr, a ; save result low part
|
||||
mov dptr, #crc16_table_h ; high part of table address
|
||||
pop a ; restore index
|
||||
movc a, @a+dptr
|
||||
mov dptr, #_crc_value+1
|
||||
movx @dptr, a ; save result high part
|
||||
pop dpl
|
||||
pop dph
|
||||
; clr DPS
|
||||
ret
|
||||
|
||||
.area BANK1 (CODE)
|
||||
|
||||
crc16_table_l:
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
|
||||
crc16_table_h:
|
||||
.byte #0x00, #0xc0, #0xc1, #0x01, #0xc3, #0x03, #0x02, #0xc2
|
||||
.byte #0xc6, #0x06, #0x07, #0xc7, #0x05, #0xc5, #0xc4, #0x04
|
||||
.byte #0xcc, #0x0c, #0x0d, #0xcd, #0x0f, #0xcf, #0xce, #0x0e
|
||||
.byte #0x0a, #0xca, #0xcb, #0x0b, #0xc9, #0x09, #0x08, #0xc8
|
||||
.byte #0xd8, #0x18, #0x19, #0xd9, #0x1b, #0xdb, #0xda, #0x1a
|
||||
.byte #0x1e, #0xde, #0xdf, #0x1f, #0xdd, #0x1d, #0x1c, #0xdc
|
||||
.byte #0x14, #0xd4, #0xd5, #0x15, #0xd7, #0x17, #0x16, #0xd6
|
||||
.byte #0xd2, #0x12, #0x13, #0xd3, #0x11, #0xd1, #0xd0, #0x10
|
||||
.byte #0xf0, #0x30, #0x31, #0xf1, #0x33, #0xf3, #0xf2, #0x32
|
||||
.byte #0x36, #0xf6, #0xf7, #0x37, #0xf5, #0x35, #0x34, #0xf4
|
||||
.byte #0x3c, #0xfc, #0xfd, #0x3d, #0xff, #0x3f, #0x3e, #0xfe
|
||||
.byte #0xfa, #0x3a, #0x3b, #0xfb, #0x39, #0xf9, #0xf8, #0x38
|
||||
.byte #0x28, #0xe8, #0xe9, #0x29, #0xeb, #0x2b, #0x2a, #0xea
|
||||
.byte #0xee, #0x2e, #0x2f, #0xef, #0x2d, #0xed, #0xec, #0x2c
|
||||
.byte #0xe4, #0x24, #0x25, #0xe5, #0x27, #0xe7, #0xe6, #0x26
|
||||
.byte #0x22, #0xe2, #0xe3, #0x23, #0xe1, #0x21, #0x20, #0xe0
|
||||
.byte #0xa0, #0x60, #0x61, #0xa1, #0x63, #0xa3, #0xa2, #0x62
|
||||
.byte #0x66, #0xa6, #0xa7, #0x67, #0xa5, #0x65, #0x64, #0xa4
|
||||
.byte #0x6c, #0xac, #0xad, #0x6d, #0xaf, #0x6f, #0x6e, #0xae
|
||||
.byte #0xaa, #0x6a, #0x6b, #0xab, #0x69, #0xa9, #0xa8, #0x68
|
||||
.byte #0x78, #0xb8, #0xb9, #0x79, #0xbb, #0x7b, #0x7a, #0xba
|
||||
.byte #0xbe, #0x7e, #0x7f, #0xbf, #0x7d, #0xbd, #0xbc, #0x7c
|
||||
.byte #0xb4, #0x74, #0x75, #0xb5, #0x77, #0xb7, #0xb6, #0x76
|
||||
.byte #0x72, #0xb2, #0xb3, #0x73, #0xb1, #0x71, #0x70, #0xb0
|
||||
.byte #0x50, #0x90, #0x91, #0x51, #0x93, #0x53, #0x52, #0x92
|
||||
.byte #0x96, #0x56, #0x57, #0x97, #0x55, #0x95, #0x94, #0x54
|
||||
.byte #0x9c, #0x5c, #0x5d, #0x9d, #0x5f, #0x9f, #0x9e, #0x5e
|
||||
.byte #0x5a, #0x9a, #0x9b, #0x5b, #0x99, #0x59, #0x58, #0x98
|
||||
.byte #0x88, #0x48, #0x49, #0x89, #0x4b, #0x8b, #0x8a, #0x4a
|
||||
.byte #0x4e, #0x8e, #0x8f, #0x4f, #0x8d, #0x4d, #0x4c, #0x8c
|
||||
.byte #0x44, #0x84, #0x85, #0x45, #0x87, #0x47, #0x46, #0x86
|
||||
.byte #0x82, #0x42, #0x43, #0x83, #0x41, #0x81, #0x80, #0x40
|
||||
+8
-1
@@ -3,6 +3,12 @@
|
||||
The RTL827x provide a CPU Port for a NIC on the 8051 side of the SoC.
|
||||
|
||||
## Receiving packets
|
||||
In order to receive packets on the ASIC side, bit 0 of RTL837X_REG_RX_CTRL
|
||||
(0x785c) must be set. Further bits in the register enable reception of various
|
||||
kinds of Ethernet frames. They should all be set in order for the firmware
|
||||
to decide what to do with them. To drop packets with incorrect Ethernet frame CRC
|
||||
already by the ASIC, clear bit 2 of this register.
|
||||
|
||||
Packets are received by either polling the RTL837X_REG_RX_AVAIL register
|
||||
(0x7874), which will be > 0 if data is within a ring-buffer on the ASIC side
|
||||
of the SoC. Alternatively, an interrupt can be triggered (EX1).
|
||||
@@ -39,7 +45,8 @@ buffer on the ASIC side by writing 0x1 to RTL837X_REG_RX_DONE (0x784c).
|
||||
|
||||
## Transmissing packets
|
||||
Packets are transmitted by preparing a frame-header plus frame in xdata memory
|
||||
and transferring both to the ASIC side via the SFRs.
|
||||
and transferring both to the ASIC side via the SFRs. The ASIC will transmit
|
||||
packets if bit 0 of RTL837X_REG_TX_CTRL (0x7860) is set.
|
||||
|
||||
```
|
||||
SS 07 00 00 LL LH 00 00
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
### SWTG024AS
|
||||
SWTG024AS has at least 4 variants that look the same.
|
||||
|
||||
Variants are `managed` and a `unmanaged` version.
|
||||
But both have pcb version `v1.0` and `v2.0`.
|
||||
Also the RJ45 connectors can be all plastic/non-shielded or with metal shielding.
|
||||
|
||||
## Brands
|
||||
|Brand|Type|Managed|PCB|PCB Label|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|---|
|
||||
| LIANGUO |SWTG024AS |No| SWTG024AS-v2.0 | CM-23-11-2336 023-17453| 512kB| 8272 |
|
||||
| Haraco |ZX-SWTG124AS | Yes | SWTG024AS-v2.0 | ??? | ??? | 8272 |
|
||||
| Xikestore |SKS3200M-4GPY2XF | Yes | SWTG024AS-v1.0 | CM-23-08-2043 023-16721 | ??? | 8272 |
|
||||
|
||||
# SWTG024AS-v2.0 managed vs unmanged
|
||||
Changes I found with my board vs [Managed version](https://github.com/up-n-atom/SWTG118AS/tree/main/photos/SWGT024AS-v2.0) of the PCB.
|
||||
|
||||
### Bottom
|
||||
* R105: Installed, goes to R10-PullDown SFP2 -> TX DISABLE
|
||||
* R85: Not Installed (Connected to K1 Reset Button)
|
||||
* R90: Not installed (System Led)
|
||||
* LED3: Not installed (System Led)
|
||||
### Top
|
||||
* K1: Not installed (Reset Button)
|
||||
* R95: Installed (SFP2 signal RX-LOS), means that the managed-version can´t use the RX-LOS function.
|
||||
* R270: Installed (SFP1 signal RX-LOS), same here as above.
|
||||
* R268: Installed (SFP2 signal TX_DISABLE, but R262 200R pull-down is to high to drive by the SOC, needs mod!)
|
||||
* U5: Flash is only 512kB instead of 2/4 MBit.
|
||||
|
||||
### Notes
|
||||
* `TX Disable`-SFP2 and Button `K1` share the same GPIO pin via `R105` and `R85`.
|
||||
But via `R88`, `TX Disable`-SFP2 can be mapped to `GPIO36`.
|
||||
* `TX Disable` pull-down resistos on both SFP are to low to drive by the SOC.
|
||||
We need to make a `Best`-BOM variant so we can use all the featues.
|
||||
|
||||
# Connectors
|
||||
|`J4` SFP1 PINs | Signal | Component | GPIO | Notes |
|
||||
|---|---|---|---|---|
|
||||
|2| TX_FAULT | B-R262 | --- | |
|
||||
|3| TX_DISABLE | B-R263, T-R268 | GPIO38 | R262 = Pull-down 200R|
|
||||
|4| MODDEF2 – SDA | B-R261, T-R266 | GPIO39 | |
|
||||
|5| MODDEF1 – SCL | B-R260, T-R267 | GPIO40 | Shared with both SFP |
|
||||
|6| MODDEF0 – PRESENT | B-R259, T-R296 | GPIO30 | |
|
||||
|7| RATE SEL | B-R257 | --- | |
|
||||
|8| LOS | B-R258, T-R270 | GPIO37 | |
|
||||
|9| TO? | B-R256 | --- | |
|
||||
|
||||
|`J2` SFP2 PINs | Signal | Component | GPIO | Notes |
|
||||
|---|---|---|---|---|
|
||||
|2| TX_FAULT | B-R70 | --- | |
|
||||
|3| TX_DISABLE | B-R10, B-R105-R, T-R88-L | GPIO54 | R10 = Pull-down 200R |
|
||||
|4| MODDEF2 – SDA | B-R26, T-R85 | GPIO41 | |
|
||||
|5| MODDEF1 – SCL | B-R15, T-R87 | GPIO40 | Shared with both SFP |
|
||||
|6| MODDEF0 – PRESENT | B-R14, T-R89 | GPIO50 | |
|
||||
|7| RATE SEL | B-R12 | --- | |
|
||||
|8| LOS | B-R13, T-R95 | GPIO51 | |
|
||||
|9| TO? | B-R11 | --- | |
|
||||
|
||||
Note: component numbering `<L>-<REFDES>-<SIDE>`
|
||||
* L: Layer, T=Top, B=Bottom
|
||||
* REFDEES: full silkscreen like `R123`
|
||||
* SIDE: Side of the component. when the rj45 are facing towards you are you can read the silkscreen normal.
|
||||
L = Left, R=right, B=bottom, T=top or P with a pin number.
|
||||
|
||||
### T3
|
||||
This connector seems to go to U4 and U10.
|
||||
I thing is used to connect a external CPU to controlle the SOC.
|
||||
Even to program the flash via the SOC.
|
||||
Signals are based on that `U4` is likely a I2C-EEPROM, `U10` is likely other SPI-chip.
|
||||
|`T3` pin|what|Signal|
|
||||
|---|---|---|
|
||||
|1| U4-P6, 33R U10-P6 | I2C-SCL, SPI-CLK |
|
||||
|2| GND | --- |
|
||||
|3| U4-P5, U10-P5 | I2C-SDA, SPI-DI/DO |
|
||||
|4| VCC |
|
||||
|5| 33R -> U10-P2 | SPI-DO/D1 |
|
||||
|6| U10-P1 | SPI-CS |
|
||||
|
||||
### T5, serial console
|
||||
|`T5` pin|GPIO|Signal|
|
||||
|---|---|---|
|
||||
| 1 | GPIO31 | U0TXD (Output) |
|
||||
| 2 | GND | |
|
||||
| 3 | GPIO32 | U0RXD (Input) |
|
||||
| 4 | 3V3 | |
|
||||
|
||||
### T8
|
||||
|`T8` pin|what|Signal|
|
||||
|---|---|---|
|
||||
| 1 | GPIO46 | |
|
||||
| 2 | GND | |
|
||||
| 3 | GPIO48 | |
|
||||
| 4 | 3V3 | |
|
||||
| 5 | GPIO47 | |
|
||||
| 6 | GPIO49 | |
|
||||
|
||||
# Reset ciruit
|
||||
| Cmp | Function |
|
||||
|---|---|
|
||||
| T-R78 | 33k PullUp |
|
||||
| T-D3 | Discharge Diode |
|
||||
| T-C187 | RC-Delay |
|
||||
|
||||
Reset-line found at `T-D3-D` active-low.
|
||||
|
||||
# GPIO
|
||||
| HEX VAL. | GPIO | Component | What | | GPIO | Component | What |
|
||||
| -------- | ------ | ---- | ---- | ---- | ---- | ---- | ---- |
|
||||
| 00000001 | GPIO00 | T-C151-T, T-R28-T, T-R29-T |? | | GPIO32 | T-R143-R | U0RXD |
|
||||
| 00000002 | GPIO01 | T-C152-T |? | | GPIO33 | | |
|
||||
| 00000004 | GPIO02 | T-C153-T |? | | GPIO34 | | |
|
||||
| 00000008 | GPIO03 | T-R33-T |? | | GPIO35 | | |
|
||||
| 00000010 | GPIO04 | B-C155 |? | | GPIO36 | T-R88-L, T-R84-B | Optional SFP-TX-DIS[^2], Reset |
|
||||
| 00000020 | GPIO05 | B-C156 |? | | GPIO37 | SFP1-8, T-R270 | SFP-LOS |
|
||||
| 00000040 | GPIO06 | T-C157-T |? | | GPIO38 | SFP1-3, T-R268 | SFP-TX-DIS[^2] |
|
||||
| 00000080 | GPIO07 | T-C158-T, R165 |? | | GPIO39 | SFP1-4, T-R266 | I2C-SDA4 |
|
||||
| 00000100 | GPIO08 | | | | GPIO40 | SFP2-5, T-R87; SFP1-5, T-R267; | I2C-SCL |
|
||||
| 00000200 | GPIO09 | SFP2-LED, T-R36-T |LED-SFP2 | | GPIO41 | SFP2-4, T-R85 | I2C-SDA |
|
||||
| 00000400 | GPIO10 | | | | GPIO42 | U8-P6, T-R124 | SPI-MEMORY, CLK |
|
||||
| 00000800 | GPIO11 | |LEDx[^1] | | GPIO43 | U8-P5, T-R127 | SPI-MEMORY, DI,IO0 |
|
||||
| 00001000 | GPIO12 | |LEDx[^1] | | GPIO44 | U8-P2, T-R128 | SPI-MEMORY, DO,IO1 |
|
||||
| 00002000 | GPIO13 | PORT1-LED-GREEN |LEDx[^1] | | GPIO45 | U8-P1, T-R123 | SPI-MEMORY, CS |
|
||||
| 00004000 | GPIO14 | PORT1-LED-YELLOW |LEDx | | GPIO46 | T8-1, T-R188| ? |
|
||||
| 00008000 | GPIO15 | |LEDx[^1] | | GPIO47 | T8-5, T-R190 | ? |
|
||||
| 00010000 | GPIO16 | PORT2-LED-GREEN |LEDx[^1] | | GPIO48 | T8-3, T-R189 | ? |
|
||||
| 00020000 | GPIO17 | PORT2-LED-YELLOW |LEDx | | GPIO49 | T8-6, T-R190 | ? |
|
||||
| 00040000 | GPIO18 | |LEDx[^1] | | GPIO50 | SFP2-6, T-R89 | SFP-DETECT |
|
||||
| 00080000 | GPIO19 | PORT3-LED-GREEN |LEDx[^1] | | GPIO51 | SFP2-8, T-R95 | SFP-LOS |
|
||||
| 00100000 | GPIO20 | PORT3-LED-YELLOW |LEDx | | GPIO52 | | |
|
||||
| 00200000 | GPIO21 | |LEDx[^1] | | GPIO53 | | |
|
||||
| 00400000 | GPIO22 | PORT4-LED-GREEN |LEDx[^1] | | GPIO54 | SFP2-3, T-R105-L | SFP-TX-DIS[^2] or via T-R85 to RESET[^3], T-R84-T |
|
||||
| 00800000 | GPIO23 | PORT4-LED-YELLOW |LEDx | | GPIO55 | T-R78-B | |
|
||||
| 01000000 | GPIO24 | SFP1-LED-J4, T-R35 |LED-SFP1 | | GPIO56 | | |
|
||||
| 02000000 | GPIO25 | | | | GPIO57 | | |
|
||||
| 04000000 | GPIO26 | ? |LEDx | | GPIO58 | | |
|
||||
| 08000000 | GPIO27 | R44L |? | | GPIO59 | | |
|
||||
| 10000000 | GPIO28 | LED-SYSTEM, T-R50-R |LED-SYSTEM | | GPIO60 | | |
|
||||
| 20000000 | GPIO29 | T-R187-R | | | GPIO61 | | |
|
||||
| 40000000 | GPIO30 | SFP1-6, T-R269 |SFP-DETECT | | GPIO62 | | |
|
||||
| 80000000 | GPIO31 | T-R144-R |U0TXD| | GPIO63 | | |
|
||||
|
||||
# LEDs
|
||||
|
||||
| NAME | COMPONENTS | GPIO | Active |
|
||||
| ---- | ---------- | ---- | ------ |
|
||||
| SYSTEM | T-R50-R (PU-4k2), T-R49-L, T-C185-L, B-R90 | GPIO28 | Low |
|
||||
| SFP1 | T-R35-L (PU-3k9), T-R34-L, T-C179-L | GPIO24 | Low |
|
||||
| SFP2 | T-R36-T (PD-4k0) | GPIO09 | High |
|
||||
| PORT1-LED-YELLOW | | GPIO14 | Low |
|
||||
| PORT2-LED-YELLOW | | GPIO17 | Low |
|
||||
| PORT3-LED-YELLOW | | GPIO20 | Low |
|
||||
| PORT4-LED-YELLOW | | GPIO23 | Low |
|
||||
|
||||
# Power supply
|
||||
|
||||
Board has two supply rails.
|
||||
`0.95` and `3.3` volt.
|
||||
|
||||
## `0.95` Core Voltage.
|
||||
|
||||
Voltage is made by a `Richtek RT8120A` Buck converter.
|
||||
0.95V must be within 3%.
|
||||
|
||||
## `3.3` Voltage
|
||||
|
||||
Voltage is crated by a `TMI3244T` Buck converter.
|
||||
3.3V must be within 4.5%.
|
||||
Chip can deliver up to 4A and the sweetspot is at 1A.
|
||||
So higher power SFP-modules should work.
|
||||
|
||||
|
||||
[^1]: LEDs are found by just plugin a RJ45 connector and see with cmd `gpio` the status change. But the bit pattern for port 1,2 are diffrent from port 3,4.
|
||||
[^2]: Only on the unmanaged verions are `R10` and `R268` placed. But the very low pull-down resistor `R10` & `R262` prevent to SOC to drive does pins. A mod is needed.
|
||||
[^3]: GPIO54 is used for the reset-button. `T-R85` is placed.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.8 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.8 MiB |
@@ -32,7 +32,7 @@ cleared by the ASIC. Data then is in the output data registers
|
||||
#define RTL837x_L2_DATA_OUT_C 0x5cd4
|
||||
|
||||
DATA_OUT_A DATA_OUT_B L2_DATA_OUT_C
|
||||
M2 M3 M4 M5 fV VV M0 M1 xx xF xx xg
|
||||
M2 M3 M4 M5 fV VV M0 M1 xx xF xx gg
|
||||
|
||||
M0-M5: 6 bytes of MAC, M0 is MSB
|
||||
V: 12 bits of VLAN-ID
|
||||
@@ -41,6 +41,9 @@ f: bit 5 set: Entry is valid, otherwise stale
|
||||
bit 7: bit 1 of port-number
|
||||
g: bit 0: bit 2 of port-number
|
||||
bit 1: bit 3 of port-number (MSB)
|
||||
bit 2: bit 0 of entry-age
|
||||
bit 3: bit 1 of entry-age
|
||||
bit 4: bit 2 of entry-age (MSB)
|
||||
F: bit 0: entry is static(1) or learned (0)
|
||||
```
|
||||
The next entry can be now found in RTL837x_TBL_DATA_0 (entry = RTL837x_TBL_DATA_0_bits(0-11) + 1),
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/ports.js"></script>
|
||||
<script src="/main.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<title>EEE Configuration</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sidebar"></nav>
|
||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||
<div id="ports"></div>
|
||||
<h1>EEE Status</h1>
|
||||
<table id="eeetable">
|
||||
<tr> <th> </th> <th colspan="3"> Advertising </th> <th colspan="3">Link-Partner advertises</th> <th></th></tr>
|
||||
<tr> <th>Port</th> <th>2.5G</th> <th>1G</th> <th>100M</th> <th>2.5G</th> <th>1G</th> <th>100M</th> <th>Active?</th></tr>
|
||||
</table>
|
||||
<div>
|
||||
<input style="width:20%;" class="action" id="eee_enable" onclick="eeeSub(0, 1);" type="button" value="Enable EEE">
|
||||
<input style="width:20%;" class="action" id="eee_enable" onclick="eeeSub(0, 0);" type="button" value="Disable EEE">
|
||||
</div>
|
||||
<script src="/eee.js"></script>
|
||||
<script src="/eee_sub.js"></script>
|
||||
</div>
|
||||
<script src="/navigation.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
function createEEE() {
|
||||
var tbl = document.getElementById('eeetable');
|
||||
if (tbl.rows.length <= 2) {
|
||||
console.log("CREATING TABLE ", tbl.rows.length);
|
||||
for (let i = 2; i < 8; i++) {
|
||||
console.log("Table row: " + i + "pState: " + pState[i-2]);
|
||||
const tr = tbl.insertRow();
|
||||
let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i-1}`));
|
||||
for (let j = 0; j < 7; j++) {
|
||||
td = tr.insertCell(); td.appendChild(document.createTextNode(" "));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getEEE() {
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
const s = JSON.parse(xhttp.responseText);
|
||||
console.log("EEE: ", JSON.stringify(s));
|
||||
var tbl = document.getElementById('eeetable');
|
||||
if (tbl.rows.length > 2) {
|
||||
for (let i = 2; i < 8; i++) {
|
||||
p = s[i-2];
|
||||
let n = p.portNum;
|
||||
console.log("Table Update row: " + i + " portNum is " + n + ", pState is " + pState[i-2]);
|
||||
let tr = tbl.rows[n+1];
|
||||
if (!p.isSFP) {
|
||||
let eee = parseInt(p.eee,2); let lp = parseInt(p.eee_lp,2);
|
||||
tr.cells[1].innerHTML = `${eee&4?"ON":"OFF"}`; tr.cells[2].innerHTML = `${eee&2?"ON":"OFF"}`; tr.cells[3].innerHTML = `${eee&1?"ON":"OFF"}`;
|
||||
tr.cells[4].innerHTML = `${lp&4?"ON":"OFF"}`; tr.cells[5].innerHTML = `${lp&2?"ON":"OFF"}`; tr.cells[6].innerHTML = `${lp&1?"ON":"OFF"}`;
|
||||
tr.cells[7].innerHTML = `${p.active}`;
|
||||
tr.classList.toggle('disabled', pState[i-2] < 0); tr.classList.toggle('isNOK', !p.active); tr.classList.toggle('isOK', p.active);
|
||||
}
|
||||
tr.classList.toggle('isSFP', p.isSFP);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
xhttp.open("GET", "/eee.json", true);
|
||||
xhttp.timeout = 1500; xhttp.send();
|
||||
}
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
getEEE();
|
||||
const iCount = setInterval(getEEE, 2000);
|
||||
});
|
||||
const stat = setInterval(createEEE, 1000);
|
||||
@@ -0,0 +1,18 @@
|
||||
async function eeeSub(port, enable) {
|
||||
var cmd = "eee ";
|
||||
if (enable)
|
||||
cmd = cmd + "on";
|
||||
else
|
||||
cmd = cmd + "off";
|
||||
console.log("eeeSub port " + port, ", value " + enable);
|
||||
try {
|
||||
const response = await fetch('/cmd', {
|
||||
method: 'POST',
|
||||
body: cmd
|
||||
});
|
||||
console.log('Completed!', response);
|
||||
} catch(err) {
|
||||
console.error(`Error: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
+20
-11
@@ -1,16 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>FreeSwitchOS Main Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="ports"> <img id="port1" width="40" height="40" src="port.svg"/> <img id="port2" width="40" height="40" src="port.svg"/>
|
||||
<img id="port3" width="40" height="40" src="port.svg"/> <img id="port4" width="40" height="40" src="port.svg"/> <img id="sfp1" width="60" height="60" src="sfp.svg"/>
|
||||
<img id="sfp2" width="60" height="60" src="sfp.svg"/> </div>
|
||||
<script src="/ports.js"></script>
|
||||
<script src="/main.js"></script>
|
||||
<script src="/main_info.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<title>FreeSwitchOS Main Page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav id="sidebar"></nav>
|
||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||
<div id="ports"></div>
|
||||
<h1>Switch Configuration</h1>
|
||||
<table>
|
||||
<tr> <th>Setting</th> <th></th> </tr>
|
||||
#{html_index}
|
||||
<table id="infoTable">
|
||||
<tr>
|
||||
<th colspan="2">Settings</th>
|
||||
</tr>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</div>
|
||||
<script src="/navigation.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
var txG = new BigInt64Array(10);
|
||||
var txB = new BigInt64Array(10);
|
||||
var rxG = new BigInt64Array(10);
|
||||
var rxB = new BigInt64Array(10);
|
||||
const linkS = ["Disabled", "No Link", "100M", "1000M", "NO", "NO", "2.5G"];
|
||||
var pState = new Int8Array(10);
|
||||
var pIsSFP = new Int8Array(10);
|
||||
var numPorts = 0;
|
||||
|
||||
function update() {
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
const s = JSON.parse(xhttp.responseText);
|
||||
if (!numPorts) {
|
||||
numPorts = s.length;
|
||||
for (let i = 0; i < s.length; i++)
|
||||
pIsSFP[s[i].portNum-1] = s[i].isSFP;
|
||||
drawPorts();
|
||||
}
|
||||
console.log("RES:", JSON.stringify(s));
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
p = s[i];
|
||||
let n = p.portNum;
|
||||
let pid = "port" + n;
|
||||
n--;
|
||||
txG[n] = BigInt(p.txG); txB[n] = BigInt(p.txB); rxG[n] = BigInt(p.rxG); rxB[n] = BigInt(p.rxB);
|
||||
var psvg = document.getElementById(pid);
|
||||
if (psvg == null || !psvg.contentDocument)
|
||||
continue;
|
||||
var bgs = psvg.contentDocument.getElementsByClassName("bg");
|
||||
var leds = psvg.contentDocument.getElementsByClassName("led");
|
||||
if (p.enabled == 0) {
|
||||
pState[n] = -1;
|
||||
bgs[0].style.fill = "red";
|
||||
leds[0].style.fill = "black"; leds[1].style.fill = "black";
|
||||
psvg.style.opacity = 0.4;
|
||||
} else {
|
||||
psvg.style.opacity = 1.0;
|
||||
pState[n] = p.link;
|
||||
if (p.link == 5) {
|
||||
leds[0].style.fill = "green"; leds[1].style.fill = "orange";
|
||||
} else if (p.link == 2) {
|
||||
leds[0].style.fill = "green"; leds[1].style.fill = "green";
|
||||
} else {
|
||||
leds[0].style.fill = "black"; leds[1].style.fill = "black";
|
||||
psvg.style.opacity = 0.4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
xhttp.open("GET", "/status.json", true);
|
||||
xhttp.timeout = 5000; xhttp.send();
|
||||
}
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
update();
|
||||
const interval = setInterval(update, 2000);
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
fetch('/information.json')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const tableBody = document.getElementById('infoTable').querySelector('tbody');
|
||||
|
||||
// Create table rows
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
const row = document.createElement('tr');
|
||||
const cellKey = document.createElement('td');
|
||||
const cellValue = document.createElement('td');
|
||||
|
||||
cellKey.textContent = key;
|
||||
cellValue.textContent = value;
|
||||
|
||||
row.appendChild(cellKey);
|
||||
row.appendChild(cellValue);
|
||||
tableBody.appendChild(row);
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error fetching the data:', error));
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/ports.js"></script>
|
||||
<script src="/main.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<title>Mirror Configuration</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sidebar"></nav>
|
||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||
<div id="ports"></div>
|
||||
<h1>Mirror Configuration</h1>
|
||||
<label class="tswitch">Enabled: <input id="me" type="checkbox"><span class="slider"></span></label><br/>
|
||||
<label for="mp">Mirroring Port:</label> <input type="number" id="mp" name="mp" min="1" max="9"/>
|
||||
<h2>Mirrored Ports (TX)</h2>
|
||||
<div id="mPortsTX"></div>
|
||||
<br />
|
||||
<h2>Mirrored Ports (RX)</h2>
|
||||
<div id="mPortsRX"></div>
|
||||
<br/> <input style="width:15%;" class="action" id="mirror_sub" onclick="mirrorSub();" type="button" value="Update / Create">
|
||||
<input style="width:15%;" class="action" id="mirror_del" onclick="mirrorDel();" type="button" value="Disable Mirroring">
|
||||
<script src="/mirror.js"></script>
|
||||
<script src="/mirror_sub.js"></script>
|
||||
</div>
|
||||
<script src="/navigation.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,59 @@
|
||||
var mirrorInterval = Number();
|
||||
const mirrors = ["mPortsTX", "mPortsRX"];
|
||||
|
||||
function mirrorForm() {
|
||||
if (!numPorts)
|
||||
return;
|
||||
clearInterval(mirrorInterval);
|
||||
for (let j=0; j < mirrors.length; j++) {
|
||||
console.log("Adding Mirror " + j)
|
||||
var m = document.getElementById(mirrors[j]);
|
||||
for (let i = 1; i <= numPorts; i++) {
|
||||
const d = document.createElement("div");
|
||||
d.classList.add("cbgroup");
|
||||
const l = document.createElement("label");
|
||||
l.innerHTML = "" + i;
|
||||
l.classList.add("cbgroup");
|
||||
const inp = document.createElement("input");
|
||||
inp.type = "checkbox"; inp.setAttribute("class","psel");
|
||||
inp.id = mirrors[j] + i;
|
||||
const o = document.createElement("img");
|
||||
if (pIsSFP[i - 1]) {
|
||||
o.src = "sfp.svg"; o.width ="60"; o.height ="60";
|
||||
} else {
|
||||
o.src = "port.svg"; o.width = "40"; o.height = "40";
|
||||
}
|
||||
l.appendChild(inp); l.appendChild(o);
|
||||
d.appendChild(l)
|
||||
m.appendChild(d);
|
||||
}
|
||||
}
|
||||
fetchMirror();
|
||||
}
|
||||
|
||||
function setM(p, c){
|
||||
document.getElementById(p).checked=c;
|
||||
}
|
||||
window.addEventListener("load", function() {
|
||||
mirrorInterval = setInterval(mirrorForm, 200);
|
||||
});
|
||||
|
||||
function fetchMirror() {
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
const s = JSON.parse(xhttp.responseText);
|
||||
console.log("MIRROR: ", JSON.stringify(s));
|
||||
document.getElementById('me').checked = s.enabled;
|
||||
document.getElementById('mp').value = s.mPort;
|
||||
let m_tx = parseInt(s.mirror_tx, 2);
|
||||
let m_rx = parseInt(s.mirror_rx, 2);
|
||||
for (let i = 1; i <= numPorts; i++) {
|
||||
setM("mPortsTX"+i, m_tx&1); setM("mPortsRX"+i, m_rx&1);
|
||||
m_tx = m_tx >> 1; m_rx = m_tx >> 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
xhttp.open("GET", `/mirror.json`, true);
|
||||
xhttp.send();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
async function mirrorSub() {
|
||||
var cmd = "mirror ";
|
||||
var mp=document.getElementById('mp').value
|
||||
if (!mp) {
|
||||
alert("Set Mirroring Port first");
|
||||
return;
|
||||
}
|
||||
document.getElementById(mirrors[0]+mp).checked=false;document.getElementById(mirrors[1]+mp).checked=false;
|
||||
cmd = cmd + mp;
|
||||
for (let i = 1; i <= numPorts; i++) {
|
||||
if (document.getElementById(mirrors[0] + i).checked && document.getElementById(mirrors[1] + i).checked)
|
||||
cmd = cmd + ` ${i}`;
|
||||
else if (document.getElementById(mirrors[0] + i).checked)
|
||||
cmd = cmd + ` ${i}t`;
|
||||
else if (document.getElementById(mirrors[1] + i).checked)
|
||||
cmd = cmd + ` ${i}r`;
|
||||
}
|
||||
if (cmd.length < 10) {
|
||||
alert("Select Mirrored Ports");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response = await fetch('/cmd', {
|
||||
method: 'POST',
|
||||
body: cmd
|
||||
});
|
||||
console.log('Completed!', response);
|
||||
} catch(err) {
|
||||
console.error(`Error: ${err}`);
|
||||
}
|
||||
}
|
||||
async function mirrorDel() {
|
||||
var cmd = "mirror off";
|
||||
try {
|
||||
const response = await fetch('/cmd', {
|
||||
method: 'POST',
|
||||
body: cmd
|
||||
});
|
||||
location.reload();
|
||||
} catch(err) {
|
||||
console.error(`Error: ${err}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
document.getElementById('sidebar').innerHTML =
|
||||
"<ul><li><a href='index.html'>Overview</a></li>"
|
||||
+ "<li><a href='stat.html'>Port Statistics</a></li>"
|
||||
+ "<li><a href='vlan.html'>VLAN</a></li>"
|
||||
+ "<li><a href='mirror.html'>Mirroring</a></li>"
|
||||
+ "<li><a href='trunk.html'>Port Aggregation</a></li>"
|
||||
+ "<li><a href='eee.html'>EEE</a></li>"
|
||||
+ "<li><a href='update.html'>Firmware Update</a></li></ul>";
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@
|
||||
<g id="g1" transform="translate(256.16 417.12)">
|
||||
<rect id="r1" style="stroke:#0a0a0a;stroke-linecap:square;stroke-width:4;fill:#ffffff" rx="4.514" ry="4.514" height="90.625" width="117.88" y="69.93" x="59.896"/>
|
||||
<g id="g2"> <g id="g3">
|
||||
<path id="rect3787"
|
||||
<path class="bg" id="rect3787"
|
||||
d="m73.958 75.66h89.41c2.3083 0 4.1667 1.8583 4.1667 4.1667l0.00028 52.653h-21.742v9.414h-8.694l0.00004 12.586h-36.871l-0.00004-12.586h-8.694v-9.414h-21.742l-0.000336-52.653c-0.000011-2.3083 1.8583-4.1667 4.1667-4.1667z"
|
||||
style="stroke:#0a0a0a;stroke-linecap:square;stroke-width:2.5;fill:#dcdcdc"/>
|
||||
<g id="g4" transform="translate(-0.368)" style="stroke:#191919;stroke-linecap:square;fill:#666666">
|
||||
@@ -18,8 +18,8 @@
|
||||
<rect id="r9" height="22.786" width="3.9062" y="75.747" x="143.17"/>
|
||||
</g>
|
||||
</g>
|
||||
<rect id="r10" style="stroke:#0a0a0a;stroke-linecap:square;stroke-width:2;fill:#1dfe0a" height="13.89" width="17.1" y="137.03" x="69.542"/>
|
||||
<rect id="r11" style="stroke:#0a0a0a;stroke-linecap:square;stroke-width:2;fill:#ffd10a" height="13.89" width="17.1" y="137.03" x="150.68"/>
|
||||
<rect class="led" id="r10" style="stroke:#0a0a0a;stroke-linecap:square;stroke-width:2;fill:#1dfe0a" height="13.89" width="17.1" y="137.03" x="69.542"/>
|
||||
<rect class="led" id="r11" style="stroke:#0a0a0a;stroke-linecap:square;stroke-width:2;fill:#ffd10a" height="13.89" width="17.1" y="137.03" x="150.68"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,21 @@
|
||||
function drawPorts() {
|
||||
var f = document.getElementById('ports');
|
||||
console.log("DRAWING PORTS: ", numPorts);
|
||||
for (let i = 0; i < numPorts; i++) {
|
||||
console.log("DRAWING isSFP: ", pIsSFP[i]);
|
||||
const l = document.createElement("object");
|
||||
l.type = "image/svg+xml";
|
||||
if (!pIsSFP[i]) {
|
||||
l.data = "port.svg";
|
||||
l.width ="40";
|
||||
l.height ="40";
|
||||
} else {
|
||||
l.data = "sfp.svg";
|
||||
l.width = "60";
|
||||
l.height = "60";
|
||||
}
|
||||
l.id="port" + (i+1);
|
||||
f.appendChild(l);
|
||||
}
|
||||
console.log("DRAWING DONE ");
|
||||
}
|
||||
+5
-5
@@ -6,18 +6,18 @@
|
||||
<path id="p1"
|
||||
d="m 117.94442,272.67478 h 7.64646 c 0.21062,0 0.38018,0.16649 0.38018,0.3733 v 4.69239 c 0,0.2068 -0.16956,0.3733 -0.38018,0.3733 h -2.1027 v 0.31956 h -3.44117 v -0.31956 h -2.1027 c -0.21062,0 -0.38018,-0.16649 -0.38018,-0.3733 v -4.69239 c 0,-0.20681 0.16956,-0.3733 0.38018,-0.3733 z"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:0.4"/>
|
||||
<path id="p2"
|
||||
<path class="bg" id="p2"
|
||||
d="m 118.36775,273.15632 h 6.79794 c 0.18725,0 0.338,0.14695 0.338,0.32946 v 4.14153 c 0,0.18252 -0.15074,0.32946 -0.338,0.32946 h -6.79794 c -0.18724,0 -0.338,-0.14695 -0.338,-0.32946 v -4.14153 c 0,-0.18252 0.15074,-0.32946 0.338,-0.32946 z"
|
||||
style="fill:#000000;stroke-width:0.26" />
|
||||
<path d="m 118.65,273.53 h 6.24 v 4.05 h -6.24 z" style="fill:#1a1a1a;stroke-width:0.26" id="p3" />
|
||||
<path d="m 118.86,276.61 h 5.82" style="fill:#1a1a1a;stroke:#000000;stroke-width:0.26" id="p4" />
|
||||
<path d="m 124.05,274.25 h 1.39 v 0.72 h -1.39 z" style="fill:url(#linearGradient63614);stroke-width:0.26" id="p5" />
|
||||
<path d="m 124.05,276 h 1.39 v 0.72 h -1.39 z" style="fill:url(#linearGradient63616);stroke-width:0.26" id="p6" />
|
||||
<path d="m 124.05,274.25 h 1.39 v 0.72 h -1.39 z" style="fill:#1a1a1a;stroke-width:0.26" id="p5" />
|
||||
<path d="m 124.05,276 h 1.39 v 0.72 h -1.39 z" style="fill:#1a1a1a;stroke-width:0.26" id="p6" />
|
||||
<path transform="matrix(0.26,0,0,0.26,116.9,272.11)" d="M 7.3648613,7.0152205 H 29.369861" style="opacity:0.61257;fill:#4d4d4d;stroke:#4d4d4d;filter:url(#filter17794-0)" id="p7" />
|
||||
</g>
|
||||
<g id="g3" style="opacity:1;fill:#37d733;" transform="matrix(0.93,0,0,0.92,62.18,-43.11)">
|
||||
<circle id="c1" cx="176.86" cy="125.7" r="0.93"/>
|
||||
<circle id="c2" r="0.93" cy="125.7" cx="180.84"/>
|
||||
<circle class="led" id="c1" cx="176.86" cy="125.7" r="0.93"/>
|
||||
<circle class="led" id="c2" r="0.93" cy="125.7" cx="180.84"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/ports.js"></script>
|
||||
<script src="/main.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<title>FreeSwitchOS Port Statistics</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sidebar"></nav>
|
||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||
<div id="ports"></div>
|
||||
<h1>Port Statistics</h1>
|
||||
<table id="statstable">
|
||||
<tr> <th>Port</th> <th>link</th> <th>TX Good</th> <th>TX Bad</th> <th>RX Good</th> <th>RX Bad</th> </tr>
|
||||
<script src="/stat.js"></script>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
<script src="/navigation.js"></script>
|
||||
</html>
|
||||
@@ -0,0 +1,26 @@
|
||||
function fillStats() {
|
||||
var tbl = document.getElementById('statstable');
|
||||
if (tbl.rows.length > 1) {
|
||||
for (let i = 0; i < 6; i++) {
|
||||
console.log("Table Update row: " + i + " state " + pState[i] + " is " + linkS[pState[i] +1]);
|
||||
tbl.rows[i+1].cells[1].innerHTML = `${linkS[pState[i]+1]}`;
|
||||
tbl.rows[i+1].cells[2].innerHTML = `${txG[i]} pkts`;
|
||||
tbl.rows[i+1].cells[3].innerHTML = `${txB[i]} pkts`;
|
||||
tbl.rows[i+1].cells[4].innerHTML = `${rxG[i]} pkts`;
|
||||
tbl.rows[i+1].cells[5].innerHTML = `${rxB[i]} pkts`;
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < 6; i++) {
|
||||
console.log("Table row: " + i);
|
||||
const tr = tbl.insertRow();
|
||||
let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i+1}`));
|
||||
td = tr.insertCell(); td.appendChild(document.createTextNode(`${linkS[pState[i]+1]}`));
|
||||
td = tr.insertCell(); td.appendChild(document.createTextNode(`${txG[i]} pkts`));
|
||||
td = tr.insertCell();td.appendChild(document.createTextNode(`${txB[i]} pkts`));
|
||||
td = tr.insertCell();td.appendChild(document.createTextNode(`${rxG[i]} pkts`));
|
||||
td = tr.insertCell();td.appendChild(document.createTextNode(`${rxB[i]} pkts`));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const stat = setInterval(fillStats, 1000);
|
||||
@@ -1,11 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Statistics</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Port configuration:</h1>
|
||||
<p>#{stat_content}</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,76 @@
|
||||
h1, h2 {
|
||||
color: #226;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 12%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
li a {
|
||||
background-color: #aaf;
|
||||
display: block;
|
||||
color: #000;
|
||||
padding: 8px 16px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Change the link color on hover */
|
||||
li a:hover {
|
||||
background-color: #226;
|
||||
color: white;
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid navy;
|
||||
padding: 8px;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
td {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
input[type=submit] { padding: 8px 16px;background-color:#aaf;color:#000; margin-bottom: 2em;}
|
||||
input[type=submit]:hover { background-color: #226; color: white;}
|
||||
button {padding: 8px; background-color:#99f; color:#000;}
|
||||
button:hover { background-color: #226; color: white;}
|
||||
.psel {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-top: 1em;
|
||||
}
|
||||
.psel + img {
|
||||
cursor: pointer;
|
||||
opacity: 0.4;
|
||||
padding: 8px;
|
||||
}
|
||||
.psel:checked + img {
|
||||
/* outline: 2px solid #f00;*/
|
||||
opacity: 1.0;
|
||||
}
|
||||
object {
|
||||
margin: 0.5em 0.5em;
|
||||
}
|
||||
.cbgroup {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
.cbgroup label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.disabled{ opacity: .4; background-color: #f88; color: #000}
|
||||
.isSFP{ opacity: .4; background-color: #660;}
|
||||
.isNOK{ color: #900;}
|
||||
.isOK{ color: #090;}
|
||||
.action{padding: 8px 16px;margin-top: 2em;margin-right: 3em; background-color: #aaf;color: #000;}
|
||||
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<title>Firmware update</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sidebar"></nav>
|
||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||
<div id="ports"></div>
|
||||
<h1>Firmware Update</h1>
|
||||
<form enctype="multipart/form-data" action="/upload" method="POST">
|
||||
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
|
||||
Choose a firmware update file to upload: <input name="uploadedfile" type="file" accept=".bin" /><br />
|
||||
<input type="submit" value="Upload File" />
|
||||
</form>
|
||||
<script src="/navigation.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/ports.js"></script>
|
||||
<script src="/main.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<title>FreeSwitchOS VLAN Configuration</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sidebar"></nav>
|
||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||
<div id="ports"></div>
|
||||
<h1>VLAN Configuration</h1>
|
||||
<form id="vform" action="/vlan.html">
|
||||
<div>
|
||||
<label for="vid">VLAN ID:</label>
|
||||
<input type="number" min="1" max="2047" id="vid" name="vid">
|
||||
<button type="button" style="margin: 0 0 0 24px" onclick="fetchVLAN();">Get Configuration</button>
|
||||
</div>
|
||||
<br/><br/>
|
||||
<label for="vname">VLAN Name:</label>
|
||||
<input type="text" id="vname" name="vname"><br><br>
|
||||
<br/>
|
||||
<h2>Tagged Ports</h2>
|
||||
<div id="tPorts"><button type="button" style="transform: translateY(-100%);margin: 0 50px 0 0" onclick="utClicked(true);">Select all</button></div>
|
||||
<h2>Untagged Ports</h2>
|
||||
<div id="uPorts"><button type="button" style="transform: translateY(-100%); margin: 0 50px 0 0" onclick="utClicked(false);">Select all</button> </div>
|
||||
<script src="/vlan.js"></script>
|
||||
<br/> <input style="width:40%;" class="action" id="vlan_sub" onclick="vlanSub();" type="button" value="Update / Create">
|
||||
<script src="/vlan_sub.js"></script>
|
||||
</form>
|
||||
</div>
|
||||
<script src="/navigation.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,70 @@
|
||||
var vlanInterval = Number();
|
||||
|
||||
function vlanForm() {
|
||||
if (!numPorts)
|
||||
return;
|
||||
clearInterval(vlanInterval);
|
||||
var t = document.getElementById('tPorts');
|
||||
var u = document.getElementById('uPorts');
|
||||
for (let i = 1; i <= numPorts; i++) {
|
||||
const d = document.createElement("div");
|
||||
d.classList.add("cbgroup");
|
||||
const l = document.createElement("label");
|
||||
l.innerHTML = "" + i;
|
||||
l.classList.add("cbgroup");
|
||||
const inp = document.createElement("input");
|
||||
inp.type = "checkbox"; inp.setAttribute("class","psel");
|
||||
inp.id = "tport" + i;
|
||||
inp.setAttribute('onclick', `setC("u", ${i}, false);`);
|
||||
const o = document.createElement("img");
|
||||
if (pIsSFP[i - 1]) {
|
||||
o.src = "sfp.svg"; o.width ="60"; o.height ="60";
|
||||
} else {
|
||||
o.src = "port.svg"; o.width = "40"; o.height = "40";
|
||||
}
|
||||
l.appendChild(inp); l.appendChild(o);
|
||||
d.appendChild(l)
|
||||
t.appendChild(d);
|
||||
var d2=d.cloneNode(true);
|
||||
d2.children[0].children[0].id = "uport" + i;
|
||||
d2.children[0].children[0].setAttribute('onclick', `setC("t", ${i}, false);`);
|
||||
u.appendChild(d2);
|
||||
}
|
||||
}
|
||||
|
||||
function setC(t, p, c){
|
||||
document.getElementById(t+'port'+p).checked=c;
|
||||
}
|
||||
|
||||
function utClicked(t){
|
||||
for (let i = 1; i <= numPorts; i++) {
|
||||
setC('t', i, t); setC('u', i, !t);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
vlanInterval = setInterval(vlanForm, 100);
|
||||
});
|
||||
|
||||
function fetchVLAN() {
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
const s = JSON.parse(xhttp.responseText);
|
||||
console.log("VLAN: ", JSON.stringify(s));
|
||||
m = parseInt(s.members, 16);
|
||||
document.getElementById('vname').value = s.name;
|
||||
for (let i = 1; i <= numPorts; i++) {
|
||||
setC('t', i, (m>>(10+i-1))&1);
|
||||
setC('u', i, (m>>(i-1))&1);
|
||||
}
|
||||
}
|
||||
};
|
||||
var v=document.getElementById('vid').value
|
||||
if (!v) {
|
||||
alert("Set VLAN ID first");
|
||||
return;
|
||||
}
|
||||
xhttp.open("GET", `/vlan.json?vid=${v}`, true);
|
||||
xhttp.send();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
async function vlanSub() {
|
||||
var cmd = "vlan ";
|
||||
var v=document.getElementById('vid').value
|
||||
if (!v) {
|
||||
alert("Set VLAN ID first");
|
||||
return;
|
||||
}
|
||||
cmd = cmd + v;
|
||||
if (document.getElementById('vname').value)
|
||||
cmd = cmd + ' ' + document.getElementById('vname').value;
|
||||
for (let i = 1; i <= numPorts; i++) {
|
||||
if (document.getElementById('tport' + i).checked)
|
||||
cmd = cmd + ` ${i}t`;
|
||||
else if (document.getElementById('uport' + i).checked)
|
||||
cmd = cmd + ` ${i}`;
|
||||
}
|
||||
try {
|
||||
const response = await fetch('/cmd', {
|
||||
method: 'POST',
|
||||
body: cmd
|
||||
});
|
||||
console.log('Completed!', response);
|
||||
} catch(err) {
|
||||
console.error(`Error: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-9
@@ -3,21 +3,24 @@ CC_FLAGS = -mmcs51 -I. -I../uip
|
||||
ASM = sdas8051
|
||||
AFLAGS= -plosgff
|
||||
|
||||
BUILDDIR = output/
|
||||
|
||||
SRCS = httpd.c page_impl.c
|
||||
OBJS = ${SRCS:.c=.rel}
|
||||
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
|
||||
|
||||
all: $(OBJS)
|
||||
all: create_build_dir $(OBJS)
|
||||
|
||||
%.asm: %.c
|
||||
$(CC) $(CC_FLAGS) -c -S $<
|
||||
create_build_dir:
|
||||
mkdir -p $(BUILDDIR)
|
||||
|
||||
%.rel: %.asm
|
||||
./treatasm.py $^ >$^.new
|
||||
mv $^.new $^
|
||||
${ASM} ${AFLAGS} $^
|
||||
$(BUILDDIR)%.asm: %.c
|
||||
$(CC) $(CC_FLAGS) -o $@ -c -S $<
|
||||
|
||||
$(BUILDDIR)%.rel: $(BUILDDIR)%.asm
|
||||
${ASM} ${AFLAGS} -o $@ $^
|
||||
|
||||
clean:
|
||||
rm .asm *.lst *.rel *.rst *.sym
|
||||
rm -r $(BUILDDIR)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
|
||||
+373
-72
@@ -1,45 +1,77 @@
|
||||
|
||||
#include "httpd.h"
|
||||
#include "page_impl.h"
|
||||
#include "../rtl837x_common.h"
|
||||
#include "../cmd_parser.h"
|
||||
#include "../rtl837x_flash.h"
|
||||
#include "uip.h"
|
||||
#include "../html_data.h"
|
||||
|
||||
// Upload Firmware to 1M
|
||||
#define FIRMWARE_UPLOAD_START 0x100000
|
||||
|
||||
// SPI FLASH MEMORY PAGE SIZE.
|
||||
#define FLASHMEM_PAGE_SIZE 0x100
|
||||
|
||||
#define CMARK_S 6
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
extern __code struct f_data f_data[];
|
||||
extern __code fcall_ptr f_calls[];
|
||||
extern __code char * __code mime_strings[];
|
||||
extern __xdata struct flash_region_t flash_region;
|
||||
|
||||
// Flash buffer to optimize flash writing speed, write_len is the current filling position
|
||||
extern __xdata uint8_t flash_buf[512];
|
||||
__xdata uint32_t uptr; // Current flash write position
|
||||
__xdata uint16_t write_len;
|
||||
|
||||
__xdata uint8_t outbuf[TCP_OUTBUF_SIZE];
|
||||
__xdata uint8_t entry;
|
||||
__xdata uint16_t slen;
|
||||
__xdata uint16_t o_idx;
|
||||
__xdata uint16_t mpos;
|
||||
__xdata uint16_t len_left;
|
||||
|
||||
// HTTP header properties
|
||||
__xdata uint8_t boundary[72];
|
||||
__xdata uint8_t *content_type = 0;
|
||||
|
||||
// Global variables holding POST state
|
||||
__xdata uint16_t bindex; // Current index into the boundary
|
||||
|
||||
__xdata uint16_t short_parsed;
|
||||
|
||||
#define TSTATE_NONE 0
|
||||
#define TSTATE_TX 1
|
||||
#define TSTATE_ACKED 2
|
||||
#define TSTATE_CLOSED 3
|
||||
#define TSTATE_POST 4
|
||||
|
||||
extern __xdata uint16_t crc_value;
|
||||
__xdata uint16_t crc_final;
|
||||
void crc16(__xdata uint8_t *v) __naked;
|
||||
|
||||
|
||||
inline uint8_t is_space(uint8_t c)
|
||||
inline uint8_t is_separator(uint8_t c)
|
||||
{
|
||||
return c == ' ' || c == '\t';
|
||||
return c == ' ' || c == '\t' || c == '?' || c == '=';
|
||||
}
|
||||
|
||||
|
||||
void httpd_init(void) __banked
|
||||
{
|
||||
__xdata struct httpd_state *s = &(uip_conn->appstate);
|
||||
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
|
||||
// Start listening to port 80
|
||||
uip_listen(HTONS(80));
|
||||
s->tstate = TSTATE_CLOSED;
|
||||
}
|
||||
|
||||
|
||||
uint8_t find_entry(uint8_t *e)
|
||||
uint8_t find_entry(__xdata uint8_t *e)
|
||||
{
|
||||
register uint8_t i, j;
|
||||
uint8_t i, j;
|
||||
|
||||
for (i = 0; f_data[i].len; i++) {
|
||||
j = 0;
|
||||
@@ -54,10 +86,272 @@ uint8_t find_entry(uint8_t *e)
|
||||
}
|
||||
|
||||
|
||||
char strcmp(__xdata uint8_t *c, __code uint8_t * __xdata d)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
while (d[i] && (d[i] == c[i]))
|
||||
i++;
|
||||
|
||||
if (c[i] < d[i])
|
||||
return -1;
|
||||
else if (c[i] > d[i])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char is_word(__xdata uint8_t *c, __code uint8_t * __xdata d)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
while (d[i] && (d[i] == c[i]))
|
||||
i++;
|
||||
|
||||
if (d[i])
|
||||
return 0;
|
||||
if (c[i] != ' ' && c[i] != '\t' && c[i] != ':' && c[i] != '?' && c[i] != '=' && c[i] != '\n' && c[i] != '\r' && c[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
char is_word_x(__xdata uint8_t *c, __xdata uint8_t *d)
|
||||
{
|
||||
register uint8_t i = 0;
|
||||
|
||||
while (d[i] && (d[i] == c[i]))
|
||||
i++;
|
||||
|
||||
if (d[i])
|
||||
return 0;
|
||||
if (c[i] != ' ' && c[i] != '\t' && c[i] != ':' && c[i] != '?' && c[i] != '=' && c[i] != '\n' && c[i] != '\r' && c[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
uint8_t parse_short(__xdata uint8_t *p)
|
||||
{
|
||||
uint8_t err = 1;
|
||||
uint8_t c = 0;
|
||||
|
||||
short_parsed = 0;
|
||||
while(1) {
|
||||
c = *p++ - '0';
|
||||
if (c > 9) { break; }
|
||||
err = 0;
|
||||
short_parsed = (short_parsed * 10) + c;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void send_not_found(void)
|
||||
{
|
||||
slen = strtox(outbuf, "HTTP/1.1 404 Not found\r\nContent-Type: text/html\r\n\r\n" \
|
||||
"<!DOCTYPE HTML PUBLIC>\n<title>404 Not Found</title>\n<h1>Not Found</h1>\n");
|
||||
}
|
||||
|
||||
|
||||
void send_bad_request(void)
|
||||
{
|
||||
slen = strtox(outbuf, "HTTP/1.1 400 Bad Request\r\nContent-Type: text/html\r\n\r\n" \
|
||||
"<!DOCTYPE HTML PUBLIC>\n<title>400 Bad Request</title>\n<h1>Bad Request</h1>\n");
|
||||
}
|
||||
|
||||
|
||||
__xdata uint8_t *skip_boundary(__xdata uint8_t *p)
|
||||
{
|
||||
while (*p) {
|
||||
if (is_word_x(p, boundary))
|
||||
return p + strlen_x(boundary);
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
__xdata uint8_t *scan_header(__xdata uint8_t *p)
|
||||
{
|
||||
content_type = 0;
|
||||
|
||||
while (*p != '\r' || *(p + 1) != '\n' || *(p + 2) != '\r' || *(p + 3) != '\n') {
|
||||
write_char(*p);
|
||||
if (!*p++)
|
||||
break;
|
||||
if (is_word(p, "\nContent-Type:"))
|
||||
content_type = p + 15;
|
||||
}
|
||||
if (content_type && is_word(content_type, "multipart/form-data; boundary")) {
|
||||
print_string("\nFound multiplart\n");
|
||||
content_type += 30;
|
||||
uint8_t i = 0;
|
||||
while (content_type[i] != '\r' && content_type[i] != '\n') {
|
||||
boundary[i + 4] = content_type[i];
|
||||
i++;
|
||||
}
|
||||
// The boundary between parts is "\r\n--" + the boundary given in the header
|
||||
boundary[0] = '\r';
|
||||
boundary[1] = '\n';
|
||||
boundary[2] = '-';
|
||||
boundary[3] = '-';
|
||||
boundary[i + 4] = 0;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reads post data from the http stream and writes it into flash memory
|
||||
* Input: the current position in the TCP buffer (uip_appdata)
|
||||
* Returns 1: More data to read, 0: Upload complete, all parts reads
|
||||
*/
|
||||
uint8_t stream_upload(uint16_t bptr)
|
||||
{
|
||||
__xdata uint8_t *p = uip_appdata;
|
||||
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
|
||||
|
||||
print_string("Stream_upload called: ");
|
||||
print_short(bptr); write_char('\n');
|
||||
|
||||
do {
|
||||
if (bptr >= uip_len) {
|
||||
s->tstate = TSTATE_POST;
|
||||
return 1;
|
||||
}
|
||||
// Have we reached the end of the part?
|
||||
if (!boundary[bindex]) {
|
||||
s->tstate = TSTATE_NONE;
|
||||
print_string("len 2: "); print_short(write_len); write_char(' ');
|
||||
flash_region.addr = uptr;
|
||||
flash_region.len = write_len;
|
||||
flash_write_bytes(flash_buf);
|
||||
uptr += write_len;
|
||||
write_len = 0;
|
||||
// TODO: This is a bit premature, what about a nice web-page saying the device will reset???
|
||||
print_string("CRC16: "); print_short(crc_final); write_char('\n');
|
||||
if (crc_final == 0xb001) {
|
||||
print_string("Checksum OK.");
|
||||
} else {
|
||||
print_string("Checksum incorrect!");
|
||||
}
|
||||
print_string("Upload to flash done, will reset!\n");
|
||||
reset_chip();
|
||||
if (bptr >= uip_len)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if (p[bptr] == boundary[bindex]) {
|
||||
if (!bindex)
|
||||
crc_final = crc_value;
|
||||
crc16(p + bptr);
|
||||
bptr++;
|
||||
bindex++;
|
||||
} else {
|
||||
if (bindex) {
|
||||
memcpy(flash_buf + write_len, boundary, bindex);
|
||||
write_len += bindex;
|
||||
bindex = 0;
|
||||
}
|
||||
crc16(p + bptr);
|
||||
flash_buf[write_len++] = p[bptr++];
|
||||
if (write_len >= FLASHMEM_PAGE_SIZE) {
|
||||
print_string("len: "); print_short(write_len); write_char(' ');
|
||||
print_string("CRC16: "); print_short(crc_value); write_char('\n');
|
||||
flash_region.addr = uptr;
|
||||
flash_region.len = FLASHMEM_PAGE_SIZE;
|
||||
flash_write_bytes(flash_buf);
|
||||
uptr += FLASHMEM_PAGE_SIZE;
|
||||
write_len -= FLASHMEM_PAGE_SIZE;
|
||||
|
||||
// Copy the remaining byte for the next page to the beginning of the buffer.
|
||||
if (write_len > 0) {
|
||||
memcpy(flash_buf, flash_buf + FLASHMEM_PAGE_SIZE, write_len);
|
||||
}
|
||||
}
|
||||
bindex = 0;
|
||||
}
|
||||
} while(1);
|
||||
}
|
||||
|
||||
|
||||
void handle_post(void)
|
||||
{
|
||||
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
|
||||
__xdata uint8_t *p = uip_appdata;
|
||||
__xdata uint8_t *request_path = p + 6;
|
||||
|
||||
print_string("Is POST\n");
|
||||
p += 5; // Skip post
|
||||
// Find end of request path
|
||||
while (*p && !is_separator(*p))
|
||||
p++;
|
||||
*p++ = '\0';
|
||||
|
||||
// Find end of request header
|
||||
boundary[0] ='\0';
|
||||
p = scan_header(p);
|
||||
print_string("Boundary: >"); print_string_x(boundary); print_string("<\n");
|
||||
if (!*p || !content_type) {
|
||||
print_string("Bad Request!\n");
|
||||
send_not_found();
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_word(request_path, "cmd")) {
|
||||
register uint8_t i = 0;
|
||||
p += 4;
|
||||
while (*p && *p != '\n' && *p != '\r')
|
||||
cmd_buffer[i++] = *p++;
|
||||
cmd_buffer[i] = '\0';
|
||||
if (i)
|
||||
cmd_available = 1;
|
||||
} else if (is_word(request_path, "upload")) {
|
||||
print_string("POST upload request\n");
|
||||
if (!boundary[0]) {
|
||||
print_string("Bad request, no boundary!\n");
|
||||
send_bad_request();
|
||||
return;
|
||||
}
|
||||
// We skip the intial parts as part of the header
|
||||
do {
|
||||
p = skip_boundary(p);
|
||||
if (!*p)
|
||||
goto bad_request;
|
||||
p = scan_header(p);
|
||||
if (!*p)
|
||||
goto bad_request;
|
||||
if (!content_type) // We are waiting for the part with the octet stream
|
||||
continue;
|
||||
} while (!is_word(content_type, "application/octet-stream"));
|
||||
print_string("Have content octets\n");
|
||||
p += 4; // Skip \r\n\r\n sequence at end of preamble of part
|
||||
|
||||
uptr = FIRMWARE_UPLOAD_START;
|
||||
crc_value = 0;
|
||||
bindex = 0;
|
||||
write_len = 0;
|
||||
stream_upload(p - uip_appdata);
|
||||
|
||||
print_string("Done reading first fragment\n");
|
||||
return;
|
||||
|
||||
} else {
|
||||
send_not_found();
|
||||
return;
|
||||
}
|
||||
slen = strtox(outbuf, "HTTP/1.1 200 OK\r\n\r\n");
|
||||
return;
|
||||
bad_request:
|
||||
send_bad_request();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void httpd_appcall(void)
|
||||
{
|
||||
__xdata struct httpd_state *s = &(uip_conn->appstate);
|
||||
__xdata uint8_t *outbuf = s->outbuf;
|
||||
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
|
||||
|
||||
write_char('P');
|
||||
if(uip_connected() && s->tstate == TSTATE_CLOSED) {
|
||||
@@ -66,49 +360,66 @@ void httpd_appcall(void)
|
||||
} else if (uip_closed()) {
|
||||
print_string("Connection closed\n");
|
||||
s->tstate = TSTATE_CLOSED;
|
||||
} else if (uip_aborted()) {
|
||||
print_string("Connection aborted\n");
|
||||
uip_close();
|
||||
s->tstate = TSTATE_CLOSED;
|
||||
} else if (uip_poll()) {
|
||||
uip_len = 0;
|
||||
if (s->tstate == TSTATE_ACKED) {
|
||||
print_string("Closing because everything has been transmitted\n");
|
||||
uip_close();
|
||||
s->tstate = TSTATE_CLOSED;
|
||||
}
|
||||
// write_char('p');
|
||||
} else if (uip_acked() && s->tstate == TSTATE_TX) {
|
||||
print_string("ACK\n");
|
||||
if (s->slen > uip_mss()) {
|
||||
s->slen -= uip_mss();
|
||||
s->o_idx += uip_mss();
|
||||
if (slen > uip_mss()) {
|
||||
slen -= uip_mss();
|
||||
o_idx += uip_mss();
|
||||
} else {
|
||||
s->slen = 0;
|
||||
s->o_idx += s->slen;
|
||||
slen = 0;
|
||||
o_idx += slen;
|
||||
}
|
||||
|
||||
s->tstate = TSTATE_ACKED;
|
||||
|
||||
if (s->slen > uip_mss()) {
|
||||
print_string("Sending A: "); print_short(s->slen); write_char('\n');
|
||||
uip_send(outbuf + s->o_idx, uip_mss());
|
||||
if (slen > uip_mss()) {
|
||||
print_string("Sending A: "); print_short(slen); write_char('\n');
|
||||
uip_send(outbuf + o_idx, uip_mss());
|
||||
print_string("Sending A done\n");
|
||||
s->tstate = TSTATE_TX;
|
||||
} else if (s->slen > 0) {
|
||||
print_string("Sending B: "); print_short(s->slen); write_char('\n');
|
||||
uip_send(outbuf + s->o_idx, s->slen);
|
||||
} else if (slen > 0) {
|
||||
print_string("Sending B: "); print_short(slen); write_char('\n');
|
||||
uip_send(outbuf + o_idx, slen);
|
||||
print_string("Sending B done\n");
|
||||
s->tstate = TSTATE_TX;
|
||||
}
|
||||
} else if (uip_newdata() && s->tstate == TSTATE_POST) {
|
||||
stream_upload(0);
|
||||
} else if (uip_newdata() && s->tstate != TSTATE_TX) {
|
||||
write_char('<'); print_short(uip_len); write_char('\n');
|
||||
__xdata uint8_t *p = uip_appdata;
|
||||
// Mark end of request header with \0
|
||||
p[uip_len] = 0;
|
||||
while (*p)
|
||||
write_char(*p++);
|
||||
write_char('\n');
|
||||
p = uip_appdata;
|
||||
if (p[0] == 'G' && p[1] == 'E' && p[2] == 'T' && p[3] == ' ')
|
||||
if (is_word(p, "POST")) {
|
||||
handle_post();
|
||||
// If this is an ongoing post stream, then wait for the next packet
|
||||
if (s->tstate == TSTATE_POST) {
|
||||
uip_len = 0;
|
||||
return;
|
||||
}
|
||||
goto do_send;
|
||||
}
|
||||
|
||||
if (is_word(p, "GET"))
|
||||
print_string("GET request ");
|
||||
p += 4;
|
||||
__xdata uint8_t *q = p;
|
||||
while (!is_space(*p))
|
||||
while (!is_separator(*p))
|
||||
p++;
|
||||
*p = '\0';
|
||||
print_string_x(q);
|
||||
@@ -118,68 +429,58 @@ void httpd_appcall(void)
|
||||
entry = find_entry(q);
|
||||
print_string("Entry is: "); print_byte(entry); write_char('\n');
|
||||
if (entry == 0xff) {
|
||||
print_string("Not found\n");
|
||||
s->slen = strtox(outbuf, "HTTP/1.1 404 Not found\r\nContent-Type: text/html\r\n\r\n");
|
||||
print_string("slen: "); print_short(s->slen); write_char('\n');
|
||||
s->slen += strtox(outbuf + s->slen, "<!DOCTYPE HTML PUBLIC>\n<title>404 Not Found</title>\n<h1>Not Found</h1>\n");
|
||||
print_string("Not file entry\n");
|
||||
if (!strcmp(q, "/status.json")) {
|
||||
send_status();
|
||||
} else if (!strcmp(q, "/information.json")) {
|
||||
send_basic_info();
|
||||
} else if (!strcmp(q, "/vlan.json")) {
|
||||
parse_short(q + 15);
|
||||
send_vlan(short_parsed);
|
||||
} else if (is_word(q, "/counters.json")) {
|
||||
send_counters(q[19]-'0');
|
||||
} else if (is_word(q, "/eee.json")) {
|
||||
send_eee();
|
||||
} else if (is_word(q, "/mirror.json")) {
|
||||
send_mirror();
|
||||
} else {
|
||||
send_not_found();
|
||||
}
|
||||
} else {
|
||||
print_string("Have entry\n");
|
||||
s->slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: ");
|
||||
s->slen += strtox(outbuf + s->slen, f_data[entry].mime);
|
||||
s->slen += strtox(outbuf + s->slen, "\r\n\r\n");
|
||||
slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: ");
|
||||
slen += strtox(outbuf + slen, mime_strings[f_data[entry].mime]);
|
||||
slen += strtox(outbuf + slen, "\r\nCache-Control: max-age=2592000\r\n\r\n");
|
||||
len_left = f_data[entry].len;
|
||||
if (f_data[entry].mime[0] == 't' && f_data[entry].mime[5] == 'h') {
|
||||
print_string("MIME is html len is "); print_short(len_left); write_char('\n');
|
||||
mpos = 0;
|
||||
flash_find_mark(f_data[entry].start, len_left, "#{");
|
||||
print_string("mpos: "); print_short(mpos); write_char('\n');
|
||||
while (mpos != 0xffff) {
|
||||
print_string("Entry-len:"); print_short(len_left); write_char('\n');
|
||||
mpos = len_left - mpos;
|
||||
print_string("l/pos: "); print_short(mpos); write_char('\n');
|
||||
flash_read_bulk(outbuf + s->slen, f_data[entry].start + f_data[entry].len - len_left, mpos + CMARK_S); // call marker is e.g. #{001}
|
||||
s->slen += mpos;
|
||||
write_char('@'); write_char(outbuf[s->slen + 2]); write_char(outbuf[s->slen + 3]); write_char(outbuf[s->slen + 4]);
|
||||
fcall_ptr ptr = f_calls[(outbuf[s->slen + 2] - '0') * 100 + (outbuf[s->slen + 3]-'0') * 10 + outbuf[s->slen + 4] - '0'];
|
||||
s->slen -= CMARK_S; // Overwrite marker with generated html
|
||||
print_string("Call location is: "); print_short((uint16_t)ptr); write_char('\n');
|
||||
// f_calls[outbuf[s->slen + 2] * 100 + outbuf[s->slen + 3] * 10 + outbuf[s->slen + 4]]();
|
||||
ptr(outbuf);
|
||||
print_string("call done\n");
|
||||
mpos += CMARK_S;
|
||||
len_left -= mpos;
|
||||
flash_find_mark(f_data[entry].start + mpos, len_left, "#{");
|
||||
}
|
||||
print_string("At end mpos: "); print_short(mpos); write_char('\n');
|
||||
flash_read_bulk(outbuf + s->slen, f_data[entry].start + f_data[entry].len - len_left, len_left);
|
||||
s->slen += len_left;
|
||||
} else {
|
||||
print_string("MIME: "); print_string(f_data[entry].mime); write_char('\n');
|
||||
flash_read_bulk(outbuf + s->slen, f_data[entry].start, len_left);
|
||||
s->slen += len_left;
|
||||
}
|
||||
|
||||
print_string("MIME: "); print_string(mime_strings[f_data[entry].mime]); write_char('\n');
|
||||
flash_region.addr = f_data[entry].start;
|
||||
flash_region.len = len_left;
|
||||
flash_read_bulk(outbuf + slen);
|
||||
slen += len_left;
|
||||
}
|
||||
print_string("slen: "); print_short(s->slen); write_char('\n');
|
||||
s->o_idx = 0;
|
||||
if (s->slen > uip_mss()) {
|
||||
print_string("Sending a: "); print_short(s->slen); write_char('\n');
|
||||
uip_send(outbuf + s->o_idx, uip_mss());
|
||||
do_send:
|
||||
print_string("slen: "); print_short(slen); write_char('\n');
|
||||
o_idx = 0;
|
||||
if (slen > uip_mss()) {
|
||||
print_string("Sending a: "); print_short(slen); write_char('\n');
|
||||
uip_send(outbuf + o_idx, uip_mss());
|
||||
print_string("Sending a done\n");
|
||||
} else {
|
||||
print_string("Sending b: "); print_short(s->slen); write_char('\n');
|
||||
uip_send(outbuf + s->o_idx, s->slen);
|
||||
print_string("Sending b: "); print_short(slen); write_char('\n');
|
||||
uip_send(outbuf + o_idx, slen);
|
||||
print_string("Sending b done\n");
|
||||
}
|
||||
s->tstate = TSTATE_TX;
|
||||
} else if (uip_rexmit()) { // Connection established, need to rexmit?
|
||||
print_string("RETRANSMIT requested\n");
|
||||
if (s->slen > uip_mss()) {
|
||||
print_string("Sending C: "); print_short(s->slen); write_char('\n');
|
||||
uip_send(outbuf + s->o_idx, uip_mss());
|
||||
if (slen > uip_mss()) {
|
||||
print_string("Sending C: "); print_short(slen); write_char('\n');
|
||||
uip_send(outbuf + o_idx, uip_mss());
|
||||
print_string("Sending C done\n");
|
||||
} else if (s->slen > 0) {
|
||||
print_string("Sending D: "); print_short(s->slen); write_char('\n');
|
||||
uip_send(outbuf + s->o_idx, s->slen);
|
||||
} else if (slen > 0) {
|
||||
print_string("Sending D: "); print_short(slen); write_char('\n');
|
||||
uip_send(outbuf + o_idx, slen);
|
||||
print_string("Sending D done\n");
|
||||
}
|
||||
s->tstate = TSTATE_TX;
|
||||
|
||||
+2
-5
@@ -1,5 +1,5 @@
|
||||
#ifndef __HELLO_WORLD_H__
|
||||
#define __HELLO_WORLD_H__
|
||||
#ifndef __HTTPD_H__
|
||||
#define __HTTPD_H__
|
||||
|
||||
/* Since this file will be included by uip.h, we cannot include uip.h
|
||||
here. But we might need to include uipopt.h if we need the u8_t and
|
||||
@@ -12,9 +12,6 @@
|
||||
for each TCP connection. */
|
||||
typedef struct httpd_state {
|
||||
uint8_t tstate;
|
||||
uint8_t outbuf[2048];
|
||||
uint16_t slen;
|
||||
uint16_t o_idx;
|
||||
} uip_tcp_appstate_t;
|
||||
|
||||
/* Finally we define the application function to be called by uIP. */
|
||||
|
||||
+341
-48
@@ -1,78 +1,371 @@
|
||||
// #define REGDBG 1
|
||||
|
||||
#include "../rtl837x_sfr.h"
|
||||
#include "../rtl837x_common.h"
|
||||
#include "../rtl837x_regs.h"
|
||||
#include "../rtl837x_port.h"
|
||||
#include "uip.h"
|
||||
#include "../html_data.h"
|
||||
#include <stdint.h>
|
||||
#include "../phy.h"
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE];
|
||||
extern __xdata uint16_t slen;
|
||||
extern __code uint8_t * __code hex;
|
||||
extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
|
||||
extern __code uint8_t ownMAC[];
|
||||
extern __code struct uip_eth_addr uip_ethaddr;
|
||||
extern __code uint8_t log_to_phys_port[9];
|
||||
extern __code uint8_t phys_to_log_port[6];
|
||||
|
||||
#define PUTC(c) *outbuf++ = c;
|
||||
extern __xdata uint8_t minPort;
|
||||
extern __xdata uint8_t maxPort;
|
||||
extern __xdata uint8_t nSFPPorts;
|
||||
extern __xdata uint8_t sfr_data[4];
|
||||
extern __xdata uint8_t cpuPort;
|
||||
extern __xdata uint8_t isRTL8373;
|
||||
extern __xdata uint8_t sfp_pins_last;
|
||||
extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
|
||||
|
||||
#define PUTBYTE(a) { *outbuf++ = hex[(a >> 4) & 0xf]; *outbuf++ = hex[a & 0xf]; }
|
||||
__code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
|
||||
|
||||
inline uint8_t itoa_html(uint8_t v, __xdata uint8_t *outbuf)
|
||||
/* Convert only the lower nibble to ascii HEX char.
|
||||
For convenience the upper nibble is masked out.
|
||||
*/
|
||||
inline char itohex(uint8_t val) {
|
||||
// Ignore upper nibble for convenience.
|
||||
val &= 0x0f;
|
||||
val -= 10;
|
||||
|
||||
// 10 or above
|
||||
if ((int8_t)val >= 0)
|
||||
val += ('a' - '0' - 10);
|
||||
|
||||
return val + ('0' + 10);
|
||||
}
|
||||
|
||||
// Convert uint8_t to ascii HEX char push on html-buffer.
|
||||
void charhex_to_html(char c)
|
||||
{
|
||||
uint8_t t = (v / 100) % 10;
|
||||
if (t)
|
||||
PUTC('0' + t);
|
||||
t = (v / 10) % 10;
|
||||
if (t)
|
||||
PUTC('0' + t);
|
||||
PUTC('0' + (v % 10));
|
||||
|
||||
if (v >= 100)
|
||||
return 3;
|
||||
else if (v >= 10)
|
||||
return 2;
|
||||
else
|
||||
return 1;
|
||||
outbuf[slen++] = itohex(c);
|
||||
}
|
||||
|
||||
|
||||
uint16_t stat_content(__xdata uint8_t *outbuf)
|
||||
// Convert (uint8_t) bool to ascii '0' or '1' char push on html-buffer.
|
||||
void bool_to_html(char c)
|
||||
{
|
||||
outbuf[slen++] = c ? '1' : '0';
|
||||
}
|
||||
|
||||
|
||||
void char_to_html(char c)
|
||||
{
|
||||
outbuf[slen++] = c;
|
||||
}
|
||||
|
||||
|
||||
// Convert uint8_t to ascii HEX char.
|
||||
void byte_to_html(uint8_t val)
|
||||
{
|
||||
uint8_t cnt = 2;
|
||||
do {
|
||||
val = (val >> 4) | (val << 4);
|
||||
charhex_to_html(val);
|
||||
cnt -= 1;
|
||||
} while(cnt);
|
||||
}
|
||||
|
||||
/* Converts a uint8_t to raw string.
|
||||
Suppress leading zeros.
|
||||
*/
|
||||
void itoa_html(uint8_t v)
|
||||
{
|
||||
uint8_t t = (v / 100);
|
||||
// when print_zeros is not zero, we know that a non-zero number has printed.
|
||||
// That have to print all the next numbers.
|
||||
uint8_t print_zeros = t;
|
||||
if (print_zeros)
|
||||
char_to_html('0' + t);
|
||||
t = (v / 10) % 10;
|
||||
print_zeros |= t;
|
||||
if (print_zeros)
|
||||
char_to_html('0' + t);
|
||||
char_to_html('0' + (v % 10));
|
||||
}
|
||||
|
||||
|
||||
uint16_t stat_content(void)
|
||||
{
|
||||
print_string("stat_content called\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint16_t port_status(__xdata uint8_t *outbuf)
|
||||
uint16_t port_status(void)
|
||||
{
|
||||
print_string("port_status called\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint16_t html_index(__xdata uint8_t *outbuf)
|
||||
/* Converts sfr_data[] into raw hex string.
|
||||
Suppress leading zeros.
|
||||
*/
|
||||
void sfr_data_to_html(void)
|
||||
{
|
||||
__xdata uint8_t *oldptr = outbuf;
|
||||
uint8_t print_zeros = 0;
|
||||
uint8_t val = 0;
|
||||
|
||||
print_string("html_index called\n");
|
||||
outbuf += strtox(outbuf, "<tr><td>IP Address</td><td>");
|
||||
outbuf += itoa_html(uip_hostaddr[0], outbuf); PUTC('.');
|
||||
outbuf += itoa_html(uip_hostaddr[0] >> 8, outbuf); PUTC('.');
|
||||
outbuf += itoa_html(uip_hostaddr[1], outbuf); PUTC('.');
|
||||
outbuf += itoa_html(uip_hostaddr[1] >> 8, outbuf);
|
||||
outbuf += strtox(outbuf, "</td></tr><tr><td>Gateway</td><td>");
|
||||
outbuf += itoa_html(uip_draddr[0], outbuf); PUTC('.');
|
||||
outbuf += itoa_html(uip_draddr[0] >> 8, outbuf); PUTC('.');
|
||||
outbuf += itoa_html(uip_draddr[1], outbuf); PUTC('.');
|
||||
outbuf += itoa_html(uip_draddr[1] >> 8, outbuf);
|
||||
outbuf += strtox(outbuf, "</td></tr><tr><td>Netmask</td><td>");
|
||||
outbuf += itoa_html(uip_netmask[0], outbuf); PUTC('.');
|
||||
outbuf += itoa_html(uip_netmask[0] >> 8, outbuf); PUTC('.');
|
||||
outbuf += itoa_html(uip_netmask[1], outbuf); PUTC('.');
|
||||
outbuf += itoa_html(uip_netmask[1] >> 8, outbuf);
|
||||
outbuf += strtox(outbuf, "</td></tr><tr><td>MAC Address</td><td>");
|
||||
PUTBYTE(ownMAC[0]); PUTC(':');
|
||||
PUTBYTE(ownMAC[1]); PUTC(':');
|
||||
PUTBYTE(ownMAC[2]); PUTC(':');
|
||||
PUTBYTE(ownMAC[3]); PUTC(':');
|
||||
PUTBYTE(ownMAC[4]); PUTC(':');
|
||||
PUTBYTE(ownMAC[5]);
|
||||
outbuf += strtox(outbuf, "</td></tr>");
|
||||
|
||||
return outbuf - oldptr;
|
||||
for (uint8_t nibble = 0; nibble < 8; nibble++) {
|
||||
if (!(nibble & 1))
|
||||
val = sfr_data[nibble>>1];
|
||||
// force the swap instruction, itohex() ignores the upper nibble.
|
||||
val = (val << 4) | (val >> 4);
|
||||
// when print_zeros is not zero, we know that a non-zero number has printed.
|
||||
// That have to print all the next numbers.
|
||||
print_zeros |= val;
|
||||
// only care about lower nibble, that is what is printed.
|
||||
print_zeros &= 0x0f;
|
||||
if (print_zeros)
|
||||
charhex_to_html(val);
|
||||
}
|
||||
if (print_zeros == 0) {
|
||||
char_to_html('0');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reg_to_html(register uint16_t reg)
|
||||
{
|
||||
reg_read_m(reg);
|
||||
sfr_data_to_html();
|
||||
}
|
||||
|
||||
void send_basic_info(void)
|
||||
{
|
||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||
print_string("send_basic_info called\n");
|
||||
slen += strtox(outbuf + slen, "{\"ip_address\":\"");
|
||||
itoa_html(uip_hostaddr[0]); char_to_html('.');
|
||||
itoa_html(uip_hostaddr[0] >> 8); char_to_html('.');
|
||||
itoa_html(uip_hostaddr[1]); char_to_html('.');
|
||||
itoa_html(uip_hostaddr[1] >> 8);
|
||||
slen += strtox(outbuf + slen, "\",\"ip_gateway\":\"");
|
||||
itoa_html(uip_draddr[0]); char_to_html('.');
|
||||
itoa_html(uip_draddr[0] >> 8); char_to_html('.');
|
||||
itoa_html(uip_draddr[1]); char_to_html('.');
|
||||
itoa_html(uip_draddr[1] >> 8);
|
||||
slen += strtox(outbuf + slen, "\",\"ip_netmask\":\"");
|
||||
itoa_html(uip_netmask[0]); char_to_html('.');
|
||||
itoa_html(uip_netmask[0] >> 8); char_to_html('.');
|
||||
itoa_html(uip_netmask[1]); char_to_html('.');
|
||||
itoa_html(uip_netmask[1] >> 8);
|
||||
slen += strtox(outbuf + slen, "\",\"mac_address\":\"");
|
||||
byte_to_html(uip_ethaddr.addr[0]); char_to_html(':');
|
||||
byte_to_html(uip_ethaddr.addr[1]); char_to_html(':');
|
||||
byte_to_html(uip_ethaddr.addr[2]); char_to_html(':');
|
||||
byte_to_html(uip_ethaddr.addr[3]); char_to_html(':');
|
||||
byte_to_html(uip_ethaddr.addr[4]); char_to_html(':');
|
||||
byte_to_html(uip_ethaddr.addr[5]);
|
||||
slen += strtox(outbuf + slen, "\",\"sw_ver\":\"v0.1-ge4c48586\",\"hw_ver\":\"SWGT024-V2.0\"}");
|
||||
// slen += strtox(outbuf + slen, "\"}");
|
||||
}
|
||||
|
||||
|
||||
void send_vlan(uint16_t vlan)
|
||||
{
|
||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||
print_string("sending VLAN\n");
|
||||
//{"members":"0x00060011"}
|
||||
slen += strtox(outbuf + slen, "{\"members\":\"0x");
|
||||
vlan_get(vlan);
|
||||
sfr_data_to_html();
|
||||
slen += strtox(outbuf + slen, "\",\"name\":\"");
|
||||
__xdata uint16_t n = vlan_name(vlan);
|
||||
if (n== 0xffff) {
|
||||
print_string("VLAN has no name\n");
|
||||
} else {
|
||||
while(vlan_names[n] && vlan_names[n] != ' ')
|
||||
char_to_html(vlan_names[n++]);
|
||||
}
|
||||
slen += strtox(outbuf + slen, "\"}");
|
||||
}
|
||||
|
||||
|
||||
void send_counters(char port)
|
||||
{
|
||||
print_string("send_counters called: "); print_byte(port); write_char('\n');
|
||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||
print_string("sending counters\n");
|
||||
|
||||
port--;
|
||||
uint8_t i = isRTL8373 ? port - 1: phys_to_log_port[port];
|
||||
slen += strtox(outbuf + slen, "{\"portNum\":");
|
||||
itoa_html(i + 1);
|
||||
for (uint8_t j = 0; j < 0x3f; j++) {
|
||||
STAT_GET(j, i);
|
||||
slen += strtox(outbuf + slen, ",\"cnt_");
|
||||
itoa_html(j);
|
||||
slen += strtox(outbuf + slen, "\":\"0x");
|
||||
reg_to_html(RTL837X_STAT_V_HIGH);
|
||||
reg_to_html(RTL837X_STAT_V_LOW);
|
||||
char_to_html('\"');
|
||||
}
|
||||
char_to_html('}');
|
||||
}
|
||||
|
||||
|
||||
void send_mirror(void)
|
||||
{
|
||||
print_string("send_eee called\n");
|
||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||
print_string("sending EEE status\n");
|
||||
|
||||
reg_read_m(RTL837x_MIRROR_CTRL);
|
||||
uint8_t mPort = sfr_data[3];
|
||||
if (mPort & 1) {
|
||||
slen += strtox(outbuf + slen, "{\"enabled\":1,\"mPort\":");
|
||||
} else {
|
||||
slen += strtox(outbuf + slen, "{\"enabled\":0,\"mPort\":");
|
||||
}
|
||||
if (!isRTL8373)
|
||||
itoa_html(log_to_phys_port[mPort >> 1]);
|
||||
else
|
||||
itoa_html((mPort >> 1) + 1);
|
||||
|
||||
reg_read_m(RTL837x_MIRROR_CONF);
|
||||
uint16_t m = sfr_data[0];
|
||||
m = (m << 8) | sfr_data[1];
|
||||
slen += strtox(outbuf + slen, ",\"mirror_rx\":\"");
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
bool_to_html(m & 0x8000);
|
||||
m <<= 1;
|
||||
}
|
||||
m = sfr_data[2];
|
||||
m = (m << 8) | sfr_data[3];
|
||||
slen += strtox(outbuf + slen, "\",\"mirror_tx\":\"");
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
bool_to_html(m & 0x8000);
|
||||
m <<= 1;
|
||||
}
|
||||
char_to_html('\"');
|
||||
char_to_html('}');
|
||||
}
|
||||
|
||||
|
||||
void send_eee(void)
|
||||
{
|
||||
print_string("send_eee called\nsending EEE status\n");
|
||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||
|
||||
reg_read_m(RTL8373_PHY_EEE_ABLTY);
|
||||
uint8_t eee_ablty = sfr_data[3];
|
||||
|
||||
char_to_html('[');
|
||||
for (uint8_t i = minPort; i <= maxPort; i++) {
|
||||
slen += strtox(outbuf + slen, "{\"portNum\":");
|
||||
if (!isRTL8373)
|
||||
itoa_html(log_to_phys_port[i]);
|
||||
else
|
||||
itoa_html(i + 1);
|
||||
|
||||
if (IS_SFP(i)) {
|
||||
slen += strtox(outbuf + slen, ",\"isSFP\":1");
|
||||
} else {
|
||||
slen += strtox(outbuf + slen, ",\"isSFP\":0,\"eee\":\"");
|
||||
uint16_t v;
|
||||
phy_read(i, PHY_MMD_AN, PHY_EEE_ADV2);
|
||||
v = SFR_DATA_U16;
|
||||
bool_to_html(v & PHY_EEE_BIT_2G5);
|
||||
|
||||
phy_read(i, PHY_MMD_AN, PHY_EEE_ADV);
|
||||
v = SFR_DATA_U16;
|
||||
bool_to_html(v & PHY_EEE_BIT_1G);
|
||||
bool_to_html(v & PHY_EEE_BIT_100M);
|
||||
|
||||
phy_read(i, PHY_MMD_AN, PHY_EEE_LP_ABILITY2);
|
||||
v = SFR_DATA_U16;
|
||||
slen += strtox(outbuf + slen, "\",\"eee_lp\":\"");
|
||||
bool_to_html (v & PHY_EEE_BIT_2G5);
|
||||
|
||||
phy_read(i, PHY_MMD_AN, PHY_EEE_LP_ABILITY);
|
||||
v = SFR_DATA_U16;
|
||||
bool_to_html(v & PHY_EEE_BIT_1G);
|
||||
bool_to_html(v & PHY_EEE_BIT_100M);
|
||||
|
||||
slen += strtox(outbuf + slen, "\",\"active\":");
|
||||
bool_to_html(eee_ablty & (1 << i));
|
||||
}
|
||||
char_to_html('}');
|
||||
if (i < maxPort)
|
||||
char_to_html(',');
|
||||
else
|
||||
char_to_html(']');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void send_status(void)
|
||||
{
|
||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||
print_string("sending status\n");
|
||||
char_to_html('[');
|
||||
|
||||
for (uint8_t i = minPort; i <= maxPort; i++) {
|
||||
slen += strtox(outbuf + slen, "{\"portNum\":");
|
||||
if (!isRTL8373)
|
||||
itoa_html(log_to_phys_port[i]);
|
||||
else
|
||||
itoa_html(i + 1);
|
||||
|
||||
if (IS_SFP(i)) {
|
||||
slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":");
|
||||
bool_to_html(!((sfp_pins_last >> (i == maxPort ? 0 : 4)) & 1));
|
||||
|
||||
slen += strtox(outbuf + slen, ",\"link\":");
|
||||
uint8_t rate = sfp_read_reg(i == maxPort ? 0 : 1, 12);
|
||||
if (rate == 0xd)
|
||||
char_to_html('2'); // 1000BX
|
||||
else if (rate == 0x1f)
|
||||
char_to_html('5'); // 2G5
|
||||
else if (rate > 0x65 && rate < 0x70)
|
||||
char_to_html('4'); // 10G "4" is not a valid value for port LINK speed
|
||||
else
|
||||
char_to_html('1'); // 100M ???
|
||||
} else {
|
||||
slen += strtox(outbuf + slen, ",\"isSFP\":0,\"enabled\":");
|
||||
phy_read(i, 0x1f, 0xa610);
|
||||
bool_to_html(SFR_DATA_8 == 0x20);
|
||||
|
||||
slen += strtox(outbuf + slen, ",\"link\":");
|
||||
reg_read_m(RTL837X_REG_LINKS);
|
||||
uint8_t b = sfr_data[3 - (i >> 1)];
|
||||
b = (i & 1) ? b >> 4 : b & 0xf;
|
||||
char_to_html('0' + b);
|
||||
}
|
||||
STAT_GET(STAT_COUNTER_TX_PKTS, i);
|
||||
slen += strtox(outbuf + slen, ",\"txG\":\"0x");
|
||||
reg_to_html(RTL837X_STAT_V_HIGH);
|
||||
reg_to_html(RTL837X_STAT_V_LOW);
|
||||
|
||||
slen += strtox(outbuf + slen, "\",\"txB\":\"0x");
|
||||
STAT_GET(STAT_COUNTER_ERR_PKTS, i);
|
||||
reg_to_html(RTL837X_STAT_V_LOW); // 32 bit Tx Packet errors
|
||||
|
||||
slen += strtox(outbuf + slen, "\",\"rxG\":\"0x");
|
||||
STAT_GET(STAT_COUNTER_RX_PKTS, i);
|
||||
reg_to_html(RTL837X_STAT_V_HIGH);
|
||||
reg_to_html(RTL837X_STAT_V_LOW);
|
||||
|
||||
slen += strtox(outbuf + slen, "\",\"rxB\":\"0x");
|
||||
STAT_GET(STAT_COUNTER_ERR_PKTS, i);
|
||||
reg_to_html(RTL837X_STAT_V_HIGH); // 32bit RX packet errors
|
||||
slen += strtox(outbuf + slen, "\"}");
|
||||
if (i < maxPort)
|
||||
char_to_html(',');
|
||||
else
|
||||
char_to_html(']');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef __PAGE_IMPL_H__
|
||||
#define __PAGE_IMPL_H__
|
||||
|
||||
void send_counters(char port);
|
||||
void send_status(void);
|
||||
void send_vlan(register uint16_t vlan);
|
||||
void send_basic_info(void);
|
||||
void send_eee(void);
|
||||
void send_mirror(void);
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python3
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
CODE_LOCATION=0x1000
|
||||
INSTALLER_ADDRESS=0x1100
|
||||
|
||||
CC = sdcc
|
||||
CC_FLAGS = -mmcs51
|
||||
ASM = sdas8051
|
||||
AFLAGS= -plosgff
|
||||
|
||||
BUILDDIR = output/
|
||||
|
||||
SRCS = installer.c
|
||||
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
|
||||
|
||||
all: create_build_dir $(BUILDDIR)updatebuilder $(BUILDDIR)rtlplayground.bin
|
||||
|
||||
create_build_dir:
|
||||
mkdir -p $(BUILDDIR)
|
||||
|
||||
$(BUILDDIR)updatebuilder: updatebuilder.c
|
||||
gcc $^ -o $@
|
||||
|
||||
$(BUILDDIR)installer.rel: installer.c
|
||||
$(CC) $(CC_FLAGS) --code-loc ${CODE_LOCATION} -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)crtstart.rel: crtstart.asm
|
||||
$(ASM) $(AFLAGS) -o $@ $<
|
||||
|
||||
$(BUILDDIR)%.rel: $(BUILDDIR)%.asm
|
||||
${ASM} ${AFLAGS} -o $@ $^
|
||||
|
||||
$(BUILDDIR)%.rel: %.c
|
||||
$(CC) $(CC_FLAGS) -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)rtlinstaller.ihx: $(BUILDDIR)crtstart.rel $(OBJS)
|
||||
$(CC) $(CC_FLAGS) -Wl-bHOME=${INSTALLER_ADDRESS} -Wl-r -o $@ $^
|
||||
|
||||
$(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlinstaller.ihx ../$(BUILDDIR)/rtlplayground.bin
|
||||
cp ../$(BUILDDIR)/rtlplayground.bin $(BUILDDIR)
|
||||
./$(BUILDDIR)/updatebuilder -i $< $(BUILDDIR)rtlplayground.bin
|
||||
|
||||
clean:
|
||||
rm -r $(BUILDDIR)
|
||||
@@ -0,0 +1,26 @@
|
||||
.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 + 0x1000
|
||||
ljmp _isr_ext0 ; 0x03
|
||||
.ds 5
|
||||
ljmp _isr_timer0 ; 0x0b
|
||||
.ds 5
|
||||
ljmp _isr_ext1 ; 0x13
|
||||
.globl __start__stack
|
||||
|
||||
.area GSINIT0 (CODE)
|
||||
|
||||
__sdcc_gsinit_startup:
|
||||
mov sp,#__start__stack - 1
|
||||
|
||||
.area GSFINAL (CODE)
|
||||
ljmp _installer
|
||||
@@ -0,0 +1,375 @@
|
||||
#include <8051.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// #define REGDBG 1
|
||||
// #define RXTXDBG 1
|
||||
|
||||
#define UPDATE_LOC 0x0001D000
|
||||
#define HEADER_LENGTH 0x14
|
||||
#define UPDATE_CODE_LOC (UPDATE_LOC + HEADER_LENGTH)
|
||||
|
||||
#include "../rtl837x_sfr.h"
|
||||
#include "../rtl837x_regs.h"
|
||||
|
||||
#define SYS_TICK_HZ 100
|
||||
#define SERIAL_BAUD_RATE 57600
|
||||
#define CLOCK_HZ 125000000
|
||||
|
||||
// Derive the divider settings for the internal clock
|
||||
#if CLOCK_HZ == 20800000
|
||||
#define CLOCK_DIV 3
|
||||
#elif CLOCK_HZ == 31250000
|
||||
#define CLOCK_DIV 2
|
||||
#elif CLOCK_HZ == 62500000
|
||||
#define CLOCK_DIV 1
|
||||
#elif CLOCK_HZ == 125000000
|
||||
#define CLOCK_DIV 0
|
||||
#endif
|
||||
|
||||
volatile __xdata uint32_t ticks;
|
||||
volatile __xdata uint8_t sec_counter;
|
||||
volatile __xdata uint16_t sleep_ticks;
|
||||
|
||||
// We buffer 1 sector as this is also the erase size
|
||||
__xdata uint8_t buffer[0x1000];
|
||||
__xdata uint8_t dio_enabled;
|
||||
|
||||
__code uint8_t * __code hex = "0123456789abcdef";
|
||||
|
||||
void isr_timer0(void) __interrupt(1)
|
||||
{
|
||||
TR0 = 0; // Stop timer 0
|
||||
TH0 = (0x10000 - (CLOCK_HZ / SYS_TICK_HZ / 32)) >> 8;
|
||||
TL0 = (0x10000 - (CLOCK_HZ / SYS_TICK_HZ / 32)) % 0xff;
|
||||
|
||||
ticks++;
|
||||
if (sleep_ticks > 0)
|
||||
sleep_ticks--;
|
||||
sec_counter++;
|
||||
|
||||
TR0 = 1; // Re-start timer 0
|
||||
}
|
||||
|
||||
|
||||
void isr_ext0(void) __interrupt(0)
|
||||
{
|
||||
EX0 = 0; // Disable interrupt for the moment
|
||||
IT0 = 1; // Trigger on falling edge of external interrupt
|
||||
EX0 = 1; // Re-enable interrupt
|
||||
}
|
||||
|
||||
|
||||
void isr_ext1(void) __interrupt(2)
|
||||
{
|
||||
EX1 = 0;
|
||||
EX1 = 1;
|
||||
}
|
||||
|
||||
|
||||
void write_char(char c)
|
||||
{
|
||||
do {
|
||||
} while (TI == 0);
|
||||
TI = 0;
|
||||
if (c =='\n') {
|
||||
SBUF = '\r';
|
||||
do {
|
||||
} while (TI == 0);
|
||||
TI = 0;
|
||||
}
|
||||
SBUF = c;
|
||||
}
|
||||
|
||||
|
||||
void print_string(__code char *p)
|
||||
{
|
||||
while (*p)
|
||||
write_char(*p++);
|
||||
}
|
||||
|
||||
|
||||
void print_byte(uint8_t a)
|
||||
{
|
||||
write_char(hex[(a >> 4) & 0xf]);
|
||||
write_char(hex[a & 0xf]);
|
||||
}
|
||||
|
||||
void print_short(uint16_t a)
|
||||
{
|
||||
print_string("0x");
|
||||
for (signed char i = 12; i >= 0; i -= 4) {
|
||||
write_char(hex[(a >> i) & 0xf]);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_serial(void)
|
||||
{
|
||||
IE = 0;
|
||||
|
||||
T2CON = 0x34; // Enable RCLK/TCLK (serial transmit/receive clock for T2), TR2 (Timer 2 RUN), disable CP/RL2 (bit 0)
|
||||
SCON = 0x50; // Mode = 1: ASYNC 8N1 with T2 as baud-rate generator, REN_0 Receive enable
|
||||
|
||||
// The RCAP2 registers contain the high/low byte that is loaded into
|
||||
// timer2 when T2 overflows to 0x10000
|
||||
RCAP2H = (0x10000 - (CLOCK_HZ / SERIAL_BAUD_RATE / 32)) >> 8;
|
||||
RCAP2L = (0x10000 - (CLOCK_HZ / SERIAL_BAUD_RATE / 32)) % 0xff;
|
||||
|
||||
PCON |= 0x80; // Double the Baud Rate
|
||||
|
||||
SCON = 0x50;
|
||||
TI = 1;
|
||||
RI = 0;
|
||||
|
||||
ES = 1; // Enable serial IRQ
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure Memory Managed IO
|
||||
*/
|
||||
void flash_configure_mmio(void)
|
||||
{
|
||||
// Set configuration for MMIO access by controller
|
||||
if (dio_enabled) {
|
||||
SFR_FLASH_MODEB = 0x18;
|
||||
SFR_FLASH_CMD_R = 0xbb; // By default we read with Dual speed
|
||||
SFR_FLASH_DUMMYCYCLES = 4;
|
||||
return;
|
||||
}
|
||||
|
||||
SFR_FLASH_MODEB = 0x0;
|
||||
SFR_FLASH_CMD_R = 0xb; // By default we read with single speed
|
||||
SFR_FLASH_DUMMYCYCLES = 8;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initializes the flash controller for programmed control
|
||||
* The configuration options are not really understood, the SPI speed
|
||||
* seems to be directly linked to the CPU frequency
|
||||
* This configures fast single IO at 20.8 MHz when the CPU clock is at 20.8MHz
|
||||
* and 62.5MHz when the CPU clock is configured at 125MHz
|
||||
*/
|
||||
void flash_init(uint8_t enable_dio)
|
||||
{
|
||||
if (enable_dio) {
|
||||
// Configure fast DIO via divider/DIO/SIOconfig = 4 and read-cmd being 0xbb (for mmio)
|
||||
SFR_FLASH_CONFIG = 9; // There may be a chip-select in here
|
||||
SFR_FLASH_CONF_RCMD = 0xbb;
|
||||
SFR_FLASH_CONF_DIV = 4;
|
||||
} else {
|
||||
// Configure fast read via divider = 8 and read-cmd being 0xb (for mmio)
|
||||
SFR_FLASH_CONFIG = 9;
|
||||
SFR_FLASH_CONF_RCMD = 0xb;
|
||||
SFR_FLASH_CONF_DIV = 8;
|
||||
}
|
||||
// Test Controller Busy
|
||||
while(SFR_FLASH_EXEC_BUSY);
|
||||
|
||||
// Write 0 to status register
|
||||
SFR_FLASH_DUMMYCYCLES = 8;
|
||||
SFR_FLASH_MODEB = 0;
|
||||
SFR_FLASH_TCONF = 0x19;
|
||||
SFR_FLASH_CMD = 1;
|
||||
SFR_FLASH_DATA0 = 0;
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
while(SFR_FLASH_EXEC_BUSY);
|
||||
|
||||
dio_enabled = enable_dio;
|
||||
flash_configure_mmio();
|
||||
}
|
||||
|
||||
|
||||
uint8_t flash_read_status(void)
|
||||
{
|
||||
// Test Controller Busy (we might call this directly after executing a command)
|
||||
while(SFR_FLASH_EXEC_BUSY);
|
||||
|
||||
// setup status read command
|
||||
SFR_FLASH_TCONF = 0x11;
|
||||
SFR_FLASH_CMD_R = 5;
|
||||
|
||||
// execute and wait for controller done
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
while(SFR_FLASH_EXEC_BUSY);
|
||||
|
||||
return SFR_FLASH_DATA0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, register uint16_t len)
|
||||
{
|
||||
short status;
|
||||
do {
|
||||
status = flash_read_status();
|
||||
} while (status & 0x1);
|
||||
|
||||
// Set fast read mode
|
||||
if (dio_enabled) {
|
||||
SFR_FLASH_MODEB = 0x18;
|
||||
SFR_FLASH_CMD_R = 0xbb;
|
||||
SFR_FLASH_DUMMYCYCLES = 4;
|
||||
} else {
|
||||
SFR_FLASH_MODEB = 0x0;
|
||||
SFR_FLASH_CMD_R = 0xb; // Fast read
|
||||
SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks after read?
|
||||
}
|
||||
// Read 4 bytes
|
||||
SFR_FLASH_TCONF = 4;
|
||||
while (len) {
|
||||
SFR_FLASH_ADDR16 = src >> 16;
|
||||
SFR_FLASH_ADDR8 = src >> 8;
|
||||
SFR_FLASH_ADDR0 = src;
|
||||
src += 4;
|
||||
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
while(SFR_FLASH_EXEC_BUSY);
|
||||
|
||||
*dst++ = SFR_FLASH_DATA0;
|
||||
if (len == 1)
|
||||
return;
|
||||
*dst++ = SFR_FLASH_DATA8;
|
||||
if (len == 2)
|
||||
return;
|
||||
*dst++ = SFR_FLASH_DATA16;
|
||||
if (len == 3)
|
||||
return;
|
||||
*dst++ = SFR_FLASH_DATA24;
|
||||
|
||||
len -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flash_write_enable(void)
|
||||
{
|
||||
short status;
|
||||
|
||||
// Wait until busy bit clear
|
||||
do {
|
||||
status = flash_read_status();
|
||||
} while (status & 0x1);
|
||||
// while (flash_read_status() & 0x1);
|
||||
|
||||
SFR_FLASH_TCONF = 0x18;
|
||||
SFR_FLASH_CMD = 6;
|
||||
SFR_FLASH_DUMMYCYCLES = 0;
|
||||
SFR_FLASH_MODEB = 0;
|
||||
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
// Wait for write status enabled
|
||||
do {
|
||||
status = flash_read_status();
|
||||
} while (!(status & 0x2));
|
||||
}
|
||||
|
||||
|
||||
// Erases the 4k sector in which the address lies
|
||||
void flash_sector_erase(uint32_t addr)
|
||||
{
|
||||
flash_write_enable();
|
||||
SFR_FLASH_TCONF = 8;
|
||||
SFR_FLASH_CMD = 0x20;
|
||||
|
||||
SFR_FLASH_ADDR16 = addr >> 16;
|
||||
SFR_FLASH_ADDR8 = addr >> 8;
|
||||
SFR_FLASH_ADDR0 = addr;
|
||||
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
while (flash_read_status() & 0x1);
|
||||
|
||||
flash_configure_mmio();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void flash_write_bytes(__xdata uint32_t addr, __xdata uint8_t *ptr, uint16_t len)
|
||||
{
|
||||
uint8_t exit_loop = 0;
|
||||
|
||||
while(1) {
|
||||
flash_write_enable();
|
||||
SFR_FLASH_CMD = 2;
|
||||
SFR_FLASH_TCONF = 0x40 | 8 | 4; // Bytes written is 4, 8 enables write, 0x40 is unknown
|
||||
// Last transfer?
|
||||
if (len < 5) {
|
||||
SFR_FLASH_TCONF = 8 | len;
|
||||
exit_loop = 1;
|
||||
}
|
||||
|
||||
SFR_FLASH_ADDR16 = addr >> 16;
|
||||
SFR_FLASH_ADDR8 = addr >> 8;
|
||||
SFR_FLASH_ADDR0 = addr;
|
||||
SFR_FLASH_DATA0 = *ptr++;
|
||||
SFR_FLASH_DATA8 = *ptr++;
|
||||
SFR_FLASH_DATA16 = *ptr++;
|
||||
SFR_FLASH_DATA24 = *ptr++;
|
||||
|
||||
// Execute transfer, we wait for completion at top of loop
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
if (exit_loop)
|
||||
break;
|
||||
len -= 4;
|
||||
addr += 4;
|
||||
}
|
||||
|
||||
while (flash_read_status() & 0x1);
|
||||
flash_configure_mmio();
|
||||
}
|
||||
|
||||
|
||||
void reg_write(uint16_t reg_addr)
|
||||
{
|
||||
/* Data to write must be in SFR A4, A5, A6, A7 */
|
||||
SFR_REG_ADDR_U16 = reg_addr;
|
||||
SFR_EXEC_GO = SFR_EXEC_WRITE_REG;
|
||||
do {
|
||||
} while (SFR_EXEC_STATUS != 0);
|
||||
}
|
||||
|
||||
|
||||
void installer(void)
|
||||
{
|
||||
|
||||
CKCON = 0; // Initial Clock configuration
|
||||
SFR_97 = 0; // HADDR?
|
||||
|
||||
// Set in managed mode:
|
||||
SFR_b9 = 0x00;
|
||||
SFR_ba = 0x80;
|
||||
|
||||
// Disable all interrupts (global and individually) by setting IE register (SFR A8) to 0
|
||||
IE = 0;
|
||||
EIE = 0; // SFR e8: EIE. Disable all external IRQs
|
||||
|
||||
// Disable all interrupts (global interrupt enable bit)
|
||||
EA = 0; // SFR A8.7 / IE.7
|
||||
|
||||
setup_serial();
|
||||
print_string("\nRTLPlayground installer starting...\n");
|
||||
|
||||
// Initialize flash functions with disable DIO because writing does not work otherwise
|
||||
flash_init(0);
|
||||
|
||||
__xdata uint32_t dest = 0x0;
|
||||
__xdata uint32_t source = UPDATE_CODE_LOC;
|
||||
// A 512kByte = 4MBit Flash has 128 sectors, we copy only 120
|
||||
for (uint8_t i=0; i < 120; i++) {
|
||||
print_string("Moving block\n");
|
||||
flash_read_bulk(buffer, source, 0x1000);
|
||||
for (uint8_t j = 0; j < 32; j++) {
|
||||
write_char(' '); print_byte(buffer[j]);
|
||||
}
|
||||
write_char('\n');
|
||||
flash_sector_erase(dest);
|
||||
flash_write_bytes(dest, buffer, 0x1000);
|
||||
dest += 0x1000;
|
||||
source += 0x1000;
|
||||
}
|
||||
print_string("Done.\n");
|
||||
print_string("Reseting now\n");
|
||||
REG_SET(RTL837X_REG_RESET, 1);
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Adds data files into specified locations of an image, optionally creates
|
||||
* an index in the form of a header file
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <argp.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define HEADER_LENGTH 0x14
|
||||
#define HEADER_MAGIC 0x12345678
|
||||
#define HEADER_RESERVED 0x332255ff
|
||||
|
||||
#define SEG_01002_LENGTH 0x2ffe
|
||||
#define SEG_1C000_LENGTH 0x1000
|
||||
#define SEG_1d000_OFFSET 0x3ffe
|
||||
|
||||
|
||||
// Use a 4MB buffer, the maximum flash rom size
|
||||
#define BUFFER_SIZE 0x400000
|
||||
uint8_t buffer[BUFFER_SIZE];
|
||||
FILE *inptr;
|
||||
int outptr;
|
||||
char line[256];
|
||||
|
||||
const char *argp_program_version = "updatebuilder 0.1";
|
||||
const char *argp_program_bug_address = "<git@logicog.de>";
|
||||
static char doc[] = "Create an update image for RTL837X-based switches";
|
||||
static char args_doc[] = "INPUT_IMAGE";
|
||||
static struct argp_option options[] = {
|
||||
{ "magic", 'm', "MAGIC", 0, "Magic number"},
|
||||
{ "reserved", 'r', "MAGIC", 0, "Reserved number"},
|
||||
{ "installer", 'i', "FILE", 0, "Installer file"},
|
||||
{ "output", 'o', "FILE", 0, "Output file"},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
struct arguments {
|
||||
uint32_t reserved;
|
||||
uint32_t magic;
|
||||
char *installer_file;
|
||||
char *output_file;
|
||||
};
|
||||
|
||||
|
||||
int get_byte(int pos)
|
||||
{
|
||||
int c1 = line[pos];
|
||||
if (c1 >= '0' && c1 <= '9')
|
||||
c1 -= '0';
|
||||
else if (c1 >= 'a' && c1 <= 'f')
|
||||
c1 = c1 - 'a' + 10;
|
||||
else if (c1 >= 'A' && c1 <= 'F')
|
||||
c1 = c1 - 'A' + 10;
|
||||
else
|
||||
return -1;
|
||||
|
||||
int c2 = line[pos + 1];
|
||||
if (c2 >= '0' && c2 <= '9')
|
||||
c2 -= '0';
|
||||
else if (c2 >= 'a' && c2 <= 'f')
|
||||
c2 = c2 - 'a' + 10;
|
||||
else if (c2 >= 'A' && c2 <= 'F')
|
||||
c2 = c2 - 'A' + 10;
|
||||
else
|
||||
return -1;
|
||||
|
||||
return c1 << 4 | c2;
|
||||
}
|
||||
|
||||
|
||||
static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
struct arguments *arguments = state->input;
|
||||
switch (key) {
|
||||
case 'm':
|
||||
arguments->magic = arg? strtol(arg, NULL, 16): HEADER_MAGIC;
|
||||
break;
|
||||
case 'r':
|
||||
arguments->reserved = arg? strtol(arg, NULL, 16): HEADER_RESERVED;
|
||||
break;
|
||||
case 'i':
|
||||
arguments->installer_file = arg;
|
||||
break;
|
||||
case 'o':
|
||||
arguments->output_file = arg;
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if(state->arg_num < 1) // Expect 1 command line argument at end
|
||||
argp_usage(state);
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct argp argp = {
|
||||
options, parse_opt, args_doc, doc, 0, 0, 0
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct arguments arguments;
|
||||
int arg_index;
|
||||
char tmpfilename[] = "image_XXXXXX";
|
||||
|
||||
arguments.reserved = HEADER_RESERVED;
|
||||
arguments.magic = HEADER_MAGIC;
|
||||
arguments.output_file = NULL;
|
||||
|
||||
argp_parse(&argp, argc, argv, 0, &arg_index, &arguments);
|
||||
|
||||
memset(buffer, 0, BUFFER_SIZE);
|
||||
|
||||
size_t filesize = 0;
|
||||
inptr = fopen(argv[arg_index], "rb");
|
||||
if (inptr == NULL) {
|
||||
printf("Cannot open input file %s\n", argv[arg_index]);
|
||||
return 5;
|
||||
}
|
||||
|
||||
fseek(inptr, 0L, SEEK_END);
|
||||
filesize = ftell(inptr);
|
||||
rewind(inptr);
|
||||
printf("Input file size: %ld\n", filesize);
|
||||
if (filesize > BUFFER_SIZE) {
|
||||
printf("File too large.\n");
|
||||
return 5;
|
||||
}
|
||||
size_t bytes_read = fread(buffer + SEG_1d000_OFFSET + 2 * HEADER_LENGTH, 1, sizeof(buffer), inptr);
|
||||
|
||||
printf("Bytes read: %ld\n", bytes_read);
|
||||
|
||||
if (bytes_read != filesize) {
|
||||
printf("Error reading input file.\n");
|
||||
return 5;
|
||||
}
|
||||
fclose(inptr);
|
||||
filesize += SEG_1d000_OFFSET + 2 * HEADER_LENGTH;
|
||||
|
||||
// Read the installer file, which is in Intel Hex format
|
||||
if (arguments.installer_file) {
|
||||
inptr = fopen(arguments.installer_file, "rb");
|
||||
if (inptr == NULL) {
|
||||
printf("Cannot open installer file %s\n", arguments.installer_file);
|
||||
return 5;
|
||||
}
|
||||
int line_num = 1;
|
||||
int address_high = 0;
|
||||
bool eof = false;
|
||||
while(fgets(line, 255, inptr)) {
|
||||
if (line[0] != ':') {
|
||||
printf("Unknwon installer file format for %s\n", arguments.installer_file);
|
||||
return 5;
|
||||
}
|
||||
int bytes = get_byte(1);
|
||||
if (bytes < 0 || bytes > 200) {
|
||||
printf("Error in %s, line %d, incorrect byte number\n", arguments.installer_file, line_num);
|
||||
return 5;
|
||||
}
|
||||
int address = (get_byte(3) *256) + get_byte(5);
|
||||
if (address < 0) {
|
||||
printf("Error in %s, line %d, not an address\n", arguments.installer_file, line_num);
|
||||
return 5;
|
||||
}
|
||||
int type = get_byte(7);
|
||||
if (type < 0 || type > 5) {
|
||||
printf("Error in %s, line %d incorrect type\n", arguments.installer_file, line_num);
|
||||
return 5;
|
||||
}
|
||||
if (type == 0) {
|
||||
for (int i = 0; i < bytes; i++) {
|
||||
int data = get_byte(9 + 2 * i);
|
||||
if (data < 0) {
|
||||
printf("Error in %s, line %d, illegal data byte\n", arguments.installer_file, line_num);
|
||||
return 5;
|
||||
} else {
|
||||
address = address > 0x1000 ? address - 0x1000 : address;
|
||||
buffer[address + HEADER_LENGTH + i] = data;
|
||||
}
|
||||
}
|
||||
} else if (type == 1) {
|
||||
eof = true;
|
||||
printf("EOF\n");
|
||||
} else {
|
||||
printf("UNKNOWN type, line %d\n", line_num);
|
||||
}
|
||||
line_num++;
|
||||
}
|
||||
if (!eof)
|
||||
printf("Something was wrong: EOF not found\n");
|
||||
|
||||
fclose(inptr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fill in the header with the magic, file-length, header sum, payload sum
|
||||
* and the reserved bytes
|
||||
*/
|
||||
*(uint32_t *)(buffer + 0x00) = htonl(arguments.magic);
|
||||
*(uint32_t *)(buffer + 0x04) = htonl(filesize - HEADER_LENGTH);
|
||||
uint32_t sum = 0;
|
||||
// for (int i = HEADER_LENGTH; i < filesize; i++)
|
||||
// sum += buffer[i];
|
||||
|
||||
for (int i = HEADER_LENGTH; i < SEG_01002_LENGTH; i++)
|
||||
sum += buffer[i];
|
||||
printf("Payload sum 1 is: 0x%x\n", sum);
|
||||
|
||||
for (int i = HEADER_LENGTH + SEG_01002_LENGTH; i < SEG_01002_LENGTH + SEG_1C000_LENGTH + HEADER_LENGTH; i++)
|
||||
sum += buffer[i];
|
||||
printf("Payload sum 2 is: 0x%x\n", sum);
|
||||
|
||||
sum += 0xff * HEADER_LENGTH;
|
||||
printf("Payload sum with header is: 0x%x\n", sum);
|
||||
|
||||
for (int i = 2 * HEADER_LENGTH + SEG_01002_LENGTH + SEG_1C000_LENGTH; i < filesize; i++)
|
||||
sum += buffer[i];
|
||||
printf("Payload sum is: 0x%x\n", sum);
|
||||
*(uint32_t *)(buffer + 0x0c) = htonl(sum);
|
||||
|
||||
*(uint32_t *)(buffer + 0x10) = htonl(arguments.reserved);
|
||||
|
||||
sum = 0;
|
||||
for (int i = 0; i < HEADER_LENGTH; i++)
|
||||
sum += buffer[i];
|
||||
printf("Header checksum is: 0x%x\n", sum);
|
||||
*(uint32_t *)(buffer + 0x08) = htonl(sum);
|
||||
|
||||
// Second header is copy of initial one:
|
||||
*(uint32_t *)(buffer + 0x00 + HEADER_LENGTH + SEG_1d000_OFFSET) = *(uint32_t *)(buffer + 0x00);
|
||||
*(uint32_t *)(buffer + 0x04 + HEADER_LENGTH + SEG_1d000_OFFSET) = *(uint32_t *)(buffer + 0x04);
|
||||
*(uint32_t *)(buffer + 0x08 + HEADER_LENGTH + SEG_1d000_OFFSET) = *(uint32_t *)(buffer + 0x08);
|
||||
*(uint32_t *)(buffer + 0x0c + HEADER_LENGTH + SEG_1d000_OFFSET) = *(uint32_t *)(buffer + 0x0c);
|
||||
*(uint32_t *)(buffer + 0x10 + HEADER_LENGTH + SEG_1d000_OFFSET) = *(uint32_t *)(buffer + 0x10);
|
||||
|
||||
if (filesize) {
|
||||
if (arguments.output_file)
|
||||
outptr = creat(arguments.output_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||
else
|
||||
outptr = mkstemp(tmpfilename);
|
||||
|
||||
if (!outptr) {
|
||||
printf("Cannot open %s\n", arguments.output_file ? arguments.output_file : tmpfilename);
|
||||
return 5;
|
||||
}
|
||||
size_t written = write(outptr, buffer, filesize);
|
||||
|
||||
if (written != filesize) {
|
||||
printf("Error writing output file.\n");
|
||||
return 5;
|
||||
}
|
||||
close(outptr);
|
||||
|
||||
if (!arguments.output_file)
|
||||
rename(tmpfilename, argv[arg_index]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef _PHY_H_
|
||||
#define _PHY_H_
|
||||
|
||||
/*
|
||||
* The RTL8272/RTL8273 appear to comprise an RTL8224 PHY
|
||||
* which in turn is a 4x RTL8221B PHY
|
||||
* These phys are all Clause 45
|
||||
* The defines below are taken from the RTL8221B datasheet
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define PHY pages
|
||||
*/
|
||||
#define PHY_MMD_AN 7
|
||||
#define PHY_SDS_CTRL 30
|
||||
#define PHY_MMD_CTRL 31
|
||||
|
||||
|
||||
/*
|
||||
* Define registers in Auto-Negotiation page
|
||||
*/
|
||||
#define PHY_ANEG_CTRL 0x00
|
||||
#define PHY_EEE_ADV 0x3c
|
||||
#define PHY_EEE_LP_ABILITY 0x3d
|
||||
#define PHY_EEE_ADV2 0x3e
|
||||
#define PHY_EEE_LP_ABILITY2 0x3f
|
||||
// Register bits for EEE capabilities at a given speed
|
||||
#define PHY_EEE_BIT_2G5 0x01
|
||||
#define PHY_EEE_BIT_1G 0x04
|
||||
#define PHY_EEE_BIT_100M 0x02
|
||||
|
||||
/*
|
||||
* Define registers in Control page
|
||||
*/
|
||||
#define PHY_CTRL_5 0x7582
|
||||
#endif
|
||||
+33
-1
@@ -4,10 +4,28 @@
|
||||
#include "uip/uip-conf.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// This has to be set to the number of SFP+ ports, i.e. 1 or 2
|
||||
#define NSFP 2
|
||||
// SCL and SDA pin numbers for SFP cage 0 and SFP cage 1
|
||||
#define SCL_PIN 3
|
||||
#define SDA_PIN_0 4
|
||||
#define SDA_PIN_1 3
|
||||
|
||||
// Define Port-masks for 9-port devices and 6-port devices
|
||||
#define PMASK_9 0x1ff
|
||||
#define PMASK_6 0x1f8
|
||||
#define PMASK_CPU 0x200
|
||||
|
||||
// The serial buffer. Defines the command line size
|
||||
// Must be 2^x and <= 128
|
||||
#define SBUF_SIZE 128
|
||||
|
||||
// Size of the TCP Output buffer
|
||||
#define TCP_OUTBUF_SIZE 2500
|
||||
|
||||
// Size of the memory area dedicated to VLAN-names
|
||||
#define VLAN_NAMES_SIZE 1024
|
||||
|
||||
// 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 VLAN tag is inserted after the RTL tag
|
||||
@@ -23,6 +41,11 @@
|
||||
// This is the standard size of an Ethernet frame header
|
||||
#define ETHER_HEADER_SIZE 14
|
||||
|
||||
#if NSFP == 1
|
||||
#define IS_SFP(port) (i == maxPort)
|
||||
#else
|
||||
#define IS_SFP(port) (i == maxPort || i == 3)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Representation of a 48-bit Ethernet address.
|
||||
@@ -31,6 +54,11 @@ struct uip_eth_addr {
|
||||
uint8_t addr[6];
|
||||
};
|
||||
|
||||
struct flash_region_t {
|
||||
uint32_t addr;
|
||||
uint16_t len;
|
||||
};
|
||||
|
||||
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
|
||||
|
||||
|
||||
@@ -41,8 +69,10 @@ void print_short(uint16_t a);
|
||||
void print_byte(uint8_t a);
|
||||
void print_sfr_data(void);
|
||||
void print_phy_data(void);
|
||||
void phy_write(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v);
|
||||
void phy_write_mask(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v);
|
||||
void phy_write(uint8_t phy_id, uint8_t dev_id, uint16_t reg, uint16_t v);
|
||||
void phy_read(uint8_t phy_id, uint8_t dev_id, uint16_t reg);
|
||||
void phy_modify(uint8_t phy_id, uint8_t dev_id, uint16_t reg, uint16_t mask, uint16_t set);
|
||||
void reg_read(uint16_t reg_addr);
|
||||
void reg_read_m(uint16_t reg_addr);
|
||||
void reg_write(uint16_t reg_addr);
|
||||
@@ -54,6 +84,7 @@ void print_reg(uint16_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_clear(uint16_t reg_addr, char bit);
|
||||
void sfr_set_zero(void);
|
||||
void reset_chip(void);
|
||||
void memcpy(__xdata void * __xdata dst, __xdata const void * __xdata src, uint16_t len);
|
||||
void memcpyc(register __xdata uint8_t *dst, register __code uint8_t *src, register uint16_t len);
|
||||
@@ -64,4 +95,5 @@ uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s);
|
||||
void tcpip_output(void);
|
||||
void print_string_x(__xdata char *p);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+108
-174
@@ -10,8 +10,20 @@
|
||||
__xdata uint8_t dio_enabled;
|
||||
__xdata uint8_t markbuf[16];
|
||||
extern __xdata uint16_t mpos;
|
||||
__xdata struct flash_region_t flash_region;
|
||||
|
||||
#pragma codeseg BANK1
|
||||
|
||||
// For the flash commands, see e.g. Windbond W25Q32JV datasheet
|
||||
#define CMD_WRITE_STATUS 0x01
|
||||
#define CMD_PAGE_PROGRAM 0x02
|
||||
#define CMD_READ 0x03
|
||||
#define CMD_WRITE_ENABLE 0x06
|
||||
#define CMD_FREAD 0x0b
|
||||
#define CMD_SECTOR_ERASE 0x20
|
||||
#define CMD_READ_SECURITY_REGS 0x48
|
||||
#define CMD_READ_UNIQUE_ID 0x4b
|
||||
#define CMD_READ_JEDEC_ID 0x9f
|
||||
#define CMD_FREAD_DIO 0xbb
|
||||
|
||||
/*
|
||||
* Configure Memory Managed IO
|
||||
@@ -21,14 +33,14 @@ void flash_configure_mmio(void)
|
||||
// Set configuration for MMIO access by controller
|
||||
if (dio_enabled) {
|
||||
SFR_FLASH_MODEB = 0x18;
|
||||
SFR_FLASH_CMD_R = 0xbb; // By default we read with Dual speed
|
||||
SFR_FLASH_DUMMYCICLES = 4;
|
||||
SFR_FLASH_CMD_R = CMD_FREAD_DIO; // By default we read with Dual speed
|
||||
SFR_FLASH_DUMMYCYCLES = 4;
|
||||
return;
|
||||
}
|
||||
|
||||
SFR_FLASH_MODEB = 0x0;
|
||||
SFR_FLASH_CMD_R = 0xb; // By default we read with single speed
|
||||
SFR_FLASH_DUMMYCICLES = 8;
|
||||
SFR_FLASH_CMD_R = CMD_FREAD; // Default is Single IO
|
||||
SFR_FLASH_DUMMYCYCLES = 8;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,27 +51,26 @@ void flash_configure_mmio(void)
|
||||
* This configures fast single IO at 20.8 MHz when the CPU clock is at 20.8MHz
|
||||
* and 62.5MHz when the CPU clock is configured at 125MHz
|
||||
*/
|
||||
void flash_init(uint8_t enable_dio) __banked
|
||||
void flash_init(uint8_t enable_dio)
|
||||
{
|
||||
if (enable_dio) {
|
||||
// Configure fast DIO via divider/DIO/SIOconfig = 4 and read-cmd being 0xbb (for mmio)
|
||||
SFR_FLASH_CONFIG = 9; // There may be a chip-select in here
|
||||
SFR_FLASH_CONF_RCMD = 0xbb;
|
||||
SFR_FLASH_CONF_RCMD = CMD_FREAD_DIO;
|
||||
SFR_FLASH_CONF_DIV = 4;
|
||||
} else {
|
||||
// Configure fast read via divider = 8 and read-cmd being 0xb (for mmio)
|
||||
// Configure fast read via divider = 8 and read-cmd being CMD_FREAD (for mmio)
|
||||
SFR_FLASH_CONFIG = 9;
|
||||
SFR_FLASH_CONF_RCMD = 0xb;
|
||||
SFR_FLASH_CONF_RCMD = CMD_FREAD;
|
||||
SFR_FLASH_CONF_DIV = 8;
|
||||
}
|
||||
// Test Controller Busy
|
||||
while(SFR_FLASH_EXEC_BUSY);
|
||||
|
||||
// Write 0 to status register
|
||||
SFR_FLASH_DUMMYCICLES = 8;
|
||||
SFR_FLASH_DUMMYCYCLES = 8;
|
||||
SFR_FLASH_MODEB = 0;
|
||||
SFR_FLASH_TCONF = 0x19;
|
||||
SFR_FLASH_CMD = 1;
|
||||
SFR_FLASH_CMD = CMD_WRITE_STATUS;
|
||||
SFR_FLASH_DATA0 = 0;
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
while(SFR_FLASH_EXEC_BUSY);
|
||||
@@ -86,14 +97,14 @@ uint8_t flash_read_status(void)
|
||||
}
|
||||
|
||||
|
||||
void flash_read_uid(void) __banked
|
||||
void flash_read_uid(void)
|
||||
{
|
||||
while (flash_read_status() & 0x1);
|
||||
|
||||
// Set slow read mode for UID
|
||||
SFR_FLASH_MODEB = 0x0;
|
||||
SFR_FLASH_CMD_R = 0x4b;
|
||||
SFR_FLASH_DUMMYCICLES = 8;
|
||||
SFR_FLASH_CMD_R = CMD_READ_UNIQUE_ID;
|
||||
SFR_FLASH_DUMMYCYCLES = 8;
|
||||
|
||||
// Transfer 4 bytes (command + 3 dummy bytes)
|
||||
SFR_FLASH_TCONF = 4;
|
||||
@@ -110,7 +121,7 @@ void flash_read_uid(void) __banked
|
||||
print_byte(SFR_FLASH_DATA24);
|
||||
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
SFR_FLASH_DUMMYCICLES = 24;
|
||||
SFR_FLASH_DUMMYCYCLES = 24;
|
||||
while(SFR_FLASH_EXEC_BUSY);
|
||||
|
||||
print_byte(SFR_FLASH_DATA0);
|
||||
@@ -122,14 +133,14 @@ void flash_read_uid(void) __banked
|
||||
}
|
||||
|
||||
|
||||
void flash_read_jedecid(void) __banked
|
||||
void flash_read_jedecid(void)
|
||||
{
|
||||
while (flash_read_status() & 0x1);
|
||||
|
||||
// Set read mode for JEDEC ID
|
||||
SFR_FLASH_MODEB = 0x0;
|
||||
SFR_FLASH_CMD_R = 0x9f;
|
||||
SFR_FLASH_DUMMYCICLES = 0;
|
||||
SFR_FLASH_CMD_R = CMD_READ_JEDEC_ID;
|
||||
SFR_FLASH_DUMMYCYCLES = 0;
|
||||
|
||||
// Transfer 3 bytes back
|
||||
SFR_FLASH_TCONF = 0x13;
|
||||
@@ -144,12 +155,12 @@ void flash_read_jedecid(void) __banked
|
||||
|
||||
// Reset slow read mode
|
||||
SFR_FLASH_MODEB = 0x0;
|
||||
SFR_FLASH_CMD_R = 0xb;
|
||||
SFR_FLASH_DUMMYCICLES = 8;
|
||||
SFR_FLASH_CMD_R = CMD_FREAD;
|
||||
SFR_FLASH_DUMMYCYCLES = 8;
|
||||
}
|
||||
|
||||
|
||||
void flash_write_enable(void) __banked
|
||||
void flash_write_enable(void)
|
||||
{
|
||||
short status;
|
||||
|
||||
@@ -157,14 +168,16 @@ void flash_write_enable(void) __banked
|
||||
do {
|
||||
status = flash_read_status();
|
||||
} while (status & 0x1);
|
||||
// while (flash_read_status() & 0x1);
|
||||
|
||||
SFR_FLASH_TCONF = 0x18;
|
||||
SFR_FLASH_CMD = 6;
|
||||
/* The following is explicitly set for SIO, is this necessary?:
|
||||
SFR_FLASH_CMD = CMD_WRITE_ENABLE;
|
||||
|
||||
/* The following makes sure that the PAGE_PROGRAM command,
|
||||
* where the data to be written follows the command word directly
|
||||
* works properly
|
||||
*/
|
||||
SFR_FLASH_DUMMYCYCLES = 0;
|
||||
SFR_FLASH_MODEB = 0;
|
||||
*/
|
||||
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
// Wait for write status enabled
|
||||
@@ -174,7 +187,7 @@ void flash_write_enable(void) __banked
|
||||
}
|
||||
|
||||
|
||||
void flash_dump(register uint32_t addr, register uint8_t len) __banked
|
||||
void flash_dump(uint8_t len)
|
||||
{
|
||||
short status;
|
||||
do {
|
||||
@@ -185,20 +198,20 @@ void flash_dump(register uint32_t addr, register uint8_t len) __banked
|
||||
// Set fast read mode
|
||||
if (dio_enabled) {
|
||||
SFR_FLASH_MODEB = 0x18;
|
||||
SFR_FLASH_CMD_R = 0xbb;
|
||||
SFR_FLASH_DUMMYCICLES = 4;
|
||||
SFR_FLASH_CMD_R = CMD_FREAD_DIO;
|
||||
SFR_FLASH_DUMMYCYCLES = 4;
|
||||
} else {
|
||||
SFR_FLASH_MODEB = 0x0;
|
||||
SFR_FLASH_CMD_R = 0xb; // Fast read
|
||||
SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks after read?
|
||||
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 = addr >> 16;
|
||||
SFR_FLASH_ADDR8 = addr >> 8;
|
||||
SFR_FLASH_ADDR0 = addr;
|
||||
addr += 4;
|
||||
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);
|
||||
@@ -222,7 +235,7 @@ void flash_dump(register uint32_t addr, register uint8_t len) __banked
|
||||
* 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
|
||||
*/
|
||||
void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, register uint16_t len) __banked
|
||||
void flash_read_bulk(__xdata uint8_t *dst)
|
||||
{
|
||||
short status;
|
||||
do {
|
||||
@@ -232,193 +245,112 @@ void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, regist
|
||||
// Set fast read mode
|
||||
if (dio_enabled) {
|
||||
SFR_FLASH_MODEB = 0x18;
|
||||
SFR_FLASH_CMD_R = 0xbb;
|
||||
SFR_FLASH_DUMMYCICLES = 4;
|
||||
SFR_FLASH_CMD_R = CMD_FREAD_DIO;
|
||||
SFR_FLASH_DUMMYCYCLES = 4;
|
||||
} else {
|
||||
SFR_FLASH_MODEB = 0x0;
|
||||
SFR_FLASH_CMD_R = 0xb; // Fast read
|
||||
SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks after read?
|
||||
SFR_FLASH_CMD_R = CMD_READ;
|
||||
SFR_FLASH_DUMMYCYCLES = 0;
|
||||
}
|
||||
|
||||
|
||||
// Read 4 bytes
|
||||
SFR_FLASH_TCONF = 4;
|
||||
while (len) {
|
||||
SFR_FLASH_ADDR16 = src >> 16;
|
||||
SFR_FLASH_ADDR8 = src >> 8;
|
||||
SFR_FLASH_ADDR0 = src;
|
||||
src += 4;
|
||||
while (1) {
|
||||
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_TCONF = 4;
|
||||
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
while(SFR_FLASH_EXEC_BUSY);
|
||||
|
||||
*dst++ = SFR_FLASH_DATA0;
|
||||
if (len == 1)
|
||||
return;
|
||||
if (flash_region.len == 1)
|
||||
break;
|
||||
*dst++ = SFR_FLASH_DATA8;
|
||||
if (len == 2)
|
||||
return;
|
||||
if (flash_region.len == 2)
|
||||
break;
|
||||
*dst++ = SFR_FLASH_DATA16;
|
||||
if (len == 3)
|
||||
return;
|
||||
if (flash_region.len == 3)
|
||||
break;
|
||||
*dst++ = SFR_FLASH_DATA24;
|
||||
|
||||
len -= 4;
|
||||
if (flash_region.len == 4)
|
||||
break;
|
||||
flash_region.len -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flash_find_mark(__xdata uint32_t src, register uint16_t len, __code uint8_t *mark) __banked
|
||||
{
|
||||
uint16_t status;
|
||||
do {
|
||||
status = flash_read_status();
|
||||
} while (status & 0x1);
|
||||
|
||||
// Set fast read mode
|
||||
if (dio_enabled) {
|
||||
SFR_FLASH_MODEB = 0x18;
|
||||
SFR_FLASH_CMD_R = 0xbb;
|
||||
SFR_FLASH_DUMMYCICLES = 4;
|
||||
} else {
|
||||
SFR_FLASH_MODEB = 0x0;
|
||||
SFR_FLASH_CMD_R = 0xb; // Fast read
|
||||
SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks after read?
|
||||
}
|
||||
|
||||
uint8_t i = 0;
|
||||
uint8_t l = 0;
|
||||
uint8_t k;
|
||||
|
||||
// Calculate the length
|
||||
while (mark[i++])
|
||||
l++;
|
||||
|
||||
if (l >= 12) {
|
||||
mpos = 0xffff;
|
||||
return;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
SFR_FLASH_TCONF = 4;
|
||||
while (len) {
|
||||
SFR_FLASH_ADDR16 = src >> 16;
|
||||
SFR_FLASH_ADDR8 = src >> 8;
|
||||
SFR_FLASH_ADDR0 = src;
|
||||
src += 4;
|
||||
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
while(SFR_FLASH_EXEC_BUSY);
|
||||
markbuf[i++] = SFR_FLASH_DATA0;
|
||||
if (len != 1) {
|
||||
markbuf[i++] = SFR_FLASH_DATA8;
|
||||
if (len != 2) {
|
||||
markbuf[i++] = SFR_FLASH_DATA16;
|
||||
if (len != 3) {
|
||||
markbuf[i++] = SFR_FLASH_DATA24;
|
||||
} else {
|
||||
markbuf[i++] = 0;
|
||||
}
|
||||
} else {
|
||||
markbuf[i++] = 0;
|
||||
}
|
||||
} else {
|
||||
markbuf[i++] = 0;
|
||||
}
|
||||
|
||||
len -= 4;
|
||||
uint8_t j = 0;
|
||||
k = (i + 13 - l) & 0xf;
|
||||
i &= 0xf;
|
||||
while (mark[j] && (k != ((i) & 0xf))) {
|
||||
if (mark[j] != markbuf[k]) {
|
||||
k = k - j + 17;
|
||||
j = 0;
|
||||
} else {
|
||||
k++;
|
||||
j++;
|
||||
}
|
||||
k &= 0xf;
|
||||
}
|
||||
if (!mark[j]) {
|
||||
mpos = len + l + ((4 - ( k & 0x3)) & 0x3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mpos = 0xffff;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void flash_read_security(uint32_t addr, uint8_t len) __banked
|
||||
void flash_read_security()
|
||||
{
|
||||
while (flash_read_status() & 0x1);
|
||||
|
||||
// Set slow read mode
|
||||
SFR_FLASH_MODEB = 0x0;
|
||||
SFR_FLASH_CMD_R = 0x48; // read security register
|
||||
SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks as for fast read
|
||||
SFR_FLASH_CMD_R = CMD_READ_SECURITY_REGS; // read security register
|
||||
SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks as for fast read
|
||||
|
||||
// Transfer 4 bytes (command + 3byte address)
|
||||
SFR_FLASH_TCONF = 4;
|
||||
while (len) {
|
||||
SFR_FLASH_ADDR16 = addr >> 16;
|
||||
SFR_FLASH_ADDR8 = addr >> 8;
|
||||
SFR_FLASH_ADDR0 = addr;
|
||||
addr += 4;
|
||||
do {
|
||||
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_byte(SFR_FLASH_DATA0);
|
||||
if (len == 1)
|
||||
return;
|
||||
if (flash_region.len == 1)
|
||||
break;
|
||||
print_byte(SFR_FLASH_DATA8);
|
||||
if (len == 2)
|
||||
return;
|
||||
if (flash_region.len == 2)
|
||||
break;
|
||||
print_byte(SFR_FLASH_DATA16);
|
||||
if (len == 3)
|
||||
return;
|
||||
if (flash_region.len == 3)
|
||||
break;
|
||||
print_byte(SFR_FLASH_DATA24);
|
||||
|
||||
len -= 4;
|
||||
}
|
||||
flash_region.len -= 4;
|
||||
} while(flash_region.len);
|
||||
}
|
||||
|
||||
|
||||
void flash_block_erase(uint32_t addr) __banked
|
||||
void flash_sector_erase(void)
|
||||
{
|
||||
flash_write_enable();
|
||||
SFR_FLASH_TCONF = 8;
|
||||
SFR_FLASH_CMD = 0x20;
|
||||
SFR_FLASH_CMD = CMD_SECTOR_ERASE;
|
||||
|
||||
SFR_FLASH_ADDR16 = addr >> 16;
|
||||
SFR_FLASH_ADDR8 = addr >> 8;
|
||||
SFR_FLASH_ADDR0 = addr;
|
||||
SFR_FLASH_ADDR16 = flash_region.addr >> 16;
|
||||
SFR_FLASH_ADDR8 = flash_region.addr >> 8;
|
||||
SFR_FLASH_ADDR0 = flash_region.addr;
|
||||
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
while (flash_read_status() & 0x1);
|
||||
|
||||
flash_configure_mmio();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void flash_write_bytes(__xdata uint32_t addr, __xdata uint8_t *ptr, uint16_t len) __banked
|
||||
void flash_write_bytes(__xdata uint8_t *ptr)
|
||||
{
|
||||
static __xdata uint8_t exit_loop = 0;
|
||||
|
||||
while(1) {
|
||||
write_char('>'); print_long(flash_region.addr); write_char(':'); print_short(flash_region.len); write_char('-'); print_byte(*ptr); write_char('\n');
|
||||
while(1) {
|
||||
flash_write_enable();
|
||||
SFR_FLASH_CMD = 2;
|
||||
SFR_FLASH_TCONF = 0x40 | 8 | 2; // Bytes written is is 4, 8 enables write, 0x2 is unkown
|
||||
SFR_FLASH_CMD = CMD_PAGE_PROGRAM;
|
||||
SFR_FLASH_TCONF = 0x40 | 8 | 4; // Bytes written is 4, 8 enables write, 0x40 is unknown
|
||||
// Last transfer?
|
||||
if (len < 5) {
|
||||
SFR_FLASH_TCONF = 8 | len;
|
||||
exit_loop = 1;
|
||||
if (flash_region.len < 5) {
|
||||
SFR_FLASH_TCONF = 8 | flash_region.len;
|
||||
}
|
||||
|
||||
SFR_FLASH_ADDR16 = addr >> 16;
|
||||
SFR_FLASH_ADDR8 = addr >> 8;
|
||||
SFR_FLASH_ADDR0 = addr;
|
||||
SFR_FLASH_ADDR16 = flash_region.addr >> 16;
|
||||
SFR_FLASH_ADDR8 = flash_region.addr >> 8;
|
||||
SFR_FLASH_ADDR0 = flash_region.addr;
|
||||
SFR_FLASH_DATA0 = *ptr++;
|
||||
SFR_FLASH_DATA8 = *ptr++;
|
||||
SFR_FLASH_DATA16 = *ptr++;
|
||||
@@ -426,11 +358,13 @@ void flash_write_bytes(__xdata uint32_t addr, __xdata uint8_t *ptr, uint16_t len
|
||||
|
||||
// Execute transfer, we wait for completion at top of loop
|
||||
SFR_FLASH_EXEC_GO = 1;
|
||||
if (exit_loop)
|
||||
|
||||
if (flash_region.len < 5)
|
||||
break;
|
||||
len -= 4;
|
||||
addr += 4;
|
||||
}
|
||||
|
||||
flash_region.len -= 4;
|
||||
flash_region.addr += 4;
|
||||
};
|
||||
|
||||
while (flash_read_status() & 0x1);
|
||||
flash_configure_mmio();
|
||||
|
||||
+9
-10
@@ -1,14 +1,13 @@
|
||||
#ifndef _RTL837X_FLASH_H_
|
||||
#define _RTL837X_FLASH_H_
|
||||
|
||||
void flash_init(uint8_t enable_dio) __banked;
|
||||
void flash_read_uid(void) __banked;
|
||||
void flash_write_enable(void)__banked ;
|
||||
void flash_dump(register uint32_t addr, register uint8_t len) __banked;
|
||||
void flash_read_jedecid(void) __banked;
|
||||
void flash_read_security(uint32_t addr, uint8_t len)__banked ;
|
||||
void flash_block_erase(uint32_t addr) __banked;
|
||||
void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, register uint16_t len) __banked;
|
||||
void flash_write_bytes(__xdata uint32_t addr, register __xdata uint8_t *ptr, register uint16_t len)__banked;
|
||||
void flash_find_mark(__xdata uint32_t src, register uint16_t len, __code uint8_t *mark) __banked;
|
||||
void flash_init(uint8_t enable_dio);
|
||||
void flash_read_uid(void);
|
||||
void flash_write_enable(void);
|
||||
void flash_dump(uint8_t len);
|
||||
void flash_read_jedecid(void);
|
||||
void flash_read_security(void);
|
||||
void flash_sector_erase(void);
|
||||
void flash_read_bulk(__xdata uint8_t *dst);
|
||||
void flash_write_bytes(__xdata uint8_t *ptr);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This is a driver implementation for the IGMP features for the RTL827x platform
|
||||
* This code is in the Public Domain
|
||||
*/
|
||||
|
||||
// #define REGDBG
|
||||
// #define DEBUG
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rtl837x_common.h"
|
||||
#include "rtl837x_sfr.h"
|
||||
#include "rtl837x_regs.h"
|
||||
#include "rtl837x_igmp.h"
|
||||
|
||||
extern __xdata uint8_t minPort;
|
||||
extern __xdata uint8_t maxPort;
|
||||
extern __xdata uint8_t nSFPPorts;
|
||||
extern __xdata uint8_t cpuPort;
|
||||
extern __xdata uint8_t isRTL8373;
|
||||
|
||||
void igmp_setup(void) __banked
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
// For now, forward all unkown MC pkts (2 bits per port. 00: flood via floodmask, 01: drop, 10: trap, 11: to rport)
|
||||
REG_SET(RTL837X_MC_LOOKUPMISS_ACTIONS, 0x00000000); //0x4f78
|
||||
// Define ports where unknown MC addresses are flooded to:
|
||||
if (isRTL8373) {
|
||||
REG_SET(RTL837X_MC_FLOODMASK, PMASK_9); // R5368-000001f8
|
||||
} else {
|
||||
REG_SET(RTL837X_MC_FLOODMASK, PMASK_6);
|
||||
}
|
||||
|
||||
// Enable lookup of IPv4 MC addresses in table
|
||||
reg_bit_set(RTL837X_L2_CTRL, 3); // 0x5350
|
||||
|
||||
// Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping,
|
||||
// bits 16-24 configure max MC group used by that port. For now all protocols are flooded (01)
|
||||
for (i = minPort; i <= maxPort; i++)
|
||||
REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), 0x00ff7c15);
|
||||
}
|
||||
|
||||
|
||||
void igmp_enable(void) __banked
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
REG_SET(0x50bc, 00010007); // Trap control?
|
||||
|
||||
// Drop unknown MC messages
|
||||
REG_SET(RTL837X_MC_LOOKUPMISS_ACTIONS, 0x00015540); //0x4f78
|
||||
|
||||
// Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping,
|
||||
// bits 16-24 configure max MC group used by that port. Trap to CPU (10)
|
||||
for (i = minPort; i <= maxPort; i++)
|
||||
REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), 0x00ff7c2a); // 0x00ff7000: Handling by ASIC (00)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef _RTL837X_IGMP_H_
|
||||
#define _RTL837X_IGMP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void igmp_setup(void) __banked;
|
||||
void igmp_enable(void) __banked;
|
||||
|
||||
#endif
|
||||
+69
-95
@@ -6,13 +6,18 @@
|
||||
|
||||
#define REGDBG
|
||||
|
||||
// Phy ID of the external RTL8224 PHY.
|
||||
#define RTL8224_PHY_ID 0x00
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rtl837x_common.h"
|
||||
#include "rtl837x_sfr.h"
|
||||
#include "rtl837x_regs.h"
|
||||
#include "rtl837x_phy.h"
|
||||
#include "phy.h"
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
extern __code uint16_t bit_mask[16];
|
||||
|
||||
@@ -66,12 +71,12 @@ __code uint16_t rtl8224_cb[60] = {
|
||||
|
||||
void rtl8224_phy_enable(void) __banked
|
||||
{
|
||||
uint16_t pval;
|
||||
|
||||
// p001e.0a90:00f3 R02f8-000000f3 R02f4-000000fc P000001.1e000a90:00fc
|
||||
print_string("\r\nrtl8224_phy_enable called\r\n");
|
||||
phy_read(0, 0x1e, 0xa90);
|
||||
uint16_t pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0;
|
||||
phy_read(RTL8224_PHY_ID, 0x1e, 0xa90);
|
||||
pval = SFR_DATA_U16;
|
||||
|
||||
// PHY Initialization:
|
||||
REG_WRITE(0x2f8, 0, 0, pval >> 8, pval);
|
||||
@@ -80,108 +85,65 @@ void rtl8224_phy_enable(void) __banked
|
||||
pval |= 0x0c;
|
||||
REG_WRITE(0x2f4, 0, 0, pval >> 8, pval);
|
||||
|
||||
phy_write(0x1, 0x1e, 0xa90, pval);
|
||||
|
||||
phy_read(0, 0x1e, 0xa90);
|
||||
pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0;
|
||||
|
||||
phy_write(RTL8224_PHY_ID, 0x1e, 0xa90, pval);
|
||||
delay(50);
|
||||
|
||||
print_string("\r\nrtl8224_phy_enable done\r\n");
|
||||
}
|
||||
|
||||
|
||||
void phy_config(uint8_t phy) __banked
|
||||
{
|
||||
uint16_t pval;
|
||||
print_string("\r\nphy_config: ");
|
||||
write_char('0' + phy);
|
||||
|
||||
delay(20);
|
||||
// PHY configuration: External 8221B?
|
||||
// p081e.75f3:ffff P000100.1e0075f3:fffe
|
||||
phy_read(phy, 0x1e, 0x75f3);
|
||||
pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0 & 0xfe;
|
||||
phy_write(bit_mask[phy], 0x1e, 0x75f3, pval);
|
||||
// p081e.75f3:ffff P000100.1e0075f3:fffe
|
||||
phy_modify(phy, 0x1e, 0x75f3, 0x0001, 0x0000);
|
||||
delay(20);
|
||||
|
||||
// p081e.697a:ffff P000100.1e00697a:ffc1 / p031e.697a:0003 P000008.1e00697a:0001
|
||||
// p081e.697a:ffff P000100.1e00697a:ffc1 / p031e.697a:0003 P000008.1e00697a:0001
|
||||
// SERDES OPTION 1 Register (MMD 30.0x6) bits 0-5: 0x01: Set HiSGMII+SGMII
|
||||
phy_read(phy, 0x1e, 0x697a);
|
||||
pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0 & 0xc0 | 0x01;
|
||||
phy_write(bit_mask[phy], 0x1e, 0x697a, pval);
|
||||
phy_modify(phy, 0x1e, 0x697a, 0x003f, 0x0001);
|
||||
delay(20);
|
||||
|
||||
// p031f.a432:0811 P000008.1f00a432:0831
|
||||
// p031f.a432:0811 P000008.1f00a432:0831
|
||||
// PHYCR2 PHY Specific Control Register 2, MMD 31. 0xA432), set bit 5: enable EEE
|
||||
phy_read(phy, 0x1f, 0xa432);
|
||||
pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0 | 0x20;
|
||||
phy_write(bit_mask[phy], 0x1f, 0xa432, pval);
|
||||
phy_modify(phy, 0x1f, 0xa432, 0x0000, 0x0020);
|
||||
|
||||
// p0307.003e:0000 P000008.0700003e:0001
|
||||
// p0307.003e:0000 P000008.0700003e:0001
|
||||
// EEE avertisment 2 register MMMD 7.0x003e, set bit 0: 2.5G has EEE capability
|
||||
phy_read(phy, 0x7, 0x3e);
|
||||
pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0 | 0x1;
|
||||
phy_write(bit_mask[phy], 0x7, 0x3e, pval);
|
||||
phy_modify(phy, 0x7, 0x3e, 0x0000, 0x0001);
|
||||
delay(20);
|
||||
|
||||
// p031f.a442:043c P000008.1f00a442:0430
|
||||
// p031f.a442:043c P000008.1f00a442:0430
|
||||
// Unknown, but clear bits 2/3
|
||||
phy_read(phy, 0x1f, 0xa442);
|
||||
pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0 & 0xf3;
|
||||
phy_write(bit_mask[phy], 0x1f, 0xa442, pval);
|
||||
phy_modify(phy, 0x1f, 0xa442, 0x0006, 0x0000);
|
||||
delay(20);
|
||||
|
||||
// P000100.1e0075b5:e084
|
||||
phy_write(bit_mask[phy], 0x1e, 0x75b5, 0xe084);
|
||||
phy_write(phy, 0x1e, 0x75b5, 0xe084);
|
||||
delay(20);
|
||||
|
||||
// p031e.75b2:0000 P000008.1e0075b2:0060
|
||||
// p031e.75b2:0000 P000008.1e0075b2:0060
|
||||
// set bits 5/6
|
||||
phy_read(phy, 0x1e, 0x75b2);
|
||||
pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0 | 0x60;
|
||||
phy_write(bit_mask[phy], 0x1e, 0x75b2, pval);
|
||||
phy_modify(phy, 0x1e, 0x75b2, 0x0000, 0x0060);
|
||||
delay(20);
|
||||
|
||||
// p081f.d040:ffff P000100.1f00d040:feff
|
||||
// p081f.d040:ffff P000100.1f00d040:feff
|
||||
// LCR6 (LED Control Register 6, MMD 31.D040), set bits 8/9 to 0b10
|
||||
phy_read(phy, 0x1e, 0xd040);
|
||||
pval = (SFR_DATA_8 & 0xfc) | 0x02;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0;
|
||||
phy_write(bit_mask[phy], 0x1e, 0xd040, pval);
|
||||
phy_modify(phy, 0x1e, 0xd040, 0x0300, 0x0200);
|
||||
delay(20);
|
||||
|
||||
// p081f.a400:ffff P000100.1f00a400:ffff, then: p081f.a400:ffff P000100.1f00a400:bfff
|
||||
// p031f.a400:1040 P000008.1f00a400:5040, then: p031f.a400:5040 P000008.1f00a400:1040
|
||||
// p081f.a400:ffff P000100.1f00a400:ffff, then: p081f.a400:ffff P000100.1f00a400:bfff
|
||||
// p031f.a400:1040 P000008.1f00a400:5040, then: p031f.a400:5040 P000008.1f00a400:1040
|
||||
// FEDCR (Fast Ethernet Duplex Control Register, MMD 31.0xA400)
|
||||
// Set bit 14, sleep, then clear again, according to the datasheet these bits are reserved
|
||||
|
||||
phy_read(phy, 0x1f, 0xa400);
|
||||
pval = SFR_DATA_8 | 0x40;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0;
|
||||
phy_write(bit_mask[phy], 0x1f, 0xa400, pval);
|
||||
phy_modify(phy, 0x1f, 0xa400, 0x0000, 0x4000);
|
||||
delay(20);
|
||||
|
||||
phy_read(phy, 0x1f, 0xa400);
|
||||
pval = SFR_DATA_8 & 0xbf;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0;
|
||||
phy_write(bit_mask[phy], 0x1f, 0xa400, pval);
|
||||
phy_modify(phy, 0x1f, 0xa400, 0x4000, 0x0000);
|
||||
delay(20);
|
||||
|
||||
print_string("\r\n phy config done\r\n");
|
||||
@@ -190,29 +152,28 @@ void phy_config(uint8_t phy) __banked
|
||||
|
||||
void phy_config_8224(void) __banked
|
||||
{
|
||||
// p001e.7b20:0bff R02f8-00000bff R02f4-00000bed P000001.1e007b20:0bed
|
||||
|
||||
uint16_t pval;
|
||||
print_string("\r\nphy_config_8224 called\r\n");
|
||||
phy_read(0, 0x1e, 0x7b20);
|
||||
pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0;
|
||||
|
||||
// p001e.7b20:0bff R02f8-00000bff R02f4-00000bed P000001.1e007b20:0bed
|
||||
phy_read(RTL8224_PHY_ID, 0x1e, 0x7b20);
|
||||
pval = SFR_DATA_U16;
|
||||
|
||||
REG_WRITE(0x2f8, 0, 0, pval >> 8, pval);
|
||||
pval &= 0x0fe0;
|
||||
pval |= 0x000d;
|
||||
REG_WRITE(0x2f4, 0, 0, pval >> 8, pval);
|
||||
phy_write(0x01, 0x1e, 0x7b20, pval);
|
||||
|
||||
phy_write(RTL8224_PHY_ID, 0x1e, 0x7b20, pval);
|
||||
|
||||
uint8_t i = 0;
|
||||
while (rtl8224_ca[i]) {
|
||||
phy_write(0x1, 0x1e, 0x400, rtl8224_ca[i]);
|
||||
phy_write(RTL8224_PHY_ID, 0x1e, 0x400, rtl8224_ca[i]);
|
||||
i++;
|
||||
phy_write(0x1, 0x1e, 0x3f8, rtl8224_ca[i]);
|
||||
phy_write(RTL8224_PHY_ID, 0x1e, 0x3f8, rtl8224_ca[i]);
|
||||
i++;
|
||||
do {
|
||||
phy_read(0, 0x1e, 0x3f8);
|
||||
phy_read(RTL8224_PHY_ID, 0x1e, 0x3f8);
|
||||
} while (SFR_DATA_8 & 0x80);
|
||||
}
|
||||
|
||||
@@ -228,41 +189,54 @@ void phy_set_mode(uint8_t port, uint8_t speed, uint8_t flow_control, uint8_t dup
|
||||
{
|
||||
uint16_t v;
|
||||
phy_read(port, 0x1f, 0xa610);
|
||||
v = (((uint16_t)SFR_DATA_8) << 8) | SFR_DATA_0;
|
||||
v = SFR_DATA_U16;
|
||||
if (speed == PHY_OFF) {
|
||||
phy_write(bit_mask[port], 0x1f, 0xa610, v | 0x0800);
|
||||
phy_write(port, 0x1f, 0xa610, v | 0x0800);
|
||||
return;
|
||||
}
|
||||
// Port is on, make sure of it:
|
||||
if (v & 0x0800)
|
||||
phy_write(bit_mask[port], 0x1f, 0xa610, v & 0xf7ff);
|
||||
phy_write(port, 0x1f, 0xa610, v & 0xf7ff);
|
||||
|
||||
if (speed == PHY_SPEED_AUTO) {
|
||||
// AN Advertisement Register (MMD 7.0x0010)
|
||||
phy_write(bit_mask[port], 0x07, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
|
||||
phy_write(port, PHY_MMD_AN, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
|
||||
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
|
||||
phy_write(bit_mask[port], 0x07, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed
|
||||
phy_write(bit_mask[port], 0x07, 0x00, 0x3200); // Restart AN
|
||||
phy_write(port, PHY_MMD_AN, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed
|
||||
phy_write(port, PHY_MMD_AN, 0x00, 0x3200); // Restart AN
|
||||
} else {
|
||||
// AN Control Register (MMD 7.0x0000)
|
||||
phy_write(bit_mask[port], 0x07, 0x00, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13)
|
||||
phy_write(port, PHY_MMD_AN, 0x00, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13)
|
||||
// AN Advertisement Register (MMD 7.0x0010)
|
||||
phy_write(bit_mask[port], 0x07, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
|
||||
phy_write(port, PHY_MMD_AN, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
|
||||
if (speed == PHY_SPEED_1G) {
|
||||
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
|
||||
phy_write(bit_mask[port], 0x07, 0x20, 0x6001); // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed
|
||||
phy_write(port, PHY_MMD_AN, 0x20, 0x6001); // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed
|
||||
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
|
||||
phy_read(port, 0x1f, 0xa412);
|
||||
v = (((uint16_t)SFR_DATA_8) << 8) | SFR_DATA_0;
|
||||
phy_write(bit_mask[port], 0x1f, 0xa412, v | 0x0200);
|
||||
phy_modify(port, 0x1f, 0xa412, 0x0000, 0x02000);
|
||||
} else if (speed == PHY_SPEED_2G5) {
|
||||
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
|
||||
phy_write(bit_mask[port], 0x07, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed
|
||||
phy_write(port, PHY_MMD_AN, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed
|
||||
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
|
||||
phy_read(port, 0x1f, 0xa412);
|
||||
v = (((uint16_t)SFR_DATA_8) << 8) | SFR_DATA_0;
|
||||
phy_write(bit_mask[port], 0x1f, 0xa412, v & 0xfdff);
|
||||
phy_modify(port, 0x1f, 0xa412, 0x02000, 0x0000);
|
||||
}
|
||||
phy_write(bit_mask[port], 0x07, 0x00, 0x3200); // Enable AN
|
||||
phy_write(port, PHY_MMD_AN, 0x00, 0x3200); // Enable AN
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void phy_reset(uint8_t port) __banked
|
||||
{
|
||||
uint16_t v;
|
||||
phy_read(port, PHY_MMD_CTRL, 0xa610);
|
||||
v = SFR_DATA_U16;
|
||||
// If PHY off, do nothing
|
||||
if (v & 0x0800)
|
||||
return;
|
||||
|
||||
// Disable PHY
|
||||
phy_write(port, PHY_MMD_CTRL, 0xa610, v | 0x0800);
|
||||
delay(2);
|
||||
// Re-enable PHY
|
||||
phy_write(port, PHY_MMD_CTRL, 0xa610, v & 0xf7ff);
|
||||
}
|
||||
|
||||
@@ -10,5 +10,6 @@ void rtl8224_phy_enable(void) __banked;
|
||||
void phy_config(uint8_t phy) __banked;
|
||||
void phy_config_8224(void) __banked;
|
||||
void phy_set_mode(uint8_t port, uint8_t speed, uint8_t flow_control, uint8_t duplex) __banked;
|
||||
void phy_reset(uint8_t port) __banked;
|
||||
|
||||
#endif
|
||||
|
||||
+228
-43
@@ -10,21 +10,42 @@
|
||||
#include "rtl837x_common.h"
|
||||
#include "rtl837x_sfr.h"
|
||||
#include "rtl837x_regs.h"
|
||||
#include "rtl837x_port.h"
|
||||
#include "rtl837x_phy.h"
|
||||
#include "phy.h"
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
|
||||
extern __code uint8_t * __code hex;
|
||||
extern __code uint16_t bit_mask[16];
|
||||
extern __xdata uint8_t minPort;
|
||||
extern __xdata uint8_t maxPort;
|
||||
extern __xdata uint8_t nSFPPorts;
|
||||
extern __xdata uint8_t sfr_data[4];
|
||||
extern __xdata uint8_t cpuPort;
|
||||
extern __xdata uint16_t vlan_ptr;
|
||||
extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
|
||||
|
||||
extern __xdata uint8_t isRTL8373;
|
||||
|
||||
__xdata uint32_t l2_head;
|
||||
|
||||
// The mapping of logical to physical ports on the RTL8372
|
||||
// Port 6 is always an SFP+ port. Port 5 may be RTL8221 or SFP+
|
||||
__code uint8_t log_to_phys_port[9] = {
|
||||
0, 0, 0, 5, 1, 2, 3, 4, 6
|
||||
};
|
||||
|
||||
#if NSFP == 2
|
||||
__code uint8_t is_sfp[9] = {
|
||||
0, 0, 0, 1, 0, 0, 0, 0, 1
|
||||
};
|
||||
#else
|
||||
__code uint8_t is_sfp[9] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1
|
||||
};
|
||||
#endif
|
||||
|
||||
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked
|
||||
{
|
||||
@@ -83,6 +104,41 @@ void vlan_delete(uint16_t vlan) __banked
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reads VLAN information from VLAN table
|
||||
* Returns data in sfr_data
|
||||
*/
|
||||
int8_t vlan_get(register uint16_t vlan) __banked
|
||||
{
|
||||
if (vlan >= 0x3ff) // VLAN 4095 is special
|
||||
return -1;
|
||||
|
||||
REG_WRITE(RTL837X_TBL_CTRL, vlan >> 8, vlan, TBL_VLAN, TBL_EXECUTE);
|
||||
do {
|
||||
reg_read_m(RTL837X_TBL_CTRL);
|
||||
} while (sfr_data[3] & TBL_EXECUTE);
|
||||
reg_read_m(RTL837x_L2_DATA_OUT_A);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
__xdata uint16_t vlan_name(register uint16_t vlan) __banked
|
||||
{
|
||||
__xdata int16_t i = 0;
|
||||
__xdata uint8_t begin = 1;
|
||||
while (vlan_names[i]) {
|
||||
if (begin && vlan_names[i] == hex[(vlan >> 8) & 0xf] && vlan_names[i + 1] == hex[(vlan >> 4) & 0xf] && vlan_names[i + 2] == hex[vlan & 0xf])
|
||||
break;
|
||||
begin = vlan_names[i++] == ' ' ? 1 : 0;
|
||||
}
|
||||
if (vlan_names[i])
|
||||
return i + 3;
|
||||
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A member that is not tagged, is untagged
|
||||
*/
|
||||
@@ -123,6 +179,10 @@ void vlan_setup(void) __banked
|
||||
{
|
||||
print_string("\nvlan_setup called \n");
|
||||
|
||||
// No VLAN names set up so far
|
||||
vlan_ptr = 0;
|
||||
vlan_names[0] = 0;
|
||||
|
||||
// Initialize VLAN table for VLAN 1, by disabling that entry
|
||||
if (isRTL8373) {
|
||||
REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007ffff);
|
||||
@@ -219,19 +279,21 @@ void trunk_set(uint8_t group, uint16_t mask) __banked
|
||||
uint8_t port_l2_forget(void) __banked
|
||||
{
|
||||
print_string("\nport_l2_forget called\n");
|
||||
// r53dc:00000000 R53dc-00000000 r53d4:000001ff r53d4:000001ff R53d4-000101ff r53d4:000001ff
|
||||
reg_read_m(0x53dc);
|
||||
if (sfr_data[0] || sfr_data[1] ||sfr_data[2] ||sfr_data[3]) {
|
||||
print_string("List busy\n");
|
||||
return 0xff;
|
||||
}
|
||||
REG_WRITE(0x53dc, sfr_data[0], sfr_data[1], sfr_data[2], sfr_data[3]);
|
||||
// Configure the entries to be flushed:
|
||||
// port-based (bits 0-1 are 0 and dynamic entries, bit 2 specifies dynamic entries
|
||||
REG_SET(RTL837x_L2_TBL_FLUSH_CNF, 0x0);
|
||||
|
||||
reg_read_m(RTL837x_L2_TBL_CTRL);
|
||||
REG_WRITE(RTL837x_L2_TBL_CTRL, 0x00, 0x01, sfr_data[2], sfr_data[3]);
|
||||
// Flush L2 table for all ports by setting the ports and the flush-exec bit (bit 16)
|
||||
if (isRTL8373) {
|
||||
REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | PMASK_9);
|
||||
} else {
|
||||
REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | PMASK_6);
|
||||
}
|
||||
|
||||
// Wait for flush completed
|
||||
do {
|
||||
reg_read_m(RTL837x_L2_TBL_CTRL);
|
||||
} while (sfr_data[1] & 0x1);
|
||||
reg_read_m(RTL837x_L2_TBL_FLUSH_CTRL);
|
||||
} while (sfr_data[1]);
|
||||
|
||||
print_string("port_l2_forget done\n");
|
||||
return 0;
|
||||
@@ -308,24 +370,22 @@ void port_l2_learned(void) __banked
|
||||
/*
|
||||
* Basic L2 configuration such as time to forget an entry
|
||||
*/
|
||||
void port_l2_setup() __banked
|
||||
void port_l2_setup(void) __banked
|
||||
{
|
||||
print_string("\nport_l2_setup called\n");
|
||||
REG_SET(0x53dc, 0x00000000);
|
||||
if(isRTL8373) {
|
||||
REG_SET(0x53d4, 0x000101ff);
|
||||
} else {
|
||||
REG_SET(0x53d4, 0x000001f8);
|
||||
}
|
||||
|
||||
port_l2_forget();
|
||||
|
||||
for (uint8_t i = minPort; i <= maxPort; i++) {
|
||||
uint16_t reg = 0x5384 + (i << 2);
|
||||
REG_SET(reg, 0x00001040);
|
||||
|
||||
reg = 0x50c0 + (i << 2);
|
||||
// All ports may communicate with each other and CPU-Port
|
||||
reg = RTL837X_PORT_ISOLATION_BASE + (i << 2);
|
||||
if(isRTL8373) {
|
||||
REG_SET(reg, 0x3ff);
|
||||
REG_SET(reg, PMASK_9 | PMASK_CPU);
|
||||
} else {
|
||||
REG_SET(reg, 0x3f8);
|
||||
REG_SET(reg, PMASK_6 | PMASK_CPU);
|
||||
}
|
||||
}
|
||||
reg_bit_set(0x4f80, 0);
|
||||
@@ -366,13 +426,13 @@ void port_stats_print(void) __banked
|
||||
break;
|
||||
}
|
||||
} else { // An SFP Module TODO: This is for 1 module devices
|
||||
reg_read_m(RTL837X_REG_GPIO_B);
|
||||
reg_read_m(RTL837X_REG_GPIO_00_31_INPUT);
|
||||
if (!(sfr_data[0] & 0x40)) {
|
||||
print_string("SFP OK\t");
|
||||
} else {
|
||||
print_string("NO SFP\t");
|
||||
}
|
||||
reg_read_m(RTL837X_REG_GPIO_C);
|
||||
reg_read_m(RTL837X_REG_GPIO_32_63_INPUT);
|
||||
if (sfr_data[3] & 0x20) {
|
||||
print_string("Down\t");
|
||||
} else {
|
||||
@@ -387,28 +447,153 @@ void port_stats_print(void) __banked
|
||||
print_string("Up\t");
|
||||
}
|
||||
}
|
||||
STAT_GET(0x2f, i);
|
||||
print_reg(RTL837X_STAT_V_LOW); write_char('\t');
|
||||
|
||||
REG_WRITE(RTL837X_STAT_GET, 0x00, 0x00, 0x05, 0xe0 | (i << 1) | 1);
|
||||
do {
|
||||
reg_read_m(RTL837X_STAT_GET);
|
||||
} while (sfr_data[3] & 0x1);
|
||||
// FIXME: Ignore HIGHER part of 64 bit value for now
|
||||
STAT_GET(0x30, i);
|
||||
print_reg(RTL837X_STAT_V_HIGH); write_char('\t');
|
||||
|
||||
STAT_GET(0x2e, i);
|
||||
print_reg(RTL837X_STAT_V_LOW); write_char('\t');
|
||||
REG_WRITE(RTL837X_STAT_GET, 0x00, 0x00, 0x06, (i << 1) | 1);
|
||||
do {
|
||||
reg_read_m(RTL837X_STAT_GET);
|
||||
} while (sfr_data[3] & 0x1);
|
||||
print_reg(RTL837X_STAT_V_LOW); write_char('\t');
|
||||
REG_WRITE(RTL837X_STAT_GET, 0x00, 0x00, 0x05, 0xc0 | (i << 1) | 1);
|
||||
do {
|
||||
reg_read_m(RTL837X_STAT_GET);
|
||||
} while (sfr_data[3] & 0x1);
|
||||
print_reg(RTL837X_STAT_V_LOW); write_char('\t');
|
||||
REG_WRITE(RTL837X_STAT_GET, 0x00, 0x00, 0x06, (i << 1) | 1);
|
||||
do {
|
||||
reg_read_m(RTL837X_STAT_GET);
|
||||
} while (sfr_data[3] & 0x1);
|
||||
|
||||
STAT_GET(0x30, i);
|
||||
print_reg(RTL837X_STAT_V_LOW); write_char('\t');
|
||||
print_string("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void port_isolate(register uint8_t port, __xdata uint16_t pmask)
|
||||
{
|
||||
if (port <= maxPort)
|
||||
REG_SET(RTL837X_PORT_ISOLATION_BASE + (port << 2), pmask);
|
||||
}
|
||||
|
||||
|
||||
uint16_t port_isolation_get(register uint8_t port)
|
||||
{
|
||||
if (port > maxPort)
|
||||
return 0;
|
||||
|
||||
reg_read_m(RTL837X_PORT_ISOLATION_BASE + (port << 2));
|
||||
return ((uint16_t)sfr_data[2]) << 8 | sfr_data[3];
|
||||
}
|
||||
|
||||
|
||||
void port_eee_enable(uint8_t port) __banked
|
||||
{
|
||||
if (is_sfp[port])
|
||||
return;
|
||||
|
||||
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);
|
||||
phy_reset(port);
|
||||
}
|
||||
|
||||
|
||||
void port_eee_disable(uint8_t port) __banked
|
||||
{
|
||||
if (is_sfp[port])
|
||||
return;
|
||||
|
||||
print_string("EEE off for "); print_byte(port); write_char('\n');
|
||||
REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), 0);
|
||||
// Disable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg
|
||||
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, 0);
|
||||
// Disable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
|
||||
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, 0);
|
||||
phy_reset(port);
|
||||
}
|
||||
|
||||
|
||||
void port_eee_status(uint8_t port) __banked
|
||||
{
|
||||
print_string("Port: "); write_char('0' + log_to_phys_port[port]);
|
||||
print_string(": ");
|
||||
if (is_sfp[port]) {
|
||||
print_string("SFP\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t v;
|
||||
print_string("Advertising: ");
|
||||
phy_read(port, PHY_MMD_AN, PHY_EEE_ADV2);
|
||||
v = SFR_DATA_U16;
|
||||
if (v & PHY_EEE_BIT_2G5)
|
||||
print_string(" 2.5G");
|
||||
else
|
||||
print_string(" ");
|
||||
phy_read(port, PHY_MMD_AN, PHY_EEE_ADV);
|
||||
v = SFR_DATA_U16;
|
||||
if (v & PHY_EEE_BIT_1G)
|
||||
print_string(" 1G ");
|
||||
else
|
||||
print_string(" ");
|
||||
if (v & PHY_EEE_BIT_100M)
|
||||
print_string(" 100M");
|
||||
else
|
||||
print_string(" ");
|
||||
|
||||
print_string(" Link Partner: ");
|
||||
phy_read(port, PHY_MMD_AN, PHY_EEE_LP_ABILITY2);
|
||||
v = SFR_DATA_U16;
|
||||
if (v & PHY_EEE_BIT_2G5)
|
||||
print_string(" 2.5G");
|
||||
else
|
||||
print_string(" ");
|
||||
phy_read(port, PHY_MMD_AN, PHY_EEE_LP_ABILITY);
|
||||
v = SFR_DATA_U16;
|
||||
if (v & PHY_EEE_BIT_1G)
|
||||
print_string(" 1G ");
|
||||
else
|
||||
print_string(" ");
|
||||
if (v & PHY_EEE_BIT_100M)
|
||||
print_string(" 100M");
|
||||
else
|
||||
print_string(" ");
|
||||
|
||||
reg_read_m(RTL8373_PHY_EEE_ABLTY);
|
||||
if (sfr_data[3] & (1 << port))
|
||||
print_string(" ACTIVE ");
|
||||
else
|
||||
print_string(" INACTIVE ");
|
||||
write_char('\n');
|
||||
}
|
||||
|
||||
|
||||
void port_eee_enable_all(void) __banked
|
||||
{
|
||||
for (uint8_t i = minPort; i <= maxPort; i++) {
|
||||
port_eee_enable(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void port_eee_disable_all(void) __banked
|
||||
{
|
||||
for (uint8_t i = minPort; i <= maxPort; i++) {
|
||||
port_eee_disable(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void port_eee_status_all(void) __banked
|
||||
{
|
||||
for (uint8_t i = minPort; i <= maxPort; i++) {
|
||||
port_eee_status(i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable RLDP, Realtek's version of LLDP
|
||||
*/
|
||||
void port_rldp_on(__xdata uint16_t p_ms)
|
||||
{
|
||||
REG_WRITE(RTL8373_RLDP_TIMER, p_ms >> 8, p_ms, p_ms >> 8, p_ms);
|
||||
|
||||
REG_SET(RTL837X_RMA0_CONF, 0x00000000); // R4ecc
|
||||
REG_SET(RTL837X_RMA_CONF, 0x00000000); // R4ecc
|
||||
}
|
||||
|
||||
+22
-2
@@ -1,16 +1,36 @@
|
||||
#ifndef _RTL837X_PORT_H_
|
||||
#define _RTL837X_PORT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define STAT_COUNTER_TX_PKTS 0x2e
|
||||
#define STAT_COUNTER_RX_PKTS 0x2f
|
||||
#define STAT_COUNTER_ERR_PKTS 0x30
|
||||
|
||||
#define STAT_GET(cnt, port) \
|
||||
REG_WRITE(RTL837X_STAT_GET, 0x00, 0x00, cnt >> 3, (cnt << 5) | (port << 1) | 1); \
|
||||
do { \
|
||||
reg_read_m(RTL837X_STAT_GET); \
|
||||
} while (sfr_data[3] & 0x1);
|
||||
|
||||
uint8_t port_l2_forget(void) __banked;
|
||||
void port_l2_learned(void) __banked;
|
||||
void port_stats_print(void) __banked;
|
||||
int8_t vlan_get(register uint16_t vlan) __banked;
|
||||
__xdata uint16_t vlan_name(register uint16_t vlan) __banked;
|
||||
void vlan_setup(void) __banked;
|
||||
void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked;
|
||||
void vlan_create(uint16_t vlan, uint16_t members, uint16_t tagged) __banked;
|
||||
void vlan_create(register uint16_t vlan, register uint16_t members, register uint16_t tagged) __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_del(void) __banked;
|
||||
void port_ingress_filter(register uint8_t port, uint8_t type) __banked;
|
||||
void port_l2_setup() __banked;
|
||||
void port_l2_setup(void) __banked;
|
||||
void trunk_set(uint8_t group, uint16_t mask) __banked;
|
||||
void port_eee_enable_all(void) __banked;
|
||||
void port_eee_disable_all(void) __banked;
|
||||
void port_eee_status_all(void) __banked;
|
||||
void port_eee_enable(uint8_t port) __banked;
|
||||
void port_eee_disable(uint8_t port) __banked;
|
||||
void port_eee_status(uint8_t port) __banked;
|
||||
#endif
|
||||
|
||||
+73
-21
@@ -39,30 +39,46 @@
|
||||
5: 2.5Gbit
|
||||
*/
|
||||
|
||||
#define RTL837X_REG_GPIO_A 0x40
|
||||
|
||||
/*
|
||||
* Pin configuration (pinmux)
|
||||
*/
|
||||
|
||||
#define RTL837X_PIN_MUX_0 0x7f8c
|
||||
#define RTL837X_PIN_MUX_1 0x7f90
|
||||
|
||||
// Output Registers
|
||||
#define RTL837X_REG_GPIO_00_31_OUTPUT 0x3c
|
||||
#define RTL837X_REG_GPIO_32_63_OUTPUT 0x40
|
||||
// BIT 4 resets RTL8224 on 9000-9XH
|
||||
|
||||
#define RTL837X_REG_GPIO_B 0x44
|
||||
// Input Registers
|
||||
#define RTL837X_REG_GPIO_00_31_INPUT 0x44
|
||||
#define RTL837X_REG_GPIO_32_63_INPUT 0x48
|
||||
// Bit 1e cleared: SFP Module inserted on 9000-6XH (MOD_DEF0 pin)
|
||||
|
||||
#define RTL837X_REG_GPIO_C 0x48
|
||||
// BIT 5 set: SIGNAL LOS of SFP module on 9000-6XH (RX_LOS pin)
|
||||
|
||||
#define RTL837X_REG_GPIO_CONF_A 0x50
|
||||
// Configures IO direction for bank a
|
||||
|
||||
#define RTL837X_REG_GPIO_EXT 0x63e8
|
||||
// Direction Registers, 0 = input, 1 = output
|
||||
#define RTL837X_REG_GPIO_00_31_DIRECTION 0x4c
|
||||
#define RTL837X_REG_GPIO_32_63_DIRECTION 0x50
|
||||
|
||||
/*
|
||||
* I2C controller
|
||||
*/
|
||||
#define RTL837X_REG_I2C_CTRL 0x0418
|
||||
#define RTL837X_REG_I2C_IN 0x0420
|
||||
#define RTL837X_REG_I2C_OUT 0x0424
|
||||
#define RTL837X_REG_I2C_MST_IF_CTRL 0x0414
|
||||
#define RTL837X_REG_I2C_CTRL 0x0418
|
||||
#define I2C_DEV_ADDR 3
|
||||
#define I2C_MEM_ADDR_WIDTH 20
|
||||
#define RTL837X_REG_I2C_CTRL2 0x041c
|
||||
#define RTL837X_REG_I2C_IN 0x0420
|
||||
#define RTL837X_REG_I2C_OUT 0x0424
|
||||
|
||||
/*
|
||||
* NIC Related registers
|
||||
*/
|
||||
#define RTL837X_REG_RX_CTRL 0x785c
|
||||
#define RTL837X_REG_TX_CTRL 0x7860
|
||||
#define RTL837X_REG_RX_AVAIL 0x7874
|
||||
#define RTL837X_REG_RX_RINGPTR 0x787c
|
||||
#define RTL837X_REG_RX_DONE 0x784c
|
||||
@@ -90,14 +106,18 @@
|
||||
#define TBL_L2_UNICAST 0x04
|
||||
#define TBL_VLAN 0x03
|
||||
|
||||
#define RTL837X_L2_CTRL 0x5350
|
||||
#define RTL837x_TBL_DATA_0 0x5cb0
|
||||
#define RTL837x_L2_DATA_OUT_A 0x5ccc
|
||||
#define RTL837x_L2_DATA_OUT_B 0x5cd0
|
||||
#define RTL837x_L2_DATA_OUT_C 0x5cd4
|
||||
#define RTL837x_TBL_DATA_IN_A 0x5cb8
|
||||
#define RTL837x_L2_TBL_CTRL 0x53d4
|
||||
#define RTL837x_PVID_BASE_REG 0x4e1c
|
||||
|
||||
#define RTL837x_L2_TBL_FLUSH_CTRL 0x53d4
|
||||
#define L2_TBL_FLUSH_EXEC 0x10000
|
||||
#define RTL837x_L2_TBL_FLUSH_CNF 0x53dc
|
||||
|
||||
/*
|
||||
* Egress / ingress filtering
|
||||
*/
|
||||
@@ -110,20 +130,52 @@
|
||||
/*
|
||||
* Mirroring
|
||||
*/
|
||||
#define RTL837x_MIRROR_CONF 0x604c
|
||||
#define RTL837x_MIRROR_CTRL 0x6048
|
||||
#define RTL837x_MIRROR_CONF 0x604c
|
||||
#define RTL837x_MIRROR_CTRL 0x6048
|
||||
|
||||
/*
|
||||
* Trunking
|
||||
*/
|
||||
#define RTL837x_TRUNK_CTRL_A 0x4f38
|
||||
#define RTL837x_TRUNK_CTRL_B 0x4f3c
|
||||
#define RTL837x_TRUNK_CTRL_A 0x4f38
|
||||
#define RTL837x_TRUNK_CTRL_B 0x4f3c
|
||||
|
||||
/*
|
||||
* Port isolation
|
||||
*/
|
||||
#define RTL837X_PORT_ISOLATION_BASE 0x50c0
|
||||
|
||||
/*
|
||||
* Multicast handling
|
||||
*/
|
||||
#define RTL837X_MC_LOOKUPMISS_ACTIONS 0x4f78
|
||||
#define RTL837X_IGMP_PORT_CFG 0x52a0
|
||||
#define RTL837X_MC_FLOODMASK 0x5368
|
||||
|
||||
/*
|
||||
* Loop detection / STP
|
||||
*/
|
||||
#define RTL8373_RLDP_TIMER 0x1074
|
||||
#define RTL837X_RMA0_CONF 0x4ecc
|
||||
#define RTL837X_RMA_CONF 0x4f1c
|
||||
#define RTL837X_MSTP_STATES 0x5310
|
||||
|
||||
/*
|
||||
* EEE
|
||||
*/
|
||||
#define RTL837X_EEE_STATUS 0x125C
|
||||
#define RTL837X_MAC_EEE_ABLTY 0x6404
|
||||
#define RTL8373_PHY_EEE_ABLTY 0x642C
|
||||
#define RTL8373_EEE_CTRL_BASE 0x606c
|
||||
#define EEE_100 0x01
|
||||
#define EEE_1000 0x04
|
||||
#define EEE_2G5 0x10
|
||||
|
||||
|
||||
#ifdef REGDBG
|
||||
|
||||
#define REG_SET(r, v) SFR_DATA_24 = ((v) >> 24) & 0xff; \
|
||||
SFR_DATA_16 = ((v) >> 16) & 0xff; \
|
||||
SFR_DATA_8 = ((v) >> 8 & 0xff); \
|
||||
#define REG_SET(r, v) SFR_DATA_24 = (((uint32_t)v) >> 24) & 0xff; \
|
||||
SFR_DATA_16 = (((uint32_t)v) >> 16) & 0xff; \
|
||||
SFR_DATA_8 = (((uint16_t)v) >> 8 & 0xff); \
|
||||
SFR_DATA_0 = (v) & 0xff; \
|
||||
reg_write(r); \
|
||||
write_char('R'); print_byte(r >> 8); print_byte(r); write_char('-'); \
|
||||
@@ -136,9 +188,9 @@
|
||||
reg_write(r); \
|
||||
write_char('R'); print_byte(r>>8); print_byte(r); write_char('-'); print_byte(v24); print_byte(v16); print_byte(v8); print_byte(v0); write_char(' ');
|
||||
#else
|
||||
#define REG_SET(r, v) SFR_DATA_24 = ((v) >> 24) & 0xff; \
|
||||
SFR_DATA_16 = ((v) >> 16) & 0xff; \
|
||||
SFR_DATA_8 = ((v) >> 8 & 0xff); \
|
||||
#define REG_SET(r, v) SFR_DATA_24 = (((uint32_t)v) >> 24) & 0xff; \
|
||||
SFR_DATA_16 = (((uint32_t)v) >> 16) & 0xff; \
|
||||
SFR_DATA_8 = (((uint16_t)v) >> 8 & 0xff); \
|
||||
SFR_DATA_0 = (v) & 0xff; \
|
||||
reg_write(r);
|
||||
|
||||
|
||||
+8
-1
@@ -1,8 +1,12 @@
|
||||
/* SFR control registers for switch register access */
|
||||
__sfr __at(0xa0) SFR_EXEC_GO;
|
||||
__sfr __at(0xa1) SFR_EXEC_STATUS;
|
||||
__sfr16 __at(0xa2a3) SFR_REG_ADDR_U16;
|
||||
__sfr __at(0xa2) SFR_REG_ADDRH;
|
||||
__sfr __at(0xa3) SFR_REG_ADDRL;
|
||||
__sfr16 __at(0xa6a7) SFR_DATA_U16;
|
||||
__sfr32 __at(0xa4a5a6a7) SFR_DATA_U32;
|
||||
__sfr32 __at(0xa7a6a5a4) SFR_DATA_U32LE;
|
||||
__sfr __at(0xa4) SFR_DATA_24;
|
||||
__sfr __at(0xa5) SFR_DATA_16;
|
||||
__sfr __at(0xa6) SFR_DATA_8;
|
||||
@@ -17,6 +21,7 @@ __sfr __at(0xa7) SFR_DATA_0;
|
||||
#define SFR_EXEC_WRITE_SMI 11
|
||||
|
||||
/* SFR control registers for phy access via SMI/MDIO */
|
||||
__sfr16 __at(0xc2c3) SFR_SMI_REG_U16;
|
||||
__sfr __at(0xc2) SFR_SMI_REG_H;
|
||||
__sfr __at(0xc3) SFR_SMI_REG_L;
|
||||
__sfr __at(0xc4) SFR_SMI_DEV;
|
||||
@@ -66,7 +71,7 @@ __sfr __at(0xbc) SFR_FLASH_CONFIG;
|
||||
|
||||
__sfr __at(0x9b) SFR_FLASH_CONF_DIV;
|
||||
__sfr __at(0x9c) SFR_FLASH_CONF_RCMD;
|
||||
__sfr __at(0x9d) SFR_FLASH_DUMMYCICLES;
|
||||
__sfr __at(0x9d) SFR_FLASH_DUMMYCYCLES;
|
||||
__sfr __at(0x9a) SFR_FLASH_MODEB;
|
||||
|
||||
__sfr __at(0x9e) SFR_FLASH_TCONF;
|
||||
@@ -86,7 +91,9 @@ __sfr __at(0xa9) SFR_FLASH_ADDR0;
|
||||
* CAREFUL: This is now Little Endian
|
||||
*/
|
||||
__sfr __at(0xb7) SFR_NIC_CTRL;
|
||||
__sfr16 __at(0xb4b3) SFR_NIC_DATA_U16LE;
|
||||
__sfr __at(0xb3) SFR_NIC_DATA_L;
|
||||
__sfr __at(0xb4) SFR_NIC_DATA_H;
|
||||
__sfr16 __at(0xb6b5) SFR_NIC_RING_U16LE;
|
||||
__sfr __at(0xb5) SFR_NIC_RING_L;
|
||||
__sfr __at(0xb6) SFR_NIC_RING_H;
|
||||
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* This is a driver implementation for the Spanning Tree Protocol features for the RTL837x platform
|
||||
* This code is in the Public Domain
|
||||
*/
|
||||
|
||||
// #define REGDBG
|
||||
// #define DEBUG
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rtl837x_common.h"
|
||||
#include "rtl837x_sfr.h"
|
||||
#include "rtl837x_regs.h"
|
||||
#include "rtl837x_stp.h"
|
||||
#include "uip.h"
|
||||
|
||||
extern __xdata uint8_t minPort;
|
||||
extern __xdata uint8_t maxPort;
|
||||
extern __xdata uint8_t nSFPPorts;
|
||||
extern __xdata uint8_t cpuPort;
|
||||
extern __xdata uint8_t isRTL8373;
|
||||
extern __xdata uint8_t sfr_data[4];
|
||||
|
||||
extern __code struct uip_eth_addr uip_ethaddr;
|
||||
|
||||
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2];
|
||||
|
||||
struct bridge {
|
||||
uint8_t prio;
|
||||
uint8_t ext;
|
||||
uint8_t mac[6];
|
||||
};
|
||||
|
||||
__xdata struct bridge root_bridge;
|
||||
__xdata uint32_t root_bridge_cost;
|
||||
|
||||
__xdata uint8_t port_types[10];
|
||||
__xdata uint16_t port_timers[10];
|
||||
__xdata uint16_t port_hello[10];
|
||||
|
||||
|
||||
// 8899 04 0000 20 0004
|
||||
struct rtl_tag {
|
||||
uint16_t tag;
|
||||
uint8_t version;
|
||||
uint16_t dummy;
|
||||
uint8_t flag;
|
||||
uint16_t pmask;
|
||||
};
|
||||
|
||||
|
||||
struct stp_pkt {
|
||||
uint8_t stp_addr[6];
|
||||
uint8_t src_addr[6];
|
||||
struct rtl_tag rtl_tag;
|
||||
uint16_t msg_len;
|
||||
uint8_t dsap;
|
||||
uint8_t ssap;
|
||||
uint8_t ctrl;
|
||||
uint16_t proto;
|
||||
uint8_t version;
|
||||
uint8_t bpdu_type;
|
||||
uint8_t flags;
|
||||
struct bridge root;
|
||||
uint32_t root_path_cost;
|
||||
struct bridge bridge;
|
||||
uint8_t port_prio;
|
||||
uint8_t port_id;
|
||||
uint16_t age;
|
||||
uint16_t age_max;
|
||||
uint16_t hello;
|
||||
uint16_t fwd_delay;
|
||||
};
|
||||
|
||||
struct stp_pkt_in {
|
||||
uint8_t stp_addr[6];
|
||||
uint8_t src_addr[6];
|
||||
struct rtl_tag rtl_tag;
|
||||
uint8_t vtag[4];
|
||||
uint16_t msg_len;
|
||||
uint8_t dsap;
|
||||
uint8_t ssap;
|
||||
uint8_t ctrl;
|
||||
uint16_t proto;
|
||||
uint8_t version;
|
||||
uint8_t bpdu_type;
|
||||
uint8_t flags;
|
||||
struct bridge root;
|
||||
uint32_t root_path_cost;
|
||||
struct bridge bridge;
|
||||
uint8_t port_prio;
|
||||
uint8_t port_id;
|
||||
uint16_t age;
|
||||
uint16_t age_max;
|
||||
uint16_t hello;
|
||||
uint16_t fwd_delay;
|
||||
};
|
||||
|
||||
#define STP_O ((__xdata struct stp_pkt *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE])
|
||||
#define STP_I ((__xdata struct stp_pkt_in *)&uip_buf[0])
|
||||
|
||||
#define FLAG_PROPOSAL 0x02
|
||||
#define P_DESIGNATED ((STP_I->flags & 0x0c) == 0x0c)
|
||||
#define P_PROPOSAL (STP_I->flags & FLAG_PROPOSAL)
|
||||
|
||||
signed char cmpMAC(__xdata uint8_t *m1, __xdata uint8_t *m2)
|
||||
{
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (m1[i] == m2[i])
|
||||
continue;
|
||||
if (m1[i] < m2[i])
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void stp_in(void) __banked
|
||||
{
|
||||
// By default we do not send anything out
|
||||
uip_len = 0;
|
||||
// MSTPSTP_I_STATES 0x5310
|
||||
// reg_read_m(RTL837X_MSTP_STATES);
|
||||
|
||||
print_string("Check BPDU... \n");
|
||||
for (uint8_t i = 0; i < 80; i++) {
|
||||
print_byte(uip_buf[i]);
|
||||
write_char(' ');
|
||||
}
|
||||
write_char('\n');
|
||||
print_byte(STP_I->dsap);
|
||||
print_byte(STP_I->ssap);
|
||||
print_byte(STP_I->ctrl);
|
||||
|
||||
write_char('\n');
|
||||
// Make sure this is the type of RSTP packet we are interested in:
|
||||
if (!(STP_I->dsap == 0x42 && STP_I->ssap == 0x42 && STP_I->ctrl == 0x03))
|
||||
return;
|
||||
print_string("Checking RSTP\n");
|
||||
if (STP_I->proto)
|
||||
return;
|
||||
// write_char('A'); print_byte(STP_I->version); write_char('\n');
|
||||
if (STP_I->version != 2)
|
||||
return;
|
||||
// write_char('B'); print_byte(STP_I->bpdu_type); write_char('\n');
|
||||
if (STP_I->bpdu_type != 2)
|
||||
return;
|
||||
// write_char('\n');
|
||||
// print_string("Flags: "); print_byte(STP_I->flags); write_char('\n');
|
||||
print_string("Check new Root\n");
|
||||
if (STP_I->root.prio < root_bridge.prio
|
||||
|| ((STP_I->root.prio == root_bridge.prio) && cmpMAC(STP_I->root.mac, STP_I->root.mac) < 0)) {
|
||||
print_string("Updating Root bridge\n");
|
||||
root_bridge.prio = STP_I->root.prio;
|
||||
memcpy(root_bridge.mac, STP_I->root.mac, 6);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void stp_cnf_send(uint8_t port)
|
||||
{
|
||||
STP_O->stp_addr[0] = 0x01; STP_O->stp_addr[1] = 0x80; STP_O->stp_addr[2] = 0xc2;
|
||||
STP_O->stp_addr[3] = STP_O->stp_addr[4] = STP_O->stp_addr[5] = 0x00;
|
||||
|
||||
STP_O->rtl_tag.tag = HTONS(0x8899);
|
||||
STP_O->rtl_tag.version = 0x04;
|
||||
STP_O->rtl_tag.dummy = 0x0000;
|
||||
STP_O->rtl_tag.flag = 0x20; // WHY ???
|
||||
STP_O->rtl_tag.pmask = HTONS(((uint16_t)1) << port);
|
||||
|
||||
STP_O->msg_len = HTONS(0x27);
|
||||
STP_O->dsap = 0x42;
|
||||
STP_O->ssap = 0x42;
|
||||
STP_O->ctrl = 0x03;
|
||||
STP_O->proto = 0x0000;
|
||||
STP_O->version = 0x02; // RSTP
|
||||
STP_O->bpdu_type = 0x00; // Config
|
||||
STP_O->flags = 0x81;
|
||||
|
||||
memcpyc(STP_O->src_addr, uip_ethaddr.addr, 6);
|
||||
memcpy(STP_O->root.mac, root_bridge.mac, 6);
|
||||
memcpyc(STP_O->bridge.mac, uip_ethaddr.addr, 6);
|
||||
|
||||
STP_O->root.prio = root_bridge.prio;
|
||||
STP_O->root.ext = 0x00;
|
||||
STP_O->root_path_cost = 0x00000000;
|
||||
|
||||
STP_O->bridge.prio = 0x80;
|
||||
STP_O->bridge.ext = 0x00;
|
||||
|
||||
STP_O->port_prio = 0x80;
|
||||
STP_O->port_id = port;
|
||||
STP_O->age = 0x00; // FIXME: This only works because we do not use HTONS and the values are in 1/256 seconds
|
||||
STP_O->age_max = 20;
|
||||
STP_O->hello = 2;
|
||||
STP_O->fwd_delay = 0x0f;
|
||||
|
||||
// uip_len = 0x27 + sizeof(struct rtl_tag);
|
||||
uip_len = sizeof(struct stp_pkt);
|
||||
tcpip_output();
|
||||
}
|
||||
|
||||
|
||||
void stp_timers(void) __banked
|
||||
{
|
||||
for (uint8_t i = minPort; i <= maxPort; i++) {
|
||||
port_hello[i]--;
|
||||
if (!port_hello[i]) {
|
||||
port_hello[i] = TIME_HELLO;
|
||||
print_string("STP_HELLO port ");
|
||||
print_byte(i); write_char('\n');
|
||||
stp_cnf_send(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void stp_setup(void) __banked
|
||||
{
|
||||
print_string("Enabling STP: ");
|
||||
sfr_data[0] = sfr_data[1] = sfr_data[2] = sfr_data[3] = 0;
|
||||
for (uint8_t i = minPort; i <= maxPort; i++) {
|
||||
// Set STP port state to blocking
|
||||
// States are: 00 disable, 01 blocking, 10 learning, 11 forwarding
|
||||
uint8_t bit_mask = 0b01 << ( (i << 1) & 0x7);
|
||||
sfr_data[3 - (i >> 2)] |= bit_mask;
|
||||
port_hello[i] = TIME_HELLO;
|
||||
port_timers[i] = 0xa00; // 10 sec in blocking state
|
||||
}
|
||||
sfr_data[1] |= 0x0f; // Do not block CPU-Port
|
||||
reg_write_m(RTL837X_MSTP_STATES); // R5310-000d555f
|
||||
|
||||
print_reg(RTL837X_MSTP_STATES); write_char('\n');
|
||||
|
||||
root_bridge.prio = 0x80; // This corresponds to 32768
|
||||
root_bridge.ext = 0x00;
|
||||
memcpyc(root_bridge.mac, uip_ethaddr.addr, 6);
|
||||
}
|
||||
|
||||
|
||||
void stp_off(void) __banked
|
||||
{
|
||||
sfr_data[0] = sfr_data[1] = sfr_data[2] = sfr_data[3] = 0;
|
||||
for (uint8_t i = minPort; i <= maxPort; i++) {
|
||||
// Set STP port state to forwarding
|
||||
// States are: 00 disable, 01 blocking, 10 learning, 11 forwarding
|
||||
uint8_t bit_mask = 0b11 << ( (i << 1) & 0x7);
|
||||
sfr_data[3 - (i >> 2)] |= bit_mask;
|
||||
}
|
||||
sfr_data[1] |= 0x0f; // Do not block CPU-Port
|
||||
reg_write_m(RTL837X_MSTP_STATES);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef _RTL837X_STP_H_
|
||||
#define _RTL837X_STP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
void stp_in(void) __banked;
|
||||
void stp_setup(void) __banked;
|
||||
void stp_timers(void) __banked;
|
||||
void stp_off(void) __banked;
|
||||
|
||||
#define TIME_HELLO 0x200 // 2 sec
|
||||
|
||||
#endif
|
||||
+294
-109
@@ -1,9 +1,6 @@
|
||||
#include <8051.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// This has to be set to the number of SFP+ ports, i.e. 1 or 2
|
||||
#define NSFP 2
|
||||
|
||||
// #define REGDBG 1
|
||||
// #define RXTXDBG 1
|
||||
|
||||
@@ -13,11 +10,19 @@
|
||||
#include "rtl837x_flash.h"
|
||||
#include "rtl837x_phy.h"
|
||||
#include "rtl837x_port.h"
|
||||
#include "rtl837x_stp.h"
|
||||
#include "cmd_parser.h"
|
||||
#include "uip/uipopt.h"
|
||||
#include "uip/uip.h"
|
||||
#include "uip/uip_arp.h"
|
||||
|
||||
extern __xdata uint16_t crc_value;
|
||||
__xdata uint8_t crc_testbytes[10];
|
||||
void crc16(__xdata uint8_t *v) __naked;
|
||||
|
||||
// Upload Firmware to 1M
|
||||
#define FIRMWARE_UPLOAD_START 0x100000
|
||||
|
||||
#define SYS_TICK_HZ 100
|
||||
#define SERIAL_BAUD_RATE 115200
|
||||
|
||||
@@ -48,7 +53,6 @@ __xdata uint8_t idle_ready;
|
||||
|
||||
__code uint8_t ownIP[] = { 192, 168, 2, 2 };
|
||||
__code struct uip_eth_addr uip_ethaddr = {{ 0x1c, 0x2a, 0xa3, 0x23, 0x00, 0x02 }};
|
||||
__code uint8_t ownMAC[] = { 0x1c, 0x2a, 0xa3, 0x23, 0x00, 0x02 };
|
||||
__code uint8_t gatewayIP[] = { 192, 168, 2, 22};
|
||||
__code uint8_t netmask[] = { 255, 255, 255, 0};
|
||||
|
||||
@@ -57,16 +61,24 @@ __xdata uint8_t isRTL8373;
|
||||
volatile __xdata uint32_t ticks;
|
||||
volatile __xdata uint8_t sec_counter;
|
||||
volatile __xdata uint16_t sleep_ticks;
|
||||
__xdata uint8_t stp_clock;
|
||||
|
||||
#define STP_TICK_DIVIDER 3
|
||||
|
||||
|
||||
// Buffer for serial input, SBUF_SIZE must be power of 2 < 256
|
||||
__xdata volatile uint8_t sbuf_ptr;
|
||||
__xdata uint8_t sbuf[SBUF_SIZE];
|
||||
__xdata uint8_t sfr_data[4];
|
||||
|
||||
extern __xdata uint8_t gpio_last_value[8];
|
||||
|
||||
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 hex = "0123456789abcdef";
|
||||
|
||||
__xdata uint8_t flash_buf[256];
|
||||
__xdata uint8_t flash_buf[512];
|
||||
|
||||
// NIC buffers for packet RX/TX
|
||||
__xdata uint8_t rx_headers[16]; // Packet header(s) on RX
|
||||
@@ -79,6 +91,7 @@ __xdata uint8_t minPort;
|
||||
__xdata uint8_t maxPort;
|
||||
__xdata uint8_t nSFPPorts;
|
||||
__xdata uint8_t cpuPort;
|
||||
__xdata uint8_t stpEnabled;
|
||||
|
||||
__code uint16_t bit_mask[16] = {
|
||||
0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
|
||||
@@ -91,6 +104,8 @@ __xdata uint8_t linkbits_last[4];
|
||||
__xdata uint8_t sfp_pins_last;
|
||||
|
||||
|
||||
#define ETHERTYPE_OFFSET (12 + VLAN_TAG_SIZE + RTL_TAG_SIZE)
|
||||
|
||||
void isr_timer0(void) __interrupt(1)
|
||||
{
|
||||
TR0 = 0; // Stop timer 0
|
||||
@@ -188,9 +203,6 @@ uint16_t strlen_x(register __xdata const char *s)
|
||||
uint16_t l = 0;
|
||||
while (s[l])
|
||||
l++;
|
||||
write_char(';');
|
||||
print_short(l);
|
||||
write_char(';');
|
||||
return l;
|
||||
}
|
||||
|
||||
@@ -283,8 +295,7 @@ void setup_timer0(void)
|
||||
|
||||
void reg_read(uint16_t reg_addr)
|
||||
{
|
||||
SFR_REG_ADDRH = reg_addr >> 8;
|
||||
SFR_REG_ADDRL = reg_addr;
|
||||
SFR_REG_ADDR_U16 = reg_addr;
|
||||
SFR_EXEC_GO = SFR_EXEC_READ_REG;
|
||||
do {
|
||||
} while (SFR_EXEC_STATUS != 0);
|
||||
@@ -297,8 +308,7 @@ void reg_read_m(uint16_t reg_addr)
|
||||
#ifdef REGDBG
|
||||
if (EA) { write_char('r'); print_byte(reg_addr >> 8); print_byte(reg_addr); write_char(':'); }
|
||||
#endif
|
||||
SFR_REG_ADDRH = reg_addr >> 8;
|
||||
SFR_REG_ADDRL = reg_addr;
|
||||
SFR_REG_ADDR_U16 = reg_addr;
|
||||
SFR_EXEC_GO = SFR_EXEC_READ_REG;
|
||||
do {
|
||||
} while (SFR_EXEC_STATUS != 0);
|
||||
@@ -315,8 +325,7 @@ void reg_read_m(uint16_t reg_addr)
|
||||
void reg_write(uint16_t reg_addr)
|
||||
{
|
||||
/* Data to write must be in SFR A4, A5, A6, A7 */
|
||||
SFR_REG_ADDRH = reg_addr >> 8;
|
||||
SFR_REG_ADDRL = reg_addr;
|
||||
SFR_REG_ADDR_U16 = reg_addr;
|
||||
SFR_EXEC_GO = SFR_EXEC_WRITE_REG;
|
||||
do {
|
||||
} while (SFR_EXEC_STATUS != 0);
|
||||
@@ -331,8 +340,7 @@ void reg_write_m(uint16_t reg_addr)
|
||||
print_byte(sfr_data[0]); print_byte(sfr_data[1]); print_byte(sfr_data[2]); print_byte(sfr_data[3]); write_char(' ');
|
||||
}
|
||||
#endif
|
||||
SFR_REG_ADDRH = reg_addr >> 8;
|
||||
SFR_REG_ADDRL = reg_addr;
|
||||
SFR_REG_ADDR_U16 = reg_addr;
|
||||
SFR_DATA_24 = sfr_data[0] ;
|
||||
SFR_DATA_16 = sfr_data[1];
|
||||
SFR_DATA_8 = sfr_data[2];
|
||||
@@ -373,7 +381,7 @@ void reg_bit_clear(uint16_t reg_addr, char bit)
|
||||
}
|
||||
|
||||
/*
|
||||
* This masks the sfr data fields, first &-ing with ~mask, the setting the bits in set
|
||||
* This masks the sfr data fields, first &-ing with ~mask, then setting the bits in set
|
||||
*/
|
||||
void sfr_mask_data(uint8_t n, uint8_t mask, uint8_t set)
|
||||
{
|
||||
@@ -383,6 +391,16 @@ void sfr_mask_data(uint8_t n, uint8_t mask, uint8_t set)
|
||||
sfr_data[3-n] = b;
|
||||
}
|
||||
|
||||
/*
|
||||
* This zeros all the sfr data fields
|
||||
*/
|
||||
void sfr_set_zero(void) {
|
||||
uint8_t idx = 4;
|
||||
while (idx) {
|
||||
idx -= 1;
|
||||
sfr_data[idx] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Transfer Network Interface RX data from the ASIC to the 8051 XMEM
|
||||
@@ -392,10 +410,8 @@ void sfr_mask_data(uint8_t n, uint8_t mask, uint8_t set)
|
||||
void nic_rx_header(uint16_t ring_ptr)
|
||||
{
|
||||
uint16_t buffer = (uint16_t) &rx_headers[0];
|
||||
SFR_NIC_DATA_H = buffer >> 8;
|
||||
SFR_NIC_DATA_L = buffer;
|
||||
SFR_NIC_RING_L = ring_ptr;
|
||||
SFR_NIC_RING_H = ring_ptr >> 8;
|
||||
SFR_NIC_DATA_U16LE = buffer;
|
||||
SFR_NIC_RING_U16LE = ring_ptr;
|
||||
SFR_NIC_CTRL = 1;
|
||||
do { } while (SFR_NIC_CTRL != 0);
|
||||
}
|
||||
@@ -409,10 +425,9 @@ void nic_rx_header(uint16_t ring_ptr)
|
||||
*/
|
||||
void nic_rx_packet(register uint16_t buffer, register uint16_t ring_ptr)
|
||||
{
|
||||
SFR_NIC_DATA_H = buffer >> 8;
|
||||
SFR_NIC_DATA_L = buffer;
|
||||
SFR_NIC_RING_L = ring_ptr;
|
||||
SFR_NIC_RING_H = ring_ptr >> 8;
|
||||
SFR_NIC_DATA_U16LE = buffer;
|
||||
SFR_NIC_RING_U16LE = ring_ptr;
|
||||
|
||||
uint16_t len = (((uint16_t)rx_headers[5]) << 8) | rx_headers[4];
|
||||
len += 7;
|
||||
len >>= 3;
|
||||
@@ -432,12 +447,12 @@ void nic_tx_packet(uint16_t ring_ptr)
|
||||
{
|
||||
// uint16_t buffer = (uint16_t) tx_buf;
|
||||
uint16_t buffer = (uint16_t) uip_buf + VLAN_TAG_SIZE;
|
||||
SFR_NIC_DATA_H = buffer >> 8;
|
||||
SFR_NIC_DATA_L = buffer;
|
||||
SFR_NIC_DATA_U16LE = buffer;
|
||||
|
||||
ring_ptr <<= 3;
|
||||
ring_ptr |= 0x8000;
|
||||
SFR_NIC_RING_L = ring_ptr;
|
||||
SFR_NIC_RING_H = ring_ptr >> 8;
|
||||
SFR_NIC_RING_U16LE = ring_ptr;
|
||||
|
||||
uint16_t len = (((uint16_t)uip_buf[VLAN_TAG_SIZE + 5]) << 8) | uip_buf[VLAN_TAG_SIZE + 4];
|
||||
len += 0xf;
|
||||
len >>= 3;
|
||||
@@ -506,8 +521,7 @@ void sds_write_v(uint8_t sds_id, uint8_t page, uint8_t reg, uint16_t v)
|
||||
print_string("Q"); print_byte(sds_id); print_byte(page); print_byte(reg);
|
||||
write_char(':'); print_byte(v >> 8); print_byte(v); write_char(' ');
|
||||
#endif
|
||||
SFR_DATA_8 = v >> 8;
|
||||
SFR_DATA_0 = v;
|
||||
SFR_DATA_U16 = v;
|
||||
SFR_93 = reg;
|
||||
SFR_94 = page << 1 | sds_id;
|
||||
SFR_EXEC_GO = SFR_EXEC_WRITE_SDS;
|
||||
@@ -711,11 +725,11 @@ uint8_t sfp_read_reg(uint8_t slot, uint8_t reg)
|
||||
{
|
||||
if (slot == 0) {
|
||||
reg_read_m(RTL837X_REG_I2C_CTRL);
|
||||
sfr_mask_data(1, 0xff, 0x72);
|
||||
sfr_mask_data(1, 0xfc, SCL_PIN << 5 | SDA_PIN_0 << 2);
|
||||
reg_write_m(RTL837X_REG_I2C_CTRL);
|
||||
} else {
|
||||
reg_read_m(RTL837X_REG_I2C_CTRL);
|
||||
sfr_mask_data(1, 0xff, 0x6e);
|
||||
sfr_mask_data(1, 0xfc, SCL_PIN << 5 | SDA_PIN_1 << 2);
|
||||
reg_write_m(RTL837X_REG_I2C_CTRL);
|
||||
}
|
||||
|
||||
@@ -740,8 +754,7 @@ uint8_t sfp_read_reg(uint8_t slot, uint8_t reg)
|
||||
*/
|
||||
void tcpip_output(void)
|
||||
{
|
||||
__xdata uint8_t *ptr = &uip_buf[0];
|
||||
// Add RTL-TAG
|
||||
// Add TX-TAG
|
||||
uip_buf[VLAN_TAG_SIZE] = tx_seq++;
|
||||
uip_buf[VLAN_TAG_SIZE + 1] = 0x07; // Enable all checksums
|
||||
uip_buf[VLAN_TAG_SIZE + 5] = uip_len >> 8;
|
||||
@@ -752,12 +765,15 @@ void tcpip_output(void)
|
||||
reg_read_m(0x7890);
|
||||
uint16_t ring_ptr = ((uint16_t)sfr_data[2]) << 8;
|
||||
ring_ptr |= sfr_data[3];
|
||||
/*
|
||||
|
||||
#ifdef RXTXDBG
|
||||
print_string("TX: \n");
|
||||
for (uint8_t i = 0; i < 120; i++) {
|
||||
print_byte(*ptr++);
|
||||
print_byte(uip_buf[i]);
|
||||
write_char(' ');
|
||||
}
|
||||
*/
|
||||
write_char('\n');
|
||||
#endif
|
||||
|
||||
// Move data over from xmem buffer to ASIC side using DMA
|
||||
nic_tx_packet(ring_ptr);
|
||||
@@ -780,9 +796,8 @@ void handle_rx(void)
|
||||
ring_ptr |= sfr_data[3];
|
||||
ring_ptr <<= 3;
|
||||
nic_rx_header(ring_ptr);
|
||||
__xdata uint8_t *ptr = rx_headers;
|
||||
|
||||
#ifdef RXTXDBG
|
||||
__xdata uint8_t *ptr = rx_headers;
|
||||
print_string("RX on port "); print_byte(rx_headers[3] & 0xf);
|
||||
print_string(": ");
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
@@ -804,8 +819,8 @@ void handle_rx(void)
|
||||
sfr_data[3] = 0x1;
|
||||
reg_write_m(RTL837X_REG_RX_DONE);
|
||||
uip_len = (((uint16_t)rx_headers[5]) << 8) | rx_headers[4];
|
||||
// write_char('>'); print_byte(uip_buf[12 + VLAN_TAG_SIZE + RTL_TAG_SIZE]); write_char('<');
|
||||
// write_char('>'); print_byte(uip_buf[13 + VLAN_TAG_SIZE + RTL_TAG_SIZE]); write_char('<');
|
||||
// write_char('>'); print_byte(uip_buf[ETHERTYPE_OFFSET]); write_char('<');
|
||||
// write_char('>'); print_byte(uip_buf[ETHERTYPE_OFFSET + 1]); write_char('<');
|
||||
// Check for ARP packet
|
||||
rx_packet_vlan = uip_buf[12 + RTL_TAG_SIZE + 2] & 0xf;
|
||||
rx_packet_vlan <<= 8;
|
||||
@@ -813,12 +828,19 @@ void handle_rx(void)
|
||||
#ifdef RXTXDBG
|
||||
print_string(" RX-VLAN: "); print_short(rx_packet_vlan); write_char('\n');
|
||||
#endif
|
||||
if (uip_buf[12 + VLAN_TAG_SIZE + RTL_TAG_SIZE] == 0x08 && uip_buf[13 + VLAN_TAG_SIZE + RTL_TAG_SIZE] == 0x06) {
|
||||
if (stpEnabled && uip_buf[0] == 0x01 && uip_buf[1] == 0x80 && uip_buf[2] == 0xc2 // STP packet?
|
||||
&& uip_buf[3] == 0x00 && uip_buf[4] == 0x00 && uip_buf[5] == 0x00) {
|
||||
stp_in();
|
||||
if (uip_len) {
|
||||
print_string("STP TX\n");
|
||||
tcpip_output();
|
||||
}
|
||||
} else if (uip_buf[ETHERTYPE_OFFSET] == 0x08 && uip_buf[ETHERTYPE_OFFSET + 1] == 0x06) { // ARP?
|
||||
uip_arp_arpin();
|
||||
if (uip_len) {
|
||||
tcpip_output();
|
||||
}
|
||||
} else if (uip_buf[12 + VLAN_TAG_SIZE + RTL_TAG_SIZE] == 0x08 && uip_buf[13 + VLAN_TAG_SIZE + RTL_TAG_SIZE] == 0x00) {
|
||||
} else if (uip_buf[ETHERTYPE_OFFSET] == 0x08 && uip_buf[ETHERTYPE_OFFSET + 1] == 0x00) {
|
||||
uip_arp_ipin();
|
||||
uip_input();
|
||||
if (uip_len) {
|
||||
@@ -869,7 +891,7 @@ void sfp_print_info(uint8_t sfp)
|
||||
|
||||
void handle_sfp(void)
|
||||
{
|
||||
reg_read_m(RTL837X_REG_GPIO_B);
|
||||
reg_read_m(RTL837X_REG_GPIO_00_31_INPUT);
|
||||
if ((sfp_pins_last & 0x1) && (!(sfr_data[0] & 0x40))) {
|
||||
sfp_pins_last &= ~0x01;
|
||||
print_string("\n<MODULE INSERTED> ");
|
||||
@@ -889,7 +911,7 @@ void handle_sfp(void)
|
||||
print_string("\n<MODULE REMOVED>\n");
|
||||
}
|
||||
|
||||
reg_read_m(RTL837X_REG_GPIO_C);
|
||||
reg_read_m(RTL837X_REG_GPIO_32_63_INPUT);
|
||||
if ((sfp_pins_last & 0x2) && (!(sfr_data[3] & 0x20))) {
|
||||
sfp_pins_last &= ~0x02;
|
||||
print_string("\n<SFP-RX OK>\n");
|
||||
@@ -899,7 +921,7 @@ void handle_sfp(void)
|
||||
print_string("\n<SFP-RX LOS>\n");
|
||||
}
|
||||
|
||||
reg_read_m(RTL837X_REG_GPIO_C);
|
||||
reg_read_m(RTL837X_REG_GPIO_32_63_INPUT);
|
||||
if ((sfp_pins_last & 0x10) && (!(sfr_data[1] & 0x04))) {
|
||||
sfp_pins_last &= ~0x10;
|
||||
print_string("\n<MODULE 2 INSERTED> ");
|
||||
@@ -985,7 +1007,7 @@ void idle(void)
|
||||
handle_sfp();
|
||||
|
||||
/* Button pressed on KL-8xhm-x2:
|
||||
reg_read(RTL837X_REG_GPIO_C);
|
||||
reg_read(RTL837X_REG_GPIO_32_63_INPUT);
|
||||
if (!(sfr_data[2] & 0x40))
|
||||
print_string("Button pressed\n");
|
||||
*/
|
||||
@@ -993,6 +1015,22 @@ void idle(void)
|
||||
handle_rx();
|
||||
// Check UIP for packets to transmit
|
||||
handle_tx();
|
||||
// If STP protocol enabled, decrease STP timers to trigger actions
|
||||
if (stpEnabled) {
|
||||
if (!stp_clock) {
|
||||
stp_clock = STP_TICK_DIVIDER;
|
||||
stp_timers();
|
||||
} else {
|
||||
stp_clock--;
|
||||
}
|
||||
}
|
||||
// Check whether a command is waiting in the cmd_buffer and execute
|
||||
if (cmd_available) {
|
||||
cmd_available = 0;
|
||||
if (!cmd_tokenize())
|
||||
cmd_parser();
|
||||
print_string("\n> ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1012,6 +1050,7 @@ void sleep(uint16_t t)
|
||||
void reset_chip(void)
|
||||
{
|
||||
REG_SET(RTL837X_REG_RESET, 1);
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1034,12 +1073,12 @@ void setup_external_irqs(void)
|
||||
void rtl8224_enable(void)
|
||||
{
|
||||
// Set Pin 4 low
|
||||
reg_bit_clear(RTL837X_REG_GPIO_A, 4);
|
||||
reg_bit_clear(RTL837X_REG_GPIO_32_63_OUTPUT, 4);
|
||||
// Configure Pin as output
|
||||
reg_bit_set(RTL837X_REG_GPIO_CONF_A, 4);
|
||||
reg_bit_set(RTL837X_REG_GPIO_32_63_DIRECTION, 4);
|
||||
delay(100);
|
||||
// Set pin 4 high
|
||||
reg_bit_set(RTL837X_REG_GPIO_A, 4);
|
||||
reg_bit_set(RTL837X_REG_GPIO_32_63_OUTPUT, 4);
|
||||
delay(500);
|
||||
}
|
||||
|
||||
@@ -1055,31 +1094,50 @@ void setup_clock(void)
|
||||
// Divider in bits 4 & 5
|
||||
sfr_mask_data(0, 0, CLOCK_DIV << 4);
|
||||
#endif
|
||||
// This is set in managed mode 125MHz
|
||||
// Bit 8 is set in managed mode 125MHz to use fast SPI mode
|
||||
sfr_mask_data(1, 0, 0x01);
|
||||
reg_write_m(RTL837X_REG_HW_CONF);
|
||||
|
||||
reg_read_m(0x7f90);
|
||||
// Enable serial interface, set bit 0
|
||||
reg_read_m(RTL837X_PIN_MUX_1);
|
||||
sfr_mask_data(0, 0x1, 0x1);
|
||||
reg_write_m(0x7f90);
|
||||
reg_write_m(RTL837X_PIN_MUX_1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write a register reg of phy phy_id, in page page
|
||||
* Write a register reg of multipule phys, using a mask to select them, in page page
|
||||
* Data to be written is in v
|
||||
*/
|
||||
void phy_write(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v)
|
||||
void phy_write_mask(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v)
|
||||
{
|
||||
#ifdef REGDBG
|
||||
print_string("P"); print_byte(phy_mask>>8); print_byte(phy_mask); print_byte(dev_id); write_char('.'); print_byte(reg>>8); print_byte(reg); write_char(':');
|
||||
print_byte(v>>8); print_byte(v); write_char(' ');
|
||||
#endif
|
||||
SFR_DATA_8 = v >> 8; // SFR_A6
|
||||
SFR_DATA_0 = v; // SFR_A7
|
||||
SFR_DATA_U16 = v; // SFR_A6, SFR_A7
|
||||
SFR_SMI_PHYMASK = phy_mask; // SFR_C5
|
||||
SFR_SMI_REG_H = reg >> 8; // SFR_C2
|
||||
SFR_SMI_REG_L = reg; // SFR_C3
|
||||
SFR_SMI_REG_U16 = reg; // SFR_C2, SFR_C3
|
||||
SFR_SMI_DEV = (phy_mask >> 8) | dev_id << 3 | 2; // SFR_C4: bit 2 can also be set for some option
|
||||
SFR_EXEC_GO = SFR_EXEC_WRITE_SMI;
|
||||
do {
|
||||
} while (SFR_EXEC_STATUS != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a register reg of phy, using a mask to select them, in page page
|
||||
* Data to be written is in v
|
||||
*/
|
||||
void phy_write(uint8_t phy_id, uint8_t dev_id, uint16_t reg, uint16_t v)
|
||||
{
|
||||
uint16_t phy_mask = bit_mask[phy_id];
|
||||
#ifdef REGDBG
|
||||
print_string("P"); print_byte(phy_mask>>8); print_byte(phy_mask); print_byte(dev_id); write_char('.'); print_byte(reg>>8); print_byte(reg); write_char(':');
|
||||
print_byte(v>>8); print_byte(v); write_char(' ');
|
||||
#endif
|
||||
SFR_DATA_U16 = v; // SFR_A6, SFR_A7
|
||||
SFR_SMI_PHYMASK = phy_mask; // SFR_C5
|
||||
SFR_SMI_REG_U16 = reg; // SFR_C2, SFR_C3
|
||||
SFR_SMI_DEV = (phy_mask >> 8) | dev_id << 3 | 2; // SFR_C4: bit 2 can also be set for some option
|
||||
SFR_EXEC_GO = SFR_EXEC_WRITE_SMI;
|
||||
do {
|
||||
@@ -1097,8 +1155,8 @@ void phy_read(uint8_t phy_id, uint8_t dev_id, uint16_t reg)
|
||||
#ifdef REGDBG
|
||||
print_string("p"); print_byte(phy_id); print_byte(dev_id); write_char('.'); print_byte(reg>>8); print_byte(reg); write_char(':');
|
||||
#endif
|
||||
SFR_SMI_REG_H = reg >> 8; // c3
|
||||
SFR_SMI_REG_L = reg; // c2
|
||||
SFR_SMI_REG_U16 = reg; // c2, c2
|
||||
|
||||
SFR_SMI_PHY = phy_id; // a5
|
||||
SFR_SMI_DEV = dev_id << 3 | 2; // c4
|
||||
|
||||
@@ -1110,6 +1168,41 @@ void phy_read(uint8_t phy_id, uint8_t dev_id, uint16_t reg)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify a register reg of phy phy_id, in page page
|
||||
* Set: bit mask of bits to set.
|
||||
* Mask: bit mask of bits to clear.
|
||||
|
||||
* Note: We assume that the registers `SFR_SMI_REG_U16`, `SFR_SMI_PHY` and `SFR_SMI_DEV`
|
||||
* keep there value, and dont have to be rewritten everytime.
|
||||
*/
|
||||
void phy_modify(uint8_t phy_id, uint8_t dev_id, uint16_t reg, uint16_t mask, uint16_t set)
|
||||
{
|
||||
uint8_t smi_phy = dev_id << 3 | 2;
|
||||
|
||||
// Read the data
|
||||
SFR_SMI_REG_U16 = reg; // c2, c2
|
||||
SFR_SMI_PHY = phy_id; // a5
|
||||
SFR_SMI_DEV = smi_phy; // c4
|
||||
SFR_EXEC_GO = SFR_EXEC_READ_SMI;
|
||||
do {
|
||||
} while (SFR_EXEC_STATUS != 0);
|
||||
|
||||
// Modify the reed data.
|
||||
// TODO: Check if we directly can modify SFR register directly.
|
||||
uint16_t data = SFR_DATA_U16 & ~(mask);
|
||||
data |= ~(set);
|
||||
|
||||
uint16_t phy_mask = bit_mask[phy_id];
|
||||
|
||||
// Write it back
|
||||
SFR_SMI_REG_U16 = data;
|
||||
SFR_SMI_PHYMASK = phy_mask; // SFR_C5
|
||||
SFR_SMI_DEV = smi_phy | (phy_mask >> 8);
|
||||
SFR_EXEC_GO = SFR_EXEC_WRITE_SMI;
|
||||
do {
|
||||
} while (SFR_EXEC_STATUS != 0);
|
||||
}
|
||||
|
||||
void nic_setup(void)
|
||||
{
|
||||
@@ -1124,22 +1217,21 @@ void nic_setup(void)
|
||||
// R7844-000007fe
|
||||
REG_SET(0x7844, 0x7fe);
|
||||
|
||||
// r785c:0401201e R785c-0401201e r785c:0401201e R785c-0400201e
|
||||
// 0x785c: Set bits 24-31 to 0x4, clear bits 16/17:
|
||||
reg_read_m(0x785c);
|
||||
// Configure NIC RX to receive various types of packets
|
||||
// RTL837X_REG_RX_CTRL: Set bits 24-31 to 0x4, clear bits 16/17
|
||||
reg_read_m(RTL837X_REG_RX_CTRL);
|
||||
sfr_mask_data(3, 0xff, 0x04);
|
||||
sfr_mask_data(2, 0x03, 0);
|
||||
reg_write_m(0x785c);
|
||||
reg_write_m(RTL837X_REG_RX_CTRL);
|
||||
|
||||
// Set bit 0 of 0x7860:
|
||||
// r7860:00000000 R7860-00000001
|
||||
reg_bit_set(0x7860, 0);
|
||||
// Enable NIC TX (set bit 0)
|
||||
reg_bit_set(RTL837X_REG_TX_CTRL, 0);
|
||||
|
||||
// r785c:0400201e R785c-0400201f
|
||||
reg_bit_set(0x785c, 0);
|
||||
// Enable NIC RX (set bit 0)
|
||||
reg_bit_set(RTL837X_REG_RX_CTRL, 0);
|
||||
|
||||
// r785c:0400201f R785c-0400201b
|
||||
reg_bit_clear(0x785c, 2);
|
||||
// Drop packets with invalid CRC
|
||||
reg_bit_clear(RTL837X_REG_RX_CTRL, 2);
|
||||
|
||||
// R603c-00000200
|
||||
REG_SET(0x603c, 0x200);
|
||||
@@ -1174,9 +1266,7 @@ void sds_init(void)
|
||||
p001e.000d:0010 p001e.000d:0010 R02f8-00000010 R02f4-00000010 P000001.1e00000d:b7fe
|
||||
*/
|
||||
phy_read(0, 0x1e, 0xd);
|
||||
uint16_t pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0;
|
||||
uint16_t pval = SFR_DATA_U16;
|
||||
|
||||
// PHY Initialization:
|
||||
REG_WRITE(0x2f8, 0, 0, pval >> 8, pval);
|
||||
@@ -1187,19 +1277,17 @@ void sds_init(void)
|
||||
REG_WRITE(0x2f4, 0, 0, pval >> 8, pval);
|
||||
delay(10);
|
||||
|
||||
phy_write(0x1, 0x1e, 0xd, pval);
|
||||
phy_write_mask(0x1, 0x1e, 0xd, pval);
|
||||
|
||||
phy_read(0, 0x1e, 0xd);
|
||||
pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0;
|
||||
pval = SFR_DATA_U16;
|
||||
|
||||
REG_WRITE(0x2f8, 0, 0, pval >> 8, pval);
|
||||
|
||||
pval &= 0xfff0;
|
||||
REG_WRITE(0x2f4, 0, 0, pval >> 8, pval);
|
||||
|
||||
phy_write(0x1, 0x1e, 0xd, pval);
|
||||
phy_write_mask(0x1, 0x1e, 0xd, pval);
|
||||
}
|
||||
|
||||
|
||||
@@ -1233,7 +1321,7 @@ void led_config_9xh(void)
|
||||
reg_bit_clear(0x65dc, 0x1b);
|
||||
|
||||
// r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000
|
||||
reg_bit_set(0x7f8c, 0x1b);
|
||||
reg_bit_set(RTL837X_PIN_MUX_0, 0x1b);
|
||||
|
||||
// R6548-0041017f
|
||||
REG_SET(0x6548, 0x0041017f);
|
||||
@@ -1285,13 +1373,13 @@ void led_config(void)
|
||||
|
||||
// Set bits 1b/1d of 0x7f8c: r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000
|
||||
if (nSFPPorts == 2) {
|
||||
reg_bit_set(0x7f8c, 0x1b); // R7f8c-28000000
|
||||
reg_bit_clear(0x7f8c, 0x1c); // R7f8c-28000000
|
||||
reg_bit_set(0x7f8c, 0x1d); // R7f8c-28000000
|
||||
reg_bit_set(RTL837X_PIN_MUX_0, 0x1b); // R7f8c-28000000
|
||||
reg_bit_clear(RTL837X_PIN_MUX_0, 0x1c); // R7f8c-28000000
|
||||
reg_bit_set(RTL837X_PIN_MUX_0, 0x1d); // R7f8c-28000000
|
||||
} else {
|
||||
reg_bit_set(0x7f8c, 0x1d);
|
||||
reg_bit_set(0x7f8c, 0x1c);
|
||||
reg_bit_set(0x7f8c, 0x1b);
|
||||
reg_bit_set(RTL837X_PIN_MUX_0, 0x1d);
|
||||
reg_bit_set(RTL837X_PIN_MUX_0, 0x1c);
|
||||
reg_bit_set(RTL837X_PIN_MUX_0, 0x1b);
|
||||
}
|
||||
// LED setup
|
||||
// r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0 r65f8:00000018 R65f8-00000018 R65fc-fffff000 r6600:00000000 R6600-0000000f r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00
|
||||
@@ -1374,15 +1462,11 @@ void rtl8373_init(void)
|
||||
|
||||
// q000601:c800 Q000601:c804 q000601:c804 Q000601:c800
|
||||
sds_read(0, 0x06, 0x01);
|
||||
uint16_t pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0;
|
||||
uint16_t pval = SFR_DATA_U16;
|
||||
sds_write_v(0, 0x06, 0x01, pval | 0x04);
|
||||
delay(50);
|
||||
sds_read(0, 0x06, 0x01);
|
||||
pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0;
|
||||
pval = SFR_DATA_U16;
|
||||
sds_write_v(0, 0x06, 0x01, pval & 0xfffb);
|
||||
|
||||
phy_config_8224();
|
||||
@@ -1396,9 +1480,7 @@ void rtl8373_init(void)
|
||||
sds_write_v(1, 0x36, 0x05, 0x4000);
|
||||
sds_write_v(1, 0x1f, 0x02, 0x001f);
|
||||
sds_read(1, 0x1f, 0x15);
|
||||
pval = SFR_DATA_8;
|
||||
pval <<= 8;
|
||||
pval |= SFR_DATA_0;
|
||||
pval = SFR_DATA_U16;
|
||||
|
||||
// r0a90:000000f3 R0a90-000000fc
|
||||
reg_read_m(0xa90);
|
||||
@@ -1408,7 +1490,7 @@ void rtl8373_init(void)
|
||||
rtl8224_phy_enable();
|
||||
|
||||
// Disable PHYs for configuration
|
||||
phy_write(0xff,0x1f,0xa610,0x2858);
|
||||
phy_write_mask(0xff,0x1f,0xa610,0x2858);
|
||||
|
||||
// Set bits 0x13 and 0x14 of 0x5fd4
|
||||
// r5fd4:0002914a R5fd4-001a914a
|
||||
@@ -1436,7 +1518,7 @@ void rtl8373_init(void)
|
||||
// TODO: patch the PHYs
|
||||
|
||||
// Re-enable PHY after configuration
|
||||
phy_write(0xff,0x1f,0xa610,0x2058);
|
||||
phy_write_mask(0xff,0x1f,0xa610,0x2058);
|
||||
|
||||
// Enables MAC access
|
||||
// Set bits 0xc-0x14 of 0x632c to 0x1f8, see rtl8372_init
|
||||
@@ -1500,7 +1582,7 @@ void rtl8372_init(void)
|
||||
reg_write_m(0xa90);
|
||||
|
||||
// Disable PHYs for configuration
|
||||
phy_write(0xf0,0x1f,0xa610,0x2858);
|
||||
phy_write_mask(0xf0,0x1f,0xa610,0x2858);
|
||||
|
||||
// Set bits 0x13 and 0x14 of 0x5fd4
|
||||
// r5fd4:0002914a R5fd4-001a914a
|
||||
@@ -1527,7 +1609,7 @@ void rtl8372_init(void)
|
||||
// TODO: patch the PHYs
|
||||
|
||||
// Re-enable PHY after configuration
|
||||
phy_write(0xf0,0x1f,0xa610,0x2058);
|
||||
phy_write_mask(0xf0,0x1f,0xa610,0x2058);
|
||||
|
||||
// Enables MAC access
|
||||
// Set bits 0xc-0x14 of 0x632c to 0x1f8, see rtl8372_init
|
||||
@@ -1568,21 +1650,23 @@ void setup_serial(void)
|
||||
|
||||
void setup_i2c(void)
|
||||
{
|
||||
REG_SET(0x0414, 0);
|
||||
REG_SET(0x0418, 0x00100280);
|
||||
REG_SET(0x041c, 0);
|
||||
REG_SET(RTL837X_REG_I2C_MST_IF_CTRL, 0);
|
||||
// Configure SFP EEPROM address (0x50) as I2C device address
|
||||
REG_SET(RTL837X_REG_I2C_CTRL, 0x1L << I2C_MEM_ADDR_WIDTH | 0x50 << I2C_DEV_ADDR);
|
||||
REG_SET(RTL837X_REG_I2C_CTRL2, 0);
|
||||
|
||||
// HW Control register, enable I2C?
|
||||
reg_read_m(0x7f90);
|
||||
reg_read_m(RTL837X_PIN_MUX_1);
|
||||
sfr_mask_data(3, 0x20, 0x00); // Clear bit 29
|
||||
sfr_mask_data(0, 0x60, 0x40); // Set bits 5-6 to 0b10
|
||||
reg_write_m(0x7f90);
|
||||
reg_write_m(RTL837X_PIN_MUX_1);
|
||||
}
|
||||
|
||||
|
||||
void bootloader(void)
|
||||
{
|
||||
ticks = 0;
|
||||
stp_clock = STP_TICK_DIVIDER;
|
||||
sbuf_ptr = 0;
|
||||
|
||||
CKCON = 0; // Initial Clock configuration
|
||||
@@ -1645,6 +1729,76 @@ void bootloader(void)
|
||||
rtl8372_init();
|
||||
delay(1000);
|
||||
|
||||
// Check update in progress and move blocks
|
||||
flash_region.addr = FIRMWARE_UPLOAD_START;
|
||||
flash_region.len = 0x100;
|
||||
flash_read_bulk(flash_buf);
|
||||
|
||||
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...\n");
|
||||
|
||||
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 (crc_value == 0xb001) {
|
||||
print_string("Checksum OK\n");
|
||||
print_string("Update in progress, moving firmware to start of FLASH!\n");
|
||||
source = FIRMWARE_UPLOAD_START;
|
||||
// A 512kByte = 4MBit Flash has 128*8=1024 512k blocks, we copy only 120
|
||||
for (i = 0; i < 960; i++) {
|
||||
print_string("Writing block: ");
|
||||
print_short(dest);
|
||||
flash_region.addr = source;
|
||||
flash_region.len = 0x200;
|
||||
flash_read_bulk(flash_buf);
|
||||
write_char('\n');
|
||||
if (!(i & 0x7)) {
|
||||
flash_region.addr = dest;
|
||||
flash_sector_erase();
|
||||
}
|
||||
flash_region.addr = dest;
|
||||
flash_region.len = 0x200;
|
||||
flash_write_bytes(flash_buf);
|
||||
dest += 0x200;
|
||||
source += 0x200;
|
||||
}
|
||||
print_string("Deleting 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;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// This register seems to work on the RTL8373 only if also the SDS
|
||||
// Is correctly configured. Therefore, we can test it, here...
|
||||
@@ -1662,7 +1816,7 @@ void bootloader(void)
|
||||
REG_SET(RTL837X_REG_SEC_COUNTER, 0x3); write_char(' ');
|
||||
print_reg(RTL837X_REG_SEC_COUNTER);
|
||||
#endif
|
||||
|
||||
stpEnabled = 0;
|
||||
nic_setup();
|
||||
vlan_setup();
|
||||
port_l2_setup();
|
||||
@@ -1687,10 +1841,41 @@ void bootloader(void)
|
||||
|
||||
execute_config();
|
||||
print_string("\n> ");
|
||||
cmd_parser_setup();
|
||||
idle_ready = 1;
|
||||
|
||||
// Wait for commands on serial connection
|
||||
// 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) {
|
||||
cmd_parser();
|
||||
while (l != sbuf_ptr) {
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
+17
-6
@@ -1,12 +1,23 @@
|
||||
CC = gcc
|
||||
CCFLAGS = -Wall -o
|
||||
BUILDDIR = output/
|
||||
|
||||
all: injector fileadder
|
||||
all: create_build_dir $(BUILDDIR)injector $(BUILDDIR)fileadder $(BUILDDIR)httpd_sim $(BUILDDIR)crc_calculator
|
||||
|
||||
create_build_dir:
|
||||
mkdir -p $(BUILDDIR)
|
||||
|
||||
clean:
|
||||
rm *.o
|
||||
rm -r $(BUILDDIR)
|
||||
|
||||
injector: injector.c
|
||||
gcc $^ -o $@
|
||||
$(BUILDDIR)injector: injector.c
|
||||
gcc $^ $(CCFLAGS) $@
|
||||
|
||||
fileadder: fileadder.c
|
||||
gcc $^ -o $@
|
||||
$(BUILDDIR)fileadder: fileadder.c
|
||||
gcc $^ $(CCFLAGS) $@
|
||||
|
||||
$(BUILDDIR)crc_calculator: crc_calculator.c
|
||||
gcc $^ $(CCFLAGS) $@
|
||||
|
||||
$(BUILDDIR)httpd_sim: httpd_sim.c httpd_sim.h
|
||||
gcc $< $(CCFLAGS) $@ -I/usr/include/json-c -ljson-c
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Calculator for the CRC16 as described in AN27 by Dallas Semiconductor
|
||||
* http://www.microshadow.com/files/files8051/app27.pdf
|
||||
* The implementation in C is based on the code given in
|
||||
* https://carta.tech/man-pages/man3/_crc_ibutton_update.3avr.html
|
||||
* The polynomial of the CRC is 0xa001: x^16 + x^15 + x^2 + 1
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <argp.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
// Use a 4MB buffer, the same as the flash rom size
|
||||
#define BUFFER_SIZE 0x400000
|
||||
char buffer[BUFFER_SIZE];
|
||||
|
||||
struct arguments {
|
||||
char *input_file;
|
||||
char *output_file;
|
||||
bool update;
|
||||
bool verify;
|
||||
};
|
||||
|
||||
const char *argp_program_version = "crc_calculator 0.1";
|
||||
const char *argp_program_bug_address = "https://github.com/logicog/RTLPlayground/issues";
|
||||
static char doc[] = "Calculate (and optionally update) the CRC of an image";
|
||||
static char args_doc[] = "crc_calculator [options] INPUT_IMAGE";
|
||||
static struct argp_option options[] = {
|
||||
{ "output", 'o', "FILE", 0, "Output image file name instead of overwriting input image"},
|
||||
{ "update", 'u', 0, OPTION_ARG_OPTIONAL, "Update the image with the CRC"},
|
||||
{ "verify", 'v', 0, OPTION_ARG_OPTIONAL, "Verify the CRC of the file"},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
uint16_t crc16_update(uint16_t crc, uint8_t a)
|
||||
{
|
||||
crc ^= a;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
crc = crc & 1 ? (crc >> 1) ^ 0xA001 : crc >> 1;
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
struct arguments *arguments = state->input;
|
||||
switch (key) {
|
||||
case 'u':
|
||||
arguments->update = true;
|
||||
break;
|
||||
case 'v':
|
||||
arguments->verify = true;
|
||||
break;
|
||||
case 'o':
|
||||
arguments->output_file = arg;
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct argp argp = {
|
||||
options, parse_opt, args_doc, doc, 0, 0, 0
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct arguments arguments;
|
||||
int arg_index;
|
||||
char tmpfilename[] = "crc_XXXXXX";
|
||||
uint16_t crc = 0;
|
||||
FILE *inptr;
|
||||
int outptr;
|
||||
int range;
|
||||
|
||||
arguments.input_file = NULL;
|
||||
arguments.output_file = NULL;
|
||||
arguments.update = false;
|
||||
arguments.verify = false;
|
||||
|
||||
argp_parse(&argp, argc, argv, 0, &arg_index, &arguments);
|
||||
if (!arg_index)
|
||||
argp_usage (0);
|
||||
|
||||
memset(buffer, 0, BUFFER_SIZE);
|
||||
|
||||
size_t filesize = 0;
|
||||
if (argv[arg_index]) {
|
||||
inptr = fopen(argv[arg_index], "rb");
|
||||
if (inptr == NULL) {
|
||||
printf("Cannot open input file %s\n", argv[arg_index]);
|
||||
return 5;
|
||||
}
|
||||
|
||||
fseek(inptr, 0L, SEEK_END);
|
||||
filesize = ftell(inptr);
|
||||
rewind(inptr);
|
||||
printf("Input file size: %ld\n", filesize);
|
||||
if (filesize > BUFFER_SIZE) {
|
||||
printf("File too large.\n");
|
||||
return 5;
|
||||
}
|
||||
size_t bytes_read = fread(buffer, 1, sizeof(buffer), inptr);
|
||||
|
||||
printf("Bytes read: %ld\n", bytes_read);
|
||||
|
||||
if (bytes_read != filesize) {
|
||||
printf("Error reading input file.\n");
|
||||
return 5;
|
||||
}
|
||||
fclose(inptr);
|
||||
}
|
||||
|
||||
range = filesize;
|
||||
if (!arguments.verify) {
|
||||
if (arguments.update) {
|
||||
range -= 2;
|
||||
} else if (arguments.output_file) {
|
||||
filesize += 2;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < range; i++)
|
||||
crc = crc16_update(crc, buffer[i]);
|
||||
|
||||
printf("CRC16 is: 0x%04x\n", crc);
|
||||
|
||||
if (arguments.verify) {
|
||||
if (crc == 0xb001) {
|
||||
printf("Checksum OK\n");
|
||||
return 0;
|
||||
} else {
|
||||
printf("Checksum Incorrect\n");
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
// We have to create a new image with updated CRC
|
||||
if (arguments.update || arguments.output_file) {
|
||||
crc ^= 0xffff;
|
||||
printf("Setting CRC bytes at position: 0x%x to CRC 1s complement 0x%04x\n", range, crc);
|
||||
// The CRC algorithm expects as input always first the LO-Byte
|
||||
buffer[range] = crc;
|
||||
buffer[range + 1] = crc >> 8;
|
||||
|
||||
if (!arguments.update)
|
||||
outptr = creat(arguments.output_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||
else
|
||||
outptr = mkstemp(tmpfilename);
|
||||
|
||||
if (!outptr) {
|
||||
printf("Cannot open %s\n", arguments.output_file);
|
||||
return 5;
|
||||
}
|
||||
size_t written = write(outptr, buffer, filesize);
|
||||
|
||||
if (written != filesize) {
|
||||
printf("Error writing output file.\n");
|
||||
return 5;
|
||||
}
|
||||
close(outptr);
|
||||
|
||||
if (arguments.update)
|
||||
rename(tmpfilename, argv[arg_index]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+26
-20
@@ -19,9 +19,9 @@
|
||||
char buffer[BUFFER_SIZE];
|
||||
FILE *inptr, *dataptr, *ofile;
|
||||
int outptr;
|
||||
#define PATH_SIZE 1024
|
||||
#define INDEX_SIZE 1024
|
||||
#define DEF_SIZE 1024
|
||||
#define PATH_SIZE 20480
|
||||
#define INDEX_SIZE 20480
|
||||
#define DEF_SIZE 20480
|
||||
char pathbuffer[PATH_SIZE];
|
||||
char ibuf[INDEX_SIZE];
|
||||
char dbuf[DEF_SIZE];
|
||||
@@ -39,10 +39,10 @@ const char *argp_program_bug_address = "<git@logicog.de>";
|
||||
static char doc[] = "Adds a file or a directory of files into an image";
|
||||
static char args_doc[] = "addfile [options] INPUT_IMAGE";
|
||||
static struct argp_option options[] = {
|
||||
{ "size", 's', "SIZE", OPTION_ARG_OPTIONAL, "Resize image"},
|
||||
{ "size", 's', "SIZE", 0, "Resize image"},
|
||||
{ "output", 'o', "FILE", 0, "Output image file name instead of overwriting input image"},
|
||||
{ "data", 'd', "FILE", 0, "File or directory to add to image"},
|
||||
{ "address", 'a', 0, OPTION_ARG_OPTIONAL, "Address where data is placed, default is 0x1000000 if option is used, otherwise 0x1fd000"},
|
||||
{ "address", 'a', "SIZE", 0, "Address where data is placed, default is 0x1000000 if option is used, otherwise 0x1fd000"},
|
||||
{ "prefix", 'p', "FILE", 0, "Prefix for header and index file generation"},
|
||||
{ "bank", 'b', "BANKNAME", 0, "Generate #pragma with given bank-name"},
|
||||
{ 0 }
|
||||
@@ -136,14 +136,18 @@ int hasSuffix(const char *str, const char *suffix)
|
||||
char *getMime(const char *name)
|
||||
{
|
||||
if (hasSuffix(name, ".html"))
|
||||
return "text/html";
|
||||
return "mime_HTML";
|
||||
else if (hasSuffix(name, ".svg"))
|
||||
return "image/svg+xml";
|
||||
return "mime_SVG";
|
||||
else if (hasSuffix(name, ".ico"))
|
||||
return "image/svg+xml";
|
||||
return "mime_SVG";
|
||||
else if (hasSuffix(name, ".png"))
|
||||
return "image/png";
|
||||
return "text/plain";
|
||||
return "mime_PNG";
|
||||
else if (hasSuffix(name, ".js"))
|
||||
return "mime_JS";
|
||||
else if (hasSuffix(name, ".css"))
|
||||
return "mime_CSS";
|
||||
return "mime_TXT";
|
||||
}
|
||||
|
||||
|
||||
@@ -160,9 +164,9 @@ int addidx(const char *name, int addr, int len)
|
||||
|
||||
defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "#define FDATA_START_%s 0x%x\n", s, addr);
|
||||
defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "#define FDATA_SIZE_%s %d\n", s, len);
|
||||
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, " {\"/%s\", FDATA_START_%s, FDATA_SIZE_%s, \"%s\"},\n", name, s, s, getMime(name));
|
||||
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, " {\"/%s\", FDATA_START_%s, FDATA_SIZE_%s, %s},\n", name, s, s, getMime(name));
|
||||
if (!strcmp(name, "index.html"))
|
||||
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, " {\"/\", FDATA_START_%s, FDATA_SIZE_%s, \"text/html\"},\n", s, s);
|
||||
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, " {\"/\", FDATA_START_%s, FDATA_SIZE_%s, mime_HTML},\n", s, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -200,7 +204,7 @@ int replaceCalls(int pos)
|
||||
buffer[pos + i + 5] = '}';
|
||||
i += 6;
|
||||
fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, " %s,\n", function_buf);
|
||||
xbuf_p += snprintf(&xbuf[xbuf_p], DEF_SIZE - xbuf_p, "extern uint16_t %s(__xdata uint8_t *outbuf);\n", function_buf);
|
||||
xbuf_p += snprintf(&xbuf[xbuf_p], DEF_SIZE - xbuf_p, "extern uint16_t %s(void);\n", function_buf);
|
||||
callNum++;
|
||||
}
|
||||
i++;
|
||||
@@ -212,8 +216,6 @@ int replaceCalls(int pos)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char * line = NULL;
|
||||
size_t len = 0;
|
||||
struct arguments arguments;
|
||||
int arg_index;
|
||||
char tmpfilename[] = "image_XXXXXX";
|
||||
@@ -265,16 +267,20 @@ int main(int argc, char **argv)
|
||||
defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "#ifndef FDATA_DEFS_H\n");
|
||||
defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "#define FDATA_DEFS_H\n\n");
|
||||
defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "#include <stdint.h>\n\n");
|
||||
defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "struct f_data {\n __code char *file;\n uint32_t start;\n uint16_t len;\n __code char *mime;\n};\n\n");
|
||||
defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "typedef uint16_t (* fcall_ptr)(__xdata uint8_t *outbuf);\n\n");
|
||||
defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p,
|
||||
"typedef enum mime_type_e {\n mime_HTML = 0,\n mime_SVG,\n mime_ICO,\n mime_PNG,\n mime_JS,\n mime_CSS,\n mime_TXT\n} mime_type_t;\n\n");
|
||||
defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "struct f_data {\n __code char *file;\n uint32_t start;\n uint16_t len;\n mime_type_t mime;\n};\n\n");
|
||||
// defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "typedef uint16_t (* fcall_ptr)(void);\n\n");
|
||||
|
||||
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, "// This file is automatically generated, do not edit!\n\n");
|
||||
if (arguments.prefix)
|
||||
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, "#include \"%s.h\"\n\n", arguments.prefix);
|
||||
if (arguments.bank)
|
||||
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, "#pragma codeseg %s\n", arguments.bank);
|
||||
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, "#pragma codeseg %s\n#pragma constseg %s\n\n", arguments.bank, arguments.bank);
|
||||
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, " __code char * __code mime_strings[] = {\n \"text/html\",\n \"image/svg+xml\",\n"
|
||||
" \"image/svg+xml\",\n \"image/png\",\n \"text/javascript\",\n \"text/css\",\n \"text/plain\"};\n\n");
|
||||
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, "__code struct f_data f_data[] = {\n");
|
||||
fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "\n__code fcall_ptr f_calls[] = {\n");
|
||||
// fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "\n__code fcall_ptr f_calls[] = {\n");
|
||||
|
||||
// Now that the beginning of the buffer is filled with out image, optionally resize the image
|
||||
if (filesize)
|
||||
@@ -329,7 +335,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, " {0, 0, 0}\n};\n");
|
||||
fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "};\n");
|
||||
// fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "};\n");
|
||||
defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "#endif\n");
|
||||
|
||||
if (filesize) {
|
||||
|
||||
@@ -0,0 +1,482 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include "httpd_sim.h"
|
||||
#include <json.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define PORTS 6
|
||||
time_t last_called;
|
||||
|
||||
uint64_t txG[PORTS], txB[PORTS], rxG[PORTS], rxB[PORTS];
|
||||
char txG_buff[20], txB_buff[20], rxG_buff[20], rxB_buff[20];
|
||||
char num_buff[20];
|
||||
char upload_buffer[4194304]; // 4MB
|
||||
|
||||
char *content_type = NULL;
|
||||
char boundary[72];
|
||||
|
||||
char is_word(char *c, char *d)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
while (d[i] && (d[i] == c[i]))
|
||||
i++;
|
||||
|
||||
if (d[i])
|
||||
return 0;
|
||||
if (c[i] != ' ' && c[i] != '\t' && c[i] != ':' && c[i] != '?' && c[i] != '=' && c[i] != '\n' && c[i] != '\r' && c[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int hasSuffix(const char *str, const char *suffix)
|
||||
{
|
||||
if (!str || !suffix)
|
||||
return 0;
|
||||
|
||||
size_t lenstr = strlen(str);
|
||||
size_t lensuffix = strlen(suffix);
|
||||
|
||||
if (lensuffix > lenstr)
|
||||
return 0;
|
||||
|
||||
return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
|
||||
}
|
||||
|
||||
|
||||
char *getMime(const char *name)
|
||||
{
|
||||
if (hasSuffix(name, ".html"))
|
||||
return "text/html";
|
||||
else if (hasSuffix(name, ".svg"))
|
||||
return "image/svg+xml";
|
||||
else if (hasSuffix(name, ".ico"))
|
||||
return "image/svg+xml";
|
||||
else if (hasSuffix(name, ".png"))
|
||||
return "image/png";
|
||||
else if (hasSuffix(name, ".js"))
|
||||
return "text/javascript";
|
||||
else if (hasSuffix(name, ".css"))
|
||||
return "text/css";
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
void send_basic_info(int socket)
|
||||
{
|
||||
char *response = "HTTP/1.1 200 OK\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\":\"v0.1-ge4c48586\",\"hw_ver\":\"SWGT024-V2.0\"}";
|
||||
write(socket, response, strlen(response));
|
||||
}
|
||||
|
||||
void send_vlan(int s, int vlan)
|
||||
{
|
||||
struct json_object *v;
|
||||
const char *jstring;
|
||||
char *header = "HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: application/json; charset=UTF-8\r\n\r\n";
|
||||
|
||||
v = json_object_new_object();
|
||||
|
||||
sprintf(num_buff, "0x%08x", 0x00060011);
|
||||
json_object_object_add(v, "members", json_object_new_string(num_buff));
|
||||
|
||||
write(s, header, strlen(header));
|
||||
|
||||
jstring = json_object_to_json_string_ext(v, JSON_C_TO_STRING_PLAIN);
|
||||
write(s, jstring, strlen(jstring));
|
||||
json_object_put(v);
|
||||
}
|
||||
|
||||
|
||||
void send_status(int s)
|
||||
{
|
||||
struct json_object *ports, *v;
|
||||
const char *jstring;
|
||||
char *header = "HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: application/json; charset=UTF-8\r\n\r\n";
|
||||
|
||||
time_t now = time(NULL);
|
||||
now = last_called ? last_called + 1 : now; // Make sure we don't divide by 0 for rates
|
||||
|
||||
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));
|
||||
json_object_object_add(v, "isSFP", json_object_new_int(i < 5 ? 0 : 1));
|
||||
json_object_object_add(v, "enabled", json_object_new_int((i % 4) ? 1 : 0));
|
||||
json_object_object_add(v, "link", json_object_new_int(i % 2 ? ((i == 1)? 5 : 2) : 0));
|
||||
if (i % 2) {
|
||||
uint64_t rate = (i == 1) ? 2400000000 : 950000000;
|
||||
txG[i-1] += rate * (now - last_called);
|
||||
rxG[i-1] += rate * (now - last_called);
|
||||
txB[i-1] += rate * (now - last_called) / 10000000;
|
||||
rxB[i-1] += rate * (now - last_called) / 10000000;
|
||||
}
|
||||
sprintf(txG_buff, "0x%016lx", txG[i-1]);
|
||||
sprintf(txB_buff, "0x%016lx", txB[i-1]);
|
||||
sprintf(rxG_buff, "0x%016lx", rxG[i-1]);
|
||||
sprintf(rxB_buff, "0x%016lx", rxB[i-1]);
|
||||
json_object_object_add(v, "txG", json_object_new_string(txG_buff));
|
||||
json_object_object_add(v, "txB", json_object_new_string(txB_buff));
|
||||
json_object_object_add(v, "rxG", json_object_new_string(rxG_buff));
|
||||
json_object_object_add(v, "rxB", json_object_new_string(rxB_buff));
|
||||
json_object_array_add(ports, v);
|
||||
}
|
||||
last_called = now;
|
||||
|
||||
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(v);
|
||||
}
|
||||
|
||||
|
||||
void send_eee(int s)
|
||||
{
|
||||
struct json_object *ports, *v;
|
||||
const char *jstring;
|
||||
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));
|
||||
json_object_object_add(v, "isSFP", json_object_new_int(i < 5 ? 0 : 1));
|
||||
uint8_t eee = 0;
|
||||
eee |= 0x02;
|
||||
char eee_buf[20];
|
||||
sprintf(eee_buf, "%08b", eee);
|
||||
json_object_object_add(v, "eee", json_object_new_string(eee_buf));
|
||||
uint8_t eee_lp = 0;
|
||||
eee_lp |= 0x04;
|
||||
sprintf(eee_buf, "%08b", eee_lp);
|
||||
json_object_object_add(v, "eee_lp", json_object_new_string(eee_buf));
|
||||
json_object_object_add(v, "active", json_object_new_int((i % 2) ? 1 : 0));
|
||||
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)
|
||||
{
|
||||
uint16_t mirror_tx, mirror_rx = 0;
|
||||
char mirror_tx_buf[20];
|
||||
char mirror_rx_buf[20];
|
||||
struct json_object *mirror;
|
||||
const char *jstring;
|
||||
char *header = "HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: application/json; charset=UTF-8\r\n\r\n";
|
||||
|
||||
mirror = json_object_new_object();
|
||||
json_object_object_add(mirror, "mPort", json_object_new_int(1));
|
||||
json_object_object_add(mirror, "enabled", json_object_new_int(1));
|
||||
|
||||
mirror_tx = 0b000110;
|
||||
mirror_rx = 0b000010;
|
||||
sprintf(mirror_tx_buf, "%016b", mirror_tx);
|
||||
sprintf(mirror_rx_buf, "%016b", mirror_rx);
|
||||
json_object_object_add(mirror, "mirror_tx", json_object_new_string(mirror_tx_buf));
|
||||
json_object_object_add(mirror, "mirror_rx", json_object_new_string(mirror_rx_buf));
|
||||
|
||||
write(s, header, strlen(header));
|
||||
|
||||
jstring = json_object_to_json_string_ext(mirror, JSON_C_TO_STRING_PLAIN);
|
||||
write(s, jstring, strlen(jstring));
|
||||
json_object_put(mirror);
|
||||
}
|
||||
|
||||
|
||||
struct Server serverConstructor(int port, void (*launch)(struct Server *server)) {
|
||||
struct Server server;
|
||||
|
||||
server.domain = AF_INET;
|
||||
server.service = SOCK_STREAM;
|
||||
server.port = port;
|
||||
server.protocol = 0;
|
||||
server.backlog = 10;
|
||||
|
||||
server.address.sin_family = server.domain;
|
||||
server.address.sin_port = htons(port);
|
||||
server.address.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
server.socket = socket(server.domain, server.service, server.protocol);
|
||||
if (server.socket < 0) {
|
||||
perror("Failed to initialize/connect to socket...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (bind(server.socket, (struct sockaddr*)&server.address, sizeof(server.address)) < 0) {
|
||||
perror("Failed to bind socket...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (listen(server.socket, server.backlog) < 0) {
|
||||
perror("Failed to start listening...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
server.launch = launch;
|
||||
return server;
|
||||
}
|
||||
|
||||
void send_not_found(int socket) {
|
||||
char *response = "HTTP/1.1 404 Not found\r\n"
|
||||
"Content-Type: text/html\r\n\r\n"
|
||||
"<!DOCTYPE html> <html><head><title>Not Found</title></head>"
|
||||
"<body><h1>Not found!</h1></html>";
|
||||
write(socket, response, strlen(response));
|
||||
}
|
||||
|
||||
|
||||
void send_bad_request(int socket) {
|
||||
char *response = "HTTP/1.1 400 Bad Request\r\n"
|
||||
"Content-Type: text/html\r\n\r\n"
|
||||
"<!DOCTYPE html> <html><head><title>Bad Request</title></head>"
|
||||
"<body><h1>Bad Request!</h1></html>";
|
||||
write(socket, response, strlen(response));
|
||||
}
|
||||
|
||||
|
||||
char *scan_header(char *p)
|
||||
{
|
||||
while (*p != '\r' || *(p + 1) != '\n' || *(p + 2) != '\r' || *(p + 3) != '\n') {
|
||||
if (!*p++)
|
||||
break;
|
||||
if (*p == '\n' && is_word(p + 1, "Content-Type:"))
|
||||
content_type = p + 15;
|
||||
}
|
||||
if (content_type && is_word(content_type, "multipart/form-data; boundary")) {
|
||||
printf("Found multiplart\n");
|
||||
content_type += 30;
|
||||
uint8_t i = 0;
|
||||
while (content_type[i] != '\r' && content_type[i] != '\n') {
|
||||
boundary[i + 2] = content_type[i];
|
||||
i++;
|
||||
}
|
||||
// The boundary between parts is "--" + the boundary given in the header
|
||||
boundary[0] = '-';
|
||||
boundary[1] = '-';
|
||||
boundary[i + 2] = 0;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
char *skip_boundary(char *p)
|
||||
{
|
||||
while (*p) {
|
||||
if (is_word(p, boundary))
|
||||
return p + strlen(boundary);
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void launch(struct Server *server)
|
||||
{
|
||||
char buffer[BUFFER_SIZE];
|
||||
FILE *inptr;
|
||||
|
||||
last_called = time(NULL);
|
||||
for (int i=0; i < PORTS; i++)
|
||||
txG[i] = txB[i] = rxG[i] = rxB[i] = 0;
|
||||
|
||||
while (1) {
|
||||
printf("=== Waiting for connection on port %d === \n", server->port);
|
||||
int addrlen = sizeof(server->address);
|
||||
int new_socket = accept(server->socket, (struct sockaddr*)&server->address, (socklen_t*)&addrlen);
|
||||
ssize_t bytesRead = read(new_socket, buffer, BUFFER_SIZE - 1);
|
||||
printf("bytesRead: %ld\n", bytesRead);
|
||||
int filesize = 0;
|
||||
char *mime;
|
||||
|
||||
if (bytesRead > 0) {
|
||||
buffer[bytesRead] = '\0'; // Null terminate the string
|
||||
puts(buffer);
|
||||
|
||||
if (is_word(buffer, "GET")) {
|
||||
printf("GET request\n");
|
||||
if (!strncmp(&buffer[4], "/status.json", 12)) {
|
||||
printf("Status request\n");
|
||||
send_status(new_socket);
|
||||
goto done;
|
||||
}
|
||||
if (!strncmp(&buffer[4], "/eee.json", 9)) {
|
||||
printf("EEE request\n");
|
||||
send_eee(new_socket);
|
||||
goto done;
|
||||
}
|
||||
if (!strncmp(&buffer[4], "/information.json", 12)) {
|
||||
printf("Status request\n");
|
||||
send_basic_info(new_socket);
|
||||
goto done;
|
||||
}
|
||||
if (!strncmp(&buffer[4], "/mirror.json", 12)) {
|
||||
printf("Mirror request\n");
|
||||
send_mirror(new_socket);
|
||||
goto done;
|
||||
}
|
||||
if (!strncmp(&buffer[4], "/vlan.json?vid=", 15)) {
|
||||
int vlan = atoi(&buffer[19]);
|
||||
printf("VLAN request for %d\n", vlan);
|
||||
send_vlan(new_socket, vlan);
|
||||
goto done;
|
||||
}
|
||||
int i = 0;
|
||||
while (!isspace(buffer[4 + i]))
|
||||
i++;
|
||||
buffer[4+i] = '\0';
|
||||
|
||||
printf("Serving file: >%s<, name length %d\n", &buffer[5], i);
|
||||
if (i > 1)
|
||||
inptr = fopen(&buffer[5], "rb");
|
||||
else
|
||||
inptr = fopen("/index.html", "rb");
|
||||
if (inptr == NULL) {
|
||||
printf("Cannot open input file %s\n", &buffer[5]);
|
||||
send_not_found(new_socket);
|
||||
goto done;
|
||||
}
|
||||
|
||||
mime = getMime(&buffer[5]);
|
||||
printf("MIME type: %s\n", mime);
|
||||
|
||||
fseek(inptr, 0L, SEEK_END);
|
||||
filesize = ftell(inptr);
|
||||
printf("Filesize: %d\n", filesize);
|
||||
rewind(inptr);
|
||||
printf("Input file size: %d\n", filesize);
|
||||
if (filesize > BUFFER_SIZE) {
|
||||
printf("File too large.\n");
|
||||
goto done;
|
||||
}
|
||||
size_t bytes_read = fread(buffer, 1, sizeof(buffer), inptr);
|
||||
|
||||
printf("Bytes read: %ld\n", bytes_read);
|
||||
|
||||
if (bytes_read != filesize) {
|
||||
printf("Error reading input file.\n");
|
||||
goto done;
|
||||
}
|
||||
fclose(inptr);
|
||||
} else if (is_word(buffer, "POST")) {
|
||||
printf("POST request\n");
|
||||
// Find end of request header
|
||||
char *p = buffer;
|
||||
boundary[0] ='\0';
|
||||
p = scan_header(p);
|
||||
printf("Boundary: >%s<\n", boundary);
|
||||
if (!*p || !content_type) {
|
||||
printf("Bad request, no content type!\n");
|
||||
send_bad_request(new_socket);
|
||||
goto done;
|
||||
}
|
||||
|
||||
printf("Bytes read %ld\n", bytesRead);
|
||||
if (is_word(&buffer[5], "/upload")) {
|
||||
printf("POST upload request\n");
|
||||
if (!boundary[0]) {
|
||||
printf("Bad request, no boundary!\n");
|
||||
send_bad_request(new_socket);
|
||||
goto done;
|
||||
}
|
||||
// We skip the intial parts as part of the header
|
||||
do {
|
||||
p = skip_boundary(p);
|
||||
if (!*p)
|
||||
goto bad_request;
|
||||
p = scan_header(p);
|
||||
if (!*p || !content_type)
|
||||
goto bad_request;
|
||||
} while (!is_word(content_type, "application/octet-stream"));
|
||||
printf("Have content: >%s<\n", content_type);
|
||||
|
||||
char *uptr = upload_buffer;
|
||||
int bindex = 0;
|
||||
int bptr = p - buffer;
|
||||
do {
|
||||
if (bptr >= bytesRead) {
|
||||
bptr = 0;
|
||||
bytesRead = read(new_socket, buffer, BUFFER_SIZE - 1);
|
||||
printf("bytesRead: %ld\n", bytesRead);
|
||||
if (!bytesRead)
|
||||
break;
|
||||
}
|
||||
if (!boundary[bindex])
|
||||
break;
|
||||
if (buffer[bptr] == boundary[bindex]) {
|
||||
bptr++;
|
||||
bindex++;
|
||||
} else {
|
||||
for (int i = 0; i < bindex; i++)
|
||||
*uptr++ = boundary[i];
|
||||
*uptr++ = buffer[bptr++];
|
||||
bindex = 0;
|
||||
}
|
||||
} while(1);
|
||||
printf("Done reading\n");
|
||||
printf("%s", upload_buffer);
|
||||
if (!bindex || boundary[bindex])
|
||||
goto bad_request;
|
||||
char *response = "HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: text/html\r\n\r\n"
|
||||
"<!DOCTYPE html> <html><head><title>Upload OK</title></head>"
|
||||
"<body><h1>File uploaded successully</h1></html>";
|
||||
write(new_socket, response, strlen(response));
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
char *response = "HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: ";
|
||||
write(new_socket, response, strlen(response));
|
||||
|
||||
write(new_socket, mime, strlen(mime));
|
||||
response = "; charset=UTF-8\r\n\r\n";
|
||||
write(new_socket, response, strlen(response));
|
||||
if (filesize)
|
||||
write(new_socket, buffer, filesize);
|
||||
} else if (bytesRead == 0) {
|
||||
printf("EOF\n");
|
||||
continue;
|
||||
} else {
|
||||
perror("Error reading buffer, nothing read...\n");
|
||||
}
|
||||
|
||||
done:
|
||||
close(new_socket);
|
||||
continue;
|
||||
bad_request:
|
||||
printf("Bad request!\n");
|
||||
send_bad_request(new_socket);
|
||||
close(new_socket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
// Make sure we can handle writes to a dead client without a signal handler
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
struct Server server = serverConstructor(8080, launch);
|
||||
server.launch(&server);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef server_h
|
||||
#define server_h
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define BUFFER_SIZE 2400
|
||||
|
||||
struct Server {
|
||||
int domain;
|
||||
int port;
|
||||
int service;
|
||||
int protocol;
|
||||
int backlog;
|
||||
u_long interface;
|
||||
|
||||
int socket;
|
||||
struct sockaddr_in address;
|
||||
|
||||
void (*launch)(struct Server *server);
|
||||
};
|
||||
|
||||
struct Server server_Constructor(int port, void (*launch)(struct Server *server));
|
||||
void launch(struct Server *server);
|
||||
|
||||
#endif
|
||||
|
||||
+11
-6
@@ -3,19 +3,24 @@ CC_FLAGS = -mmcs51 -I. -I../httpd
|
||||
ASM = sdas8051
|
||||
AFLAGS= -plosgff
|
||||
|
||||
BUILDDIR = output/
|
||||
|
||||
SRCS = timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-neighbor.c uip-split.c
|
||||
OBJS = ${SRCS:.c=.rel}
|
||||
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
|
||||
|
||||
all: $(OBJS)
|
||||
all: create_build_dir $(OBJS)
|
||||
|
||||
%.rel: %.c
|
||||
$(CC) $(CC_FLAGS) -c $<
|
||||
create_build_dir:
|
||||
mkdir -p $(BUILDDIR)
|
||||
|
||||
%.rel: %.asm
|
||||
$(BUILDDIR)%.rel: %.c
|
||||
$(CC) $(CC_FLAGS) -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)%.rel: $(BUILDDIR)%.asm
|
||||
${ASM} ${AFLAGS} $^
|
||||
|
||||
clean:
|
||||
rm *.ihx *.lk *.lst *.map *.mem *.rel *.rst *.sym *.bin
|
||||
rm -r $(BUILDDIR)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#define STATE_DATA_SENT 6
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
/*
|
||||
* Return value of the buffering functions that indicates that a
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "timer.h"
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
|
||||
+2
-2
@@ -94,14 +94,14 @@ typedef unsigned short uip_stats_t;
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_MAX_CONNECTIONS 3
|
||||
#define UIP_CONF_MAX_CONNECTIONS 1
|
||||
|
||||
/**
|
||||
* Maximum number of listening TCP ports. TODO: increase this!
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_MAX_LISTENPORTS 3
|
||||
#define UIP_CONF_MAX_LISTENPORTS 1
|
||||
|
||||
/**
|
||||
* uIP buffer size.
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "uip-fw.h"
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
#include "../rtl837x_common.h"
|
||||
|
||||
|
||||
+9
-8
@@ -44,7 +44,7 @@
|
||||
#include "../rtl837x_common.h"
|
||||
|
||||
#pragma codeseg BANK1
|
||||
|
||||
#pragma constseg BANK1
|
||||
|
||||
#define MAX_TIME 128
|
||||
|
||||
@@ -85,9 +85,9 @@ uip_neighbor_periodic(void)
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_neighbor_add(uip_ipaddr_t ipaddr, __xdata struct uip_neighbor_addr *addr)
|
||||
uip_neighbor_add(__xdata uip_ipaddr_t ipaddr, __xdata struct uip_neighbor_addr *addr)
|
||||
{
|
||||
int i, oldest;
|
||||
uint16_t i, oldest;
|
||||
u8_t oldest_time;
|
||||
|
||||
/*
|
||||
@@ -130,12 +130,13 @@ uip_neighbor_add(uip_ipaddr_t ipaddr, __xdata struct uip_neighbor_addr *addr)
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
__xdata static struct neighbor_entry *
|
||||
find_entry(uip_ipaddr_t ipaddr)
|
||||
find_entry(__xdata uip_ipaddr_t ipaddr)
|
||||
{
|
||||
int i;
|
||||
uint16_t i;
|
||||
|
||||
for(i = 0; i < ENTRIES; ++i) {
|
||||
if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) {
|
||||
// if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) {
|
||||
if (entries[i].ipaddr[0] == ipaddr[0] && entries[i].ipaddr[1] == ipaddr[1]) {
|
||||
return &entries[i];
|
||||
}
|
||||
}
|
||||
@@ -143,7 +144,7 @@ find_entry(uip_ipaddr_t ipaddr)
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_neighbor_update(uip_ipaddr_t ipaddr)
|
||||
uip_neighbor_update(__xdata uip_ipaddr_t ipaddr)
|
||||
{
|
||||
struct neighbor_entry *e;
|
||||
|
||||
@@ -154,7 +155,7 @@ uip_neighbor_update(uip_ipaddr_t ipaddr)
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
__xdata struct uip_neighbor_addr *
|
||||
uip_neighbor_lookup(uip_ipaddr_t ipaddr)
|
||||
uip_neighbor_lookup(__xdata uip_ipaddr_t ipaddr)
|
||||
{
|
||||
__xdata struct neighbor_entry *e;
|
||||
|
||||
|
||||
+3
-3
@@ -54,9 +54,9 @@ struct uip_neighbor_addr {
|
||||
};
|
||||
|
||||
void uip_neighbor_init(void);
|
||||
void uip_neighbor_add(uip_ipaddr_t ipaddr, __xdata struct uip_neighbor_addr *addr);
|
||||
void uip_neighbor_update(uip_ipaddr_t ipaddr);
|
||||
__xdata struct uip_neighbor_addr *uip_neighbor_lookup(uip_ipaddr_t ipaddr);
|
||||
void uip_neighbor_add(__xdata uip_ipaddr_t ipaddr, __xdata struct uip_neighbor_addr *addr);
|
||||
void uip_neighbor_update(__xdata uip_ipaddr_t ipaddr);
|
||||
__xdata struct uip_neighbor_addr *uip_neighbor_lookup(__xdata uip_ipaddr_t ipaddr);
|
||||
void uip_neighbor_periodic(void);
|
||||
|
||||
#endif /* __UIP-NEIGHBOR_H__ */
|
||||
|
||||
+1
-1
@@ -41,8 +41,8 @@
|
||||
#include "uip-fw.h"
|
||||
#include "uip_arch.h"
|
||||
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
#define BUF ((__xdata struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
#include "uip_arch.h"
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
#if UIP_CONF_IPV6
|
||||
#include "uip-neighbor.h"
|
||||
@@ -397,9 +398,9 @@ uip_init(void) __banked
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if UIP_ACTIVE_OPEN
|
||||
__xdata struct uip_conn *
|
||||
uip_connect(register __xdata uip_ipaddr_t *ripaddr, register u16_t rport)
|
||||
uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport)
|
||||
{
|
||||
register __xdata struct uip_conn *conn, *cconn;
|
||||
__xdata struct uip_conn *conn, *cconn;
|
||||
|
||||
/* Find an unused local port. */
|
||||
again:
|
||||
@@ -411,7 +412,7 @@ uip_connect(register __xdata uip_ipaddr_t *ripaddr, register u16_t rport)
|
||||
|
||||
/* Check if this port is already in use, and if so try to find
|
||||
another one. */
|
||||
for(c = 0; c < UIP_CONNS; ++c) {
|
||||
for(uint8_t c = 0; c < UIP_CONNS; ++c) {
|
||||
conn = &uip_conns[c];
|
||||
if(conn->tcpstateflags != UIP_CLOSED &&
|
||||
conn->lport == htons(lastport)) {
|
||||
@@ -420,7 +421,7 @@ uip_connect(register __xdata uip_ipaddr_t *ripaddr, register u16_t rport)
|
||||
}
|
||||
|
||||
conn = 0;
|
||||
for(c = 0; c < UIP_CONNS; ++c) {
|
||||
for(uint8_t c = 0; c < UIP_CONNS; ++c) {
|
||||
cconn = &uip_conns[c];
|
||||
if(cconn->tcpstateflags == UIP_CLOSED) {
|
||||
conn = cconn;
|
||||
|
||||
@@ -495,7 +495,7 @@ void uip_unlisten(u16_t port);
|
||||
* or NULL if no connection could be allocated.
|
||||
*
|
||||
*/
|
||||
__xdata struct uip_conn *uip_connect(register __xdata uip_ipaddr_t *ripaddr, register u16_t port);
|
||||
__xdata struct uip_conn *uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t port);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#include "../rtl837x_common.h"
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
struct arp_hdr_i {
|
||||
struct uip_eth_hdr ethhdr;
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "uiplib.h"
|
||||
|
||||
#pragma codeseg BANK1
|
||||
#pragma constseg BANK1
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
unsigned char
|
||||
|
||||
Reference in New Issue
Block a user