Commit Graph
1640 Commits
Author SHA1 Message Date
René van Dorst 94cfec8693 CI: Build a 4x2/8372 and 8x1/8373 version 2026-09-21 19:50:15 +02:00
René van Dorst a4bb3f1725 CI: Enable CI option to stop at warnings 2026-09-21 19:50:15 +02:00
René van Dorst 931e6da0ab Makefile: Add option CI to turn all warnings into errors 2026-09-21 19:50:11 +02:00
René van Dorst 88454ec7d7 Merge pull request #439 from vDorst/feat_i2c_precompute
I2CBUS: Calculate I2C-settings as compiletime instead at runtime.
2026-09-21 15:30:56 +02:00
René van Dorst f0efb84abb Merge pull request #494 from tofurky/sdcc_4.6.0_warnings
Fix warnings seen on SDCC 4.6.0 due to missing const qualifiers
2026-09-21 10:51:54 +02:00
René van Dorst 62d3424a92 Merge pull request #496 from DrDoof/fix/sfp-nonblocking-wake
sfp: do not block the main loop while a module wakes up
2026-09-21 10:32:22 +02:00
DrDoof a3860c29cb sfp: do not block the main loop while a module wakes up
handle_sfp() called sfp_module_read() as soon as it saw a module appear, and
that path opened with delay(100). delay() spins on PCON until the tick counter
runs down, so the main loop stood still for 100 ticks - half a second at
SYS_TICK_HZ 200. Nothing else ran in that window: no STP, no LACP, no packet
handling. A diagnostic build measured the sfp phase at up to 107 ticks, the
longest stall of any phase in the loop.

Remember when the module showed up and let the loop continue. The I2C read
happens on a later pass, once the wake-up period has elapsed. Pulling a module
cancels a pending read, and a failed read still restores the detect bit, so the
existing retry-on-the-next-poll behaviour is unchanged.

The comparison is written out rather than using a helper so that this does not
depend on anything outside the current tree. The pending flag is an array
indexed by slot, like the other per-slot state in this file.

Cost on SWTGW218AS, measured against the branch point: BANK3 11173 -> 11264,
CSEG, BANK1 and BANK2 unchanged, plus 4 bytes of xdata.
2026-09-21 09:45:18 +02:00
René van Dorst b1961c6955 Merge pull request #495 from tofurky/sfp_normalize_nul
Properly handle NULs when normalizing SFP fields
2026-09-21 08:51:57 +02:00
Matt Merhar bb84bdc55a Properly handle NULs when normalizing SFP fields
Some generic 1.25gbps DAC cables were seen to have a NUL *after* the
space padding in the model field. This caused the normalization to miss
the space padding in the string. The vendor field did not have the
issue.

Note that this seems to be against spec per SFF-8472, which mentions
only space padding or *all* NUL, not a combination of both. In the case
of all NUL, we'll waste a few cycles with no-op writes.
2026-09-20 19:55:07 -04:00
Andreas Erhard 9733ff61a0 another almost working state. port order is wrong and leds are not correct, but ports are all working 2026-09-21 01:16:16 +02:00
Matt Merhar 1b5243714e Fix warnings seen on SDCC 4.6.0 due to missing const qualifiers
Building with SDCC 4.6.0 emits tons of warnings e.g.:

	cmd_parser.c:31: warning 356: object in read-only code space should be const
	cmd_parser.c:36: warning 357: pointer to object in read-only code space should be pointer to const

These of course become fatal when building with --Werror.

