1 Commits
Author SHA1 Message Date
logicog 984831620c Use multiple concurrent TCP connections
This uses multiple concurrent TCP connections by making the state
of the connection including the output buffer a part of the application
data. This leads to the buffer, to be sent length of data and the already
sent data to be part of that state and must be handed over to functions
that generate data. At this point this leads to an overuse of OSEG and DSEG
memory space so further work needs to be done on tuning the code.
Putting it into a branch for now.
2025-08-06 17:00:14 +02:00
75 changed files with 886 additions and 4991 deletions
-7
View File
@@ -1,7 +0,0 @@
.gitignore
output/
html_data.c
html_data.h
tools/httpd_sim
tools/injector
tools/fileadder
+19 -32
View File
@@ -1,9 +1,5 @@
BOOTLOADER_ADDRESS=0x100
IMAGESIZE = 524288
CONFIG_LOCATION = 458752
HTML_LOCATION = 262144
CC = sdcc
CC_FLAGS = -mmcs51 -Ihttpd -Iuip
ASM = sdas8051
@@ -12,19 +8,14 @@ AFLAGS= -plosgff
SUBDIRS := tools uip httpd
SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS))
BUILDDIR = output/
all: $(SUBDIRS) rtlplayground.bin
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
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
html_data.c html_data.h: html tools
tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -d html -p html_data
tools/fileadder -a -s -b BANK1 -d html -p html_data
httpd: html_data.h
@@ -34,37 +25,33 @@ $(SUBDIRS):
clean:
-make -C uip clean
-make -C httpd clean
-rm html_data.c html_data.h
-rm -r $(BUILDDIR)
-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
$(BUILDDIR)crtstart.rel: crtstart.asm
$(ASM) $(AFLAGS) -o $@ $<
$(BUILDDIR)crc16.rel: crc16.asm
$(ASM) $(AFLAGS) -o $@ $<
%.rel: %.c
$(CC) $(CC_FLAGS) -c $<
$(BUILDDIR)%.rel: %.c
$(CC) $(CC_FLAGS) -o $@ -c $<
$(BUILDDIR)%.rel: $(BUILDDIR)%.asm
${ASM} ${AFLAGS} -o $@ $<
%.rel: %.asm
${ASM} ${AFLAGS} $^
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
$(BUILDDIR)rtlplayground.ihx: $(BUILDDIR)crtstart.rel $(OBJS) $(BUILDDIR)crc16.rel
rtlplayground.ihx: crtstart.rel $(OBJS)
$(CC) $(CC_FLAGS) -Wl-bHOME=${BOOTLOADER_ADDRESS} -Wl-bBANK1=0x14000 -Wl-r -o $@ $^
$(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx
%.img: %.ihx
objcopy --input-target=ihex -O binary $< $@
$(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlplayground.img
%.bin: %.img
if [ -e $@ ]; then rm $@; fi
echo "0000000: 00 40" | xxd -r - $@
cat $< >> $@
truncate --size=16K $@
dd if=$< skip=80 bs=1024 >>$@
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 $@
tools/fileadder -s -d config.txt $@
tools/fileadder -a -s -d html -p html_data $@
.PHONY: clean all $(SUBDIRS)
.PRECIOUS: %.rel %.ihx .img
+1 -1
View File
@@ -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 python
sudo apt install sdcc xxd
```
Now, building the firmware image should work:
+93 -469
View File
@@ -3,60 +3,42 @@
*/
// #define DEBUG
// #define REGDBG 1
#define CONFIG_START 0x70000
#define CONFIG_LEN 0x1000
#define REGDBG 1
#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 sfr_data[4];
extern volatile __xdata uint8_t sbuf_ptr;
extern __xdata uint8_t sbuf[SBUF_SIZE];
extern __code uint8_t * __code greeting;
extern __code uint8_t * __code hex;
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 };
extern __xdata uint8_t flash_buf[256];
// Buffer for writing to flash 0x1fd000, copy to 0x1fe000
__xdata uint8_t cmd_buffer[SBUF_SIZE];
__xdata uint8_t cmd_available;
#define CMD_BUFFER_SIZE 1024
__xdata uint8_t cmd_buffer[CMD_BUFFER_SIZE];
__xdata uint16_t cmdptr;
__xdata uint8_t l;
__xdata uint8_t line_ptr;
__xdata char is_white;
__xdata uint8_t ip[4];
#define N_WORDS SBUF_SIZE
#define N_WORDS 16
__xdata signed char cmd_words_b[N_WORDS];
// Maps the physical port (starting from 0) to the logical port
@@ -64,136 +46,53 @@ __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] && cmd_buffer[i] != ' '; i++) {
for (i = cmd_words_b[start]; i != cmd_words_b[start + 1] && sbuf[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(cmd_buffer[i]); print_string("\n");
// write_char('>'); write_char(cmd[j]); write_char('-'); write_char(sbuf[i]); print_string("\n");
if (!cmd[j])
return 1;
if (cmd_buffer[i] != cmd[j++])
if (sbuf[i] != cmd[j++])
break;
}
// write_char('.'); print_short(i); write_char(':'); print_short(i);
if (i == cmd_words_b[start + 1] || cmd_buffer[i] == ' ')
if (i == cmd_words_b[start + 1] || sbuf[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 (isnumber(cmd_buffer[idx])) {
while (sbuf[idx] >= '0' && sbuf[idx] <= '9') {
err = 0;
*vlan = (*vlan * 10) + cmd_buffer[idx] - '0';
*vlan = (*vlan * 10) + sbuf[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 = cmd_buffer[cmd_words_b[1]] - '0';
group = sbuf[cmd_words_b[1]] - '0';
uint8_t w = 2;
while (cmd_words_b[w] > 0) {
uint8_t port;
if (isnumber(cmd_buffer[cmd_words_b[w]])) {
port = cmd_buffer[cmd_words_b[w]] - '1';
if (sbuf[cmd_words_b[w]] >= '0' && sbuf[cmd_words_b[w]] <= '9') {
port = sbuf[cmd_words_b[w]] - '1';
if (port > maxPort)
goto err;
members |= ((uint16_t)1) << port;
@@ -213,40 +112,23 @@ 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 && cmd_buffer[cmd_words_b[2]] == 'd' && cmd_words_b[3] < 0) {
if (cmd_words_b[2] > 0 && sbuf[cmd_words_b[2]] == 'd') {
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 (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')
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')
tagged |= ((uint16_t)1) << port;
} else {
if (!isRTL8373)
port = phys_to_log_port[port];
if (cmd_buffer[cmd_words_b[w] + 1] == 't')
if (sbuf[cmd_words_b[w] + 1] == 't')
tagged |= ((uint16_t)1) << port;
}
if (port > maxPort)
@@ -257,10 +139,6 @@ 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]...");
@@ -273,58 +151,29 @@ void parse_mirror(void)
__xdata uint16_t rx_pmask = 0;
__xdata uint16_t tx_pmask = 0;
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();
if (sbuf[cmd_words_b[1]] < '0' || sbuf[cmd_words_b[1]] > '9') {
print_string("Port missing: port <mirroring port> [port][t/r]...");
return;
}
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';
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 (!isRTL8373)
mirroring_port = phys_to_log_port[mirroring_port];
uint8_t w = 2;
while (cmd_words_b[w] > 0) {
uint8_t port;
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 (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 (!isRTL8373)
port = phys_to_log_port[port];
if (cmd_buffer[cmd_words_b[w] + 2] == 'r')
if (sbuf[cmd_words_b[w] + 2] == 'r')
rx_pmask |= ((uint16_t)1) << port;
else if (cmd_buffer[cmd_words_b[w] + 2] == 't')
else if (sbuf[cmd_words_b[w] + 2] == 't')
tx_pmask |= ((uint16_t)1) << port;
else {
rx_pmask |= ((uint16_t)1) << port;
@@ -333,9 +182,9 @@ void parse_mirror(void)
} else {
if (!isRTL8373)
port = phys_to_log_port[port];
if (cmd_buffer[cmd_words_b[w] + 1] == 'r')
if (sbuf[cmd_words_b[w] + 1] == 'r')
rx_pmask |= ((uint16_t)1) << port;
else if (cmd_buffer[cmd_words_b[w] + 1] == 't')
else if (sbuf[cmd_words_b[w] + 1] == 't')
tx_pmask |= ((uint16_t)1) << port;
else {
rx_pmask |= ((uint16_t)1) << port;
@@ -349,166 +198,42 @@ void parse_mirror(void)
}
void parse_regget(void)
{
uint16_t reg = 0;
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
void cmd_parser(void) __banked
{
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_string("Tokenizing command\n");
print_string_x(&cmd_buffer[0]);
write_char('<'); write_char('\n');
print_long(ticks);
#endif
line_ptr = 0;
// Print line and parse command into words
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] != ' ') {
while (line_ptr != l) {
if (is_white && sbuf[line_ptr] != ' ') {
is_white = 0;
cmd_words_b[word++] = line_ptr;
}
if (cmd_buffer[line_ptr] == ' ')
if (sbuf[line_ptr] == ' ')
is_white = 1;
line_ptr++;
write_char(sbuf[line_ptr++]);
line_ptr &= SBUF_SIZE - 1;
if (word >= N_WORDS - 1) {
print_string("\ntoo many arguments, truncated");
return 1;
line_ptr = l; // BUG: We should probably ignore the command
break;
}
}
if (line_ptr == SBUF_SIZE - 1)
return 1;
cmd_words_b[word++] = line_ptr;
cmd_words_b[word++] = -1;
line_ptr = (l + 1) & (SBUF_SIZE - 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');
}
}
// Identify command
void cmd_parser(void) __banked
{
#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) {
// 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();
@@ -527,58 +252,45 @@ void cmd_parser(void) __banked
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') {
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 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();
// 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 && cmd_buffer[cmd_words_b[1]] == 'd') {
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'd') {
print_string("\nDUMPING FLASH\n");
flash_region.addr = 0;
flash_region.len = 255;
flash_dump(255);
flash_dump(0, 255);
}
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') {
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 && cmd_buffer[cmd_words_b[1]] == 'u') {
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 && cmd_buffer[cmd_words_b[1]] == 's') {
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_region.addr = 0;
flash_region.len = 255;
flash_dump(255);
flash_dump(0, 255);
}
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'e') {
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'e') {
print_string("\nFLASH erase\n");
flash_region.addr = 0x20000;
flash_sector_erase();
flash_block_erase(0x20000);
}
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'w') {
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_region.addr = 0x200000;
flash_region.len = 20;
flash_write_bytes(flash_buf);
flash_write_bytes(0x20000, flash_buf, 20);
}
if (cmd_compare(0, "port") && cmd_words_b[1] > 0) {
print_string("\nPORT ");
uint8_t p = cmd_buffer[cmd_words_b[1]] - '1';
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");
@@ -597,54 +309,16 @@ void cmd_parser(void) __banked
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';
port = sbuf[cmd_words_b[1]] - '1';
if (!isRTL8373)
port = phys_to_log_port[port];
if (!atoi_short(&pvid, cmd_words_b[2]))
@@ -662,80 +336,30 @@ void cmd_parser(void) __banked
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();
}
print_string("\n> ");
}
l++;
l &= (SBUF_SIZE - 1);
}
}
#define FLASH_READ_BURST_SIZE 0x100;
void execute_config(void) __banked
void execute_config() __banked
{
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)
flash_read_bulk(&cmd_buffer[0], 0x1fd000, CMD_BUFFER_SIZE);
// Checks for empty flash
if (cmd_buffer[0] == 0xff)
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);
print_string_x(&cmd_buffer[0]);
}
void cmd_parser_setup(void) __banked
{
l = sbuf_ptr;
line_ptr = l;
is_white = 1;
cmdptr = 0;
}
+2 -9
View File
@@ -1,14 +1,7 @@
#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 execute_config(void) __banked;
void cmd_parser_setup(void) __banked;
void execute_config() __banked;
#endif
-3
View File
@@ -1,3 +0,0 @@
ip 192.168.10.247
gw 192.168.10.1
netmask 255.255.255.0
-121
View File
@@ -1,121 +0,0 @@
;
; 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
+1 -8
View File
@@ -3,12 +3,6 @@
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).
@@ -45,8 +39,7 @@ 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. The ASIC will transmit
packets if bit 0 of RTL837X_REG_TX_CTRL (0x7860) is set.
and transferring both to the ASIC side via the SFRs.
```
SS 07 00 00 LL LH 00 00
-174
View File
@@ -1,174 +0,0 @@
### 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.

Before

Width:  |  Height:  |  Size: 7.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 MiB

+1 -4
View File
@@ -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 gg
M2 M3 M4 M5 fV VV M0 M1 xx xF xx xg
M0-M5: 6 bytes of MAC, M0 is MSB
V: 12 bits of VLAN-ID
@@ -41,9 +41,6 @@ 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),
-26
View File
@@ -1,26 +0,0 @@
<!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
View File
@@ -1,49 +0,0 @@
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);
-18
View File
@@ -1,18 +0,0 @@
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}`);
}
}
+10 -19
View File
@@ -1,25 +1,16 @@
<!DOCTYPE html>
<html>
<script src="/ports.js"></script>
<script src="/main.js"></script>
<script src="/main_info.js"></script>
<link rel="stylesheet" href="style.css">
<head>
<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>
</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>
<h1>Switch Configuration</h1>
<table id="infoTable">
<tr>
<th colspan="2">Settings</th>
</tr>
<tbody>
</tbody>
<table>
<tr> <th>Setting</th> <th></th> </tr>
#{html_index}
</table>
</div>
<script src="/navigation.js"></script>
</body>
</body>
</html>
-60
View File
@@ -1,60 +0,0 @@
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);
});
-22
View File
@@ -1,22 +0,0 @@
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));
});
-27
View File
@@ -1,27 +0,0 @@
<!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>
-59
View File
@@ -1,59 +0,0 @@
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();
}
-43
View File
@@ -1,43 +0,0 @@
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}`);
}
}
-9
View File
@@ -1,9 +0,0 @@
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
View File
@@ -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 class="bg" id="rect3787"
<path 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 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"/>
<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"/>
</g>
</g>
</g>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

