Commit Graph
67 Commits
Author SHA1 Message Date
René van Dorst 3c183f73f8 Added print_port() helper to print physical port number. 2026-08-25 07:54:15 +02:00
logicog f582576b10 Merge pull request #345 from DrDoof/fix/sfp-i2c-error
sfp: notice when an I2C read fails
2026-08-25 05:13:47 +02:00
René van Dorst fe2bcc7f2d Merge pull request #356 from bloqaudio/fix/config-post-race
httpd: buffer a configuration upload before touching the flash
2026-08-24 23:35:19 +00:00
d00f a0628c7df5 sfp: read the EEPROM in blocks instead of a byte at a time
The I2C controller transfers up to sixteen bytes per transaction and
page_impl.c already used that for sfp_send_data(), while sfp_read_reg()
asked for one byte and every caller looped. Reading a module therefore
cost one address phase per byte: 87 transactions when a module is
inserted, 52 for the sfp command, 36 for the vendor block in status.json.

sfp_read_block() replaces sfp_read_reg() and the callers that already
wanted a run of registers ask for it once: the vendor fields as three
16 byte pages, the diagnostics as one transfer, rate and encoding
together. That drops the three paths above to 8, 6 and 3 transactions,
and sfp_send_data() loses its copy of the transfer.

The vendor loops now run over 16..63 rather than 20..59 so the page base
is a multiple of sixteen and the index into the buffer is a single AND.
The four extra bytes at each end are read and discarded. The diagnostics
read asks for 16 bytes rather than the 15 it uses, because 16 is a width
the shipped firmware already exercises and 15 is not.

The device address, the bus selection and the start bit go into the
control register in one write now that the memory address is written
first, so a transfer touches that register once instead of three times.
The register reads take their result from the SFRs directly rather than
through the sfr_data mirror. The result is a bool and the destination is
sfp_buf, so a caller that cares about a failed transfer looks at the
return value instead of a flag.

Every caller gives up on the first failed read rather than carrying a
flag to the end, which is why the module read moved out of handle_sfp
into a function of its own. A module whose read fails is left marked as
absent, so the next poll retries it instead of configuring the SerDes
from bytes that never arrived.

BANK1 -194 bytes, BANK2 +382, common segment +44, xdata +15 for the
buffer, and one byte more of internal RAM free than before the series.
Built for all 25 machine definitions on sdcc 4.5.0; the tightest common
segment is 98 bytes free on SWTG024AS_V2_0, against 54 before this
series.
2026-08-25 01:09:20 +02:00
d00f 9a96c80af2 sfp: move the I2C transfer to the banked pins module
sfp_read_reg() sat in rtlplayground.c, so it occupied the common 16 KB
window that every bank shares, even though nothing outside the SFP paths
calls it. That window is the tightest resource in the image:
SWTG024AS_V2_0 and SWTG024AS_A_2_0_1_5C_1SFP had 54 bytes left in it.

rtl837x_pins.c is already in BANK2 and already holds the I2C bus helpers
this function calls, so the transfer belongs there. The function moves
verbatim and becomes __banked; the prototype in rtl837x_common.h says so,
which is what keeps the callers in BANK1 and BANK2 honest.

No behaviour change. The common segment gains 200 bytes on every machine:
159 to 359 free on SWTGW218AS, 54 to 254 on the two variants above.
BANK1 +6 bytes, BANK2 +336. Built on sdcc 4.5.0.
2026-08-24 02:34:39 +02:00
bloqaudio 772e9dc526 httpd: parse a configuration upload once the whole request has arrived
Saving the configuration works in Chrome and fails in Firefox, and the
difference is only how each browser splits the request. The handler
erased the config sector as soon as the request started and then parsed
the multipart body one TCP segment at a time, which requires every
boundary and every part header to fall inside a single segment. Firefox
splits inside a part header, so the parser lost its place and the
erased sector was left holding a truncated body or nothing at all. A
single-burst scripted post lost the whole body the same way.

The configuration is limited to two kilobytes, so the whole request body
now accumulates in xdata and is parsed only after the closing boundary
has arrived. The parts are walked in one pass, the part carrying a
filename is written to a freshly erased sector, and the client receives
a 200 instead of the previous silent close. No segmentation can confuse
this, since the parser only ever sees a complete body.