Comparing resultant binaries, it seems that a single string is shifted
(deduplication?) but the numbers emitted at the end of the build are
otherwise identical.
2026-09-20 18:25:17 -04:00
Andreas Erhard 36459fdd76 Merge branch 'main' into add-device-ONT-S207CW-62TS-SE 2026-09-20 22:18:41 +02:00
René van Dorst ce11790a0d I2C: Silence compiler warning, de-magic values. 2026-09-20 20:31:43 +02:00
René van Dorst 55431b39f6 Merge pull request #483 from DrDoof/perf/rx-nosleep
rtlplayground: do not sleep in idle() while a packet is waiting
2026-09-20 13:02:59 +00:00
René van Dorst 46e1c955ba Merge pull request #482 from DrDoof/perf/rx-budget
rtlplayground: take several packets per loop in handle_rx()
2026-09-20 13:02:07 +00:00
d00f 7b728cec6f rtlplayground: do not sleep in idle() while a packet is waiting
idle() went to sleep before it looked at the receive buffer, so a packet that
arrived just after the loop dozed off waited for the next tick before anything
touched it. Every TCP round-trip paid that toll, which is why the web UI felt
sluggish even though no phase of the loop was anywhere near busy.

Check the receive buffer first and only sleep when it is empty. The read takes
its result straight from SFR_DATA_U16 rather than going through reg_read_m()
and the sfr_data[] copy, which is what the rest of the tree already does.

Measured on SWTGW218AS with this change alone:

  web UI, median of 15 requests for the main page   88 ms -> 76 ms
  CPU port under a one-way UDP stream               159 -> 230 packets/s

The loop still sleeps normally when there is nothing to do, so this does not
turn the core into a busy-wait: loops/ticks stays at 0.99 on an idle switch,
and rises above 1.0 only while packets are actually queued.

Costs 12 bytes of code and no extra XDATA.
2026-09-20 14:56:44 +02:00
d00f 0d17dd563f rtlplayground: take several packets per loop in handle_rx()
handle_rx() picked up exactly one packet per iteration of the main loop. Since
the loop sleeps until the next tick, that capped the CPU port at roughly one
packet per tick no matter how little work it had to do. A burst of broadcast,
ARP or IGMP traffic aimed at the CPU queued up behind that and pushed out the
STP and LACP timers.

Drain up to RX_BUDGET packets in one pass instead. The budget matters: without
one a sustained flood would spin here and starve everything else in the loop.

The two register reads in the loop take their result straight from
SFR_DATA_U16 rather than going through reg_read_m() and the sfr_data[] copy,
which is what the rest of the tree already does.

Measured on SWTGW218AS with a one-way UDP stream, counting the packets the CPU
actually processed, with this change alone:

  before          159 packets/s
  RX_BUDGET 4     245 packets/s, loop iteration ~16 ms
  RX_BUDGET 8     298 packets/s, loop iteration ~26 ms

Throughput is already most of the way there at 4, so the larger budget mostly
buys a longer worst-case delay for the other phases. STP stayed responsive in
both cases.

Costs 71 bytes of code and no extra XDATA.
2026-09-20 14:42:50 +02:00
René van Dorst d556d634ca Merge pull request #487 from jagheterfredrik/patch-1
add zlib1g-dev to Dockerfile
2026-09-20 12:34:33 +00:00
Fredrik Gustafsson 2844a1ed6d add zlib1g-dev to Dockerfile
Current Docker-based build fails without it
2026-09-20 14:31:03 +02:00
René van Dorst 7b5e365d5e Merge pull request #409 from gnacho/i18n-es
feat(translate): add Spanish (es) translations
2026-09-20 11:40:56 +00:00
gnacho 45fb382b07 feat(translate): add Spanish option to the language selector 2026-09-20 13:29:12 +02:00
René van Dorst 8973774594 Merge pull request #476 from bloqaudio/fix/eee-port-argument
eee: accept a port again, and stop the web UI discarding other ports
2026-09-20 09:50:25 +00:00
René van Dorst 48c5b0c9cf Merge pull request #486 from bloqaudio/fix/syslog-null-conn
syslog: do not read the connection before there is one
2026-09-20 09:39:04 +00:00
René van Dorst 1557a7cf3c MACHINE: rebase, update the new added devices 2026-09-20 11:30:17 +02:00
René van Dorst 131bc106af boot/i2c-setup(): Remove the switch-statement defaults.
All the possibilities are handled, or otherwise a compile-time macro
I2CBUS_VALID ensures invalid options are rejected with a compiler error.