-21
View File
@@ -1,21 +0,0 @@
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
View File
@@ -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 class="bg" id="p2"
<path 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:#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 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 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 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"/>
<circle id="c1" cx="176.86" cy="125.7" r="0.93"/>
<circle 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

-20
View File
@@ -1,20 +0,0 @@
<!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>
-26
View File
@@ -1,26 +0,0 @@
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);
+11
View File
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Statistics</title>
</head>
<body>
<h1>Port configuration:</h1>
<p>#{stat_content}</p>
</body>
</html>
-76
View File
@@ -1,76 +0,0 @@
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;}
-19
View File
@@ -1,19 +0,0 @@
<!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>
-34
View File
@@ -1,34 +0,0 @@
<!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>
-70
View File
@@ -1,70 +0,0 @@
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();
}
-27
View File
@@ -1,27 +0,0 @@
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}`);
}
}
+9 -12
View File
@@ -3,24 +3,21 @@ CC_FLAGS = -mmcs51 -I. -I../uip
ASM = sdas8051
AFLAGS= -plosgff
BUILDDIR = output/
SRCS = httpd.c page_impl.c
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
OBJS = ${SRCS:.c=.rel}
all: create_build_dir $(OBJS)
all: $(OBJS)
create_build_dir:
mkdir -p $(BUILDDIR)
%.asm: %.c
$(CC) $(CC_FLAGS) -c -S $<
$(BUILDDIR)%.asm: %.c
$(CC) $(CC_FLAGS) -o $@ -c -S $<
$(BUILDDIR)%.rel: $(BUILDDIR)%.asm
${ASM} ${AFLAGS} -o $@ $^
%.rel: %.asm
./treatasm.py $^ >$^.new
mv $^.new $^
${ASM} ${AFLAGS} $^
clean:
rm -r $(BUILDDIR)
rm .asm *.lst *.rel *.rst *.sym
.PHONY: all clean
+72 -373
View File
@@ -1,77 +1,45 @@
#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 char * __code mime_strings[];
extern __xdata struct flash_region_t flash_region;
extern __code fcall_ptr f_calls[];
// 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_separator(uint8_t c)
inline uint8_t is_space(uint8_t c)
{
return c == ' ' || c == '\t' || c == '?' || c == '=';
return c == ' ' || c == '\t';
}
void httpd_init(void) __banked
{
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
__xdata struct httpd_state *s = &(uip_conn->appstate);
// Start listening to port 80
uip_listen(HTONS(80));
s->tstate = TSTATE_CLOSED;
}
uint8_t find_entry(__xdata uint8_t *e)
uint8_t find_entry(uint8_t *e)
{
uint8_t i, j;
register uint8_t i, j;
for (i = 0; f_data[i].len; i++) {
j = 0;
@@ -86,272 +54,10 @@ uint8_t find_entry(__xdata 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 * __xdata s = &(uip_conn->appstate);
__xdata struct httpd_state *s = &(uip_conn->appstate);
__xdata uint8_t *outbuf = s->outbuf;
write_char('P');
if(uip_connected() && s->tstate == TSTATE_CLOSED) {
@@ -360,66 +66,49 @@ 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 (slen > uip_mss()) {
slen -= uip_mss();
o_idx += uip_mss();
if (s->slen > uip_mss()) {
s->slen -= uip_mss();
s->o_idx += uip_mss();
} else {
slen = 0;
o_idx += slen;
s->slen = 0;
s->o_idx += s->slen;
}
s->tstate = TSTATE_ACKED;
if (slen > uip_mss()) {
print_string("Sending A: "); print_short(slen); write_char('\n');
uip_send(outbuf + o_idx, uip_mss());
if (s->slen > uip_mss()) {
print_string("Sending A: "); print_short(s->slen); write_char('\n');
uip_send(outbuf + s->o_idx, uip_mss());
print_string("Sending A done\n");
s->tstate = TSTATE_TX;
} else if (slen > 0) {
print_string("Sending B: "); print_short(slen); write_char('\n');
uip_send(outbuf + o_idx, slen);
} else if (s->slen > 0) {
print_string("Sending B: "); print_short(s->slen); write_char('\n');
uip_send(outbuf + s->o_idx, s->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 (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"))
if (p[0] == 'G' && p[1] == 'E' && p[2] == 'T' && p[3] == ' ')
print_string("GET request ");
p += 4;
__xdata uint8_t *q = p;
while (!is_separator(*p))
while (!is_space(*p))
p++;
*p = '\0';
print_string_x(q);
@@ -429,58 +118,68 @@ void httpd_appcall(void)
entry = find_entry(q);
print_string("Entry is: "); print_byte(entry); write_char('\n');
if (entry == 0xff) {
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();
}
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");
} else {
print_string("Have entry\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");
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");
len_left = f_data[entry].len;
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;
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, "#{");
}
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("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("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());
print_string("Sending a done\n");
} else {
print_string("Sending b: "); print_short(slen); write_char('\n');
uip_send(outbuf + o_idx, slen);
print_string("Sending b: "); print_short(s->slen); write_char('\n');
uip_send(outbuf + s->o_idx, s->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 (slen > uip_mss()) {
print_string("Sending C: "); print_short(slen); write_char('\n');
uip_send(outbuf + o_idx, uip_mss());
if (s->slen > uip_mss()) {
print_string("Sending C: "); print_short(s->slen); write_char('\n');
uip_send(outbuf + s->o_idx, uip_mss());
print_string("Sending C done\n");
} else if (slen > 0) {
print_string("Sending D: "); print_short(slen); write_char('\n');
uip_send(outbuf + o_idx, slen);
} else if (s->slen > 0) {
print_string("Sending D: "); print_short(s->slen); write_char('\n');
uip_send(outbuf + s->o_idx, s->slen);
print_string("Sending D done\n");
}
s->tstate = TSTATE_TX;
+5 -2
View File
@@ -1,5 +1,5 @@
#ifndef __HTTPD_H__
#define __HTTPD_H__
#ifndef __HELLO_WORLD_H__
#define __HELLO_WORLD_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,6 +12,9 @@
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. */
+47 -340
View File
@@ -1,371 +1,78 @@
// #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 struct uip_eth_addr uip_ethaddr;
extern __code uint8_t log_to_phys_port[9];
extern __code uint8_t phys_to_log_port[6];
extern __code uint8_t ownMAC[];
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 PUTC(c) *outbuf++ = c;
__code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
#define PUTBYTE(a) { *outbuf++ = hex[(a >> 4) & 0xf]; *outbuf++ = hex[a & 0xf]; }
/* 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)
inline uint8_t itoa_html(uint8_t v, __xdata uint8_t *outbuf)
{
outbuf[slen++] = itohex(c);
}
// 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);
uint8_t t = (v / 100) % 10;
if (t)
PUTC('0' + t);
t = (v / 10) % 10;
print_zeros |= t;
if (print_zeros)
char_to_html('0' + t);
char_to_html('0' + (v % 10));
if (t)
PUTC('0' + t);
PUTC('0' + (v % 10));
if (v >= 100)
return 3;
else if (v >= 10)
return 2;
else
return 1;
}
uint16_t stat_content(void)
uint16_t stat_content(__xdata uint8_t *outbuf)
{
print_string("stat_content called\n");
return 0;
}
uint16_t port_status(void)
uint16_t port_status(__xdata uint8_t *outbuf)
{
print_string("port_status called\n");
return 0;
}
/* Converts sfr_data[] into raw hex string.
Suppress leading zeros.
*/
void sfr_data_to_html(void)
uint16_t html_index(__xdata uint8_t *outbuf)
{
uint8_t print_zeros = 0;
uint8_t val = 0;
__xdata uint8_t *oldptr = outbuf;
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(']');
}
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;
}
-11
View File
@@ -1,11 +0,0 @@
#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
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/python
import re
import sys
-42
View File
@@ -1,42 +0,0 @@
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)
-26
View File
@@ -1,26 +0,0 @@
.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
-375
View File
@@ -1,375 +0,0 @@
#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);
}
-271
View File
@@ -1,271 +0,0 @@
/*
* 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;
}
-36
View File
@@ -1,36 +0,0 @@
#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
+1 -33
View File
@@ -4,28 +4,10 @@
#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
@@ -41,11 +23,6 @@
// 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.
@@ -54,11 +31,6 @@ 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];
@@ -69,10 +41,8 @@ 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_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_write(uint16_t phy_mask, 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);
@@ -84,7 +54,6 @@ 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);
@@ -95,5 +64,4 @@ 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
+172 -106
View File
@@ -10,20 +10,8 @@
__xdata uint8_t dio_enabled;
__xdata uint8_t markbuf[16];
extern __xdata uint16_t mpos;
__xdata struct flash_region_t flash_region;
// 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
#pragma codeseg BANK1
/*
* Configure Memory Managed IO
@@ -33,14 +21,14 @@ void flash_configure_mmio(void)
// Set configuration for MMIO access by controller
if (dio_enabled) {
SFR_FLASH_MODEB = 0x18;
SFR_FLASH_CMD_R = CMD_FREAD_DIO; // By default we read with Dual speed
SFR_FLASH_DUMMYCYCLES = 4;
SFR_FLASH_CMD_R = 0xbb; // By default we read with Dual speed
SFR_FLASH_DUMMYCICLES = 4;
return;
}
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = CMD_FREAD; // Default is Single IO
SFR_FLASH_DUMMYCYCLES = 8;
SFR_FLASH_CMD_R = 0xb; // By default we read with single speed
SFR_FLASH_DUMMYCICLES = 8;
}
@@ -51,26 +39,27 @@ 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)
void flash_init(uint8_t enable_dio) __banked
{
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 = CMD_FREAD_DIO;
SFR_FLASH_CONF_RCMD = 0xbb;
SFR_FLASH_CONF_DIV = 4;
} else {
// Configure fast read via divider = 8 and read-cmd being CMD_FREAD (for mmio)
// Configure fast read via divider = 8 and read-cmd being 0xb (for mmio)
SFR_FLASH_CONFIG = 9;
SFR_FLASH_CONF_RCMD = CMD_FREAD;
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_DUMMYCICLES = 8;
SFR_FLASH_MODEB = 0;
SFR_FLASH_TCONF = 0x19;
SFR_FLASH_CMD = CMD_WRITE_STATUS;
SFR_FLASH_CMD = 1;
SFR_FLASH_DATA0 = 0;
SFR_FLASH_EXEC_GO = 1;
while(SFR_FLASH_EXEC_BUSY);
@@ -97,14 +86,14 @@ uint8_t flash_read_status(void)
}
void flash_read_uid(void)
void flash_read_uid(void) __banked
{
while (flash_read_status() & 0x1);
// Set slow read mode for UID
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = CMD_READ_UNIQUE_ID;
SFR_FLASH_DUMMYCYCLES = 8;
SFR_FLASH_CMD_R = 0x4b;
SFR_FLASH_DUMMYCICLES = 8;
// Transfer 4 bytes (command + 3 dummy bytes)
SFR_FLASH_TCONF = 4;
@@ -121,7 +110,7 @@ void flash_read_uid(void)
print_byte(SFR_FLASH_DATA24);
SFR_FLASH_EXEC_GO = 1;
SFR_FLASH_DUMMYCYCLES = 24;
SFR_FLASH_DUMMYCICLES = 24;
while(SFR_FLASH_EXEC_BUSY);
print_byte(SFR_FLASH_DATA0);
@@ -133,14 +122,14 @@ void flash_read_uid(void)
}
void flash_read_jedecid(void)
void flash_read_jedecid(void) __banked
{
while (flash_read_status() & 0x1);
// Set read mode for JEDEC ID
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = CMD_READ_JEDEC_ID;
SFR_FLASH_DUMMYCYCLES = 0;
SFR_FLASH_CMD_R = 0x9f;
SFR_FLASH_DUMMYCICLES = 0;
// Transfer 3 bytes back
SFR_FLASH_TCONF = 0x13;
@@ -155,12 +144,12 @@ void flash_read_jedecid(void)
// Reset slow read mode
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = CMD_FREAD;
SFR_FLASH_DUMMYCYCLES = 8;
SFR_FLASH_CMD_R = 0xb;
SFR_FLASH_DUMMYCICLES = 8;
}
void flash_write_enable(void)
void flash_write_enable(void) __banked
{
short status;
@@ -168,16 +157,14 @@ void flash_write_enable(void)
do {
status = flash_read_status();
} while (status & 0x1);
// while (flash_read_status() & 0x1);
SFR_FLASH_TCONF = 0x18;
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_CMD = 6;
/* The following is explicitly set for SIO, is this necessary?:
SFR_FLASH_DUMMYCYCLES = 0;
SFR_FLASH_MODEB = 0;
*/
SFR_FLASH_EXEC_GO = 1;
// Wait for write status enabled
@@ -187,7 +174,7 @@ void flash_write_enable(void)
}
void flash_dump(uint8_t len)
void flash_dump(register uint32_t addr, register uint8_t len) __banked
{
short status;
do {
@@ -198,20 +185,20 @@ void flash_dump(uint8_t len)
// Set fast read mode
if (dio_enabled) {
SFR_FLASH_MODEB = 0x18;
SFR_FLASH_CMD_R = CMD_FREAD_DIO;
SFR_FLASH_DUMMYCYCLES = 4;
SFR_FLASH_CMD_R = 0xbb;
SFR_FLASH_DUMMYCICLES = 4;
} else {
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = CMD_FREAD; // Fast read
SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks after read?
SFR_FLASH_CMD_R = 0xb; // Fast read
SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks after read?
}
// Read 4 bytes
SFR_FLASH_TCONF = 4;
while (len) {
SFR_FLASH_ADDR16 = flash_region.addr >> 16;
SFR_FLASH_ADDR8 = flash_region.addr >> 8;
SFR_FLASH_ADDR0 = flash_region.addr;
flash_region.addr += 4;
SFR_FLASH_ADDR16 = addr >> 16;
SFR_FLASH_ADDR8 = addr >> 8;
SFR_FLASH_ADDR0 = addr;
addr += 4;
SFR_FLASH_EXEC_GO = 1;
while(SFR_FLASH_EXEC_BUSY);
@@ -235,7 +222,7 @@ void flash_dump(uint8_t len)
* 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(__xdata uint8_t *dst)
void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, register uint16_t len) __banked
{
short status;
do {
@@ -245,112 +232,193 @@ void flash_read_bulk(__xdata uint8_t *dst)
// Set fast read mode
if (dio_enabled) {
SFR_FLASH_MODEB = 0x18;
SFR_FLASH_CMD_R = CMD_FREAD_DIO;
SFR_FLASH_DUMMYCYCLES = 4;
SFR_FLASH_CMD_R = 0xbb;
SFR_FLASH_DUMMYCICLES = 4;
} else {
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = CMD_READ;
SFR_FLASH_DUMMYCYCLES = 0;
SFR_FLASH_CMD_R = 0xb; // Fast read
SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks after read?
}
// Read 4 bytes
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;
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 (flash_region.len == 1)
break;
if (len == 1)
return;
*dst++ = SFR_FLASH_DATA8;
if (flash_region.len == 2)
break;
if (len == 2)
return;
*dst++ = SFR_FLASH_DATA16;
if (flash_region.len == 3)
break;
if (len == 3)
return;
*dst++ = SFR_FLASH_DATA24;
if (flash_region.len == 4)
break;
flash_region.len -= 4;
len -= 4;
}
}
void flash_read_security()
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
{
while (flash_read_status() & 0x1);
// Set slow read mode
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = CMD_READ_SECURITY_REGS; // read security register
SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks as for fast read
SFR_FLASH_CMD_R = 0x48; // read security register
SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks as for fast read
// Transfer 4 bytes (command + 3byte address)
SFR_FLASH_TCONF = 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;
while (len) {
SFR_FLASH_ADDR16 = addr >> 16;
SFR_FLASH_ADDR8 = addr >> 8;
SFR_FLASH_ADDR0 = addr;
addr += 4;
SFR_FLASH_EXEC_GO = 1;
while(SFR_FLASH_EXEC_BUSY);
print_byte(SFR_FLASH_DATA0);
if (flash_region.len == 1)
break;
if (len == 1)
return;
print_byte(SFR_FLASH_DATA8);
if (flash_region.len == 2)
break;
if (len == 2)
return;
print_byte(SFR_FLASH_DATA16);
if (flash_region.len == 3)
break;
if (len == 3)
return;
print_byte(SFR_FLASH_DATA24);
flash_region.len -= 4;
} while(flash_region.len);
len -= 4;
}
}
void flash_sector_erase(void)
void flash_block_erase(uint32_t addr) __banked
{
flash_write_enable();
SFR_FLASH_TCONF = 8;
SFR_FLASH_CMD = CMD_SECTOR_ERASE;
SFR_FLASH_CMD = 0x20;
SFR_FLASH_ADDR16 = flash_region.addr >> 16;
SFR_FLASH_ADDR8 = flash_region.addr >> 8;
SFR_FLASH_ADDR0 = flash_region.addr;
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 uint8_t *ptr)
void flash_write_bytes(__xdata uint32_t addr, __xdata uint8_t *ptr, uint16_t len) __banked
{
write_char('>'); print_long(flash_region.addr); write_char(':'); print_short(flash_region.len); write_char('-'); print_byte(*ptr); write_char('\n');
static __xdata uint8_t exit_loop = 0;
while(1) {
flash_write_enable();
SFR_FLASH_CMD = CMD_PAGE_PROGRAM;
SFR_FLASH_TCONF = 0x40 | 8 | 4; // Bytes written is 4, 8 enables write, 0x40 is unknown
SFR_FLASH_CMD = 2;
SFR_FLASH_TCONF = 0x40 | 8 | 2; // Bytes written is is 4, 8 enables write, 0x2 is unkown
// Last transfer?
if (flash_region.len < 5) {
SFR_FLASH_TCONF = 8 | flash_region.len;
if (len < 5) {
SFR_FLASH_TCONF = 8 | len;
exit_loop = 1;
}
SFR_FLASH_ADDR16 = flash_region.addr >> 16;
SFR_FLASH_ADDR8 = flash_region.addr >> 8;
SFR_FLASH_ADDR0 = flash_region.addr;
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++;
@@ -358,13 +426,11 @@ void flash_write_bytes(__xdata uint8_t *ptr)
// Execute transfer, we wait for completion at top of loop
SFR_FLASH_EXEC_GO = 1;
if (flash_region.len < 5)
if (exit_loop)
break;
flash_region.len -= 4;
flash_region.addr += 4;
};
len -= 4;
addr += 4;
}
while (flash_read_status() & 0x1);
flash_configure_mmio();
+10 -9
View File
@@ -1,13 +1,14 @@
#ifndef _RTL837X_FLASH_H_
#define _RTL837X_FLASH_H_
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);
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;
#endif
-57
View File
@@ -1,57 +0,0 @@
/*
* 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)
}
-9
View File
@@ -1,9 +0,0 @@
#ifndef _RTL837X_IGMP_H_
#define _RTL837X_IGMP_H_
#include <stdint.h>
void igmp_setup(void) __banked;
void igmp_enable(void) __banked;
#endif
+95 -69
View File
@@ -6,18 +6,13 @@
#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];
@@ -71,12 +66,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(RTL8224_PHY_ID, 0x1e, 0xa90);
pval = SFR_DATA_U16;
phy_read(0, 0x1e, 0xa90);
uint16_t pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0;
// PHY Initialization:
REG_WRITE(0x2f8, 0, 0, pval >> 8, pval);
@@ -85,65 +80,108 @@ void rtl8224_phy_enable(void) __banked
pval |= 0x0c;
REG_WRITE(0x2f4, 0, 0, pval >> 8, pval);
phy_write(RTL8224_PHY_ID, 0x1e, 0xa90, pval);
delay(50);
phy_write(0x1, 0x1e, 0xa90, pval);
phy_read(0, 0x1e, 0xa90);
pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0;
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_modify(phy, 0x1e, 0x75f3, 0x0001, 0x0000);
// 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);
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_modify(phy, 0x1e, 0x697a, 0x003f, 0x0001);
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);
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_modify(phy, 0x1f, 0xa432, 0x0000, 0x0020);
phy_read(phy, 0x1f, 0xa432);
pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0 | 0x20;
phy_write(bit_mask[phy], 0x1f, 0xa432, pval);
// 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_modify(phy, 0x7, 0x3e, 0x0000, 0x0001);
phy_read(phy, 0x7, 0x3e);
pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0 | 0x1;
phy_write(bit_mask[phy], 0x7, 0x3e, pval);
delay(20);
// p031f.a442:043c P000008.1f00a442:0430
// p031f.a442:043c P000008.1f00a442:0430
// Unknown, but clear bits 2/3
phy_modify(phy, 0x1f, 0xa442, 0x0006, 0x0000);
phy_read(phy, 0x1f, 0xa442);
pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0 & 0xf3;
phy_write(bit_mask[phy], 0x1f, 0xa442, pval);
delay(20);
// P000100.1e0075b5:e084
phy_write(phy, 0x1e, 0x75b5, 0xe084);
phy_write(bit_mask[phy], 0x1e, 0x75b5, 0xe084);
delay(20);
// p031e.75b2:0000 P000008.1e0075b2:0060
// p031e.75b2:0000 P000008.1e0075b2:0060
// set bits 5/6
phy_modify(phy, 0x1e, 0x75b2, 0x0000, 0x0060);
phy_read(phy, 0x1e, 0x75b2);
pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0 | 0x60;
phy_write(bit_mask[phy], 0x1e, 0x75b2, pval);
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_modify(phy, 0x1e, 0xd040, 0x0300, 0x0200);
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);
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_modify(phy, 0x1f, 0xa400, 0x0000, 0x4000);
phy_read(phy, 0x1f, 0xa400);
pval = SFR_DATA_8 | 0x40;
pval <<= 8;
pval |= SFR_DATA_0;
phy_write(bit_mask[phy], 0x1f, 0xa400, pval);
delay(20);
phy_modify(phy, 0x1f, 0xa400, 0x4000, 0x0000);
phy_read(phy, 0x1f, 0xa400);
pval = SFR_DATA_8 & 0xbf;
pval <<= 8;
pval |= SFR_DATA_0;
phy_write(bit_mask[phy], 0x1f, 0xa400, pval);
delay(20);
print_string("\r\n phy config done\r\n");
@@ -152,28 +190,29 @@ 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");
// p001e.7b20:0bff R02f8-00000bff R02f4-00000bed P000001.1e007b20:0bed
phy_read(RTL8224_PHY_ID, 0x1e, 0x7b20);
pval = SFR_DATA_U16;
phy_read(0, 0x1e, 0x7b20);
pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0;
REG_WRITE(0x2f8, 0, 0, pval >> 8, pval);
pval &= 0x0fe0;
pval |= 0x000d;
REG_WRITE(0x2f4, 0, 0, pval >> 8, pval);
phy_write(RTL8224_PHY_ID, 0x1e, 0x7b20, pval);
phy_write(0x01, 0x1e, 0x7b20, pval);
uint8_t i = 0;
while (rtl8224_ca[i]) {
phy_write(RTL8224_PHY_ID, 0x1e, 0x400, rtl8224_ca[i]);
phy_write(0x1, 0x1e, 0x400, rtl8224_ca[i]);
i++;
phy_write(RTL8224_PHY_ID, 0x1e, 0x3f8, rtl8224_ca[i]);
phy_write(0x1, 0x1e, 0x3f8, rtl8224_ca[i]);
i++;
do {
phy_read(RTL8224_PHY_ID, 0x1e, 0x3f8);
phy_read(0, 0x1e, 0x3f8);
} while (SFR_DATA_8 & 0x80);
}
@@ -189,54 +228,41 @@ 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 = SFR_DATA_U16;
v = (((uint16_t)SFR_DATA_8) << 8) | SFR_DATA_0;
if (speed == PHY_OFF) {
phy_write(port, 0x1f, 0xa610, v | 0x0800);
phy_write(bit_mask[port], 0x1f, 0xa610, v | 0x0800);
return;
}
// Port is on, make sure of it:
if (v & 0x0800)
phy_write(port, 0x1f, 0xa610, v & 0xf7ff);
phy_write(bit_mask[port], 0x1f, 0xa610, v & 0xf7ff);
if (speed == PHY_SPEED_AUTO) {
// AN Advertisement Register (MMD 7.0x0010)
phy_write(port, PHY_MMD_AN, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
phy_write(bit_mask[port], 0x07, 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(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
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
} else {
// AN Control Register (MMD 7.0x0000)
phy_write(port, PHY_MMD_AN, 0x00, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13)
phy_write(bit_mask[port], 0x07, 0x00, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13)
// AN Advertisement Register (MMD 7.0x0010)
phy_write(port, PHY_MMD_AN, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
phy_write(bit_mask[port], 0x07, 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(port, PHY_MMD_AN, 0x20, 0x6001); // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed
phy_write(bit_mask[port], 0x07, 0x20, 0x6001); // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
phy_modify(port, 0x1f, 0xa412, 0x0000, 0x02000);
phy_read(port, 0x1f, 0xa412);
v = (((uint16_t)SFR_DATA_8) << 8) | SFR_DATA_0;
phy_write(bit_mask[port], 0x1f, 0xa412, v | 0x0200);
} else if (speed == PHY_SPEED_2G5) {
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
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(bit_mask[port], 0x07, 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_modify(port, 0x1f, 0xa412, 0x02000, 0x0000);
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_write(port, PHY_MMD_AN, 0x00, 0x3200); // Enable AN
phy_write(bit_mask[port], 0x07, 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);
}
-1
View File
@@ -10,6 +10,5 @@ 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
+42 -227
View File
@@ -10,42 +10,21 @@
#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
{
@@ -104,41 +83,6 @@ 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
*/
@@ -179,10 +123,6 @@ 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);
@@ -279,21 +219,19 @@ void trunk_set(uint8_t group, uint16_t mask) __banked
uint8_t port_l2_forget(void) __banked
{
print_string("\nport_l2_forget called\n");
// 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);
// 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);
// 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]);
// Wait for flush completed
reg_read_m(RTL837x_L2_TBL_CTRL);
REG_WRITE(RTL837x_L2_TBL_CTRL, 0x00, 0x01, sfr_data[2], sfr_data[3]);
do {
reg_read_m(RTL837x_L2_TBL_FLUSH_CTRL);
} while (sfr_data[1]);
reg_read_m(RTL837x_L2_TBL_CTRL);
} while (sfr_data[1] & 0x1);
print_string("port_l2_forget done\n");
return 0;
@@ -370,22 +308,24 @@ void port_l2_learned(void) __banked
/*
* Basic L2 configuration such as time to forget an entry
*/
void port_l2_setup(void) __banked
void port_l2_setup() __banked
{
print_string("\nport_l2_setup called\n");
port_l2_forget();
REG_SET(0x53dc, 0x00000000);
if(isRTL8373) {
REG_SET(0x53d4, 0x000101ff);
} else {
REG_SET(0x53d4, 0x000001f8);
}
for (uint8_t i = minPort; i <= maxPort; i++) {
uint16_t reg = 0x5384 + (i << 2);
REG_SET(reg, 0x00001040);
// All ports may communicate with each other and CPU-Port
reg = RTL837X_PORT_ISOLATION_BASE + (i << 2);
reg = 0x50c0 + (i << 2);
if(isRTL8373) {
REG_SET(reg, PMASK_9 | PMASK_CPU);
REG_SET(reg, 0x3ff);
} else {
REG_SET(reg, PMASK_6 | PMASK_CPU);
REG_SET(reg, 0x3f8);
}
}
reg_bit_set(0x4f80, 0);
@@ -426,13 +366,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_00_31_INPUT);
reg_read_m(RTL837X_REG_GPIO_B);
if (!(sfr_data[0] & 0x40)) {
print_string("SFP OK\t");
} else {
print_string("NO SFP\t");
}
reg_read_m(RTL837X_REG_GPIO_32_63_INPUT);
reg_read_m(RTL837X_REG_GPIO_C);
if (sfr_data[3] & 0x20) {
print_string("Down\t");
} else {
@@ -447,153 +387,28 @@ void port_stats_print(void) __banked
print_string("Up\t");
}
}
STAT_GET(0x2f, i);
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
print_reg(RTL837X_STAT_V_LOW); write_char('\t');
STAT_GET(0x30, i);
print_reg(RTL837X_STAT_V_HIGH); write_char('\t');
STAT_GET(0x2e, i);
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');
STAT_GET(0x30, i);
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);
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
}
+2 -22
View File
@@ -1,36 +1,16 @@
#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(register uint16_t vlan, register uint16_t members, register uint16_t tagged) __banked;
void vlan_create(uint16_t vlan, uint16_t members, 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(void) __banked;
void port_l2_setup() __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
+14 -66
View File
@@ -39,46 +39,30 @@
5: 2.5Gbit
*/
/*
* 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
#define RTL837X_REG_GPIO_A 0x40
// BIT 4 resets RTL8224 on 9000-9XH
// Input Registers
#define RTL837X_REG_GPIO_00_31_INPUT 0x44
#define RTL837X_REG_GPIO_32_63_INPUT 0x48
#define RTL837X_REG_GPIO_B 0x44
// 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)
// Direction Registers, 0 = input, 1 = output
#define RTL837X_REG_GPIO_00_31_DIRECTION 0x4c
#define RTL837X_REG_GPIO_32_63_DIRECTION 0x50
#define RTL837X_REG_GPIO_CONF_A 0x50
// Configures IO direction for bank a
#define RTL837X_REG_GPIO_EXT 0x63e8
/*
* I2C controller
*/
#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
@@ -106,18 +90,14 @@
#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
*/
@@ -139,43 +119,11 @@
#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 = (((uint32_t)v) >> 24) & 0xff; \
SFR_DATA_16 = (((uint32_t)v) >> 16) & 0xff; \
SFR_DATA_8 = (((uint16_t)v) >> 8 & 0xff); \
#define REG_SET(r, v) SFR_DATA_24 = ((v) >> 24) & 0xff; \
SFR_DATA_16 = ((v) >> 16) & 0xff; \
SFR_DATA_8 = ((v) >> 8 & 0xff); \
SFR_DATA_0 = (v) & 0xff; \
reg_write(r); \
write_char('R'); print_byte(r >> 8); print_byte(r); write_char('-'); \
@@ -188,9 +136,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 = (((uint32_t)v) >> 24) & 0xff; \
SFR_DATA_16 = (((uint32_t)v) >> 16) & 0xff; \
SFR_DATA_8 = (((uint16_t)v) >> 8 & 0xff); \
#define REG_SET(r, v) SFR_DATA_24 = ((v) >> 24) & 0xff; \
SFR_DATA_16 = ((v) >> 16) & 0xff; \
SFR_DATA_8 = ((v) >> 8 & 0xff); \
SFR_DATA_0 = (v) & 0xff; \
reg_write(r);
+1 -8
View File
@@ -1,12 +1,8 @@
/* 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;
@@ -21,7 +17,6 @@ __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;
@@ -71,7 +66,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_DUMMYCYCLES;
__sfr __at(0x9d) SFR_FLASH_DUMMYCICLES;
__sfr __at(0x9a) SFR_FLASH_MODEB;
__sfr __at(0x9e) SFR_FLASH_TCONF;
@@ -91,9 +86,7 @@ __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
View File
@@ -1,252 +0,0 @@
/*
* 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);
}
-12
View File
@@ -1,12 +0,0 @@
#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
+109 -294
View File
@@ -1,6 +1,9 @@
#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
@@ -10,19 +13,11 @@
#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
@@ -53,6 +48,7 @@ __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};
@@ -61,24 +57,16 @@ __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[512];
__xdata uint8_t flash_buf[256];
// NIC buffers for packet RX/TX
__xdata uint8_t rx_headers[16]; // Packet header(s) on RX
@@ -91,7 +79,6 @@ __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,
@@ -104,8 +91,6 @@ __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
@@ -203,6 +188,9 @@ 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;
}
@@ -295,7 +283,8 @@ void setup_timer0(void)
void reg_read(uint16_t reg_addr)
{
SFR_REG_ADDR_U16 = reg_addr;
SFR_REG_ADDRH = reg_addr >> 8;
SFR_REG_ADDRL = reg_addr;
SFR_EXEC_GO = SFR_EXEC_READ_REG;
do {
} while (SFR_EXEC_STATUS != 0);
@@ -308,7 +297,8 @@ 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_ADDR_U16 = reg_addr;
SFR_REG_ADDRH = reg_addr >> 8;
SFR_REG_ADDRL = reg_addr;
SFR_EXEC_GO = SFR_EXEC_READ_REG;
do {
} while (SFR_EXEC_STATUS != 0);
@@ -325,7 +315,8 @@ 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_ADDR_U16 = reg_addr;
SFR_REG_ADDRH = reg_addr >> 8;
SFR_REG_ADDRL = reg_addr;
SFR_EXEC_GO = SFR_EXEC_WRITE_REG;
do {
} while (SFR_EXEC_STATUS != 0);
@@ -340,7 +331,8 @@ 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_ADDR_U16 = reg_addr;
SFR_REG_ADDRH = reg_addr >> 8;
SFR_REG_ADDRL = reg_addr;
SFR_DATA_24 = sfr_data[0] ;
SFR_DATA_16 = sfr_data[1];
SFR_DATA_8 = sfr_data[2];
@@ -381,7 +373,7 @@ void reg_bit_clear(uint16_t reg_addr, char bit)
}
/*
* This masks the sfr data fields, first &-ing with ~mask, then setting the bits in set
* This masks the sfr data fields, first &-ing with ~mask, the setting the bits in set
*/
void sfr_mask_data(uint8_t n, uint8_t mask, uint8_t set)
{
@@ -391,16 +383,6 @@ 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
@@ -410,8 +392,10 @@ void sfr_set_zero(void) {
void nic_rx_header(uint16_t ring_ptr)
{
uint16_t buffer = (uint16_t) &rx_headers[0];
SFR_NIC_DATA_U16LE = buffer;
SFR_NIC_RING_U16LE = 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_CTRL = 1;
do { } while (SFR_NIC_CTRL != 0);
}
@@ -425,9 +409,10 @@ void nic_rx_header(uint16_t ring_ptr)
*/
void nic_rx_packet(register uint16_t buffer, register uint16_t ring_ptr)
{
SFR_NIC_DATA_U16LE = buffer;
SFR_NIC_RING_U16LE = 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;
uint16_t len = (((uint16_t)rx_headers[5]) << 8) | rx_headers[4];
len += 7;
len >>= 3;
@@ -447,12 +432,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_U16LE = buffer;
SFR_NIC_DATA_H = buffer >> 8;
SFR_NIC_DATA_L = buffer;
ring_ptr <<= 3;
ring_ptr |= 0x8000;
SFR_NIC_RING_U16LE = ring_ptr;
SFR_NIC_RING_L = ring_ptr;
SFR_NIC_RING_H = ring_ptr >> 8;
uint16_t len = (((uint16_t)uip_buf[VLAN_TAG_SIZE + 5]) << 8) | uip_buf[VLAN_TAG_SIZE + 4];
len += 0xf;
len >>= 3;
@@ -521,7 +506,8 @@ 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_U16 = v;
SFR_DATA_8 = v >> 8;
SFR_DATA_0 = v;
SFR_93 = reg;
SFR_94 = page << 1 | sds_id;
SFR_EXEC_GO = SFR_EXEC_WRITE_SDS;
@@ -725,11 +711,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, 0xfc, SCL_PIN << 5 | SDA_PIN_0 << 2);
sfr_mask_data(1, 0xff, 0x72);
reg_write_m(RTL837X_REG_I2C_CTRL);
} else {
reg_read_m(RTL837X_REG_I2C_CTRL);
sfr_mask_data(1, 0xfc, SCL_PIN << 5 | SDA_PIN_1 << 2);
sfr_mask_data(1, 0xff, 0x6e);
reg_write_m(RTL837X_REG_I2C_CTRL);
}
@@ -754,7 +740,8 @@ uint8_t sfp_read_reg(uint8_t slot, uint8_t reg)
*/
void tcpip_output(void)
{
// Add TX-TAG
__xdata uint8_t *ptr = &uip_buf[0];
// Add RTL-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;
@@ -765,15 +752,12 @@ 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(uip_buf[i]);
print_byte(*ptr++);
write_char(' ');
}
write_char('\n');
#endif
*/
// Move data over from xmem buffer to ASIC side using DMA
nic_tx_packet(ring_ptr);
@@ -796,8 +780,9 @@ void handle_rx(void)
ring_ptr |= sfr_data[3];
ring_ptr <<= 3;
nic_rx_header(ring_ptr);
#ifdef RXTXDBG
__xdata uint8_t *ptr = rx_headers;
#ifdef RXTXDBG
print_string("RX on port "); print_byte(rx_headers[3] & 0xf);
print_string(": ");
for (uint8_t i = 0; i < 8; i++) {
@@ -819,8 +804,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[ETHERTYPE_OFFSET]); write_char('<');
// write_char('>'); print_byte(uip_buf[ETHERTYPE_OFFSET + 1]); write_char('<');
// 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('<');
// Check for ARP packet
rx_packet_vlan = uip_buf[12 + RTL_TAG_SIZE + 2] & 0xf;
rx_packet_vlan <<= 8;
@@ -828,19 +813,12 @@ void handle_rx(void)
#ifdef RXTXDBG
print_string(" RX-VLAN: "); print_short(rx_packet_vlan); write_char('\n');
#endif
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?
if (uip_buf[12 + VLAN_TAG_SIZE + RTL_TAG_SIZE] == 0x08 && uip_buf[13 + VLAN_TAG_SIZE + RTL_TAG_SIZE] == 0x06) {
uip_arp_arpin();
if (uip_len) {
tcpip_output();
}
} else if (uip_buf[ETHERTYPE_OFFSET] == 0x08 && uip_buf[ETHERTYPE_OFFSET + 1] == 0x00) {
} else if (uip_buf[12 + VLAN_TAG_SIZE + RTL_TAG_SIZE] == 0x08 && uip_buf[13 + VLAN_TAG_SIZE + RTL_TAG_SIZE] == 0x00) {
uip_arp_ipin();
uip_input();
if (uip_len) {
@@ -891,7 +869,7 @@ void sfp_print_info(uint8_t sfp)
void handle_sfp(void)
{
reg_read_m(RTL837X_REG_GPIO_00_31_INPUT);
reg_read_m(RTL837X_REG_GPIO_B);
if ((sfp_pins_last & 0x1) && (!(sfr_data[0] & 0x40))) {
sfp_pins_last &= ~0x01;
print_string("\n<MODULE INSERTED> ");
@@ -911,7 +889,7 @@ void handle_sfp(void)
print_string("\n<MODULE REMOVED>\n");
}
reg_read_m(RTL837X_REG_GPIO_32_63_INPUT);
reg_read_m(RTL837X_REG_GPIO_C);
if ((sfp_pins_last & 0x2) && (!(sfr_data[3] & 0x20))) {
sfp_pins_last &= ~0x02;
print_string("\n<SFP-RX OK>\n");
@@ -921,7 +899,7 @@ void handle_sfp(void)
print_string("\n<SFP-RX LOS>\n");
}
reg_read_m(RTL837X_REG_GPIO_32_63_INPUT);
reg_read_m(RTL837X_REG_GPIO_C);
if ((sfp_pins_last & 0x10) && (!(sfr_data[1] & 0x04))) {
sfp_pins_last &= ~0x10;
print_string("\n<MODULE 2 INSERTED> ");
@@ -1007,7 +985,7 @@ void idle(void)
handle_sfp();
/* Button pressed on KL-8xhm-x2:
reg_read(RTL837X_REG_GPIO_32_63_INPUT);
reg_read(RTL837X_REG_GPIO_C);
if (!(sfr_data[2] & 0x40))
print_string("Button pressed\n");
*/
@@ -1015,22 +993,6 @@ 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> ");
}
}
@@ -1050,7 +1012,6 @@ void sleep(uint16_t t)
void reset_chip(void)
{
REG_SET(RTL837X_REG_RESET, 1);
while(1);
}
@@ -1073,12 +1034,12 @@ void setup_external_irqs(void)
void rtl8224_enable(void)
{
// Set Pin 4 low
reg_bit_clear(RTL837X_REG_GPIO_32_63_OUTPUT, 4);
reg_bit_clear(RTL837X_REG_GPIO_A, 4);
// Configure Pin as output
reg_bit_set(RTL837X_REG_GPIO_32_63_DIRECTION, 4);
reg_bit_set(RTL837X_REG_GPIO_CONF_A, 4);
delay(100);
// Set pin 4 high
reg_bit_set(RTL837X_REG_GPIO_32_63_OUTPUT, 4);
reg_bit_set(RTL837X_REG_GPIO_A, 4);
delay(500);
}
@@ -1094,50 +1055,31 @@ void setup_clock(void)
// Divider in bits 4 & 5
sfr_mask_data(0, 0, CLOCK_DIV << 4);
#endif
// Bit 8 is set in managed mode 125MHz to use fast SPI mode
// This is set in managed mode 125MHz
sfr_mask_data(1, 0, 0x01);
reg_write_m(RTL837X_REG_HW_CONF);
// Enable serial interface, set bit 0
reg_read_m(RTL837X_PIN_MUX_1);
reg_read_m(0x7f90);
sfr_mask_data(0, 0x1, 0x1);
reg_write_m(RTL837X_PIN_MUX_1);
reg_write_m(0x7f90);
}
/*
* Write a register reg of multipule phys, using a mask to select them, in page page
* Write a register reg of phy phy_id, in page page
* Data to be written is in v
*/
void phy_write_mask(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v)
void phy_write(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_U16 = v; // SFR_A6, SFR_A7
SFR_DATA_8 = v >> 8; // SFR_A6
SFR_DATA_0 = v; // 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 {
} 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_REG_H = reg >> 8; // SFR_C2
SFR_SMI_REG_L = reg; // 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 {
@@ -1155,8 +1097,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_U16 = reg; // c2, c2
SFR_SMI_REG_H = reg >> 8; // c3
SFR_SMI_REG_L = reg; // c2
SFR_SMI_PHY = phy_id; // a5
SFR_SMI_DEV = dev_id << 3 | 2; // c4
@@ -1168,41 +1110,6 @@ 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)
{
@@ -1217,21 +1124,22 @@ void nic_setup(void)
// R7844-000007fe
REG_SET(0x7844, 0x7fe);
// 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);
// r785c:0401201e R785c-0401201e r785c:0401201e R785c-0400201e
// 0x785c: Set bits 24-31 to 0x4, clear bits 16/17:
reg_read_m(0x785c);
sfr_mask_data(3, 0xff, 0x04);
sfr_mask_data(2, 0x03, 0);
reg_write_m(RTL837X_REG_RX_CTRL);
reg_write_m(0x785c);
// Enable NIC TX (set bit 0)
reg_bit_set(RTL837X_REG_TX_CTRL, 0);
// Set bit 0 of 0x7860:
// r7860:00000000 R7860-00000001
reg_bit_set(0x7860, 0);
// Enable NIC RX (set bit 0)
reg_bit_set(RTL837X_REG_RX_CTRL, 0);
// r785c:0400201e R785c-0400201f
reg_bit_set(0x785c, 0);
// Drop packets with invalid CRC
reg_bit_clear(RTL837X_REG_RX_CTRL, 2);
// r785c:0400201f R785c-0400201b
reg_bit_clear(0x785c, 2);
// R603c-00000200
REG_SET(0x603c, 0x200);
@@ -1266,7 +1174,9 @@ 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_U16;
uint16_t pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0;
// PHY Initialization:
REG_WRITE(0x2f8, 0, 0, pval >> 8, pval);
@@ -1277,17 +1187,19 @@ void sds_init(void)
REG_WRITE(0x2f4, 0, 0, pval >> 8, pval);
delay(10);
phy_write_mask(0x1, 0x1e, 0xd, pval);
phy_write(0x1, 0x1e, 0xd, pval);
phy_read(0, 0x1e, 0xd);
pval = SFR_DATA_U16;
pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0;
REG_WRITE(0x2f8, 0, 0, pval >> 8, pval);
pval &= 0xfff0;
REG_WRITE(0x2f4, 0, 0, pval >> 8, pval);
phy_write_mask(0x1, 0x1e, 0xd, pval);
phy_write(0x1, 0x1e, 0xd, pval);
}
@@ -1321,7 +1233,7 @@ void led_config_9xh(void)
reg_bit_clear(0x65dc, 0x1b);
// r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000
reg_bit_set(RTL837X_PIN_MUX_0, 0x1b);
reg_bit_set(0x7f8c, 0x1b);
// R6548-0041017f
REG_SET(0x6548, 0x0041017f);
@@ -1373,13 +1285,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(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
reg_bit_set(0x7f8c, 0x1b); // R7f8c-28000000
reg_bit_clear(0x7f8c, 0x1c); // R7f8c-28000000
reg_bit_set(0x7f8c, 0x1d); // R7f8c-28000000
} else {
reg_bit_set(RTL837X_PIN_MUX_0, 0x1d);
reg_bit_set(RTL837X_PIN_MUX_0, 0x1c);
reg_bit_set(RTL837X_PIN_MUX_0, 0x1b);
reg_bit_set(0x7f8c, 0x1d);
reg_bit_set(0x7f8c, 0x1c);
reg_bit_set(0x7f8c, 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
@@ -1462,11 +1374,15 @@ void rtl8373_init(void)
// q000601:c800 Q000601:c804 q000601:c804 Q000601:c800
sds_read(0, 0x06, 0x01);
uint16_t pval = SFR_DATA_U16;
uint16_t pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0;
sds_write_v(0, 0x06, 0x01, pval | 0x04);
delay(50);
sds_read(0, 0x06, 0x01);
pval = SFR_DATA_U16;
pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0;
sds_write_v(0, 0x06, 0x01, pval & 0xfffb);
phy_config_8224();
@@ -1480,7 +1396,9 @@ 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_U16;
pval = SFR_DATA_8;
pval <<= 8;
pval |= SFR_DATA_0;
// r0a90:000000f3 R0a90-000000fc
reg_read_m(0xa90);
@@ -1490,7 +1408,7 @@ void rtl8373_init(void)
rtl8224_phy_enable();
// Disable PHYs for configuration
phy_write_mask(0xff,0x1f,0xa610,0x2858);
phy_write(0xff,0x1f,0xa610,0x2858);
// Set bits 0x13 and 0x14 of 0x5fd4
// r5fd4:0002914a R5fd4-001a914a
@@ -1518,7 +1436,7 @@ void rtl8373_init(void)
// TODO: patch the PHYs
// Re-enable PHY after configuration
phy_write_mask(0xff,0x1f,0xa610,0x2058);
phy_write(0xff,0x1f,0xa610,0x2058);
// Enables MAC access
// Set bits 0xc-0x14 of 0x632c to 0x1f8, see rtl8372_init
@@ -1582,7 +1500,7 @@ void rtl8372_init(void)
reg_write_m(0xa90);
// Disable PHYs for configuration
phy_write_mask(0xf0,0x1f,0xa610,0x2858);
phy_write(0xf0,0x1f,0xa610,0x2858);
// Set bits 0x13 and 0x14 of 0x5fd4
// r5fd4:0002914a R5fd4-001a914a
@@ -1609,7 +1527,7 @@ void rtl8372_init(void)
// TODO: patch the PHYs
// Re-enable PHY after configuration
phy_write_mask(0xf0,0x1f,0xa610,0x2058);
phy_write(0xf0,0x1f,0xa610,0x2058);
// Enables MAC access
// Set bits 0xc-0x14 of 0x632c to 0x1f8, see rtl8372_init
@@ -1650,23 +1568,21 @@ void setup_serial(void)
void setup_i2c(void)
{
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);
REG_SET(0x0414, 0);
REG_SET(0x0418, 0x00100280);
REG_SET(0x041c, 0);
// HW Control register, enable I2C?
reg_read_m(RTL837X_PIN_MUX_1);
reg_read_m(0x7f90);
sfr_mask_data(3, 0x20, 0x00); // Clear bit 29
sfr_mask_data(0, 0x60, 0x40); // Set bits 5-6 to 0b10
reg_write_m(RTL837X_PIN_MUX_1);
reg_write_m(0x7f90);
}
void bootloader(void)
{
ticks = 0;
stp_clock = STP_TICK_DIVIDER;
sbuf_ptr = 0;
CKCON = 0; // Initial Clock configuration
@@ -1729,76 +1645,6 @@ 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...
@@ -1816,7 +1662,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();
@@ -1841,41 +1687,10 @@ 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) {
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);
}
cmd_parser();
idle(); // Enter Idle mode until interrupt occurs
}
}
+6 -17
View File
@@ -1,23 +1,12 @@
CC = gcc
CCFLAGS = -Wall -o
BUILDDIR = output/
all: create_build_dir $(BUILDDIR)injector $(BUILDDIR)fileadder $(BUILDDIR)httpd_sim $(BUILDDIR)crc_calculator
create_build_dir:
mkdir -p $(BUILDDIR)
all: injector fileadder
clean:
rm -r $(BUILDDIR)
rm *.o
$(BUILDDIR)injector: injector.c
gcc $^ $(CCFLAGS) $@
injector: injector.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
fileadder: fileadder.c
gcc $^ -o $@
-179
View File
@@ -1,179 +0,0 @@
/*
* 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;
}
+20 -26
View File
@@ -19,9 +19,9 @@
char buffer[BUFFER_SIZE];
FILE *inptr, *dataptr, *ofile;
int outptr;
#define PATH_SIZE 20480
#define INDEX_SIZE 20480
#define DEF_SIZE 20480
#define PATH_SIZE 1024
#define INDEX_SIZE 1024
#define DEF_SIZE 1024
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", 0, "Resize image"},
{ "size", 's', "SIZE", OPTION_ARG_OPTIONAL, "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', "SIZE", 0, "Address where data is placed, default is 0x1000000 if option is used, otherwise 0x1fd000"},
{ "address", 'a', 0, OPTION_ARG_OPTIONAL, "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,18 +136,14 @@ int hasSuffix(const char *str, const char *suffix)
char *getMime(const char *name)
{
if (hasSuffix(name, ".html"))
return "mime_HTML";
return "text/html";
else if (hasSuffix(name, ".svg"))
return "mime_SVG";
return "image/svg+xml";
else if (hasSuffix(name, ".ico"))
return "mime_SVG";
return "image/svg+xml";
else if (hasSuffix(name, ".png"))
return "mime_PNG";
else if (hasSuffix(name, ".js"))
return "mime_JS";
else if (hasSuffix(name, ".css"))
return "mime_CSS";
return "mime_TXT";
return "image/png";
return "text/plain";
}
@@ -164,9 +160,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, mime_HTML},\n", s, s);
ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, " {\"/\", FDATA_START_%s, FDATA_SIZE_%s, \"text/html\"},\n", s, s);
return 0;
}
@@ -204,7 +200,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(void);\n", function_buf);
xbuf_p += snprintf(&xbuf[xbuf_p], DEF_SIZE - xbuf_p, "extern uint16_t %s(__xdata uint8_t *outbuf);\n", function_buf);
callNum++;
}
i++;
@@ -216,6 +212,8 @@ 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";
@@ -267,20 +265,16 @@ 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,
"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");
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");
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#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, "#pragma codeseg %s\n", arguments.bank);
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)
@@ -335,7 +329,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) {
-482
View File
@@ -1,482 +0,0 @@
#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;
}
-26
View File
@@ -1,26 +0,0 @@
#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
+6 -11
View File
@@ -3,24 +3,19 @@ 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=$(BUILDDIR)%.rel}
OBJS = ${SRCS:.c=.rel}
all: create_build_dir $(OBJS)
all: $(OBJS)
create_build_dir:
mkdir -p $(BUILDDIR)
%.rel: %.c
$(CC) $(CC_FLAGS) -c $<
$(BUILDDIR)%.rel: %.c
$(CC) $(CC_FLAGS) -o $@ -c $<
$(BUILDDIR)%.rel: $(BUILDDIR)%.asm
%.rel: %.asm
${ASM} ${AFLAGS} $^
clean:
rm -r $(BUILDDIR)
rm *.ihx *.lk *.lst *.map *.mem *.rel *.rst *.sym *.bin
.PHONY: all clean
-1
View File
@@ -48,7 +48,6 @@
#define STATE_DATA_SENT 6
#pragma codeseg BANK1
#pragma constseg BANK1
/*
* Return value of the buffering functions that indicates that a
-1
View File
@@ -49,7 +49,6 @@
#include "timer.h"
#pragma codeseg BANK1
#pragma constseg BANK1
/*---------------------------------------------------------------------------*/
/**
+2 -2
View File
@@ -94,14 +94,14 @@ typedef unsigned short uip_stats_t;
*
* \hideinitializer
*/
#define UIP_CONF_MAX_CONNECTIONS 1
#define UIP_CONF_MAX_CONNECTIONS 3
/**
* Maximum number of listening TCP ports. TODO: increase this!
*
* \hideinitializer
*/
#define UIP_CONF_MAX_LISTENPORTS 1
#define UIP_CONF_MAX_LISTENPORTS 3
/**
* uIP buffer size.
-1
View File
@@ -60,7 +60,6 @@
#include "uip-fw.h"
#pragma codeseg BANK1
#pragma constseg BANK1
#include "../rtl837x_common.h"
+8 -9
View File
@@ -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(__xdata uip_ipaddr_t ipaddr, __xdata struct uip_neighbor_addr *addr)
uip_neighbor_add(uip_ipaddr_t ipaddr, __xdata struct uip_neighbor_addr *addr)
{
uint16_t i, oldest;
int i, oldest;
u8_t oldest_time;
/*
@@ -130,13 +130,12 @@ uip_neighbor_add(__xdata uip_ipaddr_t ipaddr, __xdata struct uip_neighbor_addr *
}
/*---------------------------------------------------------------------------*/
__xdata static struct neighbor_entry *
find_entry(__xdata uip_ipaddr_t ipaddr)
find_entry(uip_ipaddr_t ipaddr)
{
uint16_t i;
int i;
for(i = 0; i < ENTRIES; ++i) {
// if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) {
if (entries[i].ipaddr[0] == ipaddr[0] && entries[i].ipaddr[1] == ipaddr[1]) {
if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) {
return &entries[i];
}
}
@@ -144,7 +143,7 @@ find_entry(__xdata uip_ipaddr_t ipaddr)
}
/*---------------------------------------------------------------------------*/
void
uip_neighbor_update(__xdata uip_ipaddr_t ipaddr)
uip_neighbor_update(uip_ipaddr_t ipaddr)
{
struct neighbor_entry *e;
@@ -155,7 +154,7 @@ uip_neighbor_update(__xdata uip_ipaddr_t ipaddr)
}
/*---------------------------------------------------------------------------*/
__xdata struct uip_neighbor_addr *
uip_neighbor_lookup(__xdata uip_ipaddr_t ipaddr)
uip_neighbor_lookup(uip_ipaddr_t ipaddr)
{
__xdata struct neighbor_entry *e;
+3 -3
View File
@@ -54,9 +54,9 @@ struct uip_neighbor_addr {
};
void uip_neighbor_init(void);
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_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_periodic(void);
#endif /* __UIP-NEIGHBOR_H__ */
+1 -1
View File
@@ -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])
+4 -5
View File
@@ -84,7 +84,6 @@
#include "uip_arch.h"
#pragma codeseg BANK1
#pragma constseg BANK1
#if UIP_CONF_IPV6
#include "uip-neighbor.h"
@@ -398,9 +397,9 @@ uip_init(void) __banked
/*---------------------------------------------------------------------------*/
#if UIP_ACTIVE_OPEN
__xdata struct uip_conn *
uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport)
uip_connect(register __xdata uip_ipaddr_t *ripaddr, register u16_t rport)
{
__xdata struct uip_conn *conn, *cconn;
register __xdata struct uip_conn *conn, *cconn;
/* Find an unused local port. */
again:
@@ -412,7 +411,7 @@ uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport)
/* Check if this port is already in use, and if so try to find
another one. */
for(uint8_t c = 0; c < UIP_CONNS; ++c) {
for(c = 0; c < UIP_CONNS; ++c) {
conn = &uip_conns[c];
if(conn->tcpstateflags != UIP_CLOSED &&
conn->lport == htons(lastport)) {
@@ -421,7 +420,7 @@ uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport)
}
conn = 0;
for(uint8_t c = 0; c < UIP_CONNS; ++c) {
for(c = 0; c < UIP_CONNS; ++c) {
cconn = &uip_conns[c];
if(cconn->tcpstateflags == UIP_CLOSED) {
conn = cconn;
+1 -1
View File
@@ -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, __xdata u16_t port);
__xdata struct uip_conn *uip_connect(register __xdata uip_ipaddr_t *ripaddr, register u16_t port);
-1
View File
@@ -64,7 +64,6 @@
#include "../rtl837x_common.h"
#pragma codeseg BANK1
#pragma constseg BANK1
struct arp_hdr_i {
struct uip_eth_hdr ethhdr;
-1
View File
@@ -38,7 +38,6 @@
#include "uiplib.h"
#pragma codeseg BANK1
#pragma constseg BANK1
/*-----------------------------------------------------------------------------------*/
unsigned char