Locating the closing boundary first also bounds the walk over the parts,
since none can lie beyond it, so the length of the buffer is no longer
the bound and the test for the two trailing dashes is unnecessary.

The walk matches at offsets inside a buffer that is not terminated, so
neither existing helper fits: strcmp() goes on to compare the byte after
the match and is_word_x() demands a separator there. Add strstart() and
strstart_x() for that case, and use strlen_x() for the boundary length.

The firmware upload path still streams, since a megabyte cannot be
buffered, and is untouched.
2026-08-23 18:11:46 -05:00
logicog 025f72c876 Merge pull request #258 from bennydiamond/newline-on-uip-serial-print
Automatically print newline on serial interface
2026-08-22 19:14:45 +02:00
d00f 1d1e33f4d5 sfp: notice when an I2C read fails
sfp_read_reg() waited for the transfer to finish and then read the output
register whatever the outcome, so an address nothing acknowledged came back
as an ordinary byte and no caller could tell it apart from data. The vendor
SDK looks at bit 1 of the control register for exactly this, and we did
not.

A failure now sets sfp_i2c_fail and the read returns 0xff, which is already
the value sfp_apply_quirks() reads as either a failed transfer or a voltage
the spec does not allow, so that test starts being true when it should be.
The insertion path and the sfp command clear the flag first and say so
afterwards, rather than presenting the bytes as though they came from the
module.

What this deliberately does not do is act on the failure. Skipping
sds_config() when the rate read failed is the obvious next step, but a
module that raises the bit spuriously would then never be configured at
all, which is worse than what happens today, and I have no way to judge how
often the bit is right. That decision belongs with someone holding the
board.

It also leaves the other half of the rewrite alone, reading and writing up
to sixteen bytes per transaction. doc/sfp.md describes only the single byte
path and does not name a length field, and guessing at a register I cannot
test is how the last attempt at this function went wrong.

40 bytes of the common segment, 51 of BANK2 and 1 of xdata, nothing in
BANK1 or internal RAM. Built for SWTGW218AS and KP_9000_6XHML_X2 on sdcc
4.5.0. Not tested on hardware: shorting the clock line, as in #342, should
now print the failure line instead of a plausible looking byte.
2026-08-15 23:14:53 +02:00
d00f f21b3a32bd system: configurable hostname (device identity)
Add a device hostname settable from the CLI (`hostname <text>`) and the
System Settings page. The value is sanitized on ingest to JSON-safe
printable ASCII (<=23 chars), stored in a shared __xdata buffer, seeded
to "RTLPlayground" at boot, persisted through the startup-config, and
reported in /information.json. It lives in the common header so other
modules can advertise it (LLDP uses it as the System Name TLV).
2026-07-25 13:07:09 +02:00
Matt Merhar 2221f0fa32 Add SFP quirk for devices that misreport DDM capability
On a QSFPTEK QT-SFP+-T (RTL8261C) 10GBase-T module, the diag type field
(92) comes back as 0x00, but there's actually some statistics available
like temperature. Other metrics may be hard-coded values.

Add a basic struct that allows matching on vendor and/or model, using a
bitfield to allow multiple quirks for a given SFP module. Only
SFP_QUIRK_DDM is implemented.

For modules matching SFP_QUIRK_DDM, attempt an I2C read of the MSB of
module voltage during probe if DDM is "unsupported" - if it's not 0xff,
override the reported options so we can pull the diagnostic data.

To allow simpler comparisons, convert the ASCII fields (vendor,
model, serial) from space-padded to standard NULL-terminated strings.

strcmp() is moved from httpd.c to rtlplayground.c alongside other string
functions and shared between them.

The __reentrant keyword is used for the new functions to avoid using up
additional OSEG space. This allocates the variables on the stack, which
is OK for this particular code path.