Also fix a compiler warning.
2026-09-20 11:25:35 +02:00
René van Dorst 19ccc4003d i2c: Add compiletime check macro for validating the i2c pins.
Use 0x7 as error value for an invalid I2C SDA/SCL-pin value.
The macro `I2CBUS_VALID` checks for this value.
When a invalid pin is ues, the compiler errors out with:
  "machine.c:<line>: error 176: sizeof applied to an incomplete type",

Error message is not ideal but at-least points to the right location in
the code.
2026-09-20 11:25:35 +02:00
René van Dorst b5fe9f217f i2c/sfp: Demagic shift-values 2026-09-20 11:25:35 +02:00
René van Dorst f65d14f452 I2CBUS: Calculate I2C-settings as compiletime instead at runtime.
We can reduce the i2c-settings to just one byte, and this new const value
can directly be used by the I2C-peripheral without additional computation.
This saves 1-xdata load and a lot of bit-shifting.

I see a codesize savings of +200 bytes.
2026-09-20 11:25:34 +02:00
René van Dorst b92fba870c Merge pull request #484 from bloqaudio/fix/upload-auth-gate
httpd: gate /upload on authentication before it changes state, and make the length limit count
2026-09-20 09:21:25 +00:00
René van Dorst 4deee377a7 Merge pull request #485 from bloqaudio/fix/led-set-index
leds: index the second LED register from the set it belongs to
2026-09-20 08:40:52 +00:00
René van Dorst fe42b07e2b Merge pull request #481 from DrDoof/fix/rx-checksum
uip: verify TCP and UDP checksums using the RX descriptor flag
2026-09-20 07:59:46 +00:00
d00f 9984649177 uip: verify TCP and UDP checksums using the RX descriptor flag
The TODO next to the disabled TCP checksum code asks which bit of the RX tag
carries the result. It is bit 2 of byte 1: the hardware sets it when the L4
checksum is bad.

That answers the question for UDP as well, which was not being checked either
because UIP_CONF_UDP_CHECKSUMS is 0. Both paths now read the flag instead of
running a checksum over the payload on the 8051.

A zero UDP checksum, which is optional in IPv4, is not flagged by the hardware,
so DHCP keeps working and no extra condition is needed.

rx_headers lives in rtlplayground.c, which the host tests do not link, so
test_httpd_tx carries the storage itself the way it already carries uip_buf.
A zeroed descriptor reads as a good checksum, so the existing scenarios are
unaffected.

A new scenario sets the flag on a request and expects it counted as a checksum
error and left unanswered, then sends the same request with the flag clear and
expects it served. Built against uip.c without this change, those first two
checks fail and the two control checks still pass, so the scenario tells the
two versions apart rather than merely exercising the code.

Costs 156 bytes of code on SWTGW218AS and no extra XDATA.
2026-09-20 00:35:10 +02:00
René van Dorst 7d47edb649 Merge pull request #477 from bloqaudio/fix/port-speed-select
web: show the speed a port is set to, not always auto
2026-09-19 11:26:03 +00:00
René van Dorst fdb19fe0ee Merge pull request #451 from SkullyDev/main
HASIVO_S600W_4GT_2XGT_SE machine
2026-09-19 11:25:30 +00:00
SkullyDev b9b50f9a70 Merge branch 'main' into main 2026-09-19 13:07:28 +03:00
SkullyDev c31b67572b Remove led behavior & LED comments
Should work without gpio_input_setup
2026-09-19 13:03:42 +03:00
Andreas Erhard a4e3b4368b extracted ONT-S207CW-62TS-SE into separate device 2026-09-18 22:16:06 +02:00
bloqaudio 93003c8cb8 web: show the speed a port is set to, not always auto
The speed selector on the Ports tab was filled with its options and never
given a value, so it read "auto" on every load whatever the port was set
to. Forcing a port to 1G and reloading showed "auto" in the selector
beside a link badge reading 1G.

