2 Commits
Author SHA1 Message Date
logicog f8e437f3a4 Makefile: Lower limit of --xram-size to protect ChaCha20 space
ChaCha20 uses 256 bytes starting from 0xbf00 for its calculations.
Make sure the linker checks that this space is not overwritten.
2026-10-17 06:30:16 +02:00
logicog 82dfb8f789 ChaCha20 implementation for encryption
Add an implementation in 8051 assembler for the generation of a
ChaCha20 keystream and an encryption function using the keystream
in C.

A test function using the example from RFC7539 is provided in
chacha20_test.

Keys, nonce, and block counter and the pointers to the input plaintext,
its length and the output pointer are provided via a struct chacha20,
which also holds the working state of the ChaCha20 algorithm
2026-10-17 06:30:14 +02:00
95 changed files with 924 additions and 1702 deletions

No files matched your search

-11
View File
@@ -4,17 +4,6 @@
## Added
- Devices
- Support the hongyavision HYWS-SGT0204S (PCB marking `2G5F4_10G2_V1.01`), an
RTL8372 based 4x2.5G + 2xSFP+ unmanaged switch with a 512 KB Bright Moon
`T25S40` flash. It is a sibling of the KP-9000-6XH-X2 (2M-PCB43-V1.1) with
the two SFP+ cages wired the other way round (physical 5 is on SDS1,
physical 6 on SDS0), no reset button fitted, wrong silkscreen labels on the
serial header, `LED_GLB_IO_EN` bit 6 has to be set for the port LEDs to
work, and the fitted T25S40 cannot be read in DIO mode on this board, so the
target selects single-IO flash reads (`flash_sio`). New machine target
`MACHINE_2G5F4_10G2_V1_01`, see `doc/devices/2G5F4_10G2_V1.01.md`.
- Web UI
- Compress the embedded assets (minify + gzip) and switch to a single-page layout. #315
- Replace the multi-page UI with a themed single-page app: light, dark and Selenized themes following the browser by default,
+5 -5
View File
@@ -66,6 +66,7 @@ create_build_dir:
mkdir -p "$(BUILDDIR)/uip"
mkdir -p "$(BUILDDIR)/httpd"
mkdir -p "$(BUILDDIR)/machine"
mkdir -p "$(BUILDDIR)/crypto"
# Every machine is a pair machine/<MACHINE>.c + machine/<MACHINE>.h. Selecting
# them by name means no #if/#elif chain, so an unknown or empty $MACHINE is
@@ -94,16 +95,15 @@ SRCS = \
ntp.c \
ntp_cli.c \
syslog.c \
udp_apps.c
udp_apps.c \
crypto/chacha20.c
# RTL837x
SRCS += \
rtl837x_bandwidth.c \
rtl837x_cabletest.c \
rtl837x_flash.c \
rtl837x_igmp.c \
rtl837x_init.c \
rtl837x_nic.c \
rtl837x_leds.c \
rtl837x_leds_dump.c \
rtl837x_phy.c \
@@ -185,8 +185,8 @@ $(BUILDDIR)/%.rel: %.asm $(CCFLAGS_STAMP) | create_build_dir
${ASM} ${AFLAGS} -o $@ $<
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtbank.rel $(BUILDDIR)/crc16.rel
$(CC) $(CC_FLAGS) --xram-size 49151 -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-bBANK3=0x34000 -Wl-r -o $@ $^
$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtbank.rel $(BUILDDIR)/crc16.rel $(BUILDDIR)/crypto/chacha_8051.rel
$(CC) $(CC_FLAGS) --xram-size 48896 -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-bBANK3=0x34000 -Wl-r -o $@ $^
$(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx
objcopy --input-target=ihex -O binary $< $@
+9 -15
View File
@@ -103,29 +103,24 @@ docker run --rm -p 8080:8080 -v $(pwd):/workspace rtlplayground-dev \
tools/output/httpd_sim /workspace/html
```
Edit `config.txt` on your host, then re-run `make` — the
Edit `machine.h` or `config.txt` on your host, then re-run `make` — the
source directory is mounted into the container, so changes take effect
immediately. To build for a different machine, pass `MACHINE=<name>`, which
selects `machine/<name>.c` (see [Adding a new device](doc/adding-a-device.md)).
immediately. To build for a different machine, pass `MACHINE=...`.
</details>
## (1) Compiling for direct chip flashing AND upgrading an existing RTLPlayground running device
Pass the machine that matches your device, for example:
```
make MACHINE=DEFAULT_8C_1SFP
```
The name selects the board definition `machine/<name>.c`; `make` without a
`MACHINE` value stops with an error listing what is expected. If your board is
not in the list yet, see [Adding a new device](doc/adding-a-device.md).
Edit machine.h with an editor like vi or nano. Select the correct machine the firmware should build for.
> [!TIP]
> You can write configuration parameters in config.txt (see below) in order your switch to get
> straight at the first boot, a correct IP configuration.
Now, building the firmware image should work.
Now, building the firmware image should work:
```
make
```
Note, that the image generated ends in .bin, not .img, in order to make IMSProg happy.
image location is stored in `RTLPlayground/output/rtlplayground_version_machine.bin`
@@ -191,7 +186,7 @@ Go to "Firmware update" tab, select the correct file.
> [!IMPORTANT]
> If your device already runs RTLPlayground, you must upload the binary file /RTLPlayground/output/rtlplayground_Version_Machine.bin
> If your device is OEM, you must upload the binary file /RTLPlayground/installer/output/rtlplayground_oem_upgrade.bin
> If your device is OEM, you must upload the binary file /RTLPlayground/installer/outputrtlplayground_oem_upgrade.bin
> [!CAUTION]
> Check one more time that your device matches the machine type before flashing.
@@ -358,13 +353,12 @@ Enjoy playing!
## (11) Other documents
The following documents give further documentation on specific features of the RTL837x SoCs:
- [Adding a new device](doc/adding-a-device.md)
- [RTL8372/3 Feature support](doc/hardware.md)
- [CPU Port](doc/CpuPort.md)
- [L2 learning](doc/l2.md)
- [IGMP (IP-MC streaming)](doc/igmp.md)
- [SFP+ ports](doc/sfp.md)
- [Trunking aka. port aggregation](doc/link_aggregation.md)
- [Trunking aka. port aggregation](doc/trunking.md)
- [LACP (802.3ad link aggregation)](doc/lacp.md)
- [VLAN](doc/vlan.md)
- [Storm control](doc/storm_control.md)
+1 -2
View File
@@ -257,7 +257,7 @@ void nic_setup(void) __banked
// This sets the size of the RX buffer, the filling level is in 0x7874
// R7848-000004ff
REG_SET(RTL837X_REG_NIC_RXBUFF_RX, RTL837X_NIC_RX_LAST_SLOT);
REG_SET(RTL837X_REG_NIC_RXBUFF_RX, 0x4ff);
// R7844-000007fe
REG_SET(RTL837X_REG_NIC_BUFFSIZE_TX, 0x7fe);
@@ -296,7 +296,6 @@ void nic_setup(void) __banked
// Sequence number of TX packets
tx_seq = 0;
REG_SET(RTL837X_NIC_INT_MSK, NIC_INT_RXIE);
}
+3 -15
View File
@@ -20,7 +20,6 @@
#include "rtl837x_lldp.h"
#include "rtl837x_storm.h"
#include "rtl837x_trap.h"
#include "rtl837x_cabletest.h"
#include "sfp.h"
#include "dhcp.h"
#include "syslog.h"
@@ -167,15 +166,10 @@ uint8_t atoi_hex(uint8_t idx)
break;
}
if (h_idx == 8) {
h_idx = 0;
break;
}
// swap hex nibbles
val = (val >> 4) | (val << 4);
if ((uint8_t)(c - '0') < 10) {
if (c - '0' < 10) {
val |= c - '0';
} else {
c |= 0x20;
@@ -745,7 +739,7 @@ void parse_isolate(void)
if (cmd_compare(2, "off")) {
for (uint8_t i = machine.min_port; i <= machine.max_port; i++)
members |= ((uint16_t)1) << i;
members |= PMASK_CPU; // CPU-port
members |= 0x200; // CPU-port
port_isolate(port_configured, members);
return;
}
@@ -909,7 +903,6 @@ void parse_port(void)
"\nport <port> [show|on|off]" \
"\nport <port> [10m|100m|1g|2g5|duplex] [half|full]" \
"\nport <port> lldp [block|permit]" \
"\nport <port> cabletest [show]" \
"\nport <port> name [custom port name]\n");
return;
}
@@ -952,11 +945,6 @@ void parse_port(void)
}
} else if (machine.is_sfp[phy_settings.port]) {
print_string(" is SFP no PHY information available.\n");
} else if (cmd_compare(2, "cabletest")) {
if (cmd_words_len > 3 && cmd_compare(3, "show"))
cabletest_show();
else
cabletest_run();
} else if (cmd_compare(2, "10m")) {
print_string(" 10M\n");
phy_settings.speed = PHY_SPEED_10M;
@@ -2155,7 +2143,7 @@ void execute_config(void) __banked
skipping = 1;
}
c = flash_buf[cfg_idx++];
if (c == 0 || c == '\n' || c == '\r') {
if (c == 0 || c == '\n') {
if (skipping) {
skipping = 0;
} else {
+23
View File
@@ -0,0 +1,23 @@
#ifndef _CHACHA_H_
#define _CHACHA_H_
#include <stdint.h>
struct chacha20_t {
uint8_t wstate[64]; // 64 bytes written here
uint8_t constant[16]; // 128 bit constant
uint8_t key[32]; // 256-bit secret key
uint32_t cnt; // 32-bit block counter 1, 2.. Big Endian!
uint8_t nonce[12]; // 96-bit nonce
__xdata uint8_t *plaintext;
uint16_t length;
__xdata uint8_t *cyphertext;
};
// Encrypt a plaintext with ChaCha20 as per RFC7539
void chacha20_encrypt(void);
// Test ChaCha20 using the example from RFC7539
void chacha20_test(void);
#endif
+103
View File
@@ -0,0 +1,103 @@
#include "rtl837x_common.h"
#include "chacha.h"
void chacha_20(void);
void chacha_update(void);
void chacha_count(void);
// generate a block of ChaCha20 keystream as per RFC7539
__xdata struct chacha20_t __at(0xbf00) chacha20;
#ifdef CHACHA20_TEST
__xdata uint8_t plaintext[256];
__xdata uint8_t cyphertext[256];
#endif
#ifdef DEBUG
void chacha20_print_block(void)
{
for (uint8_t i=0; i < 64; i++) {
print_byte(*(uint8_t * __xdata)(chacha20.wstate + i));
if (i%4 == 3)
write_char(' ');
}
}
#endif
void chacha20_encrypt(void)
{
__xdata uint8_t *p = chacha20.plaintext;
while (chacha20.length) {
register uint8_t i;
chacha_count();
memcpy(chacha20.wstate, chacha20.wstate + 64, 64);
#ifdef DEBUG
chacha20_print_block(); write_char('\n');
#endif
chacha_20();
chacha_update();
#ifdef DEBUG
chacha20_print_block(); write_char('\n');
#endif
for (i = 0; i < ((chacha20.length > 64) ? 64 : chacha20.length); i++)
*chacha20.cyphertext++ = *p++ ^ chacha20.wstate[i];
chacha20.length -= chacha20.length > 64 ? 64 : chacha20.length;
#ifdef DEBUG
print_string("\n round done\n");
#endif
};
}
#ifdef CHACHA20_TEST
// Test the example of RFC 7539 Section 2.4.2
void chacha20_test(void)
{
__code uint8_t chacha_c[16] =
{ 0x61, 0x70, 0x78, 0x65, 0x33, 0x20, 0x64, 0x6e,
0x79, 0x62, 0x2d, 0x32, 0x6b, 0x20, 0x65, 0x74 };
__code uint8_t key[32] =
{ 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04,
0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c,
0x13, 0x12, 0x11, 0x10, 0x17, 0x16, 0x15, 0x14,
0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c };
__code uint8_t nonce[12] = {
0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
__code uint8_t sunscreen[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for " \
"the future, sunscreen would be it.";
/*
Ciphertext Sunscreen (from RFC 7539 Section 2.4.2):
000 6e 2e 35 9a 25 68 f9 80 41 ba 07 28 dd 0d 69 81 n.5.%h..A..(..i.
016 e9 7e 7a ec 1d 43 60 c2 0a 27 af cc fd 9f ae 0b .~z..C`..'......
032 f9 1b 65 c5 52 47 33 ab 8f 59 3d ab cd 62 b3 57 ..e.RG3..Y=..b.W
048 16 39 d6 24 e6 51 52 ab 8f 53 0c 35 9f 08 61 d8 .9.$.QR..S.5..a.
064 07 ca 0d bf 50 0d 6a 61 56 a3 8e 08 8a 22 b6 5e ....P.jaV....".^
080 52 bc 51 4d 16 cc f8 06 81 8c e9 1a b7 79 37 36 R.QM.........y76
096 5a f9 0b bf 74 a3 5b e6 b4 0b 8e ed f2 78 5e 42 Z...t.[......x^B
112 87 4d
*/
strcpy(plaintext, sunscreen);
memcpyc(chacha20.constant, chacha_c, 16);
memcpyc(chacha20.key, key, 32);
chacha20.cnt = 0;
memcpyc(chacha20.nonce, nonce, 12);
chacha20.plaintext = plaintext;
chacha20.length = strlen_x(plaintext);
chacha20.cyphertext = cyphertext;
print_string("Encrypting...\n");
chacha20_encrypt();
print_string("Cypertext:\n");
uint16_t len = strlen_x(plaintext);
for (uint8_t i = 0; i < len; i++) {
print_byte(cyphertext[i]); write_char(' ');
}
}
#endif
+455
View File
@@ -0,0 +1,455 @@
; ChaCha Quater-Round implementation in Assembler
.module chacha_8051
; Global variables:
.globl _chacha_20
.globl _chacha_update
.globl _chacha_count
;#define CHACHA_QR(A, B, C, D) { \
; A += B; D ^= A; D = ROTL32(D, 16); \
; C += D; B ^= C; B = ROTL32(B, 12); \
; A += B; D ^= A; D = ROTL32(D, 8); \
; C += D; B ^= C; B = ROTL32(B, 7); \
;}
; r0 r1 r2 r3
; CHACHA_QR( v[ 0], v[ 4], v[ 8], v[12] );
.area HOME (CODE)
store_32:
ar7 = 0x07
ar6 = 0x06
ar5 = 0x05
ar4 = 0x04
ar3 = 0x03
ar2 = 0x02
ar1 = 0x01
ar0 = 0x00
mov a, r7
movx @dptr, a
dec dpl
mov a, r6
movx @dptr, a
dec dpl
mov a, r5
movx @dptr, a
dec dpl
mov a, r4
movx @dptr, a
ret
rol_b:
clr c
mov a, r7
rlc a
mov r7, a
mov a, r6
rlc a
mov r6, a
mov a, r5
rlc a
mov r5, a
mov a, r4
rlc a
mov r4, a
clr a
addc a, r7
mov r7, a
djnz dpl, rol_b
ret
chacha_plus_xor:
; Load A into registers r4-r7, A pointed to by r0
mov dptr, #_chacha20
mov dpl, r0
movx a, @dptr
mov r7, a
dec dpl
movx a, @dptr
mov r6, a
dec dpl
movx a, @dptr
mov r5, a
dec dpl
movx a, @dptr
mov r4, a
; A += B, B pointed to by r1
mov dpl, r1
movx a, @dptr
add a, r7
mov r7, a
dec dpl
movx a, @dptr
addc a, r6
mov r6, a
dec dpl
movx a, @dptr
addc a, r5
mov r5, a
dec dpl
movx a, @dptr
addc a, r4
mov r4, a
mov dpl, r0 ; Store A back
mov a, r7
movx @dptr, a
dec dpl
mov a, r6
movx @dptr, a
dec dpl
mov a, r5
movx @dptr, a
dec dpl
mov a, r4
movx @dptr, a
; D ^= A
mov dpl, r3
movx a, @dptr
xrl a, r7
mov r7, a
dec dpl
movx a, @dptr
xrl a, r6
mov r6, a
dec dpl
movx a, @dptr
xrl a, r5
mov r5, a
dec dpl
movx a, @dptr
xrl a, r4
mov r4, a
dec dpl
ret
chacha_qr:
; QR Part: A += B; D ^= A; D = ROTL32(D, 16);
acall chacha_plus_xor
; rotate left 16. D is r4, r5, r6, r7 -> r6, r7, r4, r5
mov a, r6
xch a, r4
mov r6, a
mov a, r7
xch a, r5
mov r7, a
mov dpl, r3 ; Store D
acall store_32
;QR Part: C += D; B ^= C; B = ROTL32(B, 12);
; Swap A <-> C and D <-> B
mov a, r0
xch a, r2
mov r0, a
mov a, r1
xch a, r3
mov r1, a
acall chacha_plus_xor
; rotate left 12. D is r4, r5, r6, r7 -> r5, r6, r7, r4
mov a, r4
xch a, r7
xch a, r6
xch a, r5
mov r4, a
mov dpl, #4
acall rol_b
mov dpl, r3 ; Store D (being B)
acall store_32
; Swap A <-> C and D <-> B
mov a, r0
xch a, r2
mov r0, a
mov a, r1
xch a, r3
mov r1, a
; QR Part A += B; D ^= A; D = ROTL32(D, 8);
acall chacha_plus_xor
mov a, r4
xch a, r7
xch a, r6
xch a, r5
mov r4, a
mov dpl, r3 ; Store D
acall store_32
; QR Part
; C += D; B ^= C; B = ROTL32(B, 7);
line4:
; Swap A <-> C and D <-> B
mov a, r0
xch a, r2
mov r0, a
mov a, r1
xch a, r3
mov r1, a
acall chacha_plus_xor
; Roll left 7 bits, start by rolling 8 bits left, then roll 1 to the right
mov a, r4
xch a, r7
xch a, r6
xch a, r5
mov r4, a
clr c
mov a, r4
rrc a
mov r4, a
mov a, r5
rrc a
mov r5, a
mov a, r6
rrc a
mov r6, a
mov a, r7
rrc a
mov r7, a
clr a
rrc a
add a, r4
mov r4, a
; Swap A <-> C and D <-> B
mov a, r0
xch a, r2
mov r0, a
mov a, r1
xch a, r3
mov r1, a
mov dpl, r1 ; Store B
acall store_32
ret
;
; Implementation of 20 ChaCha Rounds (10 Double Rounds)
;
_chacha_20:
push acc
push b
push dpl
push dph
push ar7
push ar6
push ar5
push ar4
push ar3
push ar2
push ar1
push ar0
push psw
mov b, #10 ; 10 Double rounds
chacha_20_loop:
; CHACHA_QR( v[ 0], v[ 4], v[ 8], v[12] );
mov r0, #3
mov r1, #19
mov r2, #35
mov r3, #51
acall chacha_qr
; CHACHA_QR( v[ 1], v[ 5], v[ 9], v[13] ); 7 23 39 55
mov r0, #7
mov r1, #23
mov r2, #39
mov r3, #55
acall chacha_qr
; CHACHA_QR( v[ 2], v[ 6], v[10], v[14] ); 11 27 43 59
mov r0, #11
mov r1, #27
mov r2, #43
mov r3, #59
acall chacha_qr
; CHACHA_QR( v[ 3], v[ 7], v[11], v[15] ); 15 31 47 63
mov r0, #15
mov r1, #31
mov r2, #47
mov r3, #63
acall chacha_qr
; CHACHA_QR( v[ 0], v[ 5], v[10], v[15] ); 3 23 43 63
mov r0, #3
mov r1, #23
mov r2, #43
mov r3, #63
acall chacha_qr
; CHACHA_QR( v[ 1], v[ 6], v[11], v[12] ); 7 27 47 51
mov r0, #7
mov r1, #27
mov r2, #47
mov r3, #51
acall chacha_qr
; CHACHA_QR( v[ 2], v[ 7], v[ 8], v[13] ); 11 31 35 55
mov r0, #11
mov r1, #31
mov r2, #35
mov r3, #55
acall chacha_qr
; CHACHA_QR( v[ 3], v[ 4], v[ 9], v[14] ); 15 19 39 59
mov r0, #15
mov r1, #19
mov r2, #39
mov r3, #59
acall chacha_qr
djnz b, chacha_20_loop
pop psw
pop ar0
pop ar1
pop ar2
pop ar3
pop ar4
pop ar5
pop ar6
pop ar7
pop dph
pop dpl
pop b
pop acc
ret
;
; Update ChaCHa state
;
_chacha_update:
push acc
push b
push dpl
push dph
push ar4
push ar3
push ar2
push ar1
push ar0
push psw
mov dptr, #_chacha20
mov b, #16 ; 16 uint32
update_loop:
mov a, b ; multiply by 4 and subtract 1
rl a
rl a
dec a
; Load Working State variable into registers r0-r3
mov dpl, a
orl a, #64 ; Save pointer to state
mov r4, a
movx a, @dptr
mov r3, a
dec dpl
movx a, @dptr
mov r2, a
dec dpl
movx a, @dptr
mov r1, a
dec dpl
movx a, @dptr
mov r0, a
; Add to State variable
mov a, r4
mov dpl, a
movx a, @dptr
add a, r3
mov r3, a
dec dpl
movx a, @dptr
addc a, r2
mov r2, a
dec dpl
movx a, @dptr
addc a, r1
mov r1, a
dec dpl
movx a, @dptr
addc a, r0
mov r0, a
; Store back state variable in LSB, first sequence (serialized)
mov a, r4
xrl a, #64 ; Save pointer to working state
mov dpl, a
mov a, r0
movx @dptr, a
dec dpl
mov a, r1
movx @dptr, a
dec dpl
mov a, r2
movx @dptr, a
dec dpl
mov a, r3
movx @dptr, a
djnz b, update_loop
pop psw
pop ar0
pop ar1
pop ar2
pop ar3
pop ar4
pop dph
pop dpl
pop b
pop acc
ret
;
; Increase counter in state
;
_chacha_count:
push acc
push dpl
push dph
mov dptr, #_chacha20
mov dpl, #112 + 3
movx a, @dptr
inc a
movx @dptr, a
jnz chacha_count_done
dec dpl
movx a, @dptr
inc a
movx @dptr, a
jnz chacha_count_done
dec dpl
movx a, @dptr
inc a
movx @dptr, a
jnz chacha_count_done
dec dpl
movx a, @dptr
inc a
movx @dptr, a
chacha_count_done:
pop dph
pop dpl
pop acc
ret
+1 -1
View File
@@ -51,7 +51,7 @@ __xdata uip_ipaddr_t server;
#define DHCP_END 255
#pragma codeseg BANK3
#pragma constseg BANK3
#pragma constseg BANK2
struct dhcp_pkt {
uint8_t type;
-15
View File
@@ -34,21 +34,6 @@ Next, transfer the actual packet over by repeating the SFR function with a
pointer to the frame on the ASIC directly after the frame header and a
length as given by the length in the frame header + 7, again divided by 8.
The RX ring's inclusive last slot is configured as `0x4ff`, giving a byte
range of `0x0000` through `0x27ff`. If the descriptor occupies the last slot
at `0x27f8`, its payload starts at `0x0000`, not `0x2800`. The RX copy code
normalizes that starting address before DMA. It relies on the hardware to
wrap transfers that start inside the ring and cross its end, as observed
on SWTGW218AS. Programming an initial address of `0x2800` does not wrap
and can instead read zeros or stale TX data outside the RX ring.
Frame lengths are checked against `UIP_CONF_BUFFER_SIZE` before copying.
DMA works in whole eight-byte units. `UIP_CONF_BUFFER_ALLOC_SIZE` rounds
the backing storage up to the next complete word: 1,560 bytes for the
1,556-byte logical frame limit. This padding allows a maximum-size frame
to be transferred directly without a separate tail copy. The logical
frame limit and advertised MSS are unchanged.
The received frame will have an RTL proprietary Ethernet frame type of
0x8899 (RRPC) where normally the frame type 0x0800 for IPv4 would be located.
Further 6 bytes follow describing the frame, before the normal IPv4 data
-196
View File
@@ -1,196 +0,0 @@
# Adding a new device
A device is supported by adding one board definition `.h` and board configuration `.c` file
under `machine/`.
the build selects the definition by name, and CI compiles every file it finds.
To compile for your added device, do:
```
make MACHINE=<NAME>
```
## What a new device consists of
| File | Purpose |
|------|---------|
| `machine/<NAME>.c` | the `struct machine machine` board definition |
| `machine/<NAME>.h` | `MACHINE_MODEL`, the model string shown in the UI and the CLI |
| `doc/devices/<name>.md` + `doc/supported_devices.md` | (only if the board is verified and you want to support it publicly) user-facing documentation |
`<NAME>` is the machine symbol without its `MACHINE_` prefix, so `MACHINE` is
passed exactly as spelled on the command line: `make MACHINE=MY_BOARD_1_0`
needs `machine/MY_BOARD_1_0.c` and `machine/MY_BOARD_1_0.h`.
## Step 1: the model header
`machine/<NAME>.h` only carries the product string. Use the existing files as
the template:
```c
#ifndef _MACHINE_MY_BOARD_1_0_H_
#define _MACHINE_MY_BOARD_1_0_H_
#define MACHINE_MODEL "Brand Model V1.0"
#endif
```
The device product string is what the CLI or the Web-Interface will print to identify the device; `machine.h` includes it by name.
> [!NOTE]
> `machine_name` is a `char[30]` and `MACHINE_MODEL` is copied into it at
> compile time. A longer model string still builds, but SDCC emits
> `warning 147: excess elements in array of chars initializer` and the name is
> truncated in the UI. Keep it to 29 characters or less.
## Step 2: the board definition
`machine/<NAME>.c` starts with the shared prelude and then defines the single
`machine` object. Copy the closest existing board and adjust it — do not start
from a blank file, the field meanings are easier to see in a real example.
The best choice is usually a device that has the same number and type of Ethernet
ports and the same number of SFP+ cages.
```c
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1 },
.led_sets = {
{ /* RJ45 ports */
LEDS_2G5 | LEDS_LINK,
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0
}, { /* SFP port, single green LED */
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
0
}
},
};
```
### Fields
| Field | Meaning |
|-------|---------|
| `machine_name` | always `MACHINE_MODEL` |
| `isRTL8373` | `1` for an RTL8373 SoC, `0` for RTL8372 |
| `min_port` / `max_port` | range of logical port numbers the device has; `min_port` is `0` for RTL8373 boards and `3` for RTL8372 boards (logical ports 1–2 are the SoC's internal ports on the 8372), `max_port` is usually 8. |
| `n_sfp` | number of SFP+ cages |
| `n_10g` | SerDes 10G capability used by the RTL837xN init: `0` none, `1` one, `2` two 10G-capable SerDes |
| `log_to_phys_port[9]` | logical port (0-based index) → physical front-panel port number |
| `phys_to_log_port[9]` | the inverse, physical port 1 is index 0, unused slots are 0 |
| `is_sfp[9]` | `0` for copper, `1` for left slot and `2` for right slot |
| `sfp_port[2]` | per-cage wiring, `sfp_port[0]` is the leftmost cage |
| `reset_pin` | GPIO of the reset button, `GPIO_NA` if unpopulated |
| `high_leds` | mux/enable for the LED pins 27–29 (`LED_27`, `LED_28_SYS`, `LED_29`) |
| `port_led_set[9]` | which LED set (0–3) each logical port uses |
| `led_sets[4][4]` | Each port can have up to 4 GPIO output pins assigned. 4 sets of LEDs with 4 LED-conditions per set; the conditions define which GPIO pins become active for a port given a port link-state. Which LEDs are then enabled depends on the wiring of the pins to up to 3 LEDs for that port, which can make a logical combination of the 4 LED output-pins. |
| `led_mux_custom` / `led_mux[28]` | `1` plus the 28 mux values when the stock LED muxing does not fit the board |
| `mac_flash_offset` | flash offset of the factory MAC address, omit or `0` if the board does not store one |
Each `struct sfp_port` entry holds `pin_detect`, `pin_los`, `pin_tx_disable`,
`sds` (which SerDes drives the cage) and `i2c` (built with `I2CBUS(sda, scl)`,
or `GPIO_NA`-based values where a cage has no such pin).
`I2CBUS(...)` only accepts the pin pairs listed in `machine_defs.h`. A wrong
pair is caught at compile time: SDCC reports
`error 176: sizeof applied to an incomplete type` pointing at the offending
`.i2c` line, because the macro deliberately turns an invalid bus number into an
array of size 0.
### Reusing an existing definition
If the new board is electrically identical to one that already exists — same
port mapping, same SFP wiring, same LEDs — do not copy the file. Make the new
`.c` a symlink and keep only a distinct `.h`, so the two boards cannot drift
apart:
```
ln -s KP_9000_6XHML_X2.c machine/MY_BOARD_1_0.c
```
The new board still needs `machine/MY_BOARD_1_0.h` (pick the version number on the PCB) with its own
`MACHINE_MODEL`, because `MACHINE_MODEL` is what distinguishes the products.
Existing examples: `machine/PCB_K0402WS_V3.c`, `machine/KP_9000_9XHML_X_V3_2.c`
and the six `KP_9000_*` revision variants.
Two files that differ only in whitespace or comments are duplicates and should
be collapsed this way.
## Step 3: build and verify
```
make MACHINE=MY_BOARD_1_0
```
The generated flash image appears as `output/rtlplayground-<version>-MY_BOARD_1_0.bin`. An
unknown or empty `MACHINE` fails immediately with a message naming the expected
file, before anything is compiled.
Then run the checks CI runs:
```
make machine_check # compiles machine/<NAME>.c and machine_init.c for every machine
make -C test # host-side unit tests
```
`make machine_check` discovers the definitions with
`$(wildcard machine/*.c)`, so a new file is covered without registering it
anywhere. CI (`.github/workflows/build.yml`) runs it on every push and pull
request, alongside full builds for a 4+2 and an 8+1 board.
A successful compile only proves the definition is syntactically valid. The
actual behaviour — port numbering, SFP detection, LEDs — has to be confirmed on
hardware, and the console commands (`port`, `stat`, `sfp`, `leds`) are the
tools for that.
## Step 4: documentation
Once the board has been tested on hardware:
1. Add a row to the table in [Supported devices](supported_devices.md).
2. Add `doc/devices/<name>.md` describing the board, the build target
(`make MACHINE=MY_BOARD_1_0`), what works and what is unverified, plus
photos and the PCB silkscreen marking.
3. If the board shares a PCB with other revisions, follow
`doc/devices/KP-9000-6XH-X2.md` and document which `MACHINE` to pick for
which silkscreen.
### Identifying the CPU variant
For RTL8373-based devices, use the read-only console command below to distinguish
the N and non-N CPU variants:
```text
regget 4
```
| Register 0x0004 value | CPU |
|---|---|
| `0x83730000` | RTL8373 (non-N) |
| `0x83737000` | RTL8373N |
Record the identified CPU in the device documentation. These values identify
only the CPU variant; document PHY and flash-chip models separately when verified.
-178
View File
@@ -1,178 +0,0 @@
hongyavision HYWS-SGT0204S
RTL8372-based 4×2.5G + 2×SFP+ unmanaged switch.
Also marked on the PCB as `2G5F4_10G2_V1.01`.
Stock firmware runs a factory test console on UART at 9600 baud 8N1 (banner
`RTL8371B start`, prompt `RTL8371B:`). There is no management CLI and no Web
interface.
Using SPI clamp in-board is the only method for initial installation and update.
Erase the whole chip and verify the write (`flashrom -v`) before powering the
board, so an incomplete write is caught before the board is powered up.
Stock flash chip is 512 KB (Bright Moon `T25S40`, 4 Mbit, SOP-8), which the
RTLPlayground image fills exactly.
### Label specifications
Case, top / front / nameplate:
<img src="photos/2G5F4_10G2_V1.01/assembled-top.jpg" width="300" />
<img src="photos/2G5F4_10G2_V1.01/assembled-front.jpg" width="300" />
<img src="photos/2G5F4_10G2_V1.01/assembled-bottom.jpg" width="300" />
- **Manufacturer**: hongyavision (Shenzhen Hongyavision Electronic Technology
Co., Ltd.)
- **Model**: HYWS-SGT0204S — the nameplate is printed in Chinese and reads
"10/100/1000/2500M fibre switch" and "4x 2.5G copper port + 2x 10G SFP+
optical port"
- **Ports**:
- 4 × RJ45: 10/100/1000/2500 Mbps
- 2 × SFP+: 1G / 2.5G / 10G
- **Power**: 12 V DC, 2 A
- **Serial number**: `S/N-YYYYMMDDNNNN`, e.g. `S/N-202312010028`
The top of the case only carries generic printing ("2.5G+10G High Speed Fiber
Transceiver / 4-Port 2.5G Ethernet Switch+10G Fiber"), so the nameplate on the
bottom is what identifies the device.
### What works
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
- Both SFP+ ports supporting 1G, 2.5G and 10G modules
- Copper LEDs: white (2.5G) and blue (link/activity)
- SFP LEDs: one single LED per port (link/activity)
- SFP EEPROM and DDM readable on both cages, verified with a 10G module
(`Rate: 0x67`, module identity and DDM values via the `sfp` console command)
- Serial console at 115200 8N1 (RTLPlayground) / 9600 8N1 (stock)
### Not verified
- The reset button footprint is unpopulated and the case has no opening for it,
so it could not be tested.
### PCB overview
**Board markings**
- Top silkscreen: `2G5F4_10G2_V1.01`
**Key components**
- Main switch: RTL8372 (RTL8371B family), reported as `RTL8372` (non-N) by
RTLPlayground. The chip sits under a heatsink and its package marking is not
readable.
- U1: SPI NOR flash, Bright Moon `T25S40`, 4 Mbit / 512 KB, SOP-8
- A 3-hole reset button footprint is present but unpopulated, and the case has
no opening for it, so there is no usable reset button
Top side:
<img src="photos/2G5F4_10G2_V1.01/pcb_top.jpg" width="600" />
Bottom:
<img src="photos/2G5F4_10G2_V1.01/pcb_bottom.jpg" width="600" />
The stock flash chip, Bright Moon `T25S40` (SOP-8, 4 Mbit / 512 KB):
<img src="photos/2G5F4_10G2_V1.01/flash_t25s40.jpg" width="300" />
### Port layout
| Front panel position | Logical port | Physical port | Type |
|----------------------|--------------|---------------|---------|
| SFP left | 8 | 5 | SFP+ |
| RJ45 1 | 4 | 1 | Copper |
| RJ45 2 | 5 | 2 | Copper |
| RJ45 3 | 6 | 3 | Copper |
| RJ45 4 | 7 | 4 | Copper |
| SFP right | 3 | 6 | SFP+ |
Copper ports 1–4 match the KP-9000-6XH-X2 (2M-PCB43-V1.1) layout, which this
board is a sibling of. The two SFP+ cages are wired the other way round
compared to that board: physical port 5 is on SDS1 and physical port 6 is on
SDS0.
### Serial console
The board has three through-holes used as the serial console, next to the
heatsink in the middle of the board and visible in the top side photo above (the
silkscreen labels are printed rotated by 90°). **The silkscreen labels are
wrong**: they are shifted relative to the actual signals.
| Silkscreen label | Actual signal |
|------------------|---------------|
| TX | GND |
| RX | TX |
| GND | RX |
Wiring (following the measured signals, not the labels):
| USB-TTL adapter | Board pad |
|-----------------|----------------------|
| GND | pad labelled `TX` |
| RX | pad labelled `RX` |
| TX | pad labelled `GND` |
- **Settings**: 115200 baud / 8N1 / 3.3V TTL (RTLPlayground), 9600 baud for the
stock firmware
- The stock firmware only prints a few bytes and a factory test menu
(`?`, `rst`, `f`, `r`, `10`, `100`, `g1`, `sd`, `eye`, …); it is not an
interactive management console
### LED configuration
Case silkscreen, below the RJ45 ports:
```
White : 2.5G Blue : 1000M/2500M L/A
```
The front panel also carries a `PWR` LED and one LED per SFP cage (`SFP1`,
`SFP2`) on the right hand side.
| Port | LED | Linked, idle | With traffic |
|------------|--------------|--------------|--------------|
| Copper | white | 2.5G only | same |
| Copper | blue | solid | blinks (L/A) |
| SFP | single LED | solid | blinks (L/A) |
Measured LED-ID mapping (from the RTL837x LED set registers):
| LED-ID | Function |
|--------|---------------------------------|
| LED-ID0| copper blue LED |
| LED-ID1| copper white LED |
| LED-ID2| SFP single LED |
**Important**: `RTL837X_REG_LED_GLB_IO_EN` bit 6 must be set in
`machine_custom_init()`. Without it the RTL837x "solid" conditions (LINK/speed)
do not drive the LEDs at all and only `ACT` does, which makes the white LED
glow faintly at non-2.5G speeds.
### SFP GPIO assignments
| SFP | pin\_detect (ModAbs) | pin\_los | SerDes | I2C SDA | I2C SCL |
|-------------------|-------------------------------|------------------|--------|-------------------------|--------------------------|
| Left (logical 8, physical 5) | GPIO30\_ACL\_BIT3\_EN | GPIO37 | SDS1 | GPIO39\_I2C\_SDA4 | GPIO40\_I2C\_SCL3\_MDC1 |
| Right (logical 3, physical 6)| GPIO50\_I2C\_SCL2\_UART1\_TX | GPIO10\_LED10 | SDS0 | GPIO41\_I2C\_SDA3\_MDIO1 | GPIO40\_I2C\_SCL3\_MDC1 |
`pin_tx_disable` is GPIO\_NA on both ports. Both I2C buses are confirmed
working: with the same 10G module inserted, the `sfp` console command reads its
vendor and model from the left cage (`Slot 1`) and from the right cage
(`Slot 2`), DDM values included. The insertion also shows which SerDes drives
each cage - the left cage reports `sds_config sds: 01` and the right cage
`sds: 00`, which matches the table above.
### Machine target
Build for this device with `make MACHINE=2G5F4_10G2_V1_01`, which selects the
`machine/2G5F4_10G2_V1_01.c` board definition. It is derived from
`machine/KP_9000_6XHML_X2.c` with the SFP cage order and the reset pin changed.
The fitted T25S40 cannot be read in DIO mode on this board: an image that leaves
DIO enabled does not come up at all, both at the default read clock divider of 4
and at 8 (two boards tested), while the same image with single-IO boots and runs
normally. The board definition therefore sets `flash_sio`, which makes
`flash_init()` use `CMD_FREAD` at divider 8. Only the management plane is
slower, the ASIC keeps forwarding in hardware.
+2 -2
View File
@@ -17,8 +17,8 @@ The original web interface reports this board as hardware version V3.2
The component placement matches [2M-PCB23-V3.1](2M-PCB23-V3_1.md): same
positions for the flash (U8), the T7/T8/T9/T10 headers, the SFP cage and its
LED, and the unpopulated U7/U9 footprints. Build with
`make MACHINE=KP_9000_9XHML_X_V3_2`, whose board file is a symlink to the V3.1
definition and only differs in the reported name.
`MACHINE=KP_9000_9XHML_X_V3_2`, which uses the V3.1 machine definition and
only differs in the reported name.
## Tested
+1 -1
View File
@@ -15,7 +15,7 @@ and sold by Mokerlink.
The device is fully supported:
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
- The SFP+ port supports 1G, 2.5G and 10G modules
- LEDs work with the same indiciations as the OEM firmware (build with `make MACHINE=KP_9000_6XHML_X2_V1_1` if building yourself, or use the corresponding pre-compiled binary)
- LEDs work with the same indiciations as the OEM firmware (use KP_9000_6XHML_X2_V1_1 in machine.h if building yourself or the corresponding pre-compiled binary)
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
### Hardware overview
-41
View File
@@ -1,41 +0,0 @@
# Hasivo S1100P-8GT-1SX-S
RTL8373N switch with 8 × 2.5G RJ45 ports and 1 × SFP port. GD25Q16 2 MiB flash.
## Port mapping
| Front port | ASIC MAC | Interface |
| --- | --- | --- |
| 1–8 | 0–7 | RJ45 |
| 9 | 8 | SFP (SDS1) |
## Board signals
| Function | GPIO |
| --- | --- |
| SFP detect | 38 |
| SFP LOS | 37 |
| SFP TX disable | Not connected (`GPIO_NA`) |
| SFP I2C SDA / SCL | 39 / 40 |
| Reset | 54 |
PoE is managed by an RTL8238B and a separate STC8H8K64U controller, not directly by the RTL8373N. RTLPlayground does not control PoE on this board.
## Build
`make MACHINE=HASIVO_S1100P_8GT_1SX_S CI=1`
## Photos
Front panel:
![Front panel](photos/Hasivo-S1100P-8GT-1SX-S/front.jpg)
PCB top:
![PCB top](photos/Hasivo-S1100P-8GT-1SX-S/pcb_top.jpg)
PCB bottom:
![PCB bottom](photos/Hasivo-S1100P-8GT-1SX-S/pcb_bottom.jpg)
-2
View File
@@ -90,8 +90,6 @@ Custom mapping for ONT-S207CW-62TS-SE:
## Flashing Instructions
See the [README.md](../../README.md) for general flashing instructions.
For compilation, use command `make MACHINE=ONT_S207CW_62TS_SE` to specify the machine.
If you are using managed version of the switch, you can then also compile the installer and flash using GUI - run command `cd installer` and finally `make`.
## Stock Firmware Information
-72
View File
@@ -1,72 +0,0 @@
# PCB-K0402WS-V1.0
This is the first revision of the PCB-K0402WS series of boards; it's very similar to 2.0 in terms of layout/wiring.
The board does have footprints for a VLAN modeswitch at the front and a second flash chip on the bottom of the PCB, but these have been seen to ship unpopulated.
### Brands
* YuanLey YS25-0402 <sup><sub>Note: there are [multiple revisions](PCB-K0402WS-V3.0.md) of the YS25-0402. This first revision lacks the "Vlan" switch cutout on the front of the enclosure.</sub></sup>
### Programming
Use a SOIC-8 clamp to the flash chip (U1 on silkscreen) at the top of the board, leaving it otherwise unpowered.
The board has been seen to ship with a single [BoyaMicro BY25Q16BSSIG](https://www.lcsc.com/datasheet/C382744.pdf) 16Mbit (2MiB) chip, though exact BOM may vary.
<a href="photos/PCB-K0402WS-V1.0/flash.jpg"><img src="photos/PCB-K0402WS-V1.0/flash.jpg" width="300" /></a>
### What works
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
- Both SFP ports supporting 1G, 2.5G and 10G modules
- LEDs (Power LED is always on)
### PCB overview
#### Board markings
- Top silkscreen: PCB-K0402W-V1.0 / DIP-K0402WS-V1.0
#### Key components
- U1: SPI NOR flash, 2 MiB
- S1: unpopulated slide switch footprint (three through-holes used as serial console)
Front panel
<a href="photos/PCB-K0402WS-V1.0/ports.jpg"><img src="photos/PCB-K0402WS-V1.0/ports.jpg" width="300" /></a>
PCB top
<a href="photos/PCB-K0402WS-V1.0/pcb-top.jpg"><img src="photos/PCB-K0402WS-V1.0/pcb-top.jpg" width="300" /></a>
PCB bottom
<a href="photos/PCB-K0402WS-V1.0/pcb-bottom.jpg"><img src="photos/PCB-K0402WS-V1.0/pcb-bottom.jpg" width="300" /></a>
Bottom and rear
<a href="photos/PCB-K0402WS-V1.0/bottom.jpg"><img src="photos/PCB-K0402WS-V1.0/bottom.jpg" width="300" /></a>
### Power supply
Input power is delivered via a standard DC barrel jack (5.5x2.1mm) with an included 12V 1A adapter.
There is an optional grounding screw next to the DC input.
### Serial console
The PCB has a slide switch footprint (unpopulated) at the front right that is connected to the UART. It is labeled as "S1" on the silkscreen.
Facing the top front (port) side of the board, the pinout from left to right is:
| Position | Signal | GPIO |
|----------|--------|-------------------|
| 1 | RX | GPIO32\_UART0\_RX |
| 2 | GND | N/A |
| 3 | TX | GPIO31\_UART0\_TX |
Standard 0.1" / 2.54mm pin headers will not fit, so wires or clips may be used instead.
The image below shows some oversized clips clumsily attached.
<a href="photos/PCB-K0402WS-V1.0/uart.jpg"><img src="photos/PCB-K0402WS-V1.0/uart.jpg" width="300" /></a>
+3 -8
View File
@@ -19,14 +19,9 @@ of the device just above the big label, might be covered by a QC sticker.
<img src="photos/PCB-K0402WS-V3.0/Ztyuav_Z-QWYT0402_label.jpg" width="300" />
* SICSOLINK SL-G0402F
<img src="photos/PCB-K0402WS-V3.0/SICSOLINK SL-G0402F.jpg" width="300"/>
* YuanLey YS25-0402 <sup><sub>Note: there are [multiple revisions](PCB-K0402WS-V1.0.md) of the YS25-0402. This is the newer revision that has a "Vlan" switch on the front.</sub></sup>
<img src="photos/PCB-K0402WS-V3.0/YuanLey_YS25-0402.jpg" width="300"/>
* Siscolink SL-G0402F
<img src="photos/PCB-K0402WS-V3.0/Siscolink SL-G0402F.jpg" width="300"/>
### Programming
Using SPI clamp in-board is the only method for initial installation.
@@ -48,7 +43,7 @@ For the initial flash (at least with flashrom), the bin file produced by the bui
### PCB overview
**Board markings**
- Top silkscreen: PCB-K0402W-V3.0 / DIP-K0402WS-V3.0
- Top silkscreen: PCB-KO4022W-V3.0 / DIP-KO4022WS-V3.0
Top side
-32
View File
@@ -1,32 +0,0 @@
### SIRIVISION_S25G2206FP_V1_1
## Brands
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|---|---|---|---|---|---|
| YuanLey | YS25-0402M | Yes | SIRIVISION_S25G2206FP_V1_1 | 2M | 8372 |
### Label specifications
- **Name**:
- **Ports**:
- 4 × RJ45: 10/100/1000/2500 Mbps
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
- **Power**: 12V DC, 1A 5525 connector
### What works
The device is fully supported:
- ALL 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
- ALL SFP+ ports support 1G, 2.5G and 10G modules
- LEDs work with the same indiciations as the OEM firmware
### PCB overview
**Board markings**
- Top silkscreen: SIRIVISION S25G2206FP V1.1
Top side
<img src="photos/SIRIVISION_S25G2206FP_V1_1/dev_pcb_top.jpg" width="300" />
## Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
+2 -3
View File
@@ -4,8 +4,7 @@
|---------|------------------|-------|------------------|-----------------|---------------|
| Ampcom | SWTG018AS-A V2.0 | No | SWTG018AS-A V2.0 | 2MB | 8273N + 8224N |
| Horaco | HC-SWTGW218AS-A | Yes | SWTG018AS-A V2.0 | 2MB(25Q16JVSIQ) | 8273N + 8224N |
| GoodTop | GT-ST018M | Yes | SWTG018AS-A V2.0 | 2MB | 8273N + 8224N |
| MokerLink | 2G08110GSN | No | SWTG018AS-A V2.0 | 512KB(25Q40) | 8273N + 8224N |
| GoodTop | GT-ST018M | Yes | SWTG018AS-A V2.0 | ? | 8273N + 8224N |
The following is a documentation for the unmanaged switch marked as `SWTG018AS-A V2.0`.
@@ -15,7 +14,7 @@ The original software is running UART on 9600 baud rate.
Using a SOIC clamp in-board is the only method for initial installation.
The board has a single flash chips `BS` with 2M-byte size. The front switch, switches between the two flash chips.
The board has a single flash chips `BS` with 4M-bit size. The front switch, switches between the two flash chips.
These can be programed independently by using said switch - so it is e.g. possible to run the original and new firmware in parallel.
### Label specifications
+3 -5
View File
@@ -2,11 +2,9 @@
It is highly similar to SWTG024AS-V2.0, with the only difference being the GPIO configuration for the SFP port.
## Brands
|Brand |Type |Managed|PCB |Flash |Chip RTL|
|---------|--------------|-------|------------------------------|----------------|--------|
| Horaco | ZX-SG4T2 | No | PCB-SWTG024AS-A-V2.0.1_19650 | 512K (P25D40SH)| 8372N |
| Horaco | HC-SWTG124AS | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M (W25Q16JV)| 8372N |
| GoodTop | GT-ST024M | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M | 8372N |
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|---|---|---|---|---|---|
| Horaco | ZX-SG4T2 | | PCB-SWTG024AS-A-V2.0.1_19650 | P25D40SH | ??? |
### Label specifications
+1 -1
View File
@@ -46,4 +46,4 @@ Note,`R52`、`R53`may not be installed.You need to bridge them using either sold
## Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
Input power is delivered via barell plug, `12V 1A` adapter was provided.
+1 -1
View File
@@ -9,7 +9,7 @@
## RTLPlayground target
Build for this device with `make MACHINE=LIANGUO_ZX_SWTGW215AS`, which selects the `machine/LIANGUO_ZX_SWTGW215AS.c` board definition.
Use machine target `MACHINE_LIANGUO_ZX_SWTGW215AS` for this device.
Physical hardware verification: 5x RJ45 ports + 1x SFP port.
Port 5 RJ45 is interfaced through a RTL8221B IC.
+1 -7
View File
@@ -5,15 +5,9 @@
|---|---|---|---|---|---|
| Mokerlink | ZX-SWTGW218AS | Yes| SWTG118AS-V2.0-16029 | 2MB (FM25Q16A)| 8273N + 8224N |
| Sodola | | | | | |
| Horaco | HC-SWTGW218AS | Yes | SWTG118AS-V2.1 | 2MB | 8373 (non-N) |
| Horaco | | | | | |
| XikeStor | SKS3200-8E1X | Yes | SWTG118AS-V2.1-17462 | 2MB (25Q16JVSIQ) | |
All boards in this table use `MACHINE=SWTGW218AS`. The Horaco HC-SWTGW218AS is also sold with the
[SWTG018AS-A V2.0](SWTG018AS_A_V2_0.md) board, which needs a different firmware. Check the marking
on the PCB before flashing.
The PHY and flash-chip models for the tested Horaco units remain unverified.
## Photos
Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

+13 -21
View File
@@ -4,52 +4,44 @@ The following devices have been tested and are fully working:
| Brand | Type | Managed | PCB | Flash | Ports |
|----------|-----------------|---------|---------------------------------------------------------------------------|-------|-------|
| Ampcom | WAM902-SWTG018AS| No | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | | 8 + 1 |
| Binardat | 2G06-04210GSM | No | [PCB-SWTG024AS-A-2.0.1](devices/ONT-S207CW-62TS-SE.md) | 0.5M | 4 + 2 |
| Davuaz | Da-K6501W | No | [PCB-K0501W-V2.0](devices/K0501W_V2_0.md) | | 5 + 1 |
| FOXNEO | FNS-1200P | No | [PCB-K0402W-U13-V2.0](devices/FNS-1200P.md) | 2M | 4 + 2 |
| Goalake | IG108 | No | [PB-2132](devices/PB-2132.md) | 4M | 8 + 1 |
| GoodTop | GT-ST018M | Yes | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | 2M | 8 + 1 |
| GoodTop | GT-ST024M | Yes | [SWTG024AS-A V2.0.1](devices/SWTG024AS-A-V2.0.1_4C_2SFP.md) | 2M | 4 + 2 |
| Guangnianwei | 7018-2.5G | No | [F7008-2.5GPOE-V1.2](devices/F7008-2.5.md) | 8M | 8 + 1 |
| GoodTop | GT-ST018M | Yes | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | ? | 8 + 1 |
| Hasivo | S1100WP_8GT_1SX_SE | Yes | [S1100WP_8GT_1SX_SE-V1.05](devices/HASIVO_S1100WP_8GT_1SX_SE.md) | 2M | 8 + 1 |
| Hisource | Hi-K0402WS | No | [PCB-K0402WS-V2.0](devices/PCB-K0402WS-V2.0.md) | 2M | 4 + 2 |
| Hisource | Hi-K0402WS | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
| Hisource | Hi-K0402WS | No | [PCB-K0402WS-V2.0](devices/PCB-K0402WS-V2.0.md) | 2M | 4 + 2 |
| Hisource | Hi-K0801WS | No | [PCB-KO801W-V2.0](devices/HI-K0801WS.md) | | 8 + 1 |
| hongyavision | HYWS-SGT0204S | No | [2G5F4_10G2_V1.01](devices/2G5F4_10G2_V1.01.md) | 0.5M | 4 + 2 |
| hongyavision | LG-SG5T1 | No | [PCB-SWTG024AS-V2.0_16895](devices/SWTG024AS-V2.0.md) | 0.5M | 5 + 1 |
| Horaco | HC-SWTG124AS | Yes | [SWTG024AS-A-V2.0.1](devices/SWTG024AS-A-V2.0.1_4C_2SFP.md) | 2M | 4 + 2 |
| Horaco | HC-SWTGW215AS | Yes | [SWTG024AS-A-V2.0.1_19650 5C 1SFP](devices/SWTG024AS-A-V2.0.1_5C_1SFP.md) | ? | 5 + 1 |
| Horaco | HC-SWTGW218AS | Yes | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | | 8 + 1 |
| Horaco | HC-SWTGW218AS | Yes | [SWTG118AS-V2.1](devices/SWTGW218AS.md) | 2M | 8 + 1 |
| Horaco | ZX310S-4T2XH | Yes | [PCB-SL310S-4T1T1X-V1.0.1-24107](devices/ZX310S-4T2XH.md) | 2M | 5 + 1 |
| Horaco | ZX310S-4T2XT | Yes | [PCB-SL310S-4T2XT-V1.0.0-22273](devices/ZX310S-4T2XT.md) | 2M | 6 |
| Horaco | ZX-SG4T2 | No | [SWTG024AS-A-V2.0.1_19650_4C_2SFP](devices/SWTG024AS-A-V2.0.1_4C_2SFP.md) | 0.5M | 4 + 2 |
| Horaco | ZX-SWTG124AS | Yes | [SWTG024AS-v2.0](devices/SWTG024AS.md) | | 4 + 2 |
| keepLINK | KP-9000-6XH-X2 / KP-9000-6XHML-X2 | No/Yes | [2M-PCB43-V1.2 / V2.1](devices/KP-9000-6XH-X2.md) | | 4 + 2 |
| Keeplink | KP-9000-6XH-X2 / KP-9000-6XHML-X2 | No/Yes | [2M-PCB43-V1.2 / V2.1](devices/KP-9000-6XH-X2.md) | | 4 + 2 |
| keepLINK | KP-9000-9XHML-X | Yes | [2M-PCB23-V2.2](devices/2M-PCB23-V2_2.md) | 2M | 8 + 1 |
| keepLINK | KP-9000-9XHML-X | Yes | [2M-PCB23-V3.1](devices/2M-PCB23-V3_1.md) | 2M | 8 + 1 |
| keepLINK | KP-9000-9XHML-X | Yes | [2M-PCB23-V3.2](devices/2M-PCB23-V3_2.md) | 2M | 8 + 1 |
| LIANGUO | HYWS-SGT0108S | No | [2G5F_20G_V1.01](devices/HYWS-SGT0108S.md) | 0.5M | 8 + 1 |
| LIANGUO | SWTG024AS | No | [SWTG024AS-v2.0-17452](devices/SWTG024AS.md) | 0.5M | 4 + 2 |
| LIANGUO | ZX-SWTGW215AS | Yes | [PCB-SWTG115AS-V2.0 / PCB-SWTG115AS-V2.1](devices/SWTGW215AS.md) | 2M | 5 + 1 |
| MokerLink| 2G040210GSM | Yes | [2M-PCB43-V1.1](devices/2M-PCB43-V1.1.md) | | 4 + 2 |
| Lianguo | ZX-SWTGW215AS | Yes | [PCB-SWTG115AS-V2.0 / PCB-SWTG115AS-V2.1](devices/SWTGW215AS.md) | 2M | 5 + 1 |
| Lianguo | HYWS-SGT0108S | No | [2G5F_20G_V1.01](devices/HYWS-SGT0108S.md) | 0.5M | 8 + 1 |
| Mokerlink| 2G040210GSM | Yes | [2M-PCB43-V1.1](devices/2M-PCB43-V1.1.md) | | 4 + 2 |
| Mokerlink| ZX-SWTGW218AS | Yes | [SWTG118AS-V2.0-16029](devices/SWTGW218AS.md) | 2M | 8 + 1 |
| MokerLink| POE-2G080110GS | No | [2M-PCB51-ML-V1.1](devices/2M-PCB51-ML-V1_1.md) | 4M | 8 + 1 |
| MokerLink| ZX-SWTGW218AS | Yes | [SWTG118AS-V2.0-16029](devices/SWTGW218AS.md) | 2M | 8 + 1 |
| MokerLink| 2G08110GSN | No | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | 0.5M | 8 + 1 |
| Binardat | 2G06-04210GSM | No | [PCB-SWTG024AS-A-2.0.1](devices/ONT-S207CW-62TS-SE.md) | 0.5M | 4 + 2 |
| ONT | ONT-S207CW-62TS-SE | No | [PCB-SWTG024AS-A-2.0.1](devices/ONT-S207CW-62TS-SE.md) | 0.5M | 4 + 2 |
| Netcore | GS9 | No | [PB-2132](devices/PB-2132.md) | 4M | 8 + 1 |
| ONT | ONT-S207CW-62TS-SE | No | [PCB-SWTG024AS-A-2.0.1](devices/ONT-S207CW-62TS-SE.md) | 0.5M | 4 + 2 |
| Ruiying | RY-4GT-2SX | No | [FG-4GT-2SX_V2.0](devices/FG-4GT-2SX_V2.0.md) | 4M | 4 + 2 |
| Ruiying | RY-8GT-1SX | No | [FG-8GT-1SX](devices/FG-8GT-1SX.md) | 1M | 8 + 1 |
| SICSOLINK| SL-G0402F | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
| SiscoLink | SL-G0402F | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
| Sodola | SL-SWTG124AS-D | Yes | [SWTG024AS-v2.0-17452](devices/SWTG024AS.md) | 2M | 4 + 2 |
| Steamemo | IG204-V1 | No | [PB-2131](devices/STEAMEMO_IG204_V1.md) | | 4 + 2 |
| TRENDnet | TEG-S562 | No | [TEG-S563/EU H/W: V1.0R](devices/TEG-S562.md) | 2M | 4 + 2 |
| XikeStor | SKS3200M-4GPY2XF| Yes | [SWTG024AS-v1.0](devices/SWTG024AS.md) | | 4 + 2 |
| TrendNet | TEG-S562 | No | [TEG-S563/EU H/W: V1.0R](devices/TEG-S562.md) | 2M | 4 + 2 |
| Xikestore| SKS3200M-4GPY2XF| Yes | [SWTG024AS-v1.0](devices/SWTG024AS.md) | | 4 + 2 |
| XikeStor | SKS3200-8E1X | Yes | [SWTG118AS-V2.1-17462](devices/SWTGW218AS.md) | 2M | 8 + 1 |
| YuanLey | YS25-0402 | No | [PCB-K0402WS-V1.0](devices/PCB-K0402WS-V1.0.md) | 2M | 4 + 2 |
| YuanLey | YS25-0402 | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | 2M | 4 + 2 |
| YuanLey | YS25-0402M | Yes | [SIRIVISION_S25G2206FP_V1_1](devices/SIRIVISION_S25G2206FP_V1_1.md) | 2M | 4 + 2 |
| Ztyuav | Z-QWYT0402 | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
| Guangnianwei | 7018-2.5G | No | [F7008-2.5GPOE-V1.2](devices/F7008-2.5.md) | 8M | 8 + 1 |
For KP-9000-6XH-X2 / KP-9000-6XHML-X2 / Mokerlink 2G040210GSM devices, select
the machine target by PCB revision. The ML/non-ML or managed/unmanaged label
+47 -32
View File
@@ -11,15 +11,15 @@ th_sel_light:"Selenized Light",th_sel_dark:"Selenized Dark",
c_port:"Port",c_name:"Name",c_link:"Link",c_apply:"Apply",c_cancel:"Cancel",c_confirm:"Confirm",
c_close:"Close",c_refresh:"Refresh",c_off:"off",c_offc:"Off",c_down:"down",c_on:"On",c_auto:"Auto",c_delete:"Delete",
c_type:"Type",c_state:"State",c_enabled:"Enabled",c_load:"Load",c_disable:"Disable",c_sfp:"SFP",
c_full:"full",c_half:"half",c_yes:"yes",c_no:"no",
d_system:"System",d_traffic:"Traffic",
c_full:"full",c_half:"half",c_devices:"devices",c_yes:"yes",c_no:"no",
d_ports:"Ports",d_ports_h:"click a port for details",d_system:"System",d_traffic:"Traffic",
d_traffic_h:"packets/s, live",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX bad",d_rxbad:"RX bad",
i_host:"Hostname",i_ip:"IP address",i_mask:"Netmask",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware",
i_built:"Built",i_hw:"Hardware",i_temp:"Temperature",i_flash:"Flash",i_syslog:"Syslog",
p_state:"State",p_disabled:"disabled",p_up:"up",p_txgb:"TX good / bad",p_rxgb:"RX good / bad",
p_pkts:"pkts",p_module:"Module",p_temp:"Temperature",p_vcc:"Vcc",p_txbias:"TX bias",p_txpower:"TX power",
p_rxpower:"RX power",p_txfault:"TX fault",p_txdis:"TX disabled",p_rxlos:"RX LOS",p_adv:"Advertising",
pt_title:"Port configuration",pt_conn:"Devices learned",pt_speed:"Speed",pt_mtu:"MTU",
pt_title:"Port configuration",pt_conn:"Connected",pt_speed:"Speed",pt_mtu:"MTU",
pt_sfp_note:"SFP speed is set per slot and is not saved in the startup config.",
pt_name_err:"Port name: 1-15 characters, no spaces",pt_mtu_err:"MTU must be 64-16383",
stp_title:"Spanning tree",stp_h:"RSTP, 802.1w",stp_version:"Version",stp_v_stp:"STP compatible",
@@ -142,15 +142,15 @@ th_sel_light:"Selenized ライト",th_sel_dark:"Selenized ダーク",
c_port:"ポート",c_name:"名前",c_link:"リンク",c_apply:"適用",c_cancel:"キャンセル",c_confirm:"確認",
c_close:"閉じる",c_refresh:"更新",c_off:"オフ",c_offc:"オフ",c_down:"リンクダウン",c_on:"オン",c_auto:"自動",c_delete:"削除",
c_type:"タイプ",c_state:"状態",c_enabled:"有効",c_load:"読み込み",c_disable:"無効化",c_sfp:"SFP",
c_full:"全二重",c_half:"半二重",c_yes:"はい",c_no:"いいえ",
d_system:"システム",d_traffic:"トラフィック",
c_full:"全二重",c_half:"半二重",c_devices:"デバイス",c_yes:"はい",c_no:"いいえ",
d_ports:"ポート",d_ports_h:"ポートをクリックすると詳細を表示",d_system:"システム",d_traffic:"トラフィック",
d_traffic_h:"パケット/秒、リアルタイム",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 異常",d_rxbad:"RX 異常",
i_host:"ホスト名",i_ip:"IP アドレス",i_mask:"ネットマスク",i_gw:"ゲートウェイ",i_mac:"MAC",i_fw:"ファームウェア",
i_built:"ビルド日",i_hw:"ハードウェア",i_temp:"温度",i_flash:"フラッシュ",i_syslog:"Syslog",
p_state:"状態",p_disabled:"無効",p_up:"アップ",p_txgb:"TX 正常 / 異常",p_rxgb:"RX 正常 / 異常",
p_pkts:"pkts",p_module:"モジュール",p_temp:"温度",p_vcc:"電圧",p_txbias:"TX バイアス",p_txpower:"TX 電力",
p_rxpower:"RX 電力",p_txfault:"TX 障害",p_txdis:"TX 無効",p_rxlos:"RX 信号ロス",p_adv:"アドバタイズ",
pt_title:"ポート設定",pt_conn:"学習済みデバイス",pt_speed:"速度",pt_mtu:"MTU",
pt_title:"ポート設定",pt_conn:"接続デバイス",pt_speed:"速度",pt_mtu:"MTU",
pt_sfp_note:"SFP の速度はスロット単位で設定され、起動設定には保存されません。",
pt_name_err:"ポート名: 1〜15 文字、空白不可",pt_mtu_err:"MTU は 64〜16383 の範囲で指定してください",
stp_title:"スパニングツリー",stp_h:"RSTP, 802.1w",stp_version:"バージョン",stp_v_stp:"STP 互換",
@@ -255,15 +255,15 @@ th_sel_light:"Selenized 浅色",th_sel_dark:"Selenized 深色",
c_port:"端口",c_name:"名称",c_link:"链路",c_apply:"应用",c_cancel:"取消",c_confirm:"确认",
c_close:"关闭",c_refresh:"刷新",c_off:"关",c_offc:"关",c_down:"未连接",c_on:"开",c_auto:"自动",c_delete:"删除",
c_type:"类型",c_state:"状态",c_enabled:"启用",c_load:"读取",c_disable:"禁用",c_sfp:"SFP",
c_full:"全双工",c_half:"半双工",c_yes:"是",c_no:"否",
d_system:"系统",d_traffic:"流量",
c_full:"全双工",c_half:"半双工",c_devices:"台设备",c_yes:"是",c_no:"否",
d_ports:"端口",d_ports_h:"点击端口查看详情",d_system:"系统",d_traffic:"流量",
d_traffic_h:"包/秒,实时",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 错误",d_rxbad:"RX 错误",
i_host:"主机名",i_ip:"IP 地址",i_mask:"子网掩码",i_gw:"网关",i_mac:"MAC",i_fw:"固件",
i_built:"构建日期",i_hw:"硬件",i_temp:"温度",i_flash:"Flash",i_syslog:"Syslog",
p_state:"状态",p_disabled:"已禁用",p_up:"已连接",p_txgb:"TX 正常 / 错误",p_rxgb:"RX 正常 / 错误",
p_pkts:"个包",p_module:"模块",p_temp:"温度",p_vcc:"供电电压",p_txbias:"TX 偏置电流",p_txpower:"TX 光功率",
p_rxpower:"RX 光功率",p_txfault:"TX 故障",p_txdis:"TX 禁用",p_rxlos:"RX 信号丢失",p_adv:"通告能力",
pt_title:"端口配置",pt_conn:"已学习设备",pt_speed:"速率",pt_mtu:"MTU",
pt_title:"端口配置",pt_conn:"已连接设备",pt_speed:"速率",pt_mtu:"MTU",
pt_sfp_note:"SFP 速率按插槽设置,不会保存到启动配置。",
pt_name_err:"端口名称: 1-15 个字符,不能包含空格",pt_mtu_err:"MTU 范围为 64-16383",
stp_title:"生成树",stp_h:"RSTP, 802.1w",stp_version:"版本",stp_v_stp:"STP 兼容",
@@ -368,15 +368,15 @@ th_sel_light:"Selenized claro",th_sel_dark:"Selenized oscuro",
c_port:"Puerto",c_name:"Nombre",c_link:"Enlace",c_apply:"Aplicar",c_cancel:"Cancelar",c_confirm:"Confirmar",
c_close:"Cerrar",c_refresh:"Actualizar",c_off:"apagado",c_offc:"Apagado",c_down:"caído",c_on:"Encendido",c_auto:"Auto",c_delete:"Eliminar",
c_type:"Tipo",c_state:"Estado",c_enabled:"Habilitado",c_load:"Cargar",c_disable:"Deshabilitar",c_sfp:"SFP",
c_full:"dúplex completo",c_half:"semidúplex",c_yes:"sí",c_no:"no",
d_system:"Sistema",d_traffic:"Tráfico",
c_full:"dúplex completo",c_half:"semidúplex",c_devices:"dispositivos",c_yes:"sí",c_no:"no",
d_ports:"Puertos",d_ports_h:"pulsa un puerto para ver detalles",d_system:"Sistema",d_traffic:"Tráfico",
d_traffic_h:"paquetes/s, en vivo",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX erróneos",d_rxbad:"RX erróneos",
i_host:"Nombre de host",i_ip:"Dirección IP",i_mask:"Máscara de red",i_gw:"Puerta de enlace",i_mac:"MAC",i_fw:"Firmware",
i_built:"Compilado",i_hw:"Hardware",i_flash:"Flash",i_syslog:"Syslog",
p_state:"Estado",p_disabled:"deshabilitado",p_up:"activo",p_txgb:"TX correctos / erróneos",p_rxgb:"RX correctos / erróneos",
p_pkts:"paquetes",p_module:"Módulo",p_temp:"Temperatura",p_vcc:"Vcc",p_txbias:"Polarización TX",p_txpower:"Potencia TX",
p_rxpower:"Potencia RX",p_txfault:"Fallo TX",p_txdis:"TX deshabilitado",p_rxlos:"Pérdida RX (LOS)",p_adv:"Anunciado",
pt_title:"Configuración de puerto",pt_conn:"Dispositivos aprendidos",pt_speed:"Velocidad",pt_mtu:"MTU",
pt_title:"Configuración de puerto",pt_conn:"Conectado",pt_speed:"Velocidad",pt_mtu:"MTU",
pt_sfp_note:"La velocidad del SFP se ajusta por ranura y no se guarda en la configuración de inicio.",
pt_name_err:"Nombre de puerto: 1-15 caracteres, sin espacios",pt_mtu_err:"El MTU debe estar entre 64 y 16383",
stp_title:"Árbol de expansión",stp_h:"RSTP, 802.1w",stp_version:"Versión",stp_v_stp:"STP compatible",
@@ -480,15 +480,15 @@ th_sel_light:"Clair (sélénisé)",th_sel_dark:"Sombre (sélénisé)",
c_port:"Port",c_name:"Nom",c_link:"Lien",c_apply:"Appliquer",c_cancel:"Annuler",c_confirm:"Confirmer",
c_close:"Fermer",c_refresh:"Raffraichir",c_off:"arrêt",c_offc:"Arrêt",c_down:"arrêt",c_on:"Marche",c_auto:"Auto",c_delete:"Supprimer",
c_type:"Type",c_state:"Etat",c_enabled:"Activé",c_load:"Charger",c_disable:"Désactivé",c_sfp:"SFP",
c_full:"full",c_half:"half",c_yes:"oui",c_no:"non",
d_system:"Système",d_traffic:"Trafic",
c_full:"full",c_half:"half",c_devices:"Equipements",c_yes:"oui",c_no:"non",
d_ports:"Ports",d_ports_h:"Cliquez ou survollez pour plus de détails",d_system:"Système",d_traffic:"Trafic",
d_traffic_h:"paquets/s (en direct)",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX KO",d_rxbad:"RX KO",
i_host:"Nom d'hote",i_ip:"Adresse IP",i_mask:"Masque réseau",i_gw:"Passerelle",i_mac:"Adresse MAC",i_fw:"Micro logiciel",
i_built:"Compilé le",i_hw:"Matériel",i_temp:"Température",i_flash:"Taille Flash",i_syslog:"Journal système",
p_state:"Etat",p_disabled:"Inactif",p_up:"Actif",p_txgb:"TX bon / mauvais",p_rxgb:"RX bon / mauvais",
p_pkts:"paquets",p_module:"Module",p_temp:"Température",p_vcc:"Vcc",p_txbias:"TX biais",p_txpower:"TX puissance",
p_rxpower:"RX puissance",p_txfault:"TX erreur",p_txdis:"TX désactivé",p_rxlos:"RX pertes de signaux",p_adv:"Capacités",
pt_title:"Configuration du port",pt_conn:"Appareils appris",pt_speed:"Vitesse",pt_mtu:"MTU",
pt_title:"Configuration du port",pt_conn:"Connecté à",pt_speed:"Vitesse",pt_mtu:"MTU",
pt_sfp_note:"La vitesse SFP est paramétrée pour le port et n'est pas enregistrée dans la configuration de démarrage.",
pt_name_err:"Nom du port: 1 à 15 caractères, sans espaces",pt_mtu_err:"MTU doit être comrpis entre 64 et 16383",
stp_title:"Arborescence",stp_h:"RSTP, 802.1w",stp_version:"Protocole",stp_v_stp:"Compatible STP",
@@ -588,7 +588,7 @@ fw_timeout:"Le commutateur n'est plus joignable depuis 150 s: verifiez l'aliment
},
de:{
nav_dash:"Übersicht",nav_ports:"Ports",nav_stp:"Spanning Tree",nav_stats:"Statistik",
nav_vlan:"VLANs",nav_l2:"MAC-Tabelle",nav_mirror:"Spiegelung",nav_isolate:"Isolation",nav_lag:"LAG",nav_eee:"EEE",
nav_vlan:"VLANs",nav_l2:"MAC-Tabelle",nav_mirror:"Spiegelung",nav_lag:"LAG",nav_eee:"EEE",
nav_bw:"Bandbreite",nav_system:"System",nav_fw:"Firmware",
hdr_dirty:"ungespeicherte Änderungen",hdr_dirty_t:"Laufende Konfiguration weicht von der Startkonfiguration ab",
hdr_save:"Im Flash speichern",hdr_save_t:"Laufende Konfiguration dauerhaft im Flash speichern",
@@ -597,15 +597,15 @@ th_sel_light:"Selenized Hell",th_sel_dark:"Selenized Dunkel",
c_port:"Port",c_name:"Name",c_link:"Link",c_apply:"Übernehmen",c_cancel:"Abbrechen",c_confirm:"Bestätigen",
c_close:"Schliessen",c_refresh:"Aktualisieren",c_off:"aus",c_offc:"Aus",c_down:"getrennt",c_on:"Ein",c_auto:"Auto",c_delete:"Löschen",
c_type:"Typ",c_state:"Zustand",c_enabled:"Aktiviert",c_load:"Laden",c_disable:"Deaktivieren",c_sfp:"SFP",
c_full:"voll",c_half:"halb",c_yes:"ja",c_no:"nein",
d_system:"System",d_traffic:"Datenverkehr",
c_full:"voll",c_half:"halb",c_devices:"Geräte",c_yes:"ja",c_no:"nein",
d_ports:"Ports",d_ports_h:"Port anklicken für Details",d_system:"System",d_traffic:"Datenverkehr",
d_traffic_h:"Pakete/s, live",d_txpps:"TX Pakete/s",d_rxpps:"RX Pakete/s",d_txbad:"TX fehlerhaft",d_rxbad:"RX fehlerhaft",
i_host:"Hostname",i_ip:"IP-Adresse",i_mask:"Netzmaske",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware",
i_built:"Erstellt",i_hw:"Hardware",i_temp:"Temperatur",i_flash:"Flash",i_syslog:"Syslog",
p_state:"Zustand",p_disabled:"deaktiviert",p_up:"verbunden",p_txgb:"TX gut / fehlerhaft",p_rxgb:"RX gut / fehlerhaft",
p_pkts:"Pakete",p_module:"Modul",p_temp:"Temperatur",p_vcc:"Vcc",p_txbias:"TX-Bias",p_txpower:"Sendeleistung",
p_rxpower:"Empfangsleistung",p_txfault:"TX-Fehler",p_txdis:"TX deaktiviert",p_rxlos:"RX LOS",p_adv:"Angeboten",
pt_title:"Port-Konfiguration",pt_conn:"Gelernte Geräte",pt_speed:"Geschwindigkeit",pt_mtu:"MTU",
pt_title:"Port-Konfiguration",pt_conn:"Verbunden",pt_speed:"Geschwindigkeit",pt_mtu:"MTU",
pt_sfp_note:"Die SFP-Geschwindigkeit wird pro Steckplatz gesetzt und nicht in der Startkonfiguration gespeichert.",
pt_name_err:"Port-Name: 1-15 Zeichen, keine Leerzeichen",pt_mtu_err:"MTU muss zwischen 64 und 16383 liegen",
stp_title:"Spanning Tree",stp_h:"RSTP, 802.1w",stp_version:"Version",stp_v_stp:"STP-kompatibel",
@@ -626,7 +626,6 @@ stp_en_q:"Spanning Tree aktivieren?",
stp_en_d:"Die Ports starten blockiert und brauchen bis zum doppelten Forward Delay, bis sie weiterleiten; Edge-Ports sind sofort wieder aktiv.",
stp_dis_q:"Spanning Tree deaktivieren?",stp_dis_d:"Alle Ports leiten sofort weiter; der Schutz vor Netzwerkschleifen entfällt.",
stp_cost_err:"Pfadkosten müssen zwischen 0 und 200000000 liegen",
nav_lldp:"LLDP",lldp_enabled:"LLDP aktiv",lldp_title:"Dienststatus",lldp_portname:"Name",lldp_enable:"Pakete senden",
st_title:"Port-Statistik",st_h:"Summen seit dem Start",st_txg:"TX gut",st_txb:"TX fehlerhaft",st_rxg:"RX gut",
st_rxb:"RX fehlerhaft",st_details:"Details",st_counters:"MIB-Zähler",st_nonzero:"nur ungleich null",
st_autoref:"automatisch aktualisieren",st_counter:"Zähler",st_value:"Wert",st_fail:"Zähler konnten nicht geladen werden",
@@ -649,12 +648,8 @@ l2_learned:"gelernt",l2_loading:"lädt...",l2_failed:"Laden fehlgeschlagen",l2_e
l2_del_t:"Eintrag löschen",l2_flush_q:"Alle gelernten MAC-Einträge löschen?",
m_title:"Port-Spiegelung",m_active:"aktiv",m_monitor:"Monitor-Port",m_mirror:"Spiegeln",m_both:"Beide",
m_note:"Beide = RX und TX des Ports auf den Monitor-Port spiegeln.",m_none:"Mindestens einen zu spiegelnden Port wählen",
iso_title:"Port-Isolation",iso_from:"Von Port",iso_to:"Zu Port",iso_all:"Alle erlauben",
iso_intro:"Ein Paket, das über einen Port hereinkommt, darf den Switch nur über die Ports verlassen, die in seiner Zeile angehakt sind. Die Isolation wirkt vor der Weiterleitung: Ein nicht angehakter Port ist direkt nicht erreichbar, egal was in der MAC-Tabelle steht.",
iso_legend:"Das Feld des Ports selbst ist immer erlaubt. Eine rote Portnummer markiert einen Port, der nicht ganz offen ist.",
lag_hash:"Hash:",lag_note:"Eine LAG braucht mindestens ein Mitglied, um in der Startkonfiguration gespeichert zu werden; eine leere Gruppe zu übernehmen löscht sie.",
lag_clear_q:"LAG {n} auflösen?",lag_clear_d:"Alle Mitglieds-Ports kehren in den Normalbetrieb zurück.",
lacp_heading:"LACP (802.3ad)",lag_mode:"Modus",lag_static:"Statisch",lacp_neg:"wird ausgehandelt",lacp_agg:"Aggregator",lacp_members:"aktive Mitglieder",lacp_hint:"LACP: Ports auswählen und Übernehmen drücken, um die Aushandlung zu starten",lacp_actor:"Lokal",lacp_partner:"Partner",lacp_rxstate:"Empfangsstatus",lacp_rx:"Empfangene LACPDUs",lacp_psys:"Partner-System",
e_title:"Energy Efficient Ethernet",e_adv:"Angeboten",e_lp:"Gegenstelle",e_active:"Aktiv",e_enable:"Aktivieren",
e_note:"Angebotene und von der Gegenstelle unterstützte Stufen je Geschwindigkeit: 100M, 1G, 2.5G. SFP-Ports unterstützen kein EEE.",
e_idle:"inaktiv",e_na:"k. A.",
@@ -677,8 +672,7 @@ sy_ip_err:"Ungültige IP / Netzmaske / Gateway",sy_host_err:"Hostname: 1-23 druc
sy_net_q:"Netzwerkeinstellungen übernehmen?",sy_net_d:"Die Management-IP ändert sich auf {ip}: Diese Seite muss dort neu geöffnet werden.",
sy_ip_changed:"IP geändert, neu verbinden unter http://{ip}/",sy_dhcp_q:"Auf DHCP umstellen?",
sy_dhcp_d:"Der Switch bezieht seine Adresse per DHCP. Du musst seine neue IP herausfinden, um dich wieder zu verbinden.",
sy_sysip_err:"Ungültige IP des Syslog-Servers",sy_dns1:"DNS-Server",sy_dns2:"Zweiter DNS-Server",sy_dns_err:"Ungültige IP des DNS-Servers",sy_dns_dhcp:"von DHCP: {ip}",sy_sysport_err:"Syslog-Port muss zwischen 1 und 65535 liegen",
sy_time:"Uhrzeit",sy_ntp:"NTP",sy_ntpsrv:"NTP-Server",sy_ntpsrv_p:"Hostname oder IPv4-Adresse",sy_ntpint:"Abfrageintervall [min]",sy_tz:"Zeitzone",sy_dst:"Sommerzeit",sy_dst_eu:"Europa",sy_dst_us:"USA",sy_now:"Lokale Zeit",sy_sync:"Letzte Synchronisation",sy_ntpaddr:"Server-Adresse",sy_nosync:"nicht synchronisiert",sy_waiting:"warte auf den Server",sy_ago:"vor {n} min",sy_ntp_err:"Hostname oder IPv4-Adresse des NTP-Servers eingeben",sy_ntpint_err:"Abfrageintervall muss zwischen 1 und 1440 liegen",sy_time_note:"Der Switch hat keine batteriegepufferte Uhr: Die Zeit geht bei jedem Neustart verloren und wird neu vom NTP-Server bezogen, sobald das Netzwerk bereit ist. Im Flash speichern, damit die Einstellungen erhalten bleiben.",
sy_sysip_err:"Ungültige IP des Syslog-Servers",sy_sysport_err:"Syslog-Port muss zwischen 1 und 65535 liegen",
sy_pw_len:"Passwort: 1-20 Zeichen",sy_pw_space:"Das Passwort darf keine Leerzeichen enthalten",sy_pw_match:"Die Passwörter stimmen nicht überein",
sy_pw_q:"Admin-Passwort ändern?",sy_pw_d:"Gilt sofort für neue Anmeldungen. Im Flash speichern, damit es erhalten bleibt.",
sy_reboot_q:"Switch neu starten?",sy_reboot_d:"Es gibt UNGESPEICHERTE Änderungen, sie gehen verloren. Zuerst im Flash speichern, wenn du sie behalten willst.",
@@ -964,7 +958,6 @@ function pollStatus(){
});
}
var statusPoller=new Poller(pollStatus,2500);
statusPoller.start();
function needPorts(fn){
if(S.n)return fn();
pollStatus().then(fn).catch(function(){});
@@ -1109,7 +1102,8 @@ function dashStatus(){
});
}
tabHooks.dash={
enter:function(){pollInfo().catch(function(){})},
enter:function(){statusPoller.start();pollInfo().catch(function(){})},
leave:function(){statusPoller.stop()},
status:dashStatus,
};
@@ -1153,12 +1147,31 @@ function loadMtu(){
});
});
}
/* One learned MAC is the attached device; several means a switch or AP
* sits behind the port, so only the count is shown. */
function portsMacs(){
l2Load().then(function(all){
var by={};
all.forEach(function(e){
if(e.pport==="CPU")return;
var l=by[e.pport]=by[e.pport]||[];
if(l.indexOf(e.mac)<0)l.push(e.mac);
});
S.ports.forEach(function(p){
var el=$("pmac"+(p.portNum-1));
if(!el)return;
var m=by[p.portNum]||[];
el.textContent=!m.length?"-":(m.length===1?m[0]:m.length+" "+t("c_devices"));
el.title=m.join("\n");
});
}).catch(function(){});
}
var _macTick=0;
function portsStatus(){
buildPorts();
if(++_macTick%10===0)portsMacs();
S.ports.forEach(function(p){
var i=p.portNum-1,el=$("plink"+i);
var mc=$("pmac"+i);
if(mc)mc.textContent=parseInt(p.macs,16)&0x1fff;
if(el)el.innerHTML=linkBadge(p);
var sel=$("pspd"+i),v=p.isSFP?0:ADVSEL[parseInt(p.adv,2)];
if(sel&&v&&document.activeElement!==sel)sel.value=v;
@@ -1186,7 +1199,8 @@ function applyPort(i){
postCmds(cmds).then(loadMtu).catch(function(){});
}
tabHooks.ports={
enter:function(){needPorts(buildPorts)},
enter:function(){statusPoller.start();needPorts(function(){buildPorts();portsMacs()})},
leave:function(){statusPoller.stop();l2Gen++},
status:portsStatus,
};
@@ -1442,7 +1456,8 @@ function statsStatus(){
});
}
tabHooks.stats={
leave:function(){if(ctrPoll)ctrPoll.stop()},
enter:function(){statusPoller.start()},
leave:function(){statusPoller.stop();if(ctrPoll)ctrPoll.stop()},
status:statsStatus,
};
+14 -18
View File
@@ -55,11 +55,11 @@ a{color:var(--ac);text-decoration:none}
#navfoot{padding:10px 16px;border-top:1px solid var(--bd);font-size:12px;color:var(--fg2)}
#wrap{flex:1;min-width:0;display:flex;flex-direction:column}
#top{
display:flex;align-items:center;flex-wrap:wrap;gap:10px;padding:8px 20px;
display:flex;align-items:center;gap:10px;padding:10px 20px;
background:var(--panel);border-bottom:1px solid var(--bd);position:sticky;top:0;z-index:5;
}
#burger{display:none;background:none;border:0;cursor:pointer;padding:4px}
#ttitle{font-size:16px;font-weight:650;min-width:120px}
#ttitle{font-size:16px;font-weight:650;flex:1}
#dirty{
display:none;font-size:12px;font-weight:600;color:var(--warn);
border:1px solid var(--warn);border-radius:20px;padding:2px 10px;
@@ -112,21 +112,19 @@ label.row span.lb{width:110px;flex:none;color:var(--fg2);font-size:13px}
}
.switch input:checked+i{background:var(--ok)}
.switch input:checked+i:before{transform:translateX(15px)}
#strip{display:flex;gap:6px;flex:1;min-width:0;overflow-x:auto;scrollbar-width:thin}
.port:first-child{margin-left:auto}
.port:last-child{margin-right:auto}
#strip{display:flex;gap:8px;flex-wrap:wrap;padding:4px 0 2px}
.port{
width:40px;border:2px solid var(--bd);border-radius:7px;padding:3px 0 2px;
width:46px;border:2px solid var(--bd);border-radius:7px;padding:5px 0 3px;
text-align:center;cursor:pointer;background:var(--panel2);position:relative;
}
.port.sfp{width:50px}
.port .pn{font-weight:650;font-size:12px}
.port .ps{font-size:9px;color:var(--fg2);display:block;line-height:1.2}
.port.sfp{width:56px}
.port .pn{font-weight:650;font-size:13px}
.port .ps{font-size:10px;color:var(--fg2);display:block;line-height:1.2}
.port .jack{
display:block;width:16px;height:10px;margin:2px auto 1px;border-radius:2px;
border:2px solid var(--fg2);border-top-width:4px;opacity:.55;
display:block;width:18px;height:12px;margin:3px auto 2px;border-radius:2px;
border:2px solid var(--fg2);border-top-width:5px;opacity:.55;
}
.port.sfp .jack{width:24px;height:9px;border-top-width:3px}
.port.sfp .jack{width:28px;height:10px;border-top-width:3px}
.port.up{border-color:var(--pc);background:color-mix(in srgb,var(--pc) 10%,var(--panel2))}
.port.up .jack{border-color:var(--pc);opacity:1}
.port.up .ps{color:var(--pc);font-weight:600}
@@ -185,10 +183,6 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
#ttitle{font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#dirty{padding:2px 7px}
}
@media (max-width:720px){
#ttitle{flex:1}
#strip{order:3;flex-basis:100%}
}
</style>
<script>
(function(){
@@ -221,13 +215,15 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--fg)" stroke-width="2"><path d="M4 6h16M4 12h16M4 18h16"/></svg>
</button>
<span id="ttitle"></span>
<div id="strip"></div>
<span id="dirty" data-i18n="hdr_dirty" data-i18n-t="hdr_dirty_t">unsaved changes</span>
<button class="ctl pri" id="saveBtn" data-i18n="hdr_save" data-i18n-t="hdr_save_t">Save to flash</button>
</header>
<main>
<section class="tab act" id="tab-dash">
<div class="card"><h2><span data-i18n="d_ports">Ports</span> <span class="hint" data-i18n="d_ports_h">click a port for details</span></h2>
<div id="strip"></div>
</div>
<div class="grid2">
<div class="card"><h2 data-i18n="d_system">System</h2><table class="t" id="sysinfo"></table></div>
<div class="card"><h2><span data-i18n="d_traffic">Traffic</span> <span class="hint" data-i18n="d_traffic_h">packets/s, live</span></h2>
@@ -241,7 +237,7 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
<section class="tab" id="tab-ports">
<div class="card"><h2 data-i18n="pt_title">Port configuration</h2>
<div class="scrollx"><table class="t" id="ptable">
<thead><tr><th data-i18n="c_port">Port</th><th data-i18n="c_name">Name</th><th data-i18n="c_link">Link</th><th data-i18n="pt_conn">Devices learned</th><th data-i18n="pt_speed">Speed</th><th data-i18n="c_enabled">Enabled</th><th data-i18n="pt_mtu">MTU</th><th></th></tr></thead>
<thead><tr><th data-i18n="c_port">Port</th><th data-i18n="c_name">Name</th><th data-i18n="c_link">Link</th><th data-i18n="pt_conn">Connected</th><th data-i18n="pt_speed">Speed</th><th data-i18n="c_enabled">Enabled</th><th data-i18n="pt_mtu">MTU</th><th></th></tr></thead>
<tbody></tbody></table></div>
<p class="small mut" style="margin-top:8px" data-i18n="pt_sfp_note">SFP speed is set per slot and is not saved in the startup config.</p>
</div>
-3
View File
@@ -1111,9 +1111,6 @@ void send_status(void)
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, "\",\"macs\":\"0x");
reg_to_html(RTL837X_L2_LRN_PORT_CONSTRT_CNT + (i << 2));
slen += strtox(outbuf + slen, "\"}");
if (i < machine.max_port)
char_to_html(',');
-6
View File
@@ -64,12 +64,6 @@ struct machine {
uint8_t led_mux_custom;
uint8_t led_mux[28];
uint32_t mac_flash_offset;
// Read the flash with single-IO (CMD_FREAD) instead of DIO for MMIO/code
// fetch. Set for boards whose flash chip is not usable in DIO mode, which
// shows up as a board that does not boot at all, garbled console output or
// random resets. Costs management-plane speed only, the ASIC keeps
// forwarding in hardware.
uint8_t flash_sio;
};
struct machine_runtime
-1
View File
@@ -1 +0,0 @@
SWTG018AS_A_V_2_0.c
-6
View File
@@ -1,6 +0,0 @@
#ifndef _MACHINE_2G08110GSN_H_
#define _MACHINE_2G08110GSN_H_
#define MACHINE_MODEL "MokerLink 2G08110GSN"
#endif
-54
View File
@@ -1,54 +0,0 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
/* Same 2M-PCB43-V1.1 board family as the KP-9000-6XH-X2 (see
* machine/KP_9000_6XHML_X2.c), but the two SFP+ cages (physical ports 5 and
* 6) are wired the other way round: physical 5 is on SDS1, physical 6 on
* SDS0. Copper ports 1-4 match the KP-9000 layout. */
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
// Left SFP cage (physical port 5) = SDS1
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
// Right SFP cage (physical port 6) = SDS0
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[1].pin_los = GPIO10_LED10,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
/* The board has a 3-hole reset button footprint, but it is unpopulated and
* the case has no opening for it, so reset_pin stays GPIO_NA. GPIO54, the
* reset pin on the KP-9000 layout, reads as permanently pressed here. */
.reset_pin = GPIO_NA,
/* The fitted T25S40 does not work in DIO mode on this board, so read the flash
* with single-IO; see doc/devices/2G5F4_10G2_V1.01.md. */
.flash_sio = 1,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0},
/* Conditions for LED on:
* dual led orange: ledset_0 & ledset_2
* dual led green: ledset_2 & !ledset_0
* single right led green: ledset_0 & !ledset_1
*
* Measured on this board: LED-ID0 is the copper blue LED, LED-ID1 the
* copper white one (setting LED-ID0 to 0 killed blue while leaving white on
* at 2.5G only) and LED-ID2 carries the SFP single LED. The "solid"
* conditions (LINK/speed) barely drive the LEDs here and ACT is what
* actually lights them, which is why the white LED used to glow faintly at
* non-2.5G speeds; the fix for that is LED_GLB_IO_EN bit 6, set in
* machine_init.c. */
.led_sets = { { LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
LEDS_2G5 | LEDS_LINK | LEDS_10G,
LEDS_1G | LEDS_LINK,
0 },
},
};
-6
View File
@@ -1,6 +0,0 @@
#ifndef _MACHINE_2G5F4_10G2_V1_01_H_
#define _MACHINE_2G5F4_10G2_V1_01_H_
#define MACHINE_MODEL "2G5F4_10G2_V1.01 / SGT0204S"
#endif
-1
View File
@@ -1 +0,0 @@
KP_9000_9XH_X_EU.c
+25
View File
@@ -0,0 +1,25 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0},
.led_sets = { { LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5,
LEDS_2G5 | LEDS_LINK,
LEDS_1G | LEDS_LINK,
LEDS_2G5 | LEDS_LINK | LEDS_ACT },
},
};
-1
View File
@@ -1 +0,0 @@
PCB_K0402WS_V2.c
+55
View File
@@ -0,0 +1,55 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
/* Left SFP (logical 8, SDS1): GPIO30=ModAbs, GPIO37=RX_LOS */
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
/* Right SFP (logical 3, SDS0): GPIO50=ModAbs, GPIO51=RX_LOS */
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[1].pin_los = GPIO51_I2C_SDA2_UART1_RX,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
/* Copper ports use SET0; SFP ports use SET1 */
.port_led_set = {0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{ /* SET0: copper — LED0=amber (2.5G), LED2=green (1G/100M/10M) */
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
0,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0
},
{ /* SET1: SFP — all speeds link/act */
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0, 0
},
},
.led_mux_custom = 1,
.led_mux = {
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* GPIO0-7: unused */
0x0f, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, /* GPIO8-14 */
0x14, 0x15, 0x16, 0x18, 0x19, 0x1a, /* GPIO15-20 */
0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23 /* GPIO21-27 */
},
};
-1
View File
@@ -1 +0,0 @@
SWTG018AS_A_V_2_0.c
-6
View File
@@ -1,6 +0,0 @@
#ifndef _MACHINE_GT_ST018M_H_
#define _MACHINE_GT_ST018M_H_
#define MACHINE_MODEL "GoodTop GT-ST018M"
#endif
-1
View File
@@ -1 +0,0 @@
PCB_SWTG024AS_A_2_0_1.c
-6
View File
@@ -1,6 +0,0 @@
#ifndef _MACHINE_GT_ST024M_H_
#define _MACHINE_GT_ST024M_H_
#define MACHINE_MODEL "GoodTop GT-ST024M"
#endif
-40
View File
@@ -1,40 +0,0 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.mac_flash_offset = 0x1FC000,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO38,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO54_ACL_BIT2_EN,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = {
{
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // LED0: orange
0,
LEDS_2G5 | LEDS_LINK | LEDS_ACT, // LED2: green
0
},
{
LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT, // SFP LED0: green (both SFP LEDs are green)
0, 0, 0
}
},
.led_mux_custom = 1,
.led_mux = {
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x09,
0x0e, 0x10, 0x12, 0x0e, 0x14, 0x11, 0x12, 0x16,
0x15, 0x16, 0x18, 0x19, 0x1a, 0x1a, 0x1d, 0x1e,
0x1c, 0x1e, 0x20, 0x21
},
};
-6
View File
@@ -1,6 +0,0 @@
#ifndef _MACHINE_HASIVO_S1100P_8GT_1SX_S_H_
#define _MACHINE_HASIVO_S1100P_8GT_1SX_S_H_
#define MACHINE_MODEL "Hasivo S1100P-8GT-1SX-S"
#endif
-1
View File
@@ -1 +0,0 @@
SWTGW218AS.c
+32
View File
@@ -0,0 +1,32 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 1,
.mac_flash_offset = 0x1FC000,
.min_port = 0,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO54_ACL_BIT2_EN,
.high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = { { LEDS_2G5 | LEDS_LINK | LEDS_ACT, // Green LED (right)
0,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // Amber LED (left)
0
},
{ LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT, // SFP LED
0,
0,
0
},
},
};
-1
View File
@@ -1 +0,0 @@
PCB_SWTG024AS_A_2_0_1.c
-6
View File
@@ -1,6 +0,0 @@
#ifndef _MACHINE_HC_SWTG124AS_H_
#define _MACHINE_HC_SWTG124AS_H_
#define MACHINE_MODEL "Horaco HC-SWTG124AS"
#endif
-57
View File
@@ -1,57 +0,0 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
/* Left SFP (logical 8, SDS1): GPIO30=ModAbs, GPIO37=RX_LOS */
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
/* Right SFP (logical 3, SDS0): GPIO50=ModAbs, GPIO51=RX_LOS */
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[1].pin_los = GPIO51_I2C_SDA2_UART1_RX,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
.reset_pin = GPIO_NA,
/* These don't appear to be populated / wired-up; the power LED is always on */
.high_leds = { 0 },
/* Copper ports use SET0; SFP ports use SET1 */
.port_led_set = {0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{ /* SET0: copper — LED0=amber (2.5G), LED2=green (1G/100M/10M) */
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
0,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0
},
{ /* SET1: SFP — all speeds link/act */
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
0
},
},
.led_mux_custom = 1,
.led_mux = {
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* GPIO0-7: unused */
0x0f, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, /* GPIO8-14 */
0x14, 0x15, 0x16, 0x18, 0x19, 0x1a, /* GPIO15-20 */
0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23 /* GPIO21-27 */
},
};
-6
View File
@@ -1,6 +0,0 @@
#ifndef _MACHINE_PCB_K0402WS_V1_H_
#define _MACHINE_PCB_K0402WS_V1_H_
#define MACHINE_MODEL "PCB-K0402WS-V1.0"
#endif
+1 -1
View File
@@ -1,7 +1,7 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
-41
View File
@@ -1,41 +0,0 @@
#include "machine_defs.h"
__code const struct machine machine = {
.machine_name = MACHINE_MODEL,
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0},
.is_sfp= {0, 0, 0, 2, 0, 0, 0, 0, 1},
// Left SFP port (J4)
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ), /* GPIO 39 */
// Right SFP port (J2)
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[1].pin_los = GPIO51_I2C_SDA2_UART1_RX,
.sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ), /* GPIO 40 */
.reset_pin = GPIO36_PWM_OUT,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{ /* RJ45: Green LED */
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
0,
/* Amber LED */
LEDS_2G5 | LEDS_LINK | LEDS_ACT,
0
}, { /* SFP PORT: SINGLE GREEN LED */
LEDS_10M | LEDS_100M | LEDS_1G | LEDS_2G5 | LEDS_10G | LEDS_LINK | LEDS_ACT,
0,
0,
0,
},
},
};
-6
View File
@@ -1,6 +0,0 @@
#ifndef _MACHINE_SIRIVISION_S25G2206FP_V1_1_H_
#define _MACHINE_SIRIVISION_S25G2206FP_V1_1_H_
#define MACHINE_MODEL "SIRIVISION S25G2206FP V1.1"
#endif
-1
View File
@@ -1 +0,0 @@
PCB_SWTG018AS_V2_1_0.c
-7
View File
@@ -1,7 +0,0 @@
#ifndef _MACHINE_SKS3200_8E1X_H_
#define _MACHINE_SKS3200_8E1X_H_
#define MACHINE_MODEL "XikeStor SKS3200-8E1X"
#endif
-1
View File
@@ -38,5 +38,4 @@ __code const struct machine machine = {
0,
},
},
.mac_flash_offset = 0x1FC000,
};
-1
View File
@@ -1 +0,0 @@
SIRIVISION_S25G2206FP_V1_1.c
-6
View File
@@ -1,6 +0,0 @@
#ifndef _MACHINE_YS25_0402M_H_
#define _MACHINE_YS25_0402M_H_
#define MACHINE_MODEL "YuanLey YS25-0402M"
#endif
-1
View File
@@ -19,7 +19,6 @@
defined(MACHINE_HI_K0402WS) || \
defined(MACHINE_PCB_K0402WS_V2) || \
defined(MACHINE_PCB_K0402WS_V3) || \
defined(MACHINE_2G5F4_10G2_V1_01) || \
defined(MACHINE_FNS1200P)
void machine_custom_init(void) __banked
{
-216
View File
@@ -1,216 +0,0 @@
#include <stdint.h>
#include <stdbool.h>
#include "rtl837x_common.h"
#include "rtl837x_sfr.h"
#include "rtl837x_cabletest.h"
#include "rtl837x_phy.h"
#include "phy.h"
#include "machine.h"
#pragma codeseg BANK3
#pragma constseg BANK3
#define RTCT_CTRL 0xa422
#define RTCT_CTRL_START 0x00f1
#define RTCT_CTRL_DONE 0x8000
#define RTCT_SRAM_ADDR 0xa436
#define RTCT_SRAM_DATA 0xa438
#define RTCT_SRAM_STATUS 0x8026
#define RTCT_SRAM_LEN 0x8028
#define RTCT_ST_BUSY 0x01
#define RTCT_ST_MISMATCH 0x06
#define RTCT_ST_OPEN 0x08
#define RTCT_ST_SHORT 0x10
#define RTCT_ST_OK 0x20
#define RTCT_ST_DONE 0x40
#define RTCT_ST_CROSS_SHORT 0x80
#define RTCT_LEN_ZERO 150
#define RTCT_LEN_PER_50CM 43
#define PHY_POWER 0xa610
#define PHY_POWER_OFF 0x0800
#define BMCR_PDOWN_1G_FULL 0x0940
#define BMCR_1G_FULL 0x0140
#define BMCR_ANRESTART 0x0200
#define CT_IDLE 0
#define CT_SILENCE 1
#define CT_RUN 2
#define CT_POLL_TICKS (SYS_TICK_HZ / 20)
#define CT_POLLS 100
extern volatile __xdata uint32_t ticks;
extern __code const struct machine machine;
extern __xdata struct machine_runtime machine_detected;
__xdata uint8_t ct_state = CT_IDLE;
__xdata uint8_t ct_port;
__xdata uint8_t ct_last;
__xdata uint8_t ct_polls;
__xdata uint8_t ct_valid;
__xdata uint8_t ct_have = 0;
__xdata uint8_t ct_pair;
__xdata uint8_t ct_flags;
__xdata uint16_t ct_bmcr;
__xdata uint8_t ct_result[4];
__xdata uint16_t ct_len[4];
void rtl_phy_cable_test_start(uint8_t port) __banked
{
phy_write(port, PHY_MMD31, PHY_MMD31_FEDCR, BMCR_1G_FULL);
phy_write(port, PHY_MMD31, RTCT_CTRL, RTCT_CTRL_START);
}
bool rtl_phy_cable_test_get_status(uint8_t port) __banked
{
phy_read(port, PHY_MMD31, RTCT_CTRL);
if (!(SFR_DATA_U16 & RTCT_CTRL_DONE))
return false;
for (ct_pair = 0; ct_pair < 4; ct_pair++) {
// The flags are the low byte of the word, not the high one.
phy_write(port, PHY_MMD31, RTCT_SRAM_ADDR, RTCT_SRAM_STATUS + (ct_pair << 2));
phy_read(port, PHY_MMD31, RTCT_SRAM_DATA);
ct_flags = SFR_DATA_U16;
if (!(ct_flags & RTCT_ST_DONE))
return false;
if (ct_flags & RTCT_ST_OK)
ct_result[ct_pair] = CABLE_RESULT_OK;
else if (ct_flags & RTCT_ST_OPEN)
ct_result[ct_pair] = CABLE_RESULT_OPEN;
else if (ct_flags & RTCT_ST_SHORT)
ct_result[ct_pair] = CABLE_RESULT_SAME_SHORT;
else if (ct_flags & RTCT_ST_BUSY)
ct_result[ct_pair] = CABLE_RESULT_UNSPEC;
else if (ct_flags & RTCT_ST_CROSS_SHORT)
ct_result[ct_pair] = CABLE_RESULT_CROSS_SHORT;
else if (ct_flags & RTCT_ST_MISMATCH)
ct_result[ct_pair] = CABLE_RESULT_MISMATCH;
else
ct_result[ct_pair] = CABLE_RESULT_UNSPEC;
phy_write(port, PHY_MMD31, RTCT_SRAM_ADDR, RTCT_SRAM_LEN + (ct_pair << 2));
phy_read(port, PHY_MMD31, RTCT_SRAM_DATA);
ct_len[ct_pair] = SFR_DATA_U16;
ct_len[ct_pair] = ct_len[ct_pair] > RTCT_LEN_ZERO ? ct_len[ct_pair] - RTCT_LEN_ZERO : 0;
ct_len[ct_pair] = ct_len[ct_pair] * 5 / RTCT_LEN_PER_50CM;
}
return true;
}
static void cabletest_print(void)
{
print_string("Cable test port ");
print_phys_port(ct_port);
if (!ct_valid) {
print_string(": timed out\n");
return;
}
write_char('\n');
for (ct_pair = 0; ct_pair < 4; ct_pair++) {
print_string("Pair ");
write_char('A' + ct_pair);
switch (ct_result[ct_pair]) {
case CABLE_RESULT_OK:
print_string(": ok\n");
continue;
case CABLE_RESULT_OPEN:
print_string(": open at ");
break;
case CABLE_RESULT_SAME_SHORT:
print_string(": short at ");
break;
case CABLE_RESULT_CROSS_SHORT:
print_string(": short to another pair at ");
break;
case CABLE_RESULT_MISMATCH:
print_string(": impedance mismatch at ");
break;
default:
print_string(": unknown\n");
continue;
}
itoa_short(ct_len[ct_pair] / 10);
write_char('.');
write_char('0' + ct_len[ct_pair] % 10);
print_string(" m\n");
}
}
void cabletest_run(void) __banked
{
if (ct_state) {
print_string("Cable test running on port ");
print_phys_port(ct_port);
write_char('\n');
return;
}
if (!machine_detected.isRTL8373 && (phy_settings.port < 4 || phy_settings.port > 7)) {
print_string("No cable test on this PHY\n");
return;
}
// A test started on a port that is off never ends and blocks the PHY until reset.
phy_read(phy_settings.port, PHY_MMD31, PHY_POWER);
if (SFR_DATA_U16 & PHY_POWER_OFF) {
print_string("Port is off\n");
return;
}
ct_port = phy_settings.port;
phy_read(ct_port, PHY_MMD31, PHY_MMD31_FEDCR);
ct_bmcr = SFR_DATA_U16;
// Forcing the speed leaves the link up; only a power-down silences the partner.
phy_write(ct_port, PHY_MMD31, PHY_MMD31_FEDCR, BMCR_PDOWN_1G_FULL);
ct_last = ticks;
ct_have = 0;
ct_state = CT_SILENCE;
print_string("Cable test started\n");
}
void cabletest_show(void) __banked
{
if (ct_state)
print_string("Cable test running\n");
else if (ct_port != phy_settings.port || !ct_have)
print_string("No cable test result\n");
else
cabletest_print();
}
void cabletest_tick(void) __banked
{
if (ct_state == CT_SILENCE) {
if (!TICKS_DUE(ct_last, SYS_TICK_HZ))
return;
phy_read(ct_port, PHY_MMD31, PHY_POWER);
if (SFR_DATA_U16 & PHY_POWER_OFF) {
phy_write(ct_port, PHY_MMD31, PHY_MMD31_FEDCR, ct_bmcr);
ct_state = CT_IDLE;
print_string("Cable test aborted, port is off\n");
return;
}
rtl_phy_cable_test_start(ct_port);
ct_polls = CT_POLLS;
ct_last = ticks;
ct_state = CT_RUN;
return;
}
if (ct_state != CT_RUN || !TICKS_DUE(ct_last, CT_POLL_TICKS))
return;
ct_last = ticks;
ct_valid = rtl_phy_cable_test_get_status(ct_port);
if (!ct_valid && --ct_polls)
return;
phy_write(ct_port, PHY_MMD31, RTCT_CTRL, 0);
phy_write(ct_port, PHY_MMD31, PHY_MMD31_FEDCR, ct_bmcr | BMCR_ANRESTART);
ct_have = 1;
ct_state = CT_IDLE;
cabletest_print();
}
-21
View File
@@ -1,21 +0,0 @@
#ifndef _RTL837X_CABLETEST_H_
#define _RTL837X_CABLETEST_H_
#include <stdint.h>
#include <stdbool.h>
#define CABLE_RESULT_UNSPEC 0
#define CABLE_RESULT_OK 1
#define CABLE_RESULT_OPEN 2
#define CABLE_RESULT_SAME_SHORT 3
#define CABLE_RESULT_CROSS_SHORT 4
#define CABLE_RESULT_MISMATCH 5
void rtl_phy_cable_test_start(uint8_t port) __banked;
bool rtl_phy_cable_test_get_status(uint8_t port) __banked;
void cabletest_run(void) __banked;
void cabletest_show(void) __banked;
void cabletest_tick(void) __banked;
#endif
+2 -2
View File
@@ -23,7 +23,7 @@
// Define Port-masks for 9-port devices and 6-port devices
#define PMASK_9 0x1ff
#define PMASK_6 0x1f8
#define PMASK_CPU ((uint16_t)(1 << CPU_PORT))
#define PMASK_CPU 0x200
// Defines a port mask for dropping all packets on Lookup-miss
#define LOOKUP_MISS_DROP_6 0x00015540
@@ -142,7 +142,7 @@ extern __xdata bool stp_enabled;
* advertises it as the System Name TLV) read it from here. */
extern __xdata char hostname[24];
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE];
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
extern __xdata struct uip_eth_addr uip_ethaddr;
// Headers for calls in the common code area (HOME/BANK0)
+1 -1
View File
@@ -28,7 +28,7 @@ extern __xdata uint8_t igmpEnabled;
extern __xdata uint8_t cpuPort;
extern __xdata uint8_t sfr_data[4];
extern __xdata struct machine_runtime machine_detected;
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE];
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2];
__xdata uint16_t idx;
#define IGMP_IP_HDR offsetof(struct igmp_pkt, hlen)
+1 -1
View File
@@ -21,7 +21,7 @@ extern __code const struct machine machine;
extern __xdata struct machine_runtime machine_detected;
extern __xdata uint16_t management_vlan;
extern __xdata struct uip_eth_addr uip_ethaddr;
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE];
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2];
/* 20-byte Actor/Partner information body (802.3ad 43.4.2.2), network byte order */
struct lacp_info {
-90
View File
@@ -1,90 +0,0 @@
#include "rtl837x_common.h"
#include "rtl837x_regs.h"
#include "rtl837x_sfr.h"
#include "rtl837x_nic.h"
extern __xdata uint8_t rx_headers[16];
#ifndef RTLP_HOST_TEST
/* One RX DMA operation, starting inside the configured ring. The hardware
* wraps transfers that cross its end; the initial address must be normalized.
* Host tests supply a simulated DMA engine for this hardware boundary. */
bool nic_rx_dma(__xdata uint8_t *buffer, uint16_t ring_ptr, uint8_t words) __reentrant
{
uint16_t guard = 0;
SFR_NIC_DATA_U16LE = (uint16_t)buffer;
SFR_NIC_RING_U16LE = ring_ptr;
SFR_NIC_CTRL = words;
while (SFR_NIC_CTRL != 0) {
if (++guard == 0) {
print_string("NIC: RX transfer did not complete\n");
return false;
}
}
return true;
}
#endif
static bool nic_rx_copy(__xdata uint8_t *buffer, uint16_t ring_ptr, uint8_t words) __reentrant
{
if (ring_ptr > RTL837X_NIC_RX_RING_BYTES || (ring_ptr & 7))
return false;
if (ring_ptr == RTL837X_NIC_RX_RING_BYTES)
ring_ptr = 0;
return nic_rx_dma(buffer, ring_ptr, words);
}
bool nic_rx_header(uint16_t ring_ptr) __reentrant
{
if (ring_ptr >= RTL837X_NIC_RX_RING_BYTES)
return false;
return nic_rx_copy(rx_headers, ring_ptr, 1);
}
bool nic_rx_packet(__xdata uint8_t *buffer, uint16_t ring_ptr) __reentrant
{
uint16_t len = ((uint16_t)rx_headers[5] << 8) | rx_headers[4];
if (!len || len > UIP_CONF_BUFFER_SIZE)
return false;
return nic_rx_copy(buffer, ring_ptr, (len + 7) >> 3);
}
/*
* Transfers data in XMEM to the ASIC for transmission by the NIC
*/
void nic_tx_packet(__xdata uint8_t *buffer, uint16_t len, uint16_t ring_ptr)
{
uint16_t guard = 0;
SFR_NIC_DATA_U16LE = (uint16_t)(uintptr_t)buffer;
#ifdef RXTXDBG
print_string("TX: \n");
for (uint8_t i = 0; i < 100; i++) {
print_byte(uip_buf[i]);
write_char(' ');
}
write_char('\n');
#endif
ring_ptr <<= 3;
ring_ptr |= 0x8000;
SFR_NIC_RING_U16LE = ring_ptr;
len += 0xf;
len >>= 3;
SFR_NIC_CTRL = len;
while (SFR_NIC_CTRL != 0) {
if (++guard == 0) {
print_string("NIC: TX transfer did not complete\n");
return;
}
}
}
-20
View File
@@ -1,20 +0,0 @@
#ifndef RTL837X_NIC_H
#define RTL837X_NIC_H
#include <stdbool.h>
#include <stdint.h>
// #define RXTXDBG 1
bool nic_rx_header(uint16_t ring_ptr) __reentrant;
bool nic_rx_packet(__xdata uint8_t *buffer, uint16_t ring_ptr) __reentrant;
/* buffer starts at the eight-byte NIC descriptor; len excludes that
* descriptor. ring_ptr is the ASIC TX position in eight-byte slots. */
void nic_tx_packet(__xdata uint8_t *buffer, uint16_t len, uint16_t ring_ptr);
/* RX DMA in eight-byte units. ring_ptr must start inside the configured
* RX ring; the hardware wraps transfers that cross its end. */
bool nic_rx_dma(__xdata uint8_t *buffer, uint16_t ring_ptr, uint8_t words) __reentrant;
#endif
+2 -5
View File
@@ -57,7 +57,7 @@ void port_mirror_del(void) __banked
bool port_ingress_filter(__xdata uint8_t port, __xdata vlan_ingress_mode_t type) __banked
{
if (port > CPU_PORT || type >= VLAN_INVALID) {
if (port > 9 || type >= VLAN_INVALID) {
print_string("Invalid port or ingress filter type\n");
return false;
}
@@ -510,7 +510,7 @@ void port_media_show(uint8_t port) __banked
void port_stats_print(void) __banked
{
print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\t\tMACs\n");
print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n");
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
print_phys_port(i); write_char('\t');
@@ -584,9 +584,6 @@ void port_stats_print(void) __banked
STAT_GET(STAT_COUNTER_ERR_PKTS, i);
print_reg(RTL837X_STAT_V_HIGH); write_char('\t');
reg_read(RTL837X_L2_LRN_PORT_CONSTRT_CNT + (i << 2));
itoa_short(SFR_DATA_U16 & L2_LRN_PORT_CNT_MASK);
print_string("\n");
}
}
-5
View File
@@ -147,9 +147,6 @@
*/
#define RTL837X_REG_NIC_BUFFSIZE_TX 0x7844
#define RTL837X_REG_NIC_RXBUFF_RX 0x7848
/* RX ring: inclusive final eight-byte slot, as programmed by nic_setup(). */
#define RTL837X_NIC_RX_LAST_SLOT 0x04ff
#define RTL837X_NIC_RX_RING_BYTES ((RTL837X_NIC_RX_LAST_SLOT + 1U) * 8U)
#define RTL837X_REG_NIC_RXCMD 0x784c
#define RTL837X_REG_NIC_TXCMD 0x7850
#define RTL837X_REG_RX_CTRL 0x785c
@@ -217,8 +214,6 @@
#define RTL837x_L2_TBL_FLUSH_CNF 0x53dc
#define RTL837X_L2_LRN_PORT_CONSTRAINT 0x5384
#define RTL837X_L2_LRN_PORT_CONSTRT_ACT 0x4f80
#define RTL837X_L2_LRN_PORT_CONSTRT_CNT 0x53ac
#define L2_LRN_PORT_CNT_MASK 0x1fff
#define RTL8373_REG_MAC_L2_PORT_MAX_LEN 0x1250
/*
+1 -1
View File
@@ -30,7 +30,7 @@ extern __xdata struct machine_runtime machine_detected;
extern __xdata struct uip_eth_addr uip_ethaddr;
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE];
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2];
extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
extern __xdata uint8_t cmd_words_len;
+1 -1
View File
@@ -46,7 +46,7 @@ extern __xdata uint8_t stp_pflags[STP_ENTITIES];
extern __xdata uint32_t stp_pcost[STP_ENTITIES]; /* path cost; 0 = auto (20000) */
extern __xdata uint8_t stp_pprio[STP_ENTITIES];
extern __xdata uint8_t stp_pp2p[STP_ENTITIES];
extern __xdata uint8_t stp_ent_of[STP_PORTS]; /* the STP entity a port answers to: itself, or its lag */
extern __xdata uint8_t stp_ent_of[10]; /* the STP entity a port answers to: itself, or its lag */
extern __xdata uint16_t stp_lag_mask[STP_LAG_COUNT]; /* member ports of each lag; 0 = not part of STP */
/* Last-heard designated info per port (from received BPDUs); consult
+111 -13
View File
@@ -2,6 +2,7 @@
#include <stdint.h>
// #define REGDBG 1
// #define RXTXDBG 1
#include "rtl837x_sfr.h"
#include "rtl837x_regs.h"
@@ -11,7 +12,6 @@
#include "rtl837x_phy.h"
#include "rtl837x_port.h"
#include "rtl837x_trap.h"
#include "rtl837x_nic.h"
#include "rtl837x_stp.h"
#include "rtl837x_lacp.h"
#include "rtl837x_igmp.h"
@@ -19,7 +19,6 @@
#include "rtl837x_bandwidth.h"
#include "rtl837x_init.h"
#include "rtl837x_lldp.h"
#include "rtl837x_cabletest.h"
#include "dhcp.h"
#include "cmd_parser.h"
#include "cmd_editor.h"
@@ -34,6 +33,7 @@
#include "httpd/page_impl.h"
#include "boot.h"
#include "sfp.h"
#include "crypto/chacha.h"
extern __code const struct machine machine;
extern __xdata uint32_t flash_size;
@@ -123,8 +123,8 @@ __code const uint8_t * __code const hex = "0123456789abcdef";
__xdata uint8_t flash_buf[FLASH_BUF_SIZE];
// NIC buffers for packet RX/TX
__xdata uint8_t rx_headers[16]; // RX descriptor
__xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE];
__xdata uint8_t rx_headers[16]; // Packet header(s) on RX
__xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
__xdata uint16_t rx_packet_vlan;
__xdata uint16_t management_vlan;
@@ -714,6 +714,108 @@ void get_random_32(void)
}
/*
* Transfer Network Interface RX data from the ASIC to the 8051 XMEM
* data will be stored in the rx_header structure
* len is the length of data to be transferred
*/
bool nic_rx_header(uint16_t ring_ptr)
{
uint16_t buffer = (uint16_t) &rx_headers[0];
uint16_t guard = 0;
SFR_NIC_DATA_U16LE = buffer;
SFR_NIC_RING_U16LE = ring_ptr;
SFR_NIC_CTRL = 1;
while (SFR_NIC_CTRL != 0) {
if (++guard == 0) {
print_string("NIC: RX header transfer did not complete\n");
return false;
}
}
return true;
}
/*
* Transfer Network Interface RX data from the ASIC to the 8051 XMEM
* the description of the packet must be in the rx_headers data structure
* data will be returned in the xmem buffer points to
* ring_ptr is the current position of the RX Ring on the ASIC side
*/
bool nic_rx_packet(uint16_t buffer, uint16_t ring_ptr)
{
uint16_t guard = 0;
SFR_NIC_DATA_U16LE = buffer;
SFR_NIC_RING_U16LE = ring_ptr;
uint16_t len = (((uint16_t)rx_headers[5]) << 8) | rx_headers[4];
len += 7;
len >>= 3;
#ifdef RXTXDBG
print_string(" len: ");
print_short(len);
#endif
SFR_NIC_CTRL = len;
while (SFR_NIC_CTRL != 0) {
if (++guard == 0) {
print_string("NIC: RX transfer did not complete\n");
return false;
}
}
return true;
}
/*
* Transfers data in XMEM to the ASIC for transmission by the nic
*/
void nic_tx_packet(uint16_t ring_ptr)
{
uint16_t len;
uint16_t guard = 0;
/* A frame that got a dot1Q tag was shifted forward over its padding, so it
* starts at uip_buf and carries the q_frame layout. One that did not keeps
* the padding in front and the nonq_frame layout, so the padding is skipped.
*/
if (frame_tagged) {
SFR_NIC_DATA_U16LE = (uint16_t) uip_buf;
len = FRAME_Q->len;
/*
(__xdata struct rtl_dot1q_frame *)uip_buf
#define FRAME (((__xdata struct rtl_dot1q_frame *)&uip_buf[0]).nonq_frame)*/
} else {
SFR_NIC_DATA_U16LE = (uint16_t) uip_buf + VLAN_TAG_SIZE;
len = FRAME->len;
}
#ifdef RXTXDBG
print_string("TX: \n");
for (uint8_t i = 0; i < 100; i++) {
print_byte(uip_buf[i]);
write_char(' ');
}
write_char('\n');
#endif
ring_ptr <<= 3;
ring_ptr |= 0x8000;
SFR_NIC_RING_U16LE = ring_ptr;
len += 0xf;
len >>= 3;
SFR_NIC_CTRL = len;
while (SFR_NIC_CTRL != 0) {
if (++guard == 0) {
print_string("NIC: TX transfer did not complete\n");
return;
}
}
}
/* Read flash using the MMIO capabilities of the DW8051 core
* Bank is < 0x3f and is the MSB
* addr gives the address in the bank
@@ -897,12 +999,8 @@ void tcpip_output(void)
uint16_t ring_ptr = ((uint16_t)sfr_data[2]) << 8;
ring_ptr |= sfr_data[3];
// Move data over from xmem buffer to ASIC side using DMA. A VLAN-tagged
// frame starts at uip_buf; an untagged frame retains four bytes of padding.
if (frame_tagged)
nic_tx_packet(uip_buf, FRAME_Q->len, ring_ptr);
else
nic_tx_packet(uip_buf + VLAN_TAG_SIZE, FRAME->len, ring_ptr);
// Move data over from xmem buffer to ASIC side using DMA
nic_tx_packet(ring_ptr);
// New position of the ring-pointer on the NIC-side indicates number of bytes transmitted
reg_read_m(RTL837X_REG_NIC_TX_CURR_PKT);
@@ -939,7 +1037,7 @@ void handle_rx(void)
write_char(' ');
}
#endif
if (!nic_rx_packet(uip_buf, ring_ptr + 8)) {
if (!nic_rx_packet((uint16_t) &uip_buf[0], ring_ptr + 8)) {
REG_SET(RTL837X_REG_NIC_RXCMD, 1);
return;
}
@@ -1204,7 +1302,6 @@ static void handle_tick(void)
health_phase(HEALTH_PH_STP);
lldp_tick();
health_phase(HEALTH_LLDP);
cabletest_tick();
}
@@ -1586,7 +1683,7 @@ void main(void)
// Flash controller should be initialized before any code in other banks is being fetched
// See this issue: https://github.com/logicog/RTLPlayground/issues/70
print_string("\nInitializing Flash controller\n");
flash_init(machine.flash_sio ? 0 : 1);
flash_init(1);
// Set default for SFP pins so we can start up a module already inserted
sfp_pins_last = 0x33; // signal LOS and no module inserted (for both slots, even if only 1 present)
@@ -1707,6 +1804,7 @@ void main(void)
lacpEnabled = 0;
lacp_init();
nic_setup();
REG_SET(RTL837X_NIC_INT_MSK, NIC_INT_RXIE);
trap_init();
vlan_setup();
port_l2_setup();
-6
View File
@@ -29,7 +29,6 @@ TESTS = $(BUILDDIR)/test_cmd_editor \
$(BUILDDIR)/test_page_json \
$(BUILDDIR)/test_httpd_tx \
$(BUILDDIR)/test_tick_gate \
$(BUILDDIR)/test_nic_rx \
$(BUILDDIR)/test_lacp
# The table tests link the register mock and one environment file; stub/
@@ -53,11 +52,6 @@ $(BUILDDIR)/test_port_tables: test_port_tables.c $(TABLE_ENV) hw_mock.h | $(BUIL
$(BUILDDIR)/test_tick_gate: test_tick_gate.c support.c $(SRCROOT)/cmd_editor.c | $(BUILDDIR)
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
# Exercise the production RX ring reader; only the hardware DMA edge is mocked.
# Discard unused TX functions so this RX fixture needs no TX register mocks.
$(BUILDDIR)/test_nic_rx: test_nic_rx.c $(SRCROOT)/rtl837x_nic.c $(SRCROOT)/rtl837x_nic.h | $(BUILDDIR)
$(CC) $(CFLAGS) -ffunction-sections -fdata-sections $(filter %.c,$^) -o $@ $(LDFLAGS) -Wl,--gc-sections
$(BUILDDIR)/test_page_json: test_page_json.c $(TABLE_ENV) hw_mock.h | $(BUILDDIR)
$(CC) $(CFLAGS) $(filter %.c,$^) -o $@ $(LDFLAGS)
+1 -1
View File
@@ -112,7 +112,7 @@ void read_reg_timer(uint32_t *tmr) { *tmr = 0; }
/* uip-conf.h asks uIP not to define the packet buffer: on the switch it lives
* at a fixed XDATA address, so the bench provides the storage itself. */
u8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE];
u8_t uip_buf[UIP_BUFSIZE + 2];
uint16_t strlen_x(const char *s) { return (uint16_t)strlen(s); }
+1 -1
View File
@@ -11,7 +11,7 @@
/* ---------- platform mocks ---------- */
uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE];
uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2];
uint16_t uip_len;
struct uip_eth_addr uip_ethaddr = { .addr = {0x02,0x11,0x22,0x33,0x44,0x55} };
const struct machine machine = { .min_port = 0, .max_port = 7,
-277
View File
@@ -1,277 +0,0 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "rtl837x_common.h"
#include "rtl837x_regs.h"
#include "rtl837x_nic.h"
uint8_t rx_headers[16];
/* Model the DMA behavior reported on SWTGW218AS: a transfer starting inside
* the RX ring wraps at its end. An initial address outside the ring instead
* reads flat ASIC memory, including stale TX bytes at 0x2800. */
static uint8_t asic[0x8000];
static struct {
uint8_t before[16];
uint8_t data[UIP_CONF_BUFFER_ALLOC_SIZE];
uint8_t after[16];
} destination;
struct dma_request {
uint8_t *buffer;
uint16_t ring;
uint8_t words;
};
static struct dma_request requests[8];
static unsigned request_count, fail_request;
static int failures;
static void check(bool condition, const char *what)
{
if (!condition) {
printf(" FAIL: %s\n", what);
failures++;
}
}
bool nic_rx_dma(uint8_t *buffer, uint16_t ring, uint8_t words)
{
size_t bytes = (size_t)words * 8;
unsigned call = ++request_count;
if (call <= sizeof(requests) / sizeof(requests[0]))
requests[call - 1] = (struct dma_request){ buffer, ring, words };
if (call == fail_request || !words || (size_t)ring + bytes > sizeof(asic))
return false;
if (ring < RTL837X_NIC_RX_RING_BYTES) {
for (size_t i = 0; i < bytes; i++)
buffer[i] = asic[((size_t)ring + i) % RTL837X_NIC_RX_RING_BYTES];
} else {
memcpy(buffer, asic + ring, bytes);
}
return true;
}
static void fixture_reset(void)
{
memset(asic, 0xd7, sizeof(asic));
memset(&destination, 0xa5, sizeof(destination));
memset(rx_headers, 0x6c, sizeof(rx_headers));
memset(requests, 0, sizeof(requests));
request_count = 0;
fail_request = 0;
}
static bool filled(const uint8_t *data, size_t len, uint8_t value)
{
while (len--)
if (*data++ != value)
return false;
return true;
}
static bool guards_intact(void)
{
return filled(destination.before, sizeof(destination.before), 0xa5)
&& filled(destination.after, sizeof(destination.after), 0xa5);
}
static bool requests_start_in_rx_ring(void)
{
for (unsigned i = 0; i < request_count; i++) {
if (i >= sizeof(requests) / sizeof(requests[0]) || !requests[i].words
|| (requests[i].ring & 7)
|| requests[i].ring >= RTL837X_NIC_RX_RING_BYTES)
return false;
}
return true;
}
static void ring_write(uint16_t offset, const uint8_t *data, size_t len)
{
for (size_t i = 0; i < len; i++)
asic[((size_t)offset + i) % RTL837X_NIC_RX_RING_BYTES] = data[i];
}
static void put_descriptor(uint16_t offset, uint16_t len)
{
uint8_t descriptor[8] = { 0x03, 0x00, 0xb0, 0xc8, len, len >> 8, 0, 0 };
ring_write(offset, descriptor, sizeof(descriptor));
}
static void expect_descriptor(uint16_t len)
{
uint8_t descriptor[8] = { 0x03, 0x00, 0xb0, 0xc8, len, len >> 8, 0, 0 };
check(!memcmp(rx_headers, descriptor, sizeof(descriptor)), "the first eight descriptor bytes stay intact");
}
static void pattern(uint8_t *data, size_t len)
{
for (size_t i = 0; i < len; i++)
data[i] = (uint8_t)(i * 37 + (i >> 8) + 0x13);
}
static void t_last_descriptor(void)
{
static const uint8_t root_bpdu[68] = {
0x01, 0x80, 0xc2, 0, 0, 0, 0xd0, 0xea, 0x11, 0x12, 0x34, 0x56,
0x88, 0x99, 0x04, 0, 0, 0, 0, 8,
0, 0x27, 0x42, 0x42, 3, 0, 0, 2, 2, 0x3c,
0x10, 0, 0xd0, 0xea, 0x11, 0x12, 0x34, 0x56, 0, 0, 0, 0,
0x10, 0, 0xd0, 0xea, 0x11, 0x12, 0x34, 0x56, 0x80, 0x0a,
0, 0, 0x14, 0, 2, 0, 0x0f, 0, 0
};
uint8_t stale_tx[72] = { 0 };
uint16_t last = RTL837X_NIC_RX_RING_BYTES - 8;
printf("[test] the last RX descriptor wraps its BPDU payload before DMA\n");
fixture_reset();
put_descriptor(last, sizeof(root_bpdu));
ring_write(0, root_bpdu, sizeof(root_bpdu));
memcpy(stale_tx, root_bpdu, sizeof(root_bpdu));
stale_tx[17] = 0x20;
stale_tx[19] = 1; /* retained TX destination mask, not ingress port 8 */
memcpy(asic + RTL837X_NIC_RX_RING_BYTES, stale_tx, sizeof(stale_tx));
check(nic_rx_header(last), "the final descriptor is readable");
expect_descriptor(sizeof(root_bpdu));
check(nic_rx_packet(destination.data, last + 8), "a payload address at the RX ring limit wraps to zero");
check(!memcmp(destination.data, root_bpdu, sizeof(root_bpdu)), "the complete upstream BPDU is read instead of stale TX bytes");
check(destination.data[19] == 8, "the upstream ingress tag survives the ring boundary");
check(request_count == 2 && requests[0].ring == last && requests[0].words == 1
&& requests[1].ring == 0 && requests[1].words == 9,
"descriptor and rounded payload DMA both start in the RX ring");
check(requests_start_in_rx_ring() && guards_intact(), "DMA starts inside the RX ring and preserves destination guards");
expect_descriptor(sizeof(root_bpdu));
}
static void t_payload_layouts(void)
{
static const struct {
uint16_t descriptor, len;
} cases[] = {
{ 0x0100, 8 }, { 0x0100, 16 }, { 0x0100, 64 },
{ 0x0100, 68 }, { 0x0100, 72 },
{ RTL837X_NIC_RX_RING_BYTES - 16, 8 },
{ RTL837X_NIC_RX_RING_BYTES - 16, 16 },
{ RTL837X_NIC_RX_RING_BYTES - 16, 68 },
{ RTL837X_NIC_RX_RING_BYTES - 72, 64 },
{ RTL837X_NIC_RX_RING_BYTES - 48, 68 }
};
uint8_t frame[80];
printf("[test] payload DMA handles ordinary, exact-boundary, and crossing frames\n");
pattern(frame, sizeof(frame));
for (unsigned i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
size_t rounded = (cases[i].len + 7u) & ~7u;
fixture_reset();
put_descriptor(cases[i].descriptor, cases[i].len);
ring_write(cases[i].descriptor + 8, frame, rounded);
check(nic_rx_header(cases[i].descriptor), "the descriptor transfer completes");
check(nic_rx_packet(destination.data, cases[i].descriptor + 8), "the payload transfer completes");
check(!memcmp(destination.data, frame, rounded), "every payload and permitted padding byte reaches the correct destination offset");
check(filled(destination.data + rounded, sizeof(destination.data) - rounded, 0xa5), "DMA does not write beyond the rounded frame");
check(request_count == 2, "the payload uses one DMA request even when crossing the ring end");
check(requests_start_in_rx_ring() && guards_intact(), "crossing DMA starts inside the RX ring and preserves destination guards");
expect_descriptor(cases[i].len);
}
}
static void t_maximum_frames(void)
{
uint8_t frame[(UIP_CONF_BUFFER_SIZE + 7u) & ~7u];
static const uint16_t lengths[] = { 1, 7, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556 };
printf("[test] rounded maximum frames fit without overwriting their descriptor\n");
pattern(frame, sizeof(frame));
for (unsigned layout = 0; layout < 3; layout++) {
uint16_t descriptor = layout == 0 ? 0x0100
: RTL837X_NIC_RX_RING_BYTES - (layout == 1 ? 16 : 8);
for (unsigned i = 0; i < sizeof(lengths) / sizeof(lengths[0]); i++) {
uint16_t len = lengths[i];
size_t rounded = (len + 7u) & ~7u;
fixture_reset();
put_descriptor(descriptor, len);
ring_write(descriptor + 8, frame, rounded);
check(nic_rx_header(descriptor), "the maximum-frame descriptor transfer completes");
check(nic_rx_packet(destination.data, descriptor + 8), "all supported frame lengths fit the destination");
check(!memcmp(destination.data, frame, rounded), "the full rounded frame is preserved");
check(filled(destination.data + rounded, sizeof(destination.data) - rounded, 0xa5), "rounded DMA writes no bytes beyond the available destination");
check(request_count == 2, "maximum frames use a single payload DMA request");
check(requests_start_in_rx_ring() && guards_intact(), "rounded DMA starts inside the RX ring and preserves destination guards");
expect_descriptor(len);
}
}
}
static void t_invalid_frames(void)
{
static const uint16_t invalid_lengths[] = { 0, UIP_CONF_BUFFER_SIZE + 1, 0xffff };
static const uint16_t invalid_pointers[] = { 1, 7, RTL837X_NIC_RX_RING_BYTES + 8, 0xfff8 };
printf("[test] invalid lengths and DMA addresses are rejected before transfer\n");
for (unsigned i = 0; i < sizeof(invalid_lengths) / sizeof(invalid_lengths[0]); i++) {
fixture_reset();
rx_headers[4] = invalid_lengths[i];
rx_headers[5] = invalid_lengths[i] >> 8;
check(!nic_rx_packet(destination.data, 0x0100), "unsupported or overflowing lengths are rejected");
check(!request_count && filled(destination.data, sizeof(destination.data), 0xa5) && guards_intact(),
"invalid frame lengths cause no DMA or destination changes");
}
for (unsigned i = 0; i < sizeof(invalid_pointers) / sizeof(invalid_pointers[0]); i++) {
fixture_reset();
rx_headers[4] = 68;
rx_headers[5] = 0;
check(!nic_rx_header(invalid_pointers[i]), "an invalid descriptor address is rejected");
check(!nic_rx_packet(destination.data, invalid_pointers[i]), "an invalid payload address is rejected");
check(!request_count && guards_intact(), "invalid addresses never reach DMA");
}
fixture_reset();
check(!nic_rx_header(RTL837X_NIC_RX_RING_BYTES) && !request_count,
"a descriptor at the ring limit is rejected rather than wrapped");
}
static void t_dma_failure(void)
{
uint8_t frame[UIP_CONF_BUFFER_ALLOC_SIZE];
static const uint16_t lengths[] = { 68, UIP_CONF_BUFFER_SIZE };
printf("[test] failed descriptor and single-payload DMA transfers propagate failure\n");
fixture_reset();
fail_request = 1;
check(!nic_rx_header(0x0100) && request_count == 1, "descriptor DMA failure reaches the caller");
pattern(frame, sizeof(frame));
for (unsigned layout = 0; layout < 3; layout++) {
uint16_t descriptor = layout == 0 ? 0x0100
: RTL837X_NIC_RX_RING_BYTES - (layout == 1 ? 16 : 8);
for (unsigned i = 0; i < sizeof(lengths) / sizeof(lengths[0]); i++) {
uint16_t len = lengths[i];
fixture_reset();
put_descriptor(descriptor, len);
ring_write(descriptor + 8, frame, (len + 7u) & ~7u);
check(nic_rx_header(descriptor), "the descriptor precedes the injected payload failure");
fail_request = 2;
check(!nic_rx_packet(destination.data, descriptor + 8), "payload DMA failure reaches the caller");
check(request_count == fail_request, "a failed payload DMA is not retried or split");
check(filled(destination.data, sizeof(destination.data), 0xa5) && guards_intact(),
"an injected failure before DMA preserves the destination and guards");
expect_descriptor(len);
}
}
}
int main(void)
{
t_last_descriptor();
t_payload_layouts();
t_maximum_frames();
t_invalid_frames();
t_dma_failure();
if (failures) {
printf("%d NIC RX check(s) failed\n", failures);
return 1;
}
puts("all NIC RX checks passed");
return 0;
}
-18
View File
@@ -185,23 +185,6 @@ static void t_l2_page(void)
CHECK(balanced(), "every page is valid JSON");
}
static void t_status_macs(void)
{
const char *p1, *end, *mac;
printf("[test] /status.json reports the MAC addresses learned on each port\n");
hw_reset(); out_reset();
hw_reg_set(RTL837X_L2_LRN_PORT_CONSTRT_CNT + (1 << 2), 0x21);
send_status();
p1 = strstr(body(), "\"logPort\":1,");
end = p1 ? strchr(p1, '}') : NULL;
mac = p1 ? strstr(p1, "\"macs\":\"0x21\"") : NULL;
CHECK(mac && mac < end, "port 1 shows its learned count");
CHECK(has("\"macs\":\"0x0\""), "a port without learned addresses shows 0");
CHECK(slen <= TCP_OUTBUF_SIZE, "fits the buffer");
CHECK(balanced(), "valid JSON");
}
static void t_status_counters(void)
{
printf("[test] /status.json prints 64-bit packet counters in full\n");
@@ -228,7 +211,6 @@ int main(void)
t_l2();
t_l2_page();
t_status_counters();
t_status_macs();
printf("\n%d checks, %d failed\n", tests_run, tests_failed);
return tests_failed ? 1 : 0;
}
-52
View File
@@ -1,52 +0,0 @@
#!/usr/bin/env python3
"""Compile the current firmware execute_config() with mocked flash/tokenizer edges."""
import pathlib, subprocess
root=pathlib.Path(__file__).resolve().parent.parent
src=(root/'cmd_parser.c').read_text()
start=src.index('void execute_config(void) __banked')
end=src.index('// Execute multiple commands',start)
body=src[start:end]
out=root/'test/build';out.mkdir(exist_ok=True)
harness=r"""
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define __xdata
#define __banked
#define CONFIG_START 0
#define CONFIG_LEN 1024
#define FLASH_READ_BURST_SIZE 256
#define CMD_BUF_SIZE 64
#define ERR_OK 0
#define NUL 0
#define PASSWORD "test-default"
uint8_t flash_buf[256],cmd_buffer[64],save_cmd,err_status;
char passwd[32],image[1024],seen[16][64];int count;
struct {uint32_t addr;uint16_t len;} flash_region;
void strtox(char*d,const char*s){strcpy(d,s);}
void flash_read_bulk(uint8_t*d){memcpy(d,image+flash_region.addr,256);}
void print_string(const char*s){(void)s;}
void print_string_x(uint8_t*s){(void)s;}
void write_char(char c){(void)c;}
void clear_command_history(void){}
void cmd_tokenize(void){err_status=cmd_buffer[0]=='#'?1:0;}
void cmd_parser(void){assert(count<16);strcpy(seen[count++],(char*)cmd_buffer);}
"""
tests=r"""
void run(const char*s){memset(image,0,sizeof image);strncpy(image,s,sizeof image-1);count=0;execute_config();assert(save_cmd==1);}
int main(void){
run("one\ntwo\n");assert(count==2&&!strcmp(seen[1],"two"));
run("one\rtwo\r");assert(count==2&&!strcmp(seen[0],"one"));
run("one\r\ntwo\r\n");assert(count==2&&!strcmp(seen[1],"two"));
run("\r\n# ignored\r\none\r\n\r\ntwo");assert(count==2&&!strcmp(seen[0],"one"));
run("one\0ignored");assert(count==1&&!strcmp(seen[0],"one"));
char longline[300];memset(longline,'x',sizeof longline);strcpy(longline+280,"\r\nok\r\n");run(longline);assert(count==1&&!strcmp(seen[0],"ok"));
/* CR at the end of a flash burst, LF at the start of the next. */
char boundary[300];memset(boundary,'\n',255);strcpy(boundary+255,"\r\nok\r\n");run(boundary);assert(count==1&&!strcmp(seen[0],"ok"));
puts("startup CR/LF/CRLF, comments, NUL, overlong and burst-boundary cases passed");return 0;
}
"""
(out/'startup_crlf.c').write_text(harness+body+tests)
subprocess.run(['gcc','-std=gnu11','-Wall','-Wextra','-Werror','-g','-fsanitize=address,undefined','-fno-omit-frame-pointer','-no-pie',str(out/'startup_crlf.c'),'-o',str(out/'test_startup_crlf')],check=True)
subprocess.run([str(out/'test_startup_crlf')],check=True)
-7
View File
@@ -56,7 +56,6 @@ time_t last_session_use;
uint64_t txG[PORTS], txB[PORTS], rxG[PORTS], rxB[PORTS];
char txG_buff[20], txB_buff[20], rxG_buff[20], rxB_buff[20], counter_buf[20], counter_name[20];
char macs_buff[8];
char sfp_temp[8], sfp_vcc[8], sfp_txbias[8], sfp_txpower[8], sfp_rxpower[8], sfp_laser[8], sfp_options[6];
char num_buff[20];
char l2_idx_buff[20];
@@ -181,12 +180,6 @@ void send_status(int s)
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));
uint16_t macs = 0;
for (int e = 0; e < L2_ENTRY_NUM; e++)
if (l2_entries[e].port == physToLogPort[i-1] && l2_entries[e].type != 's')
macs++;
sprintf(macs_buff, "0x%04x", macs);
json_object_object_add(v, "macs", json_object_new_string(macs_buff));
if (i >= PORTS - NSFP) {
uint16_t temp = 0x28fb + rand() / (RAND_MAX / 100);
uint16_t vcc = 0x7eda + rand() / (RAND_MAX / 100);
-4
View File
@@ -132,10 +132,6 @@ typedef unsigned short uip_stats_t;
*/
#define UIP_CONF_BUFFER_SIZE 1556
/* Backing storage includes padding for the NIC's eight-byte DMA transfers.
* Keep UIP_CONF_BUFFER_SIZE as the logical frame/MSS limit. */
#define UIP_CONF_BUFFER_ALLOC_SIZE ((UIP_CONF_BUFFER_SIZE + 7U) & ~7U)
/**
* Bytes of the buffer kept out of the advertised MSS.
*
+1 -1
View File
@@ -136,7 +136,7 @@ static __code const uip_ipaddr_t all_zeroes_addr =
#endif /* UIP_CONF_IPV6 */
#ifndef UIP_CONF_EXTERNAL_BUFFER
u8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE]; /* The packet buffer that contains
u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains
incoming packets. */
#endif /* UIP_CONF_EXTERNAL_BUFFER */
+1 -1
View File
@@ -419,7 +419,7 @@
#endif /* UIP_CONF_BUFFER_EXTRA */
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE];
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
/**
* Determines if statistics support should be compiled in.