The JSON assembly in send_status() is slightly modified to treat the
sfp_module_* data as standard NULL-terminated strings, and a repeated
subtraction was moved into a uint8_t to declutter the code.
2026-07-13 01:31:29 -04:00
bennydiamond 7a7ffd3bf8 Automatically print newline on serial interface
For some print_string
2026-06-07 14:52:56 -04:00
logicog 1a457c29ac Add support for 100FX modules and forcing 100FX 2026-05-30 23:08:44 +02:00
logicog 8c61010a84 Add support for configuring SFP modules speeds 2026-05-29 20:46:08 +02:00
feelfree69 3f66a18104 Merge branch 'main' into syslog 2026-04-24 12:01:30 +02:00
logicog baa4e5e142 Use header structures of TX and RX, add dot1q for management VLAN TX 2026-04-22 22:36:26 +02:00
logicog 946e80cebe Add frame descriptor structure 2026-04-22 22:36:26 +02:00
feelfree69 f7989cc737 Merge branch 'logicog:main' into syslog 2026-04-21 14:29:44 +02:00
René van Dorst 52d943d5e4 rtlplayground: de-__gptrput()-call in read_reg_timer() 2026-04-19 22:18:39 +02:00
René van Dorst 1a5208110c Merge pull request #195 from logicog/fix_config_reading
Fix reading configuration over flash block boundaries
2026-04-17 11:46:03 +02:00
logicog 1769528420 Introduce global error variable, check during config execution 2026-04-16 22:01:51 +02:00
feelfree69 b31179acbe move extern declaration for port_names to trl837x_common.h 2026-04-13 19:14:24 +02:00
feelfree69 41f0dad49d Add ability to assign a name to a port 2026-04-13 14:55:10 +02:00
feelfree69 c1a414833d Various refactorings 2026-04-12 13:02:42 +02:00
feelfree69 eaa21d5975 rebase First try to make use of uIP for sending syslog 2026-04-12 13:02:37 +02:00
Jan Hoffmann e210f31f0e Add commands to access SerDes registers 2026-04-06 18:25:35 +02:00
logicog 14bc823024 Add reg_bit_test function 2026-03-08 20:55:50 +01:00
René van Dorst e33cd9d0c5 Merge pull request #143 from feelfree69/flashsize_web
Show flash_size to web interface and console
2026-03-06 18:22:48 +00:00
Tobias Diedrich 9bd2d446d7 Optimize printing functions
This saves 508 bytes in the HOME area by:
- Getting rid of the expensive hex array indexing
- Having print_short and print_long delegate to print_byte

This is at the expense of increasing the stack depth a tiny bit.
Stack usage isn't an issue so far since I see ~96 bytes of
untouched stack memory.
2026-03-01 12:45:31 +01:00
feelfree69 7a0f248424 Add flash_size to web interface 2026-02-28 19:56:18 +01:00
logicog 94d4ace88b Add support for command line editing
The current code for entering commands via the serial CLI is completely
refactored and moved out of rtlplayground.c into a separate file cmd_edit.c
putting code into BANK2.
The serial ring buffer sbuf[] is now exclusively used for receiving
keys, including escape sequences (DEL will generate a 4-byte escape
sequence). The command is now held in cmd_buffer. This reduces
XMEM use, because the serial buffer can be much smaller.

Supported is only editing the current command line via backspace, del,
cursor left and right.

Because the code cannot distinguish escape sequences which are not yet
complete (because the serial isr has not yet put all characters into
the serial buffer) from the dozens of unsupported ones (F-keys/home,
Page up/down, cursor up/down...) they are ignored and remain in the
serial buffer until the ring-pointer overwrites them. This is standard
behaviour for consoles, which will print out garbage for unsupported
characters. In this implementation, the command line buffer and the
visible command line in the terminal are always synced, so garbage
can be removed again by ediing the line.