The advertisement bits ports.json already reports say what the port is
set to: phy_set_speed() writes the same three registers the JSON reads
back, and every forced speed leaves exactly one of the six bits standing
while auto leaves the lot. Map those to the selector, and leave it alone
while it has focus, as the MTU field does.

Values with no entry in the table, such as the 100M setting that
advertises both duplex modes, leave the selector untouched rather than
claim a setting the list cannot express.
2026-09-18 15:13:41 -05:00
bloqaudio fd058ea74d port: name the port an eee command acted on the way the user wrote it
port_eee_enable() and port_eee_disable() report the port with
print_byte(), which prints the internal index in hex, so turning EEE off
on port 5 answers "EEE off for 04". port_eee_status() in the same file
already uses print_phys_port(), and the status listing it produces counts
from one, so the two halves of the same command disagreed.

Use print_phys_port() in all three messages.
2026-09-18 14:59:47 -05:00
bloqaudio edc469fe29 httpd: make the firmware upload length limit count
max_upload was armed once when the upload began and never reduced, so
`max_upload - uip_len > 0` was an unsigned expression that only went
false when a segment arrived whose length matched the limit exactly. The
write pointer climbed from the staging address with nothing to stop it,
while flash_write_bytes() carries the address in three bytes and drops
whatever does not fit.

Subtract each segment as it is taken and compare before subtracting, which
is what the comment there described. The limit was only ever armed for
firmware uploads; configuration uploads keep the bound their own buffer
already imposes.
2026-09-18 14:01:03 -05:00
bloqaudio a71c5359a5 httpd: refuse an unauthenticated firmware upload before it changes state
The multipart branch for /config tests authenticated before it touches
anything; the branch for /upload does not, and the 401 for it is only
raised further down at the dispatch. By then the request has already set
config_upload, uptr, verify_crc, max_upload and pre_acc, and announced a
firmware upload on the console.

Those five are globals while the transfer state they steer is per
connection, and the stack is built for ten connections, so a request that
is about to be rejected can still retarget an upload another client is in
the middle of: a configuration upload continues as a firmware one and its
remaining parts are written to the staging area instead of the
configuration sector.

Apply the same test the neighbouring branch uses, before the assignments.
2026-09-18 14:00:51 -05:00
bloqaudio 9e3863cc4e syslog: do not read the connection before there is one
udp_callbacks() offers every UDP connection event to syslog_callback(),
which decides whether the event is its own by comparing the local port
against state.syslog_conn->lport. The pointer is null until syslog is
started: syslog_init() clears it at boot and syslog_stop() clears it
again, so with syslog off, which is the default, every poll dereferences
null and reads whatever lives at the bottom of xdata.

Should that word ever match the port being offered, the send path runs on
another application's connection, overwrites uip_appdata and drops the
log line it was holding.

Test the pointer first.
2026-09-18 13:59:59 -05:00
bloqaudio d22ec04b5b leds: index the second LED register from the set it belongs to
leds_setup() walks all four LED sets and writes the high-speed nibble of
each into one of two registers, LED3_0_SET1 for sets 0 and 1 and
LED3_0_SET3 for sets 2 and 3. The second branch reuses the index
expression of the first without rebasing it, so sets 2 and 3 address
sfr_data[-1], [-2], [-3] and [-4].

Two things follow. Sets 2 and 3 never receive their nibble, because the
read-modify-write pair writes back exactly what it read. And four bytes
below sfr_data are overwritten on every boot of every machine: the loop
runs over all four sets whatever the board declares. On this build the
linker places sfr_data directly after the serial receive ring, so the
writes land in the tail of that ring.