The code makes several redundant checks in order to prevent race-conditions
between the serial ISR and the comand-editing code.
2026-02-24 19:57:22 +01:00
feelfree69 e5d23f11de Demagic FLASH_BUF_SIZE 2026-02-15 13:28:31 +01:00
feelfree69 79c9d0deab Add button handling with the possibility to revert to default settings 2026-02-14 10:55:35 +01:00
logicog ea230615f9 Use a MAC address based on the SoC's UUID
We use the SoC's UUID to generate a fixed MAC for a particular
switch device. The MAC generated uses a Realtek prefix and then
is followed by 3 bytes genertaed from the first 3 bytes of the
UUID xored with the last byte in order to prevent being able
to deduce the UUID from the public MAC.
2026-02-08 15:49:49 +01:00
diijkstra 7d62b24a42 Advanced I2C pin definition
RTL has up to 3 SCL pins and up to 4 SDA pins. Lets allow configuring
I2C with individual BUS numbers instead of 0/1 I2C.

This enables support for devices where SCL line is not shared between
SFP modules. MUX registry is now initialized depending on needed
pin function.

More over, some SFP pins require special MUX settings, lets initialize
those depending on SFP configuration. This adds TX Disable pin,
which right now is set to low at startup.

Caveats:
 - We may still override MUX registry later
 - Not sure how to handle invalid bus definitions
 - Without SFP is it fine to *not* initialize anything?
 - Do to RAM limitation we do inititalize output GPIO to low
2026-02-01 12:58:16 +01:00
feelfree69 0345bf7bf2 Use DIO mode for normal operation; disable DIO before flashing. Use SYS_LED for indicating booting (slow), flashing (fast) and normal operation (on) 2026-01-22 19:38:17 +01:00
logicog 5eecab4844 Move SYS_TICK_HZ to rtl837x_common.h
The definition is needed everywhere in the code where the ticks
need to be related to seconds.
2026-01-18 07:50:38 +01:00
logicog e8a719d911 Add itoa function 2026-01-18 07:39:49 +01:00
logicog d2d7ab7ff1 De-magic NIC rx and tx registers, cleanup 2026-01-11 07:51:18 +01:00
logicog 44792699bf Add sfr_mask_data function header 2025-12-17 06:43:31 +01:00
logicog c8c524b71f Add an implementation for IGMP
This adds an implementation for trapping IGMP packets to the CPU
which will identify IGMPv1/2/3 packets, but handle only v3.
The implementation then inserts/updates/deletes L3 MC entries
in the L3 lookup table. The entries consist of an Ipv4
Destination IP (the IPv4 MC address), a Source IP (0.0.0.0) and
a Portmask. Note that this implementation is not VLAN aware,
as there is no hardware support in the device.

An alternative strategy is to control switching of the L2-MC packets
in which the IPv4-MC packets are transported (dst-MaC is
01:00:5e:xx:yy:zz, with xx:yy:zz corresponding to bits in the Ipv4-MC
address). This will allow to use VLAN-aware packet switching. While
code support is there for table insert/update/deletes, some further
L2 configuration is missing.

There is no support for IPv6 MC, yet.
2025-12-15 06:54:41 +01:00
logicog 96977b5d88 Move rtl_tag structure definition to common inlude 2025-12-14 20:35:17 +01:00
logicog a84c5dcd0c IGMP refactoring 2025-12-14 20:35:17 +01:00
logicog edfb86bff4 Use SFP pin definitions and I2C ports for SFP modules 2025-12-13 09:25:58 +01:00
logicog d75ad636f9 Use machine structure 2025-12-12 09:06:52 +01:00
logicog 32b5539670 Do not show non-ascii Transceiver field in SFP module description 2025-12-07 10:59:39 +01:00
logicog 9c21d94b65 Add read_reg_timer function 2025-12-01 18:26:46 +01:00
logicog 70c14fb23e Add get_random_32() 2025-12-01 18:26:46 +01:00
logicog 4d915a0d80 Add support for command history
This adds a command history, both for the CLI as well as for
commands sent by the web-interface. They are written to a ring buffer
in order to work safely with a relatively small amount of RAM
The buffer is used to read the current in-RAM configuration
from the switch by the web-interface. It could also be used
to implement cmd history via cursor up/down in the CLI.
2025-11-29 12:44:23 +01:00
logicog 9c7572b289 De-Magic I2C configuration for SFP-EEPROM reads 2025-11-02 09:49:13 +01:00
René van Dorst 7a87b79871 Convert flash_addr to struct flash_region.
flash_region storage flash address and length, which a operation is needed.
2025-10-05 15:36:08 +02:00