leds_dump() reads the same two registers back and already rebases with
(set - 2); use the same form here.
2026-09-18 13:59:50 -05:00
bloqaudio 0a65536a7f web: send an eee command in the documented argument order
The EEE toggle posted `eee <port> <on|off>`, the reverse of the
`eee [on|off|status] [port] [100m|1g|2g5]` the parser and the
documentation describe, so the switch answered with its usage line and
the checkbox sprang back. The multi-page UI this replaced sent `eee on`
with no port at all, which toggled every port instead of one.

Moving the port to the end breaks the stored-configuration merge, which
builds its drop key as a line prefix: with the port trailing, a per-port
line matches the bare eee entry and replaces every eee line in the
configuration rather than the one for that port. Give the command its own
case beside the bandwidth one, so a line with a port replaces only that
port and a line without one clears them all, and accept the optional
speed word the command has always taken.

Reported by tofurky in issue #459.
2026-09-18 13:57:07 -05:00
bloqaudio 0631c813e2 cmd: parse the port of an eee command from the start of the word
parse_eee() sniffs word 2 for a trailing 'g' or 'm' to tell a speed from
a port number, and advances idx past the digits to do so. The port branch
then hands that advanced idx to cmd_parse_port_separator(), which expects
the first character of the number and finds the separator instead, so it
returns 0 and the command is rejected. Every other caller passes
cmd_words_b[].

The result is that no eee command carrying a port number works, in any
argument order, and the stored per-port lines a saved configuration
replays are silently dropped.

Reported by tofurky in issue #459, along with this fix.
2026-09-18 13:56:53 -05:00
René van Dorst eaebeba528 Merge pull request #464 from DrDoof/fix/json-escape
httpd: don't let a quote in a port name break the web page
2026-09-18 18:40:16 +00:00
René van Dorst b36fd95356 Merge pull request #450 from bloqaudio/feat/idle-poll-pause
web: stop polling when the page has had no input for ten minutes
2026-09-18 18:36:34 +00:00
d00f 52b1d1a4ea web: show the chip temperature in the System page
The row sits between Hardware and Flash. The firmware sends the formatted string
rather than the raw register, since the System table prints its values as they
arrive.

Costs 186 bytes in BANK1.
2026-09-18 18:28:13 +02:00
d00f 48f28ae7ff temp: read the on-chip thermal sensor
The chip has a pair of thermal meters and nothing was reading them. This adds a
`temp` command that prints the current reading next to the one taken at power-on.

The result register at 0x340 splits a 19 bit value across two fields: bits 18:3
live in the low 16 bits, bits 2:0 in bits 18:16, with the sign at bit 18, degrees
in 17:10 and a fraction below. The nice part of that layout is that the degrees
fall out of a shift of the low half, so the conversion stays 16 bit.

The meter comes out of reset latched: the register keeps whatever was measured
when the board powered up and then never moves. Four samples 40 s apart came back
identical down to the raw ADC, and 0x340 matched the power-on register at 0x350.
Clearing bit 2 of the control register at 0x338 during init is what makes it live.

Measured on an SWTGW218AS: 58.7 to 59.5 C while running, with the power-on
register still showing the 49.2 C it started from. For what it is worth, the
scale lines up three ways: the threshold register reads -40 and +125, the slope
from warm-up works out at 4450 LSB/C, and the slope between the two meters at
4388 LSB/C.

We only read the meter that is up after boot. The other sits in reset with no
coefficients, so it would just repeat its power-on value.

Costs 231 bytes in BANK2.
2026-09-18 18:28:13 +02:00
d00f a7fc8303e9 cmd: move name_char() above the parse_mac_cmd comment
The helper landed between that comment and the function it describes, so the
comment now reads as if it belonged to name_char(). Moving the helper up puts
the two back together. The generated code is unchanged.
2026-09-18 17:33:24 +02:00