142 Commits
Author SHA1 Message Date
logicog 855d587243 Add dhcpd VLAN parameter to restrict dhcpd to given VLAN 2026-03-09 22:11:29 +01:00
logicog aa12adc098 Add web frontend support for dhcp/dhcpd 2026-03-09 22:11:27 +01:00
logicog 4db49b2ee5 Add simulation backend for dhcp/dhcpd 2026-03-09 22:06:57 +01:00
logicog 294174d152 Add web backend for dhcp/dhcpd 2026-03-09 22:06:57 +01:00
logicog 19bcf86e80 Fix syntax error in mirror.js 2026-03-09 22:06:57 +01:00
logicog 8d467b2099 Remove unused uIP neighbour code 2026-03-09 22:06:57 +01:00
logicog a45d0f659f Correctly handle incoming and outgoing IP packets in uip_arp.c 2026-03-09 22:06:57 +01:00
logicog 820477cd27 Better comments for rtlplayground.c 2026-03-09 22:06:57 +01:00
logicog e9171d7d22 Handle outgoing DHCP server messages correctly 2026-03-09 22:06:57 +01:00
logicog dd0ecc5438 Enable ARP processing for IP packets 2026-03-09 22:06:57 +01:00
logicog 5e1ea935a7 More DHCPD work 2026-03-09 22:06:57 +01:00
logicog 57e7d7dd2a Do not drop DHCP packets for a DHCP-server 2026-03-09 22:06:57 +01:00
logicog 855383052b Fix uip.c 2026-03-09 22:06:57 +01:00
logicog acaa80b732 Make dhcpd server implementation available 2026-03-09 22:06:57 +01:00
logicog 233ff5a728 Initial support for dhcp server 2026-03-09 22:06:57 +01:00
René van Dorst c2f5a91763 Merge pull request #150 from logicog/bandwidth_web
Bandwidth web
2026-03-09 19:54:31 +00:00
logicog ed8dc0f43c Fix bug in atoi_hex when uneven number of digits parsed
We fix a bug in atoi_hex when parsing an unneven number of digits
by rotating the entire number 4 bits right as would have been
done if the number had been preceded by a 0 to make the number
of digits even.
2026-03-09 06:48:24 +01:00
logicog 7949975191 Add backend support for bandwidth control 2026-03-08 20:55:50 +01:00
logicog 1374272db6 Add simulation support for bandwidth control 2026-03-08 20:55:50 +01:00
logicog 20fb626cc1 Make bandwidth control page accessible 2026-03-08 20:55:50 +01:00
logicog 31a488e4e9 Add web page for bandwidth control 2026-03-08 20:55:50 +01:00
logicog 14bc823024 Add reg_bit_test function 2026-03-08 20:55:50 +01:00
René van Dorst 87c161dc70 Merge pull request #147 from logicog/bandwidth
Bandwidth control
2026-03-08 19:46:51 +00:00
logicog 04ab083652 Add documentation for bandwidth control 2026-03-08 19:04:48 +01:00
logicog 1836c7dcb6 Add Bandwidth control for ingress/egreess at port 2026-03-08 19:04:48 +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
feelfree69 71880a95f5 optimization as suggested by review comment 2026-03-06 08:55:59 +01:00
feelfree69 494320b191 Resolve review comments 2026-03-05 08:55:51 +01:00
logicog eb13d4ab04 Add iniital implementation of bandwidth control 2026-03-05 07:43:11 +01:00
René van Dorst a15500c493 Merge pull request #146 from ranma/printopt
Optimize printing functions
2026-03-02 20:59:26 +00:00
logicog a89467febc Merge pull request #144 from ranma/xpage
Add DW8051 MPAGE SFR
2026-03-01 18:55:43 +01:00
logicog 706abcf78d Merge pull request #145 from ranma/libc-main-vectors
Rename bootloader to main
2026-03-01 17:53:56 +01:00
Tobias Diedrich c868482669 Rename bootloader to main
The presence of the main function is a hardcoded trigger in sdcc that causes
the interrupt vectors and atomic rollback helpers to be generated as part of
compilation of the file containing the main function.

This makes sure the runtime library is correctly initialized and reduces
crtstart.asm to contain only the banked call helpers.

To ensure that the __interrupt_vect in area HOME is located at the beginning
of the firmware, the linker flags are updated to set the HOME start to
0x00000 and the linker object order is modified to have rtlplayground.rel
first.

Generated code in rtlplayground.asm:
```
;--------------------------------------------------------
; interrupt vector
;--------------------------------------------------------
	.area HOME    (CODE)
__interrupt_vect:
	ljmp	__sdcc_gsinit_startup
	ljmp	_isr_ext0
	.ds	5
	ljmp	_isr_timer0
	.ds	5
	ljmp	_isr_ext1
	.ds	5
	reti
	.ds	7
	ljmp	_isr_serial
	.ds	5
	ljmp	_isr_timer2
	.ds	5
	reti
	.ds	7
	reti
	.ds	7
	ljmp	_isr_ext2
	.ds	5
	ljmp	_isr_ext3
; restartable atomic support routines
	.ds	2
sdcc_atomic_exchange_rollback_start::
	nop
	nop
sdcc_atomic_exchange_pdata_impl:
	movx	a, @r0
	mov	r3, a
	mov	a, r2
	movx	@r0, a
	sjmp	sdcc_atomic_exchange_exit
	nop
	nop
sdcc_atomic_exchange_xdata_impl:
	movx	a, @dptr
	mov	r3, a
	mov	a, r2
	movx	@dptr, a
	sjmp	sdcc_atomic_exchange_exit
sdcc_atomic_compare_exchange_idata_impl:
	mov	a, @r0
	cjne	a, ar2, .+#5
	mov	a, r3
	mov	@r0, a
	ret
	nop
sdcc_atomic_compare_exchange_pdata_impl:
	movx	a, @r0
	cjne	a, ar2, .+#5
	mov	a, r3
	movx	@r0, a
	ret
	nop
sdcc_atomic_compare_exchange_xdata_impl:
	movx	a, @dptr
	cjne	a, ar2, .+#5
	mov	a, r3
	movx	@dptr, a
	ret
sdcc_atomic_exchange_rollback_end::

sdcc_atomic_exchange_gptr_impl::
	jnb	b.6, sdcc_atomic_exchange_xdata_impl
	mov	r0, dpl
	jb	b.5, sdcc_atomic_exchange_pdata_impl
sdcc_atomic_exchange_idata_impl:
	mov	a, r2
	xch	a, @r0
	mov	dpl, a
	ret
sdcc_atomic_exchange_exit:
	mov	dpl, r3
	ret
sdcc_atomic_compare_exchange_gptr_impl::
	jnb	b.6, sdcc_atomic_compare_exchange_xdata_impl
	mov	r0, dpl
	jb	b.5, sdcc_atomic_compare_exchange_pdata_impl
	sjmp	sdcc_atomic_compare_exchange_idata_impl
```
2026-03-01 17:35:13 +01: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
Tobias Diedrich c3a6a46852 Add DW8051 MPAGE SFR
This adds the MPAGE (sdcc _XPAGE) SFR, which is used by sdcc in `--xstack`
mode to provide the upper byte of the address for `MOVX A, @Ri` and
`MOVX @Ri, A` instructions.

Classic 8051 uses the P2 SFR value for this, but the RTL IP block does not
seem to be using the "Port 2 module".

From the databook:
```
To replace the function of the Port 2 latch in designs that do not use a
Port 2 module, the DW8051 provides an additional special function register,
MPAGE, at SFR address 92h. During MOVX A, @Ri and MOVX @Ri, A instructions,
the DW8051 places the contents of the MPAGE register on the upper 8 address
bits (mem_addr[15:8]). This provides the paging function that is normally
provided by the Port 2 latch. The MPAGE register has no function when a
Port 2 module is used to connect external RAM.
```
2026-03-01 09:32:13 +01:00
feelfree69 7a0f248424 Add flash_size to web interface 2026-02-28 19:56:18 +01:00
logicog 23e2f5a99e Merge pull request #140 from feelfree69/flashsize
Check for sufficient flashsize before applying an update
2026-02-28 11:48:38 +01:00
René van Dorst 81a7393a81 Merge pull request #141 from logicog/SWTG018AS_A_V_2_0
Add support for the SWTG018AS-A V2.0 8+1 unmanged switch
2026-02-27 19:30:25 +00:00
logicog dc16b25d62 Add support for the SWTG018AS-A V2.0 8+1 unmanged switch
The SWTG018AS-A V2.0 is an 8x2.5GBit/s port + 1 SFP+ port unmanged device
It is sold in an unbranded casing e.g. by Ampcom.
Hardware:
SoC: RTL8373N
Additional PHY: RTL8224
Flash: Puya P25D40SH (4MBit, slimmer, not standard SOP-8 package!)
LEDs: 1 Green + 1 Orange per Ethernet port (green designates 2.5GBit)
      1 Green LED for the SFP+ port

The photos already show a modified PCB: Unpopulated resistors R52 and R53
have been bridged in order to enable the serial console. The smaller flash
memory chip at U2 has been replaced with a Windbond 128MBit standard-sized
SOIC-8 chip in order to easily use SOIC clamps to flash the device. Also
the serial header has been populated.
2026-02-27 20:11:53 +01:00
feelfree69 ffbd2c512d Check for sifficient flashsize before applying an update 2026-02-25 18:51:00 +01:00
René van Dorst ba18fa19b0 Merge pull request #138 from logicog/kp_9000_x6hml_x2
Add device photos of KeepLink KP-9000-6XHML-X2
2026-02-25 17:45:53 +00:00
logicog 70127018da Add device photos of KeepLink KP-9000-6XHML-X2 2026-02-25 18:07:54 +01:00
feelfree69 e26a9e3db9 Merge pull request #93 from logicog/cmdbuf
Add support for command line editing
2026-02-25 15:55:41 +01:00
René van Dorst d29d7dcf98 Merge pull request #139 from logicog/fix_6xhml_reset
Fix reset button GPIO-Number for MACHINE_KP_9000_6XHML_X2
2026-02-25 08:28:28 +01:00
logicog 734cce381a Fix reset button GPIO-Number for MACHINE_KP_9000_6XHML_X2 2026-02-25 06:28:49 +01:00
logicog dfc96761b3 Add support for history editing 2026-02-24 19:57:22 +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
logicog 284b2b003d Merge pull request #127 from feelfree69/resetbutton
Add button handling with the possibility to revert to default settings
2026-02-23 21:01:14 +01:00
logicog 68a8a9ee92 Merge pull request #128 from vDorst/doc_mods_fix
docs: mods: Fix MiB numbers.
2026-02-23 07:46:54 +01:00
logicog 0045a74df0 Merge pull request #102 from TylerDurden-23/opt-system-settings
Add startup config editor to system settings menu
2026-02-16 20:53:52 +01:00
feelfree69 0bdb238c0a Check fir button presses once a second 2026-02-15 16:42:18 +01:00
René van Dorst 033616ef63 Merge pull request #130 from MaDill/patch-1
Update README.md how to compile
2026-02-15 15:38:45 +00:00
René van Dorst a57aeda053 Merge pull request #132 from feelfree69/default_machine
fix `make MACHINE=DEFAULT_8C_1SFP`
2026-02-15 15:22:12 +00:00
feelfree69 556899d346 fix make MACHINE=DEFAULT_8C_1SFP 2026-02-15 14:05:49 +01:00
MaDill cc734ecac2 Update README.md
changed as requested
2026-02-15 14:02:37 +01:00
feelfree69 e5d23f11de Demagic FLASH_BUF_SIZE 2026-02-15 13:28:31 +01:00
feelfree69 3c648d5936 Fix messed up merge commit; add button user feedback via sysled 2026-02-15 13:01:22 +01:00
feelfree69 4658667459 fix compiler warning 2026-02-15 13:00:02 +01:00
feelfree69 e966b153af Merge branch 'main' into resetbutton 2026-02-15 12:34:46 +01:00
feelfree69 5ecd0e6a32 revert changing machine.h 2026-02-15 12:15:06 +01:00
René van Dorst d8b52d50de Merge pull request #131 from vDorst/fix_github_action
Fix GitHub actions build and select machine-type via variable.
2026-02-15 11:08:18 +00:00
René van Dorst 1f6f7fbcd4 Fix GITHUB action build.
PR #119 made that no machine-type is selected, so the build will fail.
commit 2f787fee enables us select a machine via a variable, use this to
select a machine-type `KP_9000_6XHML_X2` to build.
2026-02-15 11:25:47 +01:00
René van Dorst c7ea28393a machine: Fix missing MACHINE_KP_9000_9XHML_X, fixes #120 2026-02-15 11:24:40 +01:00
René van Dorst 2f787feebf Makefile: Select MACHINE via a variable 2026-02-15 11:12:26 +01:00
René van Dorst 4c1266dca9 Merge pull request #119 from feelfree69/swtgw218as
Add MACHINE_SWTGW218AS Managed Switch.
Deselect all MACHINE type so the use always have to select a machine type.
2026-02-15 09:21:33 +00:00
MaDill 4d11d70356 Update README.md how to compile
Updte the "compiling" chapter
2026-02-15 09:13:53 +01:00
René van Dorst ff94e383aa docs: mods: Fix MiB numbers. 2026-02-14 19:35:18 +01:00
feelfree69 9f7e10fe7c Merge branch 'main' into swtgw218as 2026-02-14 19:22:17 +01:00
René van Dorst b67e3eb602 Merge pull request #122 from logicog/fix_6xhml_x2_new
Fix MACHINE_KP_9000_6XHML_X2: swap SFP-ports remove unnecessary LED-MUX
2026-02-14 17:44:31 +00:00
chriz 5d731393f1 Delay reset, to allow TCP reset to be transmitted. 2026-02-14 11:17:42 +01:00
chriz 0e2a5fb7bc Reload startup config after save. 2026-02-14 11:02:05 +01:00
feelfree69 79c9d0deab Add button handling with the possibility to revert to default settings 2026-02-14 10:55:35 +01:00
logicog 73c56ecfe5 Merge pull request #126 from TylerDurden-23/add-kp-pics
Add photos keeplink KP-9000-6XH-X2 unmanaged
2026-02-14 06:01:26 +01:00
chriz 5e9f3324d5 Add photos keeplink KP-9000-6XH-X2 unmanaged. 2026-02-13 19:01:53 +01:00
René van Dorst 94739644b7 Merge pull request #124 from TylerDurden-23/hs-add-fix
Fix SFP numbering for HI-K0402WS
2026-02-13 16:04:54 +01:00
chriz 257d8aac4f Fix SFP numbering. 2026-02-13 14:54:35 +01:00
chriz d5019b41df Add warning for advanced safe. 2026-02-13 10:32:23 +01:00
chriz eae7f10d7a Make Advanced configuration tabbed. 2026-02-13 08:43:48 +01:00
logicog 1b43addb11 Fix MACHINE_KP_9000_6XHML_X2: swap SFP-ports remove unnecessary LED-MUX
The left and right SFP ports were swapped in the machine structure. They
are now correctly identified a comment is added. The custo LED-mux
is removed again, as this was accidentally added for demonstration
purposes. It is not necessary, as the device uses the default.
2026-02-13 07:53:29 +01:00
feelfree69 f8c1ab4198 Add .md and photos 2026-02-12 21:56:37 +01:00
feelfree69 11a5feb49d Add GPIO for reset button 2026-02-12 19:55:04 +01:00
feelfree69 1e7e1f42cc respect max length of machine_name 2026-02-12 19:30:50 +01:00
chriz ea37126e87 New apporach: Make startup config independent. 2026-02-12 14:17:22 +01:00
TylerDurden-23 670e0f02ec Merge branch 'logicog:main' into opt-system-settings 2026-02-11 23:02:20 +01:00
feelfree69 b4e7865bb7 Merge branch 'main' into swtgw218as 2026-02-11 23:00:07 +01:00
René van Dorst 15b0bf9664 Merge pull request #97 from TylerDurden-23/hs-add-clean
Add support for HiSource K0402WS-V3.0.
2026-02-11 21:37:11 +00:00
TylerDurden-23 8bd07ee649 Correct device name from Hi-KO4022WS to Hi-K0402WS 2026-02-11 22:34:55 +01:00
TylerDurden-23 3e1031b0f0 Highlight efficiency with 5V power supply
Emphasize the efficiency improvement with 5V power supply.
2026-02-11 22:33:59 +01:00
TylerDurden-23 9918a6267c Update documentation for Hi-KO4022WS switch
Added information about UART baud rate and installation method.
2026-02-11 22:33:02 +01:00
TylerDurden-23 bea162962e Correct model name in HI-K0402WS documentation 2026-02-11 22:32:37 +01:00
chriz a2ce5550fc Add documentation file. 2026-02-11 22:30:40 +01:00
TylerDurden-23 1d91c1bf2c Merge branch 'logicog:main' into opt-system-settings 2026-02-11 21:15:56 +01:00
feelfree69 9d8d6f03cc Adding more speeds to SFP link LED 2026-02-11 20:12:16 +01:00
chriz 98f3f15e7e Fix sfp marker. 2026-02-11 20:03:38 +01:00
TylerDurden-23 6f223d3f66 Merge branch 'logicog:main' into hs-add-clean 2026-02-11 20:00:45 +01:00
logicog fe1df83a88 Merge pull request #120 from vDorst/dev_keeplink_kp-9000-9xhml-x_3
Add Keeplink KP-9000-9XHML-X (RTL8373N + RTL8224N) to machine file.
2026-02-11 19:57:48 +01:00
logicog e7b7cb0253 Merge pull request #118 from TylerDurden-23/fix-link-speed
Fix no 10Mbit link speed shown
2026-02-11 19:55:25 +01:00
René van Dorst 4a3cd7b73c Update Keeplink KP-9000-9XHML-X docs. 2026-02-11 19:19:38 +01:00
René van Dorst f538a9344b Add Keeplink KP-9000-9XHML-X to machine-file. 2026-02-11 19:18:24 +01:00
feelfree69 f2b81af702 Do not set default machine in machine.h to force the user to choose one 2026-02-11 19:01:53 +01:00
feelfree69 651bdb6489 Add MACHINE_SWTGW218AS; do not set a default MACHINE, but force the user the choose one 2026-02-11 18:51:06 +01:00
feelfree69 841e1bf95e set sysled to slow blinking directly after leds have been configured 2026-02-11 18:21:19 +01:00
TylerDurden-23 7e652f3fb7 Merge branch 'logicog:main' into opt-system-settings 2026-02-11 12:31:00 +01:00
TylerDurden-23 90be2f47a3 Merge branch 'logicog:main' into fix-link-speed 2026-02-11 12:30:26 +01:00
chriz 859a50bd82 fix-link-speed 2026-02-10 23:17:04 +01:00
chriz 75b06ac90a Add support for HiSource K0402WS-V3.0 2026-02-10 22:52:03 +01:00
René van Dorst d2edb92ddf Merge pull request #107 from logicog/hg0502xg
Generic Port LED configuration based on machine-configuration
2026-02-10 16:58:42 +00:00
chriz 0099c2a03a Fix no 10Mbit link speed shown. Determine link state and speed seperately. Additional handling for port > 8. 2026-02-09 20:16:57 +01:00
logicog d29adafe3c Use generic led configuration 2026-02-08 20:25:01 +01:00
logicog 59894e68cb Add LED-pad mapping 2026-02-08 20:24:58 +01:00
logicog 6af072eb2c Add LED configuration in machine profile 2026-02-08 20:24:05 +01:00
logicog 8cae3f1212 Add generic LED configuration support 2026-02-08 20:23:30 +01:00
logicog 9aaddcd9b9 Reduce DSEG usage as we need 1 OSEG byte 2026-02-08 20:23:30 +01:00
logicog 196e430ec6 Remove debug output 2026-02-08 20:23:30 +01:00
logicog 9424aa3a3b LED configuration support 2026-02-08 20:23:30 +01:00
logicog 7a57416e4c Add MACHINE_HG0402XG_V1_1 2026-02-08 20:23:29 +01:00
René van Dorst fc53003022 Merge pull request #116 from logicog/speed_fixes
Fix Speed Setting using Auton-Neg
2026-02-08 18:26:43 +00:00
logicog 47878ac580 Add more printout 2026-02-08 16:46:56 +01:00
logicog d83f91f9e8 Fix Auto-negotiation
Commit 7f4c276 used the wrong MMD device
for use with the auto-negotiation page:
- phy_write(port, PHY_MMD_AN, 0x00, 0x3200);	// Restart AN
+ phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x3200);	// Restart AN

Fix this.
2026-02-08 16:46:56 +01:00
logicog 708b6b7f28 Use new signatures for vlan_create and phy-settings 2026-02-08 16:46:56 +01:00
logicog 9d07416641 Convert phy_set_duplex phy_set_speed to use struct phy_settings 2026-02-08 16:46:56 +01:00
logicog 4747eac9bf Reduce DSEG usage for parameters used in port/vlan configuration
Currently 5 Bytes are used by the port and vlan configuration:
--------------------------------------------------------
; internal ram data
;--------------------------------------------------------
	.area DSEG    (DATA)
_port_ingress_filter_PARM_2:
	.ds 1
_vlan_create_PARM_2:
	.ds 2
_vlan_create_PARM_3:
	.ds 2

They are used for passing parameters. Use __xdata to pass the
parameters instead.
2026-02-08 16:03:37 +01:00
logicog ecf152990f Fix MACHINE_KP_9000_6XHML_X2: the SDS ids were swapped 2026-02-08 16:03:37 +01:00
René van Dorst d4ed753715 Merge pull request #117 from logicog/uuid_mac
Generate a random stable locally administered addresses (LAA) MAC address based on the SoC's UUID + LOT number.
2026-02-08 14:58:36 +00: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
TylerDurden-23 8f3cabdaff Merge branch 'logicog:main' into opt-system-settings 2026-02-07 18:57:32 +01:00
logicog eafe2e96e8 Merge pull request #113 from diijkstra/trendnet_limited
Partial TRENDNET TEG-S562 support
2026-02-07 16:58:32 +01:00
logicog c4dc930ca8 Merge pull request #114 from TylerDurden-23/eee-on-boot
Add EEE speed option and enable EEE with 2g5 as default at boot
2026-02-07 16:49:49 +01:00
TylerDurden-23 180de32060 Merge branch 'logicog:main' into opt-system-settings 2026-02-07 14:22:20 +01:00
chriz 68fd5d41a7 Add additional output. 2026-02-07 14:06:06 +01:00
logicog 6263b7e4c6 Merge pull request #112 from diijkstra/enable_sfp_setup
Enable SFP GPIO pins setup
2026-02-06 19:56:07 +01:00
logicog ee190a86a1 Merge pull request #88 from TylerDurden-23/main
Add Hisource HI-K0402WS pictures
2026-02-06 18:31:17 +01:00
TylerDurden-23 97b46071e0 Merge branch 'logicog:main' into opt-system-settings 2026-02-06 10:50:46 +01:00
chriz ed37d75aba Enable EEE on boot, do not reset interfaces immediately to save boot time. 2026-02-05 17:23:50 +01:00
chriz 3496d12111 Extend command parser. 2026-02-05 16:47:58 +01:00
TylerDurden-23 cfb7a589a8 Merge branch 'logicog:main' into eee-on-boot 2026-02-05 16:12:43 +01:00
diijkstra 5391d3ec32 Partial TRENDNET TEG-S562 support
Mostly working, lacking LED initialization changes.
LEDs will be added later once #107 is merged.

Closes #76.
2026-02-04 18:25:07 +01:00
diijkstra f6e4f13ebd Enable SFP GPIO pins
Previous changes addded initialization rotine, which was never called.
2026-02-04 18:17:25 +01:00
chriz 55fd2d5fb6 Add speed option to EEE function. 2026-01-28 09:21:03 +01:00
chriz 5662285a3e Clear command log after saving. 2026-01-26 23:29:23 +01:00
chriz b5c249995f Add startup config editor. 2026-01-26 20:40:30 +01:00
chriz a528436572 Add HiSource HI-K0402WS pictures 2026-01-21 14:43:04 +01:00
68 changed files with 2851 additions and 649 deletions
+1 -1
View File
@@ -18,4 +18,4 @@ jobs:
apt update apt update
apt install make gcc sdcc xxd python-is-python3 libjson-c-dev -y apt install make gcc sdcc xxd python-is-python3 libjson-c-dev -y
- name: Make project - name: Make project
run: make run: make MACHINE="KP_9000_6XHML_X2"
+13 -6
View File
@@ -1,7 +1,6 @@
BOOTLOADER_ADDRESS=0x100
VERSION=0.1.0 VERSION=0.1.0
IMAGESIZE = 524288 IMAGESIZE = 524288
DEFAULT_CONFIG_LOCATION = 454656
CONFIG_LOCATION = 458752 CONFIG_LOCATION = 458752
HTML_LOCATION = 262144 HTML_LOCATION = 262144
@@ -16,14 +15,20 @@ SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS))
BUILDDIR = output/ BUILDDIR = output/
VERSION_HEADER := version.h VERSION_HEADER := version.h
ifeq ($(MACHINE),)
else
CC_FLAGS += -DMACHINE_$(MACHINE)
endif
all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)rtlplayground.bin all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)rtlplayground.bin
create_build_dir: create_build_dir:
mkdir -p $(BUILDDIR) mkdir -p $(BUILDDIR)
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_leds.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c SRCS = rtlplayground.c rtl837x_flash.c rtl837x_leds.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c \
rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c cmd_editor.c rtl837x_bandwidth.c
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel} OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
OBJS += uip/$(BUILDDIR)/timer.rel uip/$(BUILDDIR)/uip-fw.rel uip/$(BUILDDIR)/uip-neighbor.rel uip/$(BUILDDIR)/uip-split.rel uip/$(BUILDDIR)/uip.rel uip/$(BUILDDIR)/uip_arp.rel uip/$(BUILDDIR)/uiplib.rel httpd/$(BUILDDIR)/httpd.rel httpd/$(BUILDDIR)/page_impl.rel OBJS += uip/$(BUILDDIR)/timer.rel uip/$(BUILDDIR)/uip-fw.rel uip/$(BUILDDIR)/uip-split.rel uip/$(BUILDDIR)/uip.rel uip/$(BUILDDIR)/uip_arp.rel uip/$(BUILDDIR)/uiplib.rel httpd/$(BUILDDIR)/httpd.rel httpd/$(BUILDDIR)/page_impl.rel
html_data.c html_data.h: html tools html_data.c html_data.h: html tools
tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -d html -p html_data tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -d html -p html_data
@@ -32,6 +37,7 @@ $(VERSION_HEADER):
@echo "#ifndef VERSION_H" > $(VERSION_HEADER) @echo "#ifndef VERSION_H" > $(VERSION_HEADER)
@echo "#define VERSION_H" >> $(VERSION_HEADER) @echo "#define VERSION_H" >> $(VERSION_HEADER)
@echo "#define VERSION_SW \"v$(VERSION)-g$(shell git rev-parse --short HEAD)\"" >> $(VERSION_HEADER) @echo "#define VERSION_SW \"v$(VERSION)-g$(shell git rev-parse --short HEAD)\"" >> $(VERSION_HEADER)
@echo "#define BUILD_DATE \"$(shell date +"%Y-%m-%d %H:%M:%S")\"" >> $(VERSION_HEADER)
@echo "#endif" >> $(VERSION_HEADER) @echo "#endif" >> $(VERSION_HEADER)
httpd: html_data.h httpd: html_data.h
@@ -58,8 +64,8 @@ $(BUILDDIR)%.rel: $(BUILDDIR)%.asm
${ASM} ${AFLAGS} -o $@ $< ${ASM} ${AFLAGS} -o $@ $<
# mv -f $(addprefix $(basename $^), .lst .rel .sym) . # mv -f $(addprefix $(basename $^), .lst .rel .sym) .
$(BUILDDIR)rtlplayground.ihx: $(BUILDDIR)crtstart.rel $(OBJS) $(BUILDDIR)crc16.rel $(BUILDDIR)rtlplayground.ihx: $(OBJS) $(BUILDDIR)crtstart.rel $(BUILDDIR)crc16.rel
$(CC) $(CC_FLAGS) -Wl-bHOME=${BOOTLOADER_ADDRESS} -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-r -o $@ $^ $(CC) $(CC_FLAGS) -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-r -o $@ $^
$(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx $(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx
objcopy --input-target=ihex -O binary $< $@ objcopy --input-target=ihex -O binary $< $@
@@ -67,6 +73,7 @@ $(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx
$(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlplayground.img $(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlplayground.img
if [ -e $@ ]; then rm $@; fi if [ -e $@ ]; then rm $@; fi
tools/$(BUILDDIR)imagebuilder -i $^ $@ tools/$(BUILDDIR)imagebuilder -i $^ $@
tools/$(BUILDDIR)fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
tools/$(BUILDDIR)fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@ tools/$(BUILDDIR)fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -d html -p html_data $@ tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -d html -p html_data $@
tools/$(BUILDDIR)crc_calculator -u $@ tools/$(BUILDDIR)crc_calculator -u $@
+3 -11
View File
@@ -56,20 +56,12 @@ device simulator is provided, which runs entirely under Linux as a local webserv
Install the following particular build requisites (Debian 12/13), note that Ubuntu 24.04 Install the following particular build requisites (Debian 12/13), note that Ubuntu 24.04
still has an older version of sdcc, but you will need sdcc version 4.5 for the code to compile: still has an older version of sdcc, but you will need sdcc version 4.5 for the code to compile:
``` ```
sudo apt install sdcc xxd python-is-python3 libjson-c-dev sudo apt install make gcc sdcc xxd python-is-python3 libjson-c-dev
``` ```
Edit machine.h with an editor like vi or nano. Select the correct machine the firmware should build for.
Now, building the firmware image should work: Now, building the firmware image should work:
``` ```
$ make make
sdas8051 -plosgff crtstart.asm
sdcc -mmcs51 -c rtlplayground.c
sdcc -mmcs51 -c rtl837x_flash.c
sdcc -mmcs51 -Wl-bHOME=0x100 -o rtlplayground.ihx crtstart.rel rtlplayground.rel rtl837x_flash.rel
objcopy --input-target=ihex -O binary rtlplayground.ihx rtlplayground.img
if [ -e rtlplayground.bin ]; then rm rtlplayground.bin; fi
echo "0000000: 00 40" | xxd -r - rtlplayground.bin
cat rtlplayground.img >> rtlplayground.bin
``` ```
Note, that the image generated ends in .bin, not .img, in order to make Note, that the image generated ends in .bin, not .img, in order to make
IMSProg happy. IMSProg happy.
+208
View File
@@ -0,0 +1,208 @@
#include "cmd_parser.h"
#include "machine.h"
#pragma codeseg BANK2
#pragma constseg BANK2
// Position in the serial buffer
__xdata uint8_t l;
// Properties of currently edited command line in cmd_buffer[CMD_BUF_SIZE]
__xdata uint8_t cursor;
__xdata uint8_t cmd_line_len;
__xdata uint8_t current_cmdline[CMD_BUF_SIZE];
__xdata uint16_t history_editptr;
extern __xdata uint8_t cmd_history[CMD_HISTORY_SIZE];
extern __xdata uint16_t cmd_history_ptr;
void cmd_editor_init(void) __banked
{
l = sbuf_ptr; // We have printed out entered characters until l
cursor = 0;
cmd_line_len = 0;
cmd_available = 0;
history_editptr = 0xffff;
}
/*
* Allows editing the current command line held in cmd_buffer[CMD_BUF_SIZE] by
* identifying new characters typed or up to 4-byte escape sequences in the
* serial buffer ring sbuf[SBUF_SIZE].
* Upon detecting new characters or escape sequences, the cmd_buffer and the
* representation of the command line in the terminal are updated.
* To debug, the easist is to interpose a tty-interceptor between the physical
* serial device and a logical one created by interceptty:
* sudo interceptty -s 'ispeed 115200 ospeed 115200' /dev/ttyUSB0 /dev/tmpS
* picocom -b 115200 /dev/tmpS
*/
void cmd_edit(void) __banked
{
while (l != sbuf_ptr) {
if (sbuf[l] >= ' ' && sbuf[l] < 127) { // A printable character, copy to command line
if (cmd_line_len >= CMD_BUF_SIZE)
continue;
write_char(sbuf[l]);
// Shift buffer to right
for (uint8_t i = cmd_line_len; i > cursor; i--)
cmd_buffer[i] = cmd_buffer[i-1];
// Insert char in comand buffer
cmd_buffer[cursor++] = sbuf[l];
cmd_line_len++;
// Print rest of line
for (uint8_t i = cursor; i < cmd_line_len; i++)
write_char(cmd_buffer[i]);
// Move backwards
for (uint8_t i = cursor; i < cmd_line_len; i++)
write_char('\010'); // BS works like cursor-left
} else if (sbuf[l] == '\033') { // ESC-Sequence
// Wait until we have at least 3 characters including the ESC character in the serial buffer
if (((sbuf_ptr + SBUF_SIZE - l) & SBUF_MASK) < 3)
continue;
if (((sbuf_ptr > l ? sbuf_ptr - l : SBUF_SIZE + sbuf_ptr - l) >= 4)
&& sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == '3' && sbuf[(l + 3) & SBUF_MASK] == '~') { // DEL
if (cursor < cmd_line_len) {
write_char('\033'); write_char('['); write_char('1'); write_char('P'); // Delete to end of line
cmd_line_len--;
for (uint8_t i = cursor; i < cmd_line_len; i++) {
cmd_buffer[i] = cmd_buffer[i+1];
write_char(cmd_buffer[i]);
}
for (uint8_t i = cursor; i < cmd_line_len; i++)
write_char('\010');
}
l += 4;
l &= SBUF_MASK;
continue;
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'D') { // <CURSOR-LEFT>
if (cursor) {
write_char('\010'); // BS works like cursor-left
cursor--;
}
l += 3;
l &= SBUF_MASK;
continue;
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'C') { // <CURSOR-RIGHT>
if (cursor < cmd_line_len) {
write_char('\033'); write_char('['); write_char('C');
cursor++;
}
l += 3;
l &= SBUF_MASK;
continue;
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'A') { // <CURSOR-UP>
for (uint8_t i = 0; i < cmd_line_len; i++)
current_cmdline[i] = cmd_buffer[i];
current_cmdline[cmd_line_len] = 0;
__xdata uint16_t p;
if (history_editptr == 0xffff)
p = (cmd_history_ptr - 2) & CMD_HISTORY_MASK;
else
p = history_editptr;
// Move cursor to beginning of line
write_char('\033'); write_char('['); itoa(cursor + 2); write_char('D');
cursor = 0;
while (cmd_history[p] && cmd_history[p] != '\n') {
cursor++;
p--;
p &= CMD_HISTORY_MASK;
}
history_editptr = (p - 1) & CMD_HISTORY_MASK;
p = (p + 1) & CMD_HISTORY_MASK;
if (cursor) {
print_string("\033[2K> "); // Clear entire line: ^[[2K and print new prompt
for (uint8_t i = 0; i < cursor; i++) {
cmd_buffer[i] = cmd_history[p];
write_char(cmd_buffer[i]);
p = (p+1) & CMD_HISTORY_MASK;
}
cmd_line_len = cursor;
} else {
print_string("\033[2C"); // Move 2 right to start of editing space
}
l += 3;
l &= SBUF_MASK;
continue;
} else if (sbuf[l] == '\033' && sbuf[(l + 1) & SBUF_MASK] == '[' && sbuf[(l + 2) & SBUF_MASK] == 'B') { // <CURSOR-DOWN>
if (history_editptr != 0xffff) {
__xdata uint16_t p = (history_editptr + 2) & CMD_HISTORY_MASK;
// Move cursor to beginning of line
write_char('\033'); write_char('['); itoa(cursor + 2); write_char('D');
print_string("\033[2K> "); // Clear entire line: ^[[2K and print new prompt
uint8_t i = 0;
while (cmd_history[p] && cmd_history[p] != '\n') {
p = (p + 1) & CMD_HISTORY_MASK;
}
p = (p + 1) & CMD_HISTORY_MASK;
while (cmd_history[p] && cmd_history[p] != '\n') {
cmd_buffer[i] = cmd_history[p];
write_char(cmd_buffer[i++]);
p = (p + 1) & CMD_HISTORY_MASK;
}
history_editptr = (p - 1) & CMD_HISTORY_MASK;
if (!i) {
if (current_cmdline[i]) {
while (current_cmdline[i]) {
cmd_buffer[i] = current_cmdline[i];
write_char(cmd_buffer[i++]);
}
} else {
write_char('\033'); write_char('['); write_char('C');
}
history_editptr = 0xffff;
// Move cursor right
}
cmd_line_len = i;
cursor = 0;
// Move cursor again to beginning of line
write_char('\033'); write_char('['); itoa(i); write_char('D');
} else {
// If we are at the last entry of the history, just move the cursor to the end of the line
if (cursor < cmd_line_len) {
write_char('\033'); write_char('['); itoa(cmd_line_len - cursor); write_char('C');
}
cursor = cmd_line_len;
}
l += 3;
l &= SBUF_MASK;
continue;
} else { // An unknown or not yet complete Escape sequence: wait
continue;
}
} else if (sbuf[l] == 127) { // Backspace
if (cursor > 0) {
write_char('\010');
for (uint8_t i = cursor; i < cmd_line_len; i++)
write_char(cmd_buffer[i]);
write_char(' '); // Overwrite end of line
// Move backwards n steps:
for (uint8_t i = cursor; i <= cmd_line_len; i++)
write_char('\010');
cursor--;
for (uint8_t i = cursor; i <= cmd_line_len; i++)
cmd_buffer[i] = cmd_buffer[i+1];
cmd_line_len--;
}
}
// If the command buffer is currently in use, we cannot copy to it
if (cmd_available)
break;
// Check whether return was pressed:
if (sbuf[l] == '\n' || sbuf[l] == '\r') {
write_char('\n');
cmd_buffer[cmd_line_len] = '\0';
// write_char('>'); print_string_x(cmd_buffer); write_char('<');
// If there is a command we print the prompt after execution
// otherwise immediately because there is nothing to execute
if (cmd_line_len)
cmd_available = 1;
else
print_string("\n> ");
cursor = 0;
cmd_line_len = 0;
history_editptr = 0xffff;
}
l++;
l &= SBUF_MASK;
}
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef _CMD_EDITOR_H_
#define _CMD_EDITOR_H_
#include <stdint.h>
void cmd_editor_init(void) __banked;
void cmd_edit(void) __banked;
#endif
+230 -96
View File
@@ -13,6 +13,7 @@
#include "rtl837x_sfr.h" #include "rtl837x_sfr.h"
#include "rtl837x_stp.h" #include "rtl837x_stp.h"
#include "rtl837x_igmp.h" #include "rtl837x_igmp.h"
#include "rtl837x_bandwidth.h"
#include "dhcp.h" #include "dhcp.h"
#include "uip/uip.h" #include "uip/uip.h"
#include "version.h" #include "version.h"
@@ -33,7 +34,7 @@ extern volatile __xdata uint8_t sfr_data[4];
extern __code uint8_t * __code greeting; extern __code uint8_t * __code greeting;
extern __code uint8_t * __code hex; extern __code uint8_t * __code hex;
extern __xdata uint8_t flash_buf[512]; extern __xdata uint8_t flash_buf[FLASH_BUF_SIZE];
extern __xdata struct flash_region_t flash_region; extern __xdata struct flash_region_t flash_region;
extern __xdata char passwd[21]; extern __xdata char passwd[21];
@@ -43,6 +44,7 @@ extern __xdata struct dhcp_state dhcp_state;
__xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; __xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
__xdata uint16_t vlan_ptr; __xdata uint16_t vlan_ptr;
extern __xdata uint16_t management_vlan; extern __xdata uint16_t management_vlan;
extern __xdata uint16_t dhcpd_vlan;
__xdata uint8_t gpio_last_value[8] = { 0 }; __xdata uint8_t gpio_last_value[8] = { 0 };
// Temporatly for str to hex convertion value. // Temporatly for str to hex convertion value.
@@ -51,17 +53,16 @@ __xdata uint8_t hexvalue[4] = { 0 };
// Buffer for writing to flash 0x1fd000, copy to 0x1fe000 // Buffer for writing to flash 0x1fd000, copy to 0x1fe000
__xdata uint8_t cmd_buffer[SBUF_SIZE]; __xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
__xdata uint8_t cmd_available; __xdata uint8_t cmd_available;
__xdata uint8_t l;
__xdata uint8_t line_ptr; __xdata uint8_t line_ptr;
__xdata char is_white; __xdata char is_white;
__xdata char save_cmd; __xdata char save_cmd;
__xdata uint8_t ip[4]; __xdata uint8_t ip[4];
#define N_WORDS SBUF_SIZE #define N_WORDS CMD_BUF_SIZE
__xdata signed char cmd_words_b[N_WORDS]; __xdata signed char cmd_words_b[N_WORDS];
__xdata uint8_t cmd_history[CMD_HISTORY_SIZE]; __xdata uint8_t cmd_history[CMD_HISTORY_SIZE];
@@ -93,7 +94,7 @@ uint8_t cmd_compare(uint8_t start, uint8_t * __code cmd)
signed char j = 0; signed char j = 0;
for (i = cmd_words_b[start]; i != cmd_words_b[start + 1] && cmd_buffer[i] != ' '; i++) { for (i = cmd_words_b[start]; i != cmd_words_b[start + 1] && cmd_buffer[i] != ' '; i++) {
i &= SBUF_SIZE - 1; i &= CMD_BUF_SIZE - 1;
// print_byte(i); write_char(':'); print_byte(j); write_char('#'); print_string("\n"); // print_byte(i); write_char(':'); print_byte(j); write_char('#'); print_string("\n");
// write_char('>'); write_char(cmd[j]); write_char('-'); write_char(cmd_buffer[i]); print_string("\n"); // write_char('>'); write_char(cmd[j]); write_char('-'); write_char(cmd_buffer[i]); print_string("\n");
if (!cmd[j] && !isletter(cmd_buffer[i])) if (!cmd[j] && !isletter(cmd_buffer[i]))
@@ -150,6 +151,14 @@ uint8_t atoi_hex(uint8_t idx)
h_idx++; h_idx++;
} }
if (h_idx & 1) {
hexvalue[h_idx >> 1] <<= 4;
hexvalue[3] = hexvalue[3] >> 4 | (hexvalue[2] << 4);
hexvalue[2] = hexvalue[2] >> 4 | (hexvalue[1] << 4);
hexvalue[1] = hexvalue[1] >> 4 | (hexvalue[0] << 4);
hexvalue[0] >>= 4;
}
return ((h_idx + 1) >> 1); return ((h_idx + 1) >> 1);
} }
@@ -282,17 +291,17 @@ void parse_lag_hash(void)
void parse_vlan(void) void parse_vlan(void)
{ {
__xdata uint16_t vlan; vlan_settings.vlan = 0;
__xdata uint16_t members = 0; vlan_settings.members = 0;
__xdata uint16_t tagged = 0; vlan_settings.tagged = 0;
if (!atoi_short(&vlan, cmd_words_b[1])) { if (!atoi_short(&vlan_settings.vlan, cmd_words_b[1])) {
if (cmd_words_b[2] > 0 && cmd_buffer[cmd_words_b[2]] == 'd' && cmd_words_b[3] < 0) { if (cmd_words_b[2] > 0 && cmd_buffer[cmd_words_b[2]] == 'd' && cmd_words_b[3] < 0) {
vlan_delete(vlan); vlan_delete(vlan_settings.vlan);
return; return;
} }
if (cmd_words_b[2] > 0 && cmd_compare(2, "mgmt")) { if (cmd_words_b[2] > 0 && cmd_compare(2, "mgmt")) {
management_vlan = vlan; management_vlan = vlan_settings.vlan;
if (!vlan) if (!vlan_settings.vlan)
print_string("Management VLAN disabled\n"); print_string("Management VLAN disabled\n");
else else
print_string("Management VLAN set to "); print_short(management_vlan); write_char('\n'); print_string("Management VLAN set to "); print_short(management_vlan); write_char('\n');
@@ -301,9 +310,9 @@ void parse_vlan(void)
uint8_t w = 2; uint8_t w = 2;
if (cmd_words_b[w] > 0 && isletter(cmd_buffer[cmd_words_b[w]])) { if (cmd_words_b[w] > 0 && isletter(cmd_buffer[cmd_words_b[w]])) {
register uint8_t i = 0; register uint8_t i = 0;
vlan_names[vlan_ptr++] = hex[(vlan >> 8) & 0xf]; vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 8) & 0xf];
vlan_names[vlan_ptr++] = hex[(vlan >> 4) & 0xf] ; vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 4) & 0xf] ;
vlan_names[vlan_ptr++] = hex[vlan & 0xf]; vlan_names[vlan_ptr++] = hex[vlan_settings.vlan & 0xf];
while(cmd_buffer[cmd_words_b[w] + i] != ' ') { while(cmd_buffer[cmd_words_b[w] + i] != ' ') {
write_char(cmd_buffer[cmd_words_b[w] + i]); write_char(cmd_buffer[cmd_words_b[w] + i]);
vlan_names[vlan_ptr++] = cmd_buffer[cmd_words_b[w] + i++]; vlan_names[vlan_ptr++] = cmd_buffer[cmd_words_b[w] + i++];
@@ -313,25 +322,25 @@ void parse_vlan(void)
print_string("<\n"); print_string("<\n");
} }
while (cmd_words_b[w] > 0) { while (cmd_words_b[w] > 0) {
uint8_t port; __xdata uint8_t port;
if (isnumber(cmd_buffer[cmd_words_b[w]])) { if (isnumber(cmd_buffer[cmd_words_b[w]])) {
port = cmd_buffer[cmd_words_b[w]] - '1'; port = cmd_buffer[cmd_words_b[w]] - '1';
if (isnumber(cmd_buffer[cmd_words_b[w] + 1])) { if (isnumber(cmd_buffer[cmd_words_b[w] + 1])) {
port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1'; port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1';
if (cmd_buffer[cmd_words_b[w] + 2] == 't') if (cmd_buffer[cmd_words_b[w] + 2] == 't')
tagged |= ((uint16_t)1) << port; vlan_settings.tagged |= ((uint16_t)1) << port;
} else { } else {
port = machine.phys_to_log_port[port]; port = machine.phys_to_log_port[port];
if (cmd_buffer[cmd_words_b[w] + 1] == 't') if (cmd_buffer[cmd_words_b[w] + 1] == 't')
tagged |= ((uint16_t)1) << port; vlan_settings.tagged |= ((uint16_t)1) << port;
} }
if (port > machine.max_port) if (port > machine.max_port)
goto err; goto err;
members |= ((uint16_t)1) << port; vlan_settings.members |= ((uint16_t)1) << port;
} }
w++; w++;
} }
vlan_create(vlan, members, tagged); vlan_create();
} }
if (cmd_words_b[2] > 0 && isletter(cmd_buffer[cmd_words_b[2]])) { if (cmd_words_b[2] > 0 && isletter(cmd_buffer[cmd_words_b[2]])) {
print_string("vlan_ptr "); print_short(vlan_ptr); write_char(':'); print_string("vlan_ptr "); print_short(vlan_ptr); write_char(':');
@@ -422,10 +431,10 @@ void parse_mirror(void)
void parse_port(void) void parse_port(void)
{ {
print_string("\nPORT "); print_string("\nPORT ");
uint8_t p = cmd_buffer[cmd_words_b[1]] - '1'; phy_settings.port = cmd_buffer[cmd_words_b[1]] - '1';
p = machine.phys_to_log_port[p]; phy_settings.port = machine.phys_to_log_port[phy_settings.port];
print_byte(p); print_byte(phy_settings.port);
if (machine.is_sfp[p]) { if (machine.is_sfp[phy_settings.port]) {
print_string(" is SFP no PHY information available.\n"); print_string(" is SFP no PHY information available.\n");
return; return;
} }
@@ -433,46 +442,53 @@ void parse_port(void)
print_string("\nport <port> [show|on|off|10m|100m|1g|2g5] [half|full]"); print_string("\nport <port> [show|on|off|10m|100m|1g|2g5] [half|full]");
return; return;
} }
phy_settings.duplex = PHY_DUPLEX_BOTH;
if (cmd_compare(2, "10m")) { if (cmd_compare(2, "10m")) {
print_string(" 10M\n"); print_string(" 10M\n");
phy_settings.speed = PHY_SPEED_10M;
if (cmd_words_b[3] > 0 && cmd_compare(3, "half")) if (cmd_words_b[3] > 0 && cmd_compare(3, "half"))
phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_HALF); phy_settings.duplex = PHY_DUPLEX_HALF;
else if (cmd_words_b[3] > 0 && cmd_compare(3, "full")) else if (cmd_words_b[3] > 0 && cmd_compare(3, "full"))
phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_FULL); phy_settings.duplex = PHY_DUPLEX_FULL;
else phy_set_speed();
phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_BOTH);
} else if (cmd_compare(2, "100m")) { } else if (cmd_compare(2, "100m")) {
print_string(" 100M\n"); print_string(" 100M\n");
phy_settings.speed = PHY_SPEED_100M;
if (cmd_words_b[3] > 0 && cmd_compare(3, "half")) if (cmd_words_b[3] > 0 && cmd_compare(3, "half"))
phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_HALF); phy_settings.duplex = PHY_DUPLEX_HALF;
else if (cmd_words_b[3] > 0 && cmd_compare(3, "full")) else if (cmd_words_b[3] > 0 && cmd_compare(3, "full"))
phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_FULL); phy_settings.duplex = PHY_DUPLEX_FULL;
else phy_set_speed();
phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_BOTH);
} else if (cmd_compare(2, "2g5")) { } else if (cmd_compare(2, "2g5")) {
print_string(" 2.5G\n"); print_string(" 2.5G\n");
phy_set_speed(p, PHY_SPEED_2G5, PHY_DUPLEX_BOTH); phy_settings.speed = PHY_SPEED_2G5;
phy_set_speed();
} else if (cmd_compare(2, "1g")) { } else if (cmd_compare(2, "1g")) {
print_string(" 1G\n"); print_string(" 1G\n");
phy_set_speed(p, PHY_SPEED_1G, PHY_DUPLEX_BOTH); phy_settings.speed = PHY_SPEED_1G;
phy_set_speed();
} else if (cmd_compare(2, "auto")) { } else if (cmd_compare(2, "auto")) {
print_string(" AUTO\n"); print_string(" AUTO\n");
phy_set_speed(p, PHY_SPEED_AUTO, PHY_DUPLEX_BOTH); phy_settings.speed = PHY_SPEED_AUTO;
phy_set_speed();
} else if (cmd_compare(2, "off")) { } else if (cmd_compare(2, "off")) {
print_string(" OFF\n"); print_string(" OFF\n");
phy_set_speed(p, PHY_OFF, PHY_DUPLEX_BOTH); phy_settings.speed = PHY_OFF;
phy_set_speed();
} else if (cmd_compare(2, "on")) { } else if (cmd_compare(2, "on")) {
print_string(" ON\n"); print_string(" ON\n");
phy_set_speed(p, PHY_SPEED_AUTO, PHY_DUPLEX_BOTH); phy_settings.speed = PHY_SPEED_AUTO;
phy_set_speed();
} else if (cmd_compare(2, "duplex")) { } else if (cmd_compare(2, "duplex")) {
print_string(" DUPLEX\n"); print_string(" DUPLEX\n");
if (cmd_words_b[3] > 0 && cmd_compare(3, "full")) if (cmd_words_b[3] > 0 && cmd_compare(3, "full"))
phy_set_duplex(p, PHY_DUPLEX_FULL); phy_settings.speed = PHY_DUPLEX_FULL;
else else
phy_set_duplex(p, PHY_DUPLEX_HALF); phy_settings.speed = PHY_DUPLEX_HALF;
phy_set_duplex();
} }
if (cmd_words_b[2] > 0 && cmd_compare(2, "show")) { if (cmd_words_b[2] > 0 && cmd_compare(2, "show")) {
phy_show(p); phy_show(phy_settings.port);
} }
} }
@@ -633,6 +649,137 @@ void parse_passwd(void)
} }
void parse_eee(void)
{
__xdata int8_t port = -1;
__xdata uint8_t speed = EEE_2G5;
__xdata uint8_t speed_word = 0;
// Check if word 2 is a speed (contains 'g' or 'm') or a port number
if (cmd_words_b[3] > 0) {
uint8_t idx = cmd_words_b[2];
// Skip digits to check if there's a letter after
while (isnumber(cmd_buffer[idx]))
idx++;
if (cmd_buffer[idx] == 'g' || cmd_buffer[idx] == 'm') {
// Word 2 is a speed (e.g., "2g5", "100m", "1g")
speed_word = 2;
} else if (cmd_buffer[idx] == ' ' || cmd_buffer[idx] == '\0') {
// Word 2 is a port number
port = cmd_buffer[cmd_words_b[2]] - '1';
port = machine.phys_to_log_port[port];
// Check if word 3 is a speed
if (cmd_words_b[4] > 0)
speed_word = 3;
}
}
// Parse speed if found
if (speed_word > 0) {
if (cmd_compare(speed_word, "100m"))
speed = EEE_100;
else if (cmd_compare(speed_word, "1g"))
speed = EEE_1000;
else if (cmd_compare(speed_word, "2g5"))
speed = EEE_2G5;
else
{
print_string("Speed word invalid, use: [100m|1g|2g5]\n");
return;
}
}
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
if (port >= 0)
port_eee_enable(port, speed);
else
port_eee_enable_all(speed);
} else if (cmd_words_b[1] > 0 && cmd_compare(1, "off")) {
if (port >= 0)
port_eee_disable(port);
else
port_eee_disable_all();
} else if (cmd_words_b[1] > 0 && cmd_compare(1, "status")) {
if (port >= 0)
port_eee_status(port);
else
port_eee_status_all();
} else {
print_string("eee [on|off|status] [port] [100m|1g|2g5]\n");
}
}
void parse_bw(void)
{
__xdata uint8_t port;
__xdata uint32_t bw = 0;
if (cmd_words_b[3] < 0) // Check for at least 2 arguments
goto err;
port = cmd_buffer[cmd_words_b[2]] - '1';
if (port > 9)
goto err;
port = machine.phys_to_log_port[port];
if (cmd_compare(1, "status")) {
bandwidth_status(port);
return;
}
if (cmd_words_b[4] < 0) // Check for at least 3 arguments
goto err;
if (cmd_compare(3, "drop")) {
if (cmd_compare(1, "in")) {
bandwidth_ingress_drop(port);
return;
}
goto err;
}
if (cmd_compare(3, "fc")) {
if (cmd_compare(1, "in")) {
bandwidth_ingress_fc(port);
return;
}
goto err;
}
if (cmd_compare(3, "off")) {
if (cmd_compare(1, "in")) {
bandwidth_ingress_disable(port);
return;
} else if (cmd_compare(1, "out")) {
bandwidth_egress_disable(port);
return;
}
goto err;
}
uint8_t hex_size = atoi_hex(cmd_words_b[3]);
if (hex_size == 0 || hex_size > 4) {
goto err;
}
uint8_t i = 0;
while (hex_size) {
hex_size--;
*(((uint8_t *) &bw) + hex_size) = hexvalue[i++];
}
if (cmd_compare(1, "in")) {
bandwidth_ingress_set(port, bw);
} else if (cmd_compare(1, "out")) {
bandwidth_egress_set(port, bw);
} else {
goto err;
}
return;
err:
print_string("usage: bw [in|out|status] <port> [<hexvalue>|off|drop|fc]\n");
}
// Parse command into words // Parse command into words
uint8_t cmd_tokenize(void) __banked uint8_t cmd_tokenize(void) __banked
{ {
@@ -645,7 +792,7 @@ uint8_t cmd_tokenize(void) __banked
is_white = 1; is_white = 1;
uint8_t word = 0; uint8_t word = 0;
cmd_words_b[0] = -1; cmd_words_b[0] = -1;
while (cmd_buffer[line_ptr] && line_ptr < SBUF_SIZE - 1) { while (cmd_buffer[line_ptr] && line_ptr < CMD_BUF_SIZE - 1) {
if (is_white && cmd_buffer[line_ptr] != ' ') { if (is_white && cmd_buffer[line_ptr] != ' ') {
is_white = 0; is_white = 0;
cmd_words_b[word++] = line_ptr; cmd_words_b[word++] = line_ptr;
@@ -658,7 +805,7 @@ uint8_t cmd_tokenize(void) __banked
return 1; return 1;
} }
} }
if (line_ptr == SBUF_SIZE - 1) if (line_ptr == CMD_BUF_SIZE - 1)
return 1; return 1;
cmd_words_b[word++] = line_ptr; cmd_words_b[word++] = line_ptr;
cmd_words_b[word++] = -1; cmd_words_b[word++] = -1;
@@ -695,9 +842,8 @@ void print_gpio_status(void) {
// Show software version // Show software version
void print_sw_version(void) __banked { void print_sw_version(void) __banked {
print_string("Software version: "); print_string("Software version: " VERSION_SW);
print_string(VERSION_SW); print_string("\nBuild date: " BUILD_DATE);
print_string("\nBuild: " __DATE__ " " __TIME__);
print_string("\nHardware: "); print_string("\nHardware: ");
print_string(machine.machine_name); print_string(machine.machine_name);
write_char('\n'); write_char('\n');
@@ -740,47 +886,27 @@ void cmd_parser(void) __banked
} }
} else if (cmd_compare(0, "stat")) { } else if (cmd_compare(0, "stat")) {
port_stats_print(); port_stats_print();
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') { } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 's') {
print_string("\nPRINT SECURITY REGISTERS\n"); print_string("\nSECURITY REGISTERS\n");
// The following will only show something else than 0xff if it was programmed for a managed switch // The following will only show something else than 0xff if it was programmed for a managed switch
print_string("Region 1: ");
flash_region.addr = 0x0001000; flash_region.addr = 0x0001000;
flash_region.len = 40; flash_region.len = 40;
flash_read_security(); flash_read_security();
print_string("\nRegion 2: ");
flash_region.addr = 0x0002000; flash_region.addr = 0x0002000;
flash_region.len = 40; flash_region.len = 40;
flash_read_security(); flash_read_security();
print_string("\nRegion 3: ");
flash_region.addr = 0x0003000; flash_region.addr = 0x0003000;
flash_region.len = 40; flash_region.len = 40;
flash_read_security(); flash_read_security();
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'd') {
print_string("\nDUMPING FLASH\n");
flash_region.addr = 0;
flash_region.len = 255;
flash_dump(255);
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') { } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') {
print_string("\nJEDEC ID\n"); print_string("\nJEDEC ID\n");
flash_read_jedecid(); flash_read_jedecid();
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'u') { } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'u') {
print_string("\nUNIQUE ID\n"); print_string("\nUNIQUE ID (note: only 4 bytes are likely correct here!)\n");
flash_read_uid(); flash_read_uid();
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 's') {
print_string("\nFLASH FAST MODE\n"); // Switch to flash 62.5 MHz mode
flash_init(1);
print_string("\nNow dumping flash\n");
flash_region.addr = 0;
flash_region.len = 255;
flash_dump(255);
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'e') {
print_string("\nFLASH erase\n");
flash_region.addr = 0x20000;
flash_sector_erase();
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'w') {
print_string("\nFLASH write\n");
for (uint8_t i = 0; i < 20; i++)
flash_buf[i] = greeting[i];
flash_region.addr = 0x200000;
flash_region.len = 20;
flash_write_bytes(flash_buf);
} else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) { } else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) {
parse_port(); parse_port();
} else if (cmd_compare(0, "mtu") && cmd_words_b[1] > 0) { } else if (cmd_compare(0, "mtu") && cmd_words_b[1] > 0) {
@@ -867,6 +993,24 @@ void cmd_parser(void) __banked
stp_off(); stp_off();
stpEnabled = 0; stpEnabled = 0;
} }
} else if (cmd_compare(0, "dhcp")) {
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
dhcp_start();
} else {
print_string("DHCP disabled\n");
dhcp_stop();
}
} else if (cmd_compare(0, "dhcpd")) {
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
if (cmd_words_b[2] > 0)
atoi_short(&dhcpd_vlan, cmd_words_b[2]);
else
dhcpd_vlan = 0;
dhcpd_start();
} else {
print_string("DHCP Server disabled\n");
dhcpd_stop();
}
} else if (cmd_compare(0, "pvid") && cmd_words_b[1] > 0 && cmd_words_b[2] > 0) { } else if (cmd_compare(0, "pvid") && cmd_words_b[1] > 0 && cmd_words_b[2] > 0) {
__xdata uint16_t pvid; __xdata uint16_t pvid;
uint8_t port; uint8_t port;
@@ -895,27 +1039,9 @@ void cmd_parser(void) __banked
} else if (cmd_compare(0, "passwd")) { } else if (cmd_compare(0, "passwd")) {
parse_passwd(); parse_passwd();
} else if (cmd_compare(0, "eee")) { } else if (cmd_compare(0, "eee")) {
int8_t port = -1; parse_eee();
if (cmd_words_b[3] > 0) { } else if (cmd_compare(0, "bw")) {
port = cmd_buffer[cmd_words_b[2]] - '1'; parse_bw();
port = machine.phys_to_log_port[port];
}
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
if (port >= 0)
port_eee_enable(port);
else
port_eee_enable_all();
} else if (cmd_words_b[1] > 0 && cmd_compare(1, "off")) {
if (port >= 0)
port_eee_disable(port);
else
port_eee_disable_all();
} else if (cmd_words_b[1] > 0 && cmd_compare(1, "status")) {
if (port >= 0)
port_eee_status(port);
else
port_eee_status_all();
}
} else if (cmd_compare(0, "version")) { } else if (cmd_compare(0, "version")) {
print_sw_version(); print_sw_version();
} else if (cmd_compare(0, "time")) { } else if (cmd_compare(0, "time")) {
@@ -957,6 +1083,16 @@ void cmd_parser(void) __banked
} }
} }
void clear_command_history(void) __banked
{
for (cmd_history_ptr = 0; cmd_history_ptr < CMD_HISTORY_SIZE; cmd_history_ptr++)
cmd_history[cmd_history_ptr] = 0;
cmd_history_ptr = 0;
return;
}
#define FLASH_READ_BURST_SIZE 0x100 #define FLASH_READ_BURST_SIZE 0x100
#define PASSWORD "1234" #define PASSWORD "1234"
void execute_config(void) __banked void execute_config(void) __banked
@@ -976,7 +1112,7 @@ void execute_config(void) __banked
__xdata uint8_t cfg_idx = 0; __xdata uint8_t cfg_idx = 0;
uint8_t c = 0; uint8_t c = 0;
do { do {
for (uint8_t cmd_idx = 0; cmd_idx < (SBUF_SIZE - 1); cmd_idx++) { for (uint8_t cmd_idx = 0; cmd_idx < (CMD_BUF_SIZE - 1); cmd_idx++) {
c = flash_buf[cfg_idx++]; c = flash_buf[cfg_idx++];
if (c == 0 || c == '\n') { if (c == 0 || c == '\n') {
cmd_buffer[cmd_idx] = '\0'; cmd_buffer[cmd_idx] = '\0';
@@ -997,8 +1133,6 @@ void execute_config(void) __banked
config_done: config_done:
// Start saving commands to cmd_history // Start saving commands to cmd_history
clear_command_history();
save_cmd = 1; save_cmd = 1;
for (cmd_history_ptr = 0; cmd_history_ptr < CMD_HISTORY_SIZE; cmd_history_ptr++)
cmd_history[cmd_history_ptr] = 0;
cmd_history_ptr = 0;
} }
+2 -1
View File
@@ -5,11 +5,12 @@
#include "rtl837x_common.h" #include "rtl837x_common.h"
extern __xdata uint8_t cmd_buffer[SBUF_SIZE]; extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
extern __xdata uint8_t cmd_available; extern __xdata uint8_t cmd_available;
uint8_t cmd_tokenize(void) __banked; uint8_t cmd_tokenize(void) __banked;
void cmd_parser(void) __banked; void cmd_parser(void) __banked;
void execute_config(void) __banked; void execute_config(void) __banked;
void print_sw_version(void) __banked; void print_sw_version(void) __banked;
void clear_command_history(void) __banked;
#endif #endif
-40
View File
@@ -1,44 +1,4 @@
.globl __start__stack
;--------------------------------------------------------
; Stack segment in internal ram
;--------------------------------------------------------
.area SSEG (DATA)
__start__stack:
.ds 1
.area VECTOR (CODE)
.globl __interrupt_vect
__interrupt_vect:
ljmp __sdcc_gsinit_startup
ljmp _isr_ext0 ; 0x03
.ds 5
ljmp _isr_timer0 ; 0x0b
.ds 5
ljmp _isr_ext1 ; 0x13
.ds 5
reti ; 0x1b TIMER 1 IRQ
.ds 7
ljmp _isr_serial ; 0x23
.ds 5
ljmp _isr_timer2 ; 0x2b TIMER 2 IRQ
.ds 5
reti ; 0x33 NOT used by DW8051
.ds 7
reti ; 0x3b Serial port 1 RX/TX IRQ
.ds 7
ljmp _isr_ext2 ; 0x43
.ds 5
ljmp _isr_ext3 ; 0x4b
.globl __start__stack
.area GSINIT0 (CODE)
__sdcc_gsinit_startup::
mov sp,#__start__stack - 1
.area GSFINAL (CODE) .area GSFINAL (CODE)
ljmp _bootloader
__sdcc_banked_call:: __sdcc_banked_call::
push _PSBANK push _PSBANK
+270 -24
View File
@@ -12,10 +12,12 @@
#include "uip.h" #include "uip.h"
#include "uip/uip.h" #include "uip/uip.h"
extern __code struct uip_eth_addr uip_ethaddr;
__xdata struct dhcp_state dhcp_state; __xdata struct dhcp_state dhcp_state;
__xdata uip_ipaddr_t server; __xdata uip_ipaddr_t server;
#define BOOTP_REQUEST 1
#define BOOTP_REPY 2
#define DHCP_HW_TYPE_ETH 1 #define DHCP_HW_TYPE_ETH 1
#define DHCP_SUBNET_MASK 1 #define DHCP_SUBNET_MASK 1
@@ -33,6 +35,7 @@ __xdata uip_ipaddr_t server;
#define DHCP_MESSAGE_DISCOVER 1 #define DHCP_MESSAGE_DISCOVER 1
#define DHCP_MESSAGE_OFFER 2 #define DHCP_MESSAGE_OFFER 2
#define DHCP_MESSAGE_REQUEST 3 #define DHCP_MESSAGE_REQUEST 3
#define DHCP_MESSAGE_NACK 4
#define DHCP_MESSAGE_ACK 5 #define DHCP_MESSAGE_ACK 5
#define DHCP_LEASE 51 #define DHCP_LEASE 51
#define DHCP_LEASE_LEN 4 #define DHCP_LEASE_LEN 4
@@ -44,15 +47,23 @@ __xdata uip_ipaddr_t server;
#define DHCP_CLIENT_ID_LEN 7 #define DHCP_CLIENT_ID_LEN 7
#define DHCP_REQUEST_IP 50 #define DHCP_REQUEST_IP 50
#define DHCP_REQUEST_IP_LEN 4 #define DHCP_REQUEST_IP_LEN 4
#define DHCP_CLIENT_NAME 12
#define DHCP_PARAMS 55 #define DHCP_PARAMS 55
#define DHCP_VENDOR_ID 60
#define DHCP_CLIENT_ID 61
#define DHCP_PARAM_SUBNET 1 #define DHCP_PARAM_SUBNET 1
#define DHCP_PARAM_ROUTER 3 #define DHCP_PARAM_ROUTER 3
#define DHCP_PARAM_DNS 6 #define DHCP_PARAM_DNS 6
#define DHCP_END 255 #define DHCP_END 255
#define LEASE_TIME 43200
#define RENEWAL_TIME 21600
#define REBIND_TIME 21600
#pragma codeseg BANK2 #pragma codeseg BANK2
#pragma constseg BANK2 #pragma constseg BANK2
struct dhcp_pkt { struct dhcp_pkt {
uint8_t type; uint8_t type;
uint8_t hw; uint8_t hw;
@@ -72,16 +83,13 @@ struct dhcp_pkt {
uint8_t cookie[4]; uint8_t cookie[4];
}; };
/*
#define DHCP_P ((__xdata struct dhcp_pkt *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE])
#define DHCP_OPT ((__xdata uint8_t *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE + sizeof (struct dhcp_pkt)])
*/
#define DHCP_P ((__xdata struct dhcp_pkt *)uip_appdata) #define DHCP_P ((__xdata struct dhcp_pkt *)uip_appdata)
#define DHCP_OPT ((__xdata uint8_t *)(uip_appdata) + sizeof (struct dhcp_pkt)) #define DHCP_OPT ((__xdata uint8_t *)(uip_appdata) + sizeof (struct dhcp_pkt))
__xdata uint32_t long_value; __xdata uint32_t long_value;
__xdata struct dhcpd_cstate cstates[DHCPD_MAX_CLIENTS];
__xdata uint8_t client_idx;
__xdata uint16_t dhcpd_vlan;
void dhcp_print_ip(uint8_t *a) void dhcp_print_ip(uint8_t *a)
{ {
@@ -92,19 +100,19 @@ void dhcp_print_ip(uint8_t *a)
} }
void dhcp_prepare_request(void) void dhcp_prepare_msg(void)
{ {
DHCP_P->type = 1; DHCP_P->type = BOOTP_REQUEST;
DHCP_P->hw = DHCP_HW_TYPE_ETH; DHCP_P->hw = DHCP_HW_TYPE_ETH;
DHCP_P->hw_len = 6; DHCP_P->hw_len = 6;
DHCP_P->hops = 0; DHCP_P->hops = 0;
DHCP_P->tid = HTONS(dhcp_state.transaction_id); DHCP_P->tid = dhcp_state.transaction_id; // In network byte order
DHCP_P->delay = HTONS(0); DHCP_P->delay = HTONS(0);
DHCP_P->flags = 0; DHCP_P->flags = 0;
// Clear fields client_ip to bootp_file // Clear fields client_ip to bootp_file
memset(DHCP_P->client_ip, 0, 224); memset(DHCP_P->client_ip, 0, 224);
memcpyc(DHCP_P->client_addr, uip_ethaddr.addr, 6); memcpy(DHCP_P->client_addr, uip_ethaddr.addr, 6);
DHCP_P->cookie[0] = 0x63; DHCP_P->cookie[0] = 0x63;
DHCP_P->cookie[1] = 0x82; DHCP_P->cookie[1] = 0x82;
DHCP_P->cookie[2] = 0x53; DHCP_P->cookie[2] = 0x53;
@@ -117,7 +125,7 @@ void dhcp_addopt_client_id(void)
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID; DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID_LEN; DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_HW_TYPE_ETH; DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_HW_TYPE_ETH;
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 6); memcpy(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 6);
dhcp_state.opt_ptr += 6; dhcp_state.opt_ptr += 6;
} }
@@ -130,7 +138,6 @@ void dhcp_addopt_request_ip(void)
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[1]; DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[1];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[2]; DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[2];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[3]; DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[3];
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4);
} }
@@ -142,14 +149,68 @@ void dhcp_addopt_server_id(void)
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[1]; DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[1];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[2]; DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[2];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[3]; DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[3];
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4); }
void dhcp_addopt_subnet(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_SUBNET_MASK;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_SUBNET_MASK_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.subnet[0];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.subnet[1];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.subnet[2];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.subnet[3];
}
void dhcp_addopt_router(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_ROUTER;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_ROUTER_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.router[0];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.router[1];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.router[2];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.router[3];
}
void dhcp_addopt_lease(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_LEASE;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_LEASE_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = LEASE_TIME >> 8;
DHCP_OPT[dhcp_state.opt_ptr++] = LEASE_TIME & 0xff;
}
void dhcp_addopt_renewal(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_RENEWAL;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_RENEWAL_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = RENEWAL_TIME >> 8;
DHCP_OPT[dhcp_state.opt_ptr++] = RENEWAL_TIME & 0xff;
}
void dhcp_addopt_rebind(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REBIND;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REBIND_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = REBIND_TIME >> 8;
DHCP_OPT[dhcp_state.opt_ptr++] = REBIND_TIME & 0xff;
} }
void dhcp_send_discover(void) void dhcp_send_discover(void)
{ {
print_string("dhcp_send_discover called\n"); print_string("dhcp_send_discover called\n");
dhcp_prepare_request(); dhcp_prepare_msg();
dhcp_state.opt_ptr = 0; dhcp_state.opt_ptr = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE; DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
@@ -184,7 +245,7 @@ void dhcp_send_discover(void)
void dhcp_send_request(void) void dhcp_send_request(void)
{ {
print_string("dhcp_send_request called\n"); print_string("dhcp_send_request called\n");
dhcp_prepare_request(); dhcp_prepare_msg();
dhcp_state.opt_ptr = 0; dhcp_state.opt_ptr = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE; DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
@@ -217,6 +278,41 @@ void dhcp_send_request(void)
} }
void dhcp_send_reply(uint8_t rtype)
{
print_string("dhcp_send_reply called\n");
dhcp_prepare_msg();
DHCP_P->type = BOOTP_REPY;
DHCP_P->client_addr[0] = cstates[client_idx].mac[0]; DHCP_P->client_addr[1] = cstates[client_idx].mac[1];
DHCP_P->client_addr[2] = cstates[client_idx].mac[2]; DHCP_P->client_addr[3] = cstates[client_idx].mac[3];
DHCP_P->client_addr[4] = cstates[client_idx].mac[4]; DHCP_P->client_addr[5] = cstates[client_idx].mac[5];
if (rtype != DHCP_MESSAGE_NACK) {
DHCP_P->your_ip[0] = dhcp_state.server[0];
DHCP_P->your_ip[1] = dhcp_state.server[1];
DHCP_P->your_ip[2] = dhcp_state.server[2];
DHCP_P->your_ip[3] = DHCPD_START_IP + client_idx;
}
dhcp_state.opt_ptr = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = rtype;
if (rtype != DHCP_MESSAGE_NACK) {
dhcp_addopt_subnet();
dhcp_addopt_router();
dhcp_addopt_server_id();
dhcp_addopt_rebind();
dhcp_addopt_lease();
dhcp_addopt_renewal();
}
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_END;
uip_udp_send(sizeof(struct dhcp_pkt) + dhcp_state.opt_ptr);
}
void ip_opt(uint8_t * __xdata ip) void ip_opt(uint8_t * __xdata ip)
{ {
dhcp_state.opt_ptr++; dhcp_state.opt_ptr++;
@@ -244,6 +340,22 @@ void long_opt(void)
} }
void print_txt_opt(void)
{
dhcp_state.opt_ptr++;
for (uint8_t l = DHCP_OPT[dhcp_state.opt_ptr++]; l ; l--)
write_char(DHCP_OPT[dhcp_state.opt_ptr++]);
}
void print_eth_opt(void)
{
dhcp_state.opt_ptr++;
for (uint8_t l = DHCP_OPT[dhcp_state.opt_ptr++]; l ; l--)
print_byte(DHCP_OPT[dhcp_state.opt_ptr++]);
}
void parse_opts(void) void parse_opts(void)
{ {
while (DHCP_OPT[dhcp_state.opt_ptr] && DHCP_OPT[dhcp_state.opt_ptr] != DHCP_END) { while (DHCP_OPT[dhcp_state.opt_ptr] && DHCP_OPT[dhcp_state.opt_ptr] != DHCP_END) {
@@ -263,6 +375,9 @@ void parse_opts(void)
case DHCP_BROADCAST: case DHCP_BROADCAST:
ip_opt(&dhcp_state.broadcast[0]); ip_opt(&dhcp_state.broadcast[0]);
break; break;
case DHCP_REQUEST_IP:
ip_opt(&dhcp_state.current_ip[0]);
break;
case DHCP_LEASE: case DHCP_LEASE:
long_opt(); long_opt();
dhcp_state.lease = long_value; dhcp_state.lease = long_value;
@@ -275,6 +390,27 @@ void parse_opts(void)
long_opt(); long_opt();
dhcp_state.renewal = long_value; dhcp_state.renewal = long_value;
break; break;
case DHCP_CLIENT_NAME:
print_string("Client name: ");
print_txt_opt();
write_char('\n');
break;
case DHCP_VENDOR_ID:
print_string("Vendor ID: ");
print_txt_opt();
write_char('\n');
break;
case DHCP_CLIENT_ID:
print_string("Client ID: ");
print_eth_opt();
write_char('\n');
break;
case DHCP_PARAMS:
print_string("PARAMS request (ignored)\n");
dhcp_state.opt_ptr++;
dhcp_state.opt_ptr += DHCP_OPT[dhcp_state.opt_ptr];
dhcp_state.opt_ptr++;
break;
case DHCP_END: case DHCP_END:
break; break;
default: default:
@@ -287,9 +423,39 @@ void parse_opts(void)
} }
void parse_dhcp(void) void find_client(void)
{ {
if (!DHCP_P->tid == HTONS(dhcp_state.transaction_id)) uint8_t i;
for (i = 0; i < DHCPD_MAX_CLIENTS; i++) {
if (cstates[i].mac[0] == DHCP_P->client_addr[0] && cstates[i].mac[1] == DHCP_P->client_addr[1]
&& cstates[i].mac[2] == DHCP_P->client_addr[2] && cstates[i].mac[3] == DHCP_P->client_addr[3]
&& cstates[i].mac[4] == DHCP_P->client_addr[4] && cstates[i].mac[5] == DHCP_P->client_addr[5]
)
break;
}
if (i < DHCPD_MAX_CLIENTS) {
client_idx = i;
return;
}
client_idx = 255;
}
void find_slot(void)
{
for (client_idx = 0; client_idx < DHCPD_MAX_CLIENTS; client_idx++) {
if (!cstates[client_idx].cstate)
return;
}
client_idx = 255;
return;
}
void parse_dhcp_response(void)
{
if (!DHCP_P->tid == dhcp_state.transaction_id)
return; return;
if (DHCP_P->cookie[0] != 0x63 || DHCP_P->cookie[1] != 0x82 || DHCP_P->cookie[2] != 0x53 || DHCP_P->cookie[3] != 0x63) if (DHCP_P->cookie[0] != 0x63 || DHCP_P->cookie[1] != 0x82 || DHCP_P->cookie[2] != 0x53 || DHCP_P->cookie[3] != 0x63)
return; return;
@@ -328,13 +494,50 @@ void parse_dhcp(void)
} }
void parse_dhcp_request(void)
{
print_string("parse_dhcp_request called\n");
if (DHCP_P->cookie[0] != 0x63 || DHCP_P->cookie[1] != 0x82 || DHCP_P->cookie[2] != 0x53 || DHCP_P->cookie[3] != 0x63)
return;
dhcp_state.opt_ptr = 0;
if (DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE || DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE_LEN)
return;
if (DHCP_OPT[dhcp_state.opt_ptr] == DHCP_MESSAGE_DISCOVER) {
dhcp_state.opt_ptr++;
find_client();
if (client_idx == 255)
find_slot();
// If there is no empty slot, we play possum and do not answer to the request
if (client_idx == 255)
return;
cstates[client_idx].cstate = CSTATE_OFFERED;
cstates[client_idx].mac[0] = DHCP_P->client_addr[0]; cstates[client_idx].mac[1] = DHCP_P->client_addr[1];
cstates[client_idx].mac[2] = DHCP_P->client_addr[2]; cstates[client_idx].mac[3] = DHCP_P->client_addr[3];
cstates[client_idx].mac[4] = DHCP_P->client_addr[4]; cstates[client_idx].mac[5] = DHCP_P->client_addr[5];
dhcp_state.transaction_id = DHCP_P->tid;
parse_opts();
dhcp_send_reply(DHCP_MESSAGE_OFFER);
} else if (DHCP_OPT[dhcp_state.opt_ptr++] == DHCP_MESSAGE_REQUEST) {
find_client();
if (client_idx == 255) {
dhcp_send_reply(DHCP_MESSAGE_NACK);
return;
}
parse_opts();
dhcp_send_reply(DHCP_MESSAGE_ACK);
}
}
void dhcp_start(void) __banked void dhcp_start(void) __banked
{ {
uip_ipaddr(server, 255,255,255,255); uip_ipaddr(server, 255,255,255,255);
dhcp_state.conn = uip_udp_new(&server, HTONS(DHCPC_SERVER_PORT)); dhcp_state.conn = uip_udp_new(&server, HTONS(DHCP_SERVER_PORT));
dhcp_state.current_ip[0] = dhcp_state.current_ip[1] = dhcp_state.current_ip[2] = dhcp_state.current_ip[3] = 0; dhcp_state.current_ip[0] = dhcp_state.current_ip[1] = dhcp_state.current_ip[2] = dhcp_state.current_ip[3] = 0;
if(dhcp_state.conn) { if(dhcp_state.conn) {
uip_udp_bind(dhcp_state.conn, HTONS(DHCPC_CLIENT_PORT)); uip_udp_bind(dhcp_state.conn, HTONS(DHCP_CLIENT_PORT));
} else { } else {
print_string("dhcp_start failed to set up socket\n"); print_string("dhcp_start failed to set up socket\n");
return; return;
@@ -346,6 +549,43 @@ void dhcp_start(void) __banked
} }
void dhcpd_start(void) __banked
{
memset(&cstates[0], 0, sizeof (struct dhcpd_cstate) * DHCPD_MAX_CLIENTS);
dhcp_state.conn = uip_udp_new(0, 0);
if(dhcp_state.conn) {
uip_udp_bind(dhcp_state.conn, HTONS(DHCP_SERVER_PORT));
} else {
print_string("dhcpd_start failed to set up socket\n");
return;
}
if (!dhcpd_vlan)
print_string("dhcpd: enabling for all VLANs\n");
else
print_string("dhcpd: enabling for VLAN "); print_short(dhcpd_vlan); write_char('\n');
dhcp_state.state = DHCP_SERVER;
dhcp_state.server[1] = uip_hostaddr[0] >> 8; dhcp_state.server[0] = uip_hostaddr[0] & 0xff;
dhcp_state.server[3] = uip_hostaddr[1] >> 8; dhcp_state.server[2] = uip_hostaddr[1] & 0xff;
dhcp_state.router[1] = uip_draddr[0] >> 8; dhcp_state.router[0] = uip_draddr[0] & 0xff;
dhcp_state.router[3] = uip_draddr[1] >> 8; dhcp_state.router[2] = uip_draddr[1] & 0xff;
dhcp_state.subnet[1] = uip_netmask[0] >> 8; dhcp_state.subnet[0] = uip_netmask[0] & 0xff;
dhcp_state.subnet[3] = uip_netmask[1] >> 8; dhcp_state.subnet[2] = uip_netmask[1] & 0xff;
dhcp_state.broadcast[0] = dhcp_state.router[0]; dhcp_state.broadcast[1] = dhcp_state.router[1];
dhcp_state.broadcast[2] = dhcp_state.router[2]; dhcp_state.broadcast[3] = 0xff;
for (uint8_t i = 0; i < DHCPD_MAX_CLIENTS; i++) {
cstates[i].cstate = CSTATE_NONE;
}
// TODO: DNS, correct broadcast address
print_string("dhcpd_start done\n");
}
void dhcp_stop(void) __banked void dhcp_stop(void) __banked
{ {
print_string("dhcp_stop called\n"); print_string("dhcp_stop called\n");
@@ -353,6 +593,13 @@ void dhcp_stop(void) __banked
dhcp_state.state = DHCP_OFF; dhcp_state.state = DHCP_OFF;
} }
void dhcpd_stop(void) __banked
{
print_string("dhcpd_stop called\n");
uip_udp_remove(dhcp_state.conn);
dhcp_state.state = DHCP_OFF;
}
void dhcp_callback(void) __banked void dhcp_callback(void) __banked
{ {
@@ -361,8 +608,10 @@ void dhcp_callback(void) __banked
if (uip_closed()) { if (uip_closed()) {
print_string("Closed\n"); print_string("Closed\n");
return; return;
} else if (dhcp_state.state == DHCP_SERVER && uip_newdata()) {
parse_dhcp_request();
} else if (uip_newdata()) { } else if (uip_newdata()) {
parse_dhcp(); parse_dhcp_response();
} else { } else {
if (dhcp_state.state == DHCP_START) { if (dhcp_state.state == DHCP_START) {
dhcp_send_discover(); dhcp_send_discover();
@@ -385,7 +634,4 @@ void dhcp_callback(void) __banked
} }
} }
} }
// By default we do not send anything out
uip_len = 0;
} }
+21 -4
View File
@@ -3,22 +3,27 @@
#include "uipopt.h" #include "uipopt.h"
#include <stdint.h> #include <stdint.h>
#define DHCPD_MAX_CLIENTS 20
#define DHCPD_START_IP 100
#define DHCPC_SERVER_PORT 67 #define DHCP_SERVER_PORT 67
#define DHCPC_CLIENT_PORT 68 #define DHCP_CLIENT_PORT 68
#define DHCP_OFF 0 #define DHCP_OFF 0
#define DHCP_START 1 #define DHCP_START 1
#define DHCP_DISCOVER_SENT 2 #define DHCP_DISCOVER_SENT 2
#define DHCP_REQUEST_SENT 3 #define DHCP_REQUEST_SENT 3
#define DHCP_LEASING 4 #define DHCP_LEASING 4
#define DHCP_SERVER 5
#define CSTATE_NONE 0
#define CSTATE_OFFERED 1
#define CSTATE_LEASED 2
void dhcp_start(void) __banked; void dhcp_start(void) __banked;
void dhcp_stop(void) __banked; void dhcp_stop(void) __banked;
// void dhcp_periodic(void) __banked;
void dhcp_callback(void) __banked; void dhcp_callback(void) __banked;
struct dhcp_state { struct dhcp_state {
uint8_t state; uint8_t state;
uint32_t transaction_id; uint32_t transaction_id;
@@ -38,6 +43,18 @@ struct dhcp_state {
struct uip_udp_conn *conn; struct uip_udp_conn *conn;
}; };
struct dhcpd_cstate {
uint8_t cstate;
uint16_t timer;
uint32_t transaction_id;
uint8_t mac[6];
uint8_t ip[4];
};
void dhcpd_start(void) __banked;
void dhcpd_stop(void) __banked;
typedef struct dhcp_state uip_udp_appstate_t; typedef struct dhcp_state uip_udp_appstate_t;
/* Finally we define the application function to be called by uIP. */ /* Finally we define the application function to be called by uIP. */
+238
View File
@@ -0,0 +1,238 @@
# Egress and Ingress Bandwidth Control
The RTL8372/3 allows to control the bandwidth of data transmitted (egress) and/or
admitted (ingress) at any given port. Once admitted, packets are internally switched
at wire-speed, since the backplane of the devices has a bandwidth of 60GBit/s.
The devices schedules transmission of packets by assigning packets to 8 queues
implemented in hardware per port, which share a total of 8Mbit of memory internal
to the switching part of the SoCs. Packets are assigned to the respective queues
based on the priority assigned to a packet, which can be based on various
properties of a packet such as IEEE 802.1P priority, DSCP value, physical port
number, destination or source MAC, Ether-Type-based, CVID, SVID, IPv4 source or
destination IP, IPv4/IPv6 TOS field, IPv6 Flow Label and even TCP/UDP
source/destination port. Once in a queue, packets are scheduled for egress
based on differnent configurable algorithms.
RTLPlayground currently allows only to control the bandwidth at ingress at a port
or just before packets leave a port. There is no control of the priority assignment
or queue scheduling mechanisms. The bandwidth can be controlled in steps of 16Kbit/s
from 16Kbit/s to 10Gbp/s.
The bandwidth control as currently implemented allows e.g. to assign a certain
share of bandwidth to an attached device (e.g. to share an uplink), or simulate
connections with low bandwidth and even bad connectivity with packet drops when
ingress is not controlled by Flow Control but by simply droping packets.
## Ingress/Egress control
The relevant registers for controlling Ingress and Egress at a port are:
```
#define RTL837X_IGBW_CTRL 0x4c10
#define IGBW_INC_BYPASS_PKT 0x100
#define IGBW_INC_IFG 0x80
#define IGBW_ADM_DHCP 0x20
#define IGBW_ADM_ARPREQ 0x10
#define IGBW_ADM_RMA 0x08
#define IGBW_ADM_BPDU 0x04
#define IGBW_ADM_RTKPKT 0x02
#define IGBW_ADM_IGMP 0x01
#define RTL837X_IGBW_PORT_CTRL 0x4C18
#define RTL837X_IGBW_PORT_FC_CTRL 0x4C8C
#define RTL837X_EGBW_PORT_CTRL 0x1c34
#define RTL837X_EGBW_CTRL 0x447c
#define EGBW_INC_IFG 0x02
#define EGBW_CPUMODE 0x01
```
`RTL837X_IGBW_CTRL/RTL837X_EGBW_CTRL` control the behaviour of the bandwidth control
at ingress and egress. The flags such as `IGBW_ADM_DHCP`control whether certain types
of packets such as DHCP are exempt from being ingress controlled. The
`IGBW_INC_IFG/EGBW_INC_IFG` flags control whether the Inter Frame Gaps are part of
the bandwidth being controlled. `EGBW_CPUMODE` controls whether packets generated
by the internal CPU are subject to egress control.
`RTL837X_IGBW_PORT_CTRL/RTL837X_EGBW_PORT_CTRL` configure the bandwidth for ingress
and egress at a port.
`RTL837X_IGBW_PORT_FC_CTRL` configures whether packets are bandwidth-controlled using
Flow Control (port-bit set), or simply dropped (port-bit clear).
## Ingress/Egress bandwidth API
The code currently provides the following functions:
```
void bandwidth_setup(void) __banked;
void bandwidth_ingress_set(uint8_t port, __xdata uint32_t bw) __banked;
void bandwidth_ingress_disable(uint8_t port) __banked;
void bandwidth_ingress_drop(uint8_t port) __banked;
void bandwidth_egress_set(uint8_t port, __xdata uint32_t bw) __banked;
void bandwidth_egress_disable(uint8_t port) __banked;
void bandwidth_status(uint8_t port) __banked;
```c
`bandwidth_setup()` is called at boot-time and configures excluding all special packets
that may be for the CPU and packets outgoing from the CPU to be excluded from bandwidth
control. IFG is not part of the bandwidth calculation.
`bandwidth_ingress_set()` enables ingress bandwidth control for a particular port given
the specified bandwidth. This also enabled Flow Control at a port.
`bandwidth_ingress_set()` enables egress bandwidth control for a particular port given
the specified bandwidth
`bandwidth_ingress_disable() / bandwidth_egress_disable()` disable ingress and egress
bandwidth control at a given port
`bandwidth_ingress_drop(port)` configures packets exceeding bandwidth limitations to
simply be dropped
`bandwidth_status(port)` shows the current bandwidth control status for a given port
## Bandwidth control configuration on the Serial Console
The following commands are provided on the serial console:
```
> bw [in|out|status] <port> [<hexvalue>|off|drop]
Configures or shows the status of bandwidth control
```
The bandwidth is given as the `<hexvalue>` in Kbit/s. Note that the control is only
possible at a granularity of 16 Kbit/s and the minimum value is also 16 Kbit/s. The
hexadecimal numbers must be given in full bytes, i.e. have an even number of digits.
To enable bandwidth control of ingress for physical port 2 to be set to 256 Kbit/s
do:
```
> bw in 2 0100
```
To drop packets when the bandwidth is exceeeded at port 2 do:
```
> bw in 2 drop
```
To disable bandwidth control for incoming packets on port 2 do:
```
> bw in 2 off
```
## Bandwidth configuration via the Web Interface
Not implemented, yet!
## A Test using iperf3
The following is and example how to test bandwidth control with a signle Linux device using
network namespaces to route packets between a client and a server on the same Linux device
through an external switch.
You will need 2 network intefaces on the linux device, say, 2 USB-Ethernet controllers called
eth0 and eth1:
```
$ sudo ip netns add client
$ sudo ip netns add server
$ sudo ip link set dev eth0 netns client
$ sudo ip link set dev eth1 netns server
$ sudo ip netns exec client ip link set dev eth0 up
$ sudo ip netns exec server ip link set dev eth1 up
$ sudo ip netns exec client ip addr add dev eth0 192.168.99.1/24
$ sudo ip netns exec server ip addr add dev eth1 192.168.99.2/24
$ sudo ip netns exec server iperf3 -s
```
This will start an iper3 server in the above shell.
In a different shell you can now run the iperf3 client against your server:
```
$ sudo ip netns exec client iperf -c 192.168.99.2
```
The LEDs on your switch where your network adapters are connected should start to flicker.
On a 1GBit connection, you should see:
```
$ sudo ip netns exec client iperf3 -c 192.168.99.2
Connecting to host 192.168.99.2, port 5201
[ 5] local 192.168.99.1 port 46776 connected to 192.168.99.2 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 114 MBytes 952 Mbits/sec 0 339 KBytes
[ 5] 1.00-2.00 sec 113 MBytes 946 Mbits/sec 0 356 KBytes
[ 5] 2.00-3.00 sec 112 MBytes 937 Mbits/sec 0 390 KBytes
[ 5] 3.00-4.00 sec 112 MBytes 942 Mbits/sec 0 390 KBytes
[ 5] 4.00-5.00 sec 112 MBytes 943 Mbits/sec 0 390 KBytes
[ 5] 5.00-6.00 sec 112 MBytes 944 Mbits/sec 0 390 KBytes
[ 5] 6.00-7.00 sec 112 MBytes 938 Mbits/sec 0 390 KBytes
[ 5] 7.00-8.00 sec 112 MBytes 942 Mbits/sec 0 410 KBytes
[ 5] 8.00-9.00 sec 113 MBytes 947 Mbits/sec 0 410 KBytes
[ 5] 9.00-10.00 sec 112 MBytes 940 Mbits/sec 0 410 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 1.10 GBytes 943 Mbits/sec 0 sender
[ 5] 0.00-10.00 sec 1.10 GBytes 941 Mbits/sec receiver
```
Now, we limit ingress on port 1 (connected to eth0) to 4 MBit/s:
```> bw in 1 1000
bandwidth_ingress_set called, port 04
RTL837X_IGBW_PORT_CTRL:0x00100100
RTL837X_IGBW_PORT_FC_CTRL:0x00000010
```
We now get:
```
$ sudo ip netns exec client iperf3 -c 192.168.99.2
[ 5] local 192.168.99.1 port 43324 connected to 192.168.99.2 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 1.12 MBytes 9.43 Mbits/sec 0 160 KBytes
[ 5] 1.00-2.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
[ 5] 2.00-3.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes
[ 5] 3.00-4.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes
[ 5] 4.00-5.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
[ 5] 5.00-6.00 sec 256 KBytes 2.10 Mbits/sec 0 160 KBytes
[ 5] 6.00-7.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
[ 5] 7.00-8.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes
[ 5] 8.00-9.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes
[ 5] 9.00-10.00 sec 256 KBytes 2.10 Mbits/sec 0 160 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 5.25 MBytes 4.40 Mbits/sec 0 sender
[ 5] 0.00-10.16 sec 4.75 MBytes 3.92 Mbits/sec receiver
iperf Done.
```
Which is the 4Mbit/s we configured. There are no packet drops (retries) because
Flow Control is used to signal the Ethernet adapter on the incoming interface
(port 1 of the router) to slow down.
We can also configure a mere 256KBit/s and packet drop to simulate a bad connection:
```
> bw in 1 0100
bandwidth_ingress_set called, port 04
RTL837X_IGBW_PORT_CTRL:0x00100010
RTL837X_IGBW_PORT_FC_CTRL:0x00000010
> bw in 1 drop
RTL837X_IGBW_PORT_FC_CTRL:0x00000000
```
We now get:
```
$ sudo ip netns exec client iperf3 -c 192.168.99.2
Connecting to host 192.168.99.2, port 5201
[ 5] local 192.168.99.1 port 46060 connected to 192.168.99.2 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 384 KBytes 3.14 Mbits/sec 2 1.41 KBytes
[ 5] 1.00-2.00 sec 0.00 Bytes 0.00 bits/sec 54 1.41 KBytes
[ 5] 2.00-3.00 sec 0.00 Bytes 0.00 bits/sec 31 29.7 KBytes
[ 5] 3.00-4.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes
[ 5] 4.00-5.00 sec 0.00 Bytes 0.00 bits/sec 23 1.41 KBytes
[ 5] 5.00-6.00 sec 128 KBytes 1.05 Mbits/sec 16 14.1 KBytes
[ 5] 6.00-7.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes
[ 5] 7.00-8.00 sec 0.00 Bytes 0.00 bits/sec 11 1.41 KBytes
[ 5] 8.00-9.00 sec 128 KBytes 1.05 Mbits/sec 9 8.48 KBytes
[ 5] 9.00-10.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 640 KBytes 524 Kbits/sec 152 sender
[ 5] 0.00-10.00 sec 256 KBytes 210 Kbits/sec receiver
iperf Done.
```
Which shows a large number of retries due to dropped packets and an average number
of received packets (the client sends the packets to the server, and they are sent
back to the client by the server) of 210 KBit/s, the number is higher for the transmitted
packets, because they may include dropped packets.
+51 -23
View File
@@ -5,13 +5,30 @@
|---|---|---|---|---|---| |---|---|---|---|---|---|
| keepLINK | KP-9000-9XHML-X | Yes| 2M-PCB23-V3.1 | 2M| 8273N + 8224N | | keepLINK | KP-9000-9XHML-X | Yes| 2M-PCB23-V3.1 | 2M| 8273N + 8224N |
## PCB
<img src="photos/2M-PCB23-V3.1-managed/2M-PCB23-V3.1-top.jpeg" width="300" />
## Port overview
```
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ┌──────────┐ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ SFP (J4) │ │
│ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ PORT 9 │ │
│ │ PORT 1 │ │ PORT 2 │ │ PORT 3 │ │ PORT 4 │ │ PORT 5 │ │ PORT 6 │ │ PORT 7 │ │ PORT 8 │ │ MAC 8 │ O (PWR) │
│ O │ MAC 0 │ │ MAC 1 │ │ MAC 2 │ │ MAC 3 │ │ MAC 4 │ │ MAC 5 │ │ MAC 6 │ │ MAC 7 │ │ SerDes 1 │ O (SFP) │
│ RST └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
```
# Connectors # Connectors
|`J4` SFP PINs | Signal | Component | GPIO | Notes | |`J4` SFP PINs | Signal | Component | GPIO | Notes |
|---|---|---|---|---| |---|---|---|---|---|
|2| TX_FAULT | | --- | | |2| TX_FAULT | | --- | |
|3| TX_DISABLE | | --- | Pull down - 0R | |3| TX_DISABLE | | --- | Pull down - 0R |
|4| MODDEF2 SDA | b-r273 | GPIO39 | | |4| MODDEF2 SDA | b-r273 | GPIO39-SDA4 | |
|5| MODDEF1 SCL | b-r274 | GPIO40 | | |5| MODDEF1 SCL | b-r274 | GPIO40-SCL3 | |
|6| MODDEF0 PRESENT | B-R275 | GPIO38 | | |6| MODDEF0 PRESENT | B-R275 | GPIO38 | |
|7| RATE SEL | | --- | | |7| RATE SEL | | --- | |
|8| LOS | B-R276 | GPIO38 | | |8| LOS | B-R276 | GPIO38 | |
@@ -31,15 +48,26 @@ Note: component numbering `<L>-<REFDES>-<SIDE>`
| 3 | GPIO32 | U0RXD (Input) | | 3 | GPIO32 | U0RXD (Input) |
| 4 | 3V3 | PWR | | 4 | 3V3 | PWR |
### T7 ### T7, Slave Interface
|`T7` pin|what|Signal| |`T7` pin|what|Signal|Components|
|---|---|---| |---|---|---|---|
| 1 | GPIO | | | 1 | Slave Interface | Slave SCK/SCL/MDC/EE_SCL | U7-6 |
| 2 | GND | | | 2 | GND | | |
| 3 | GPIO | | | 3 | Slave Interface | Slave SDI/SDA/MDIO/EE_SDA | U7-5 |
| 4 | 3V3 | | | 4 | 3V3 | | |
| 5 | GPIO | | | 5 | GPIO? | | |
| 6 | GPIO | | | 6 | GPIO? | | |
`U7` can be a standard I2C eeprom memory, like `24LC32`.
The Slave Interface allows an extenal host to controll the SOC even if the internal MCU is used.
Depending on the `IF_SEL` bootstrap resistors, this can me `I2C`, `SPI` or `SMI`.
On this device it is `I2C` on address `0b1011100` or `0x5c` (7-bit notation).
* I2c Read: must be a write_read opperation `<Dev-ADDR><RegAddr15:8><RegAddr7:0>` `<DevAddr><Data7:0><Data15:8><Data23:16><Data31:24>`.
* I2c Write: `<Dev-ADDR><RegAddr15:8><RegAddr7:0><DevAddr><Data7:0><Data15:8><Data23:16><Data31:24>`.
Example register `0x0004` return chip id `0x00, 0x00, 0x72, 0x83` = `0x83720000`.
### T9 ### T9
|`T9` SMI | Signal | Component | GPIO | Notes | |`T9` SMI | Signal | Component | GPIO | Notes |
@@ -68,22 +96,22 @@ Reset-line found at `T-D6-L`, `T-R83`, `T-R97`, `T-R94`, `T-R93` active-low.
| -------- | ------ | ---- | ---- | ---- | ---- | ---- | ---- | | -------- | ------ | ---- | ---- | ---- | ---- | ---- | ---- |
| 00000001 | GPIO00 | T-R34-R, P1-LED-YL |? | | GPIO32 | B-r126-r | U0RXD | | 00000001 | GPIO00 | T-R34-R, P1-LED-YL |? | | GPIO32 | B-r126-r | U0RXD |
| 00000002 | GPIO01 | T-R99-R, P1-LED-GR |? | | GPIO33 | | | | 00000002 | GPIO01 | T-R99-R, P1-LED-GR |? | | GPIO33 | | |
| 00000004 | GPIO02 | |? | | GPIO34 | B-R172, To RTL8225 | Already driver HIGH INT? | | 00000004 | GPIO02 | |? | | GPIO34 | B-R172, To RTL8224 | SMI-MDC0 |
| 00000008 | GPIO03 | T-R113-R, P2-LED-GR |? | | GPIO35 | B-R173, To RTL8225 | Easy to pulldown Reset? | | 00000008 | GPIO03 | T-R113-R, P2-LED-GR |? | | GPIO35 | B-R173, To RTL8224 | SMI-MDIO0 |
| 00000010 | GPIO04 | T-R115-R, P3-LED-YL |? | | GPIO36 | | | | | 00000010 | GPIO04 | T-R115-R, P3-LED-YL |? | | GPIO36 | | | |
| 00000020 | GPIO05 | T-R117-R, P3-LED-GR |? | | GPIO37 | To RTL8225 | Already driver low I2C-SCL? | | | 00000020 | GPIO05 | T-R117-R, P3-LED-GR |? | | GPIO37 | To RTL8224 ?? | Already driver low | |
| 00000040 | GPIO06 | |? | | GPIO38 | sfp-6 via B-R275, sfp-8 via B-R276 | | | 00000040 | GPIO06 | |? | | GPIO38 | sfp-6 via B-R275, sfp-8 via B-R276 | SFP-PRESENT |
| 00000080 | GPIO07 | |? | | GPIO39 | sfp-4, b-r273, B-r143 | | | 00000080 | GPIO07 | |? | | GPIO39 | sfp-4, b-r273, B-r143 | I2C4-SDA |
| 00000100 | GPIO08 | | | | GPIO40 | T9-2, sfp-5 b-r274, B-r146 | SMI-MDC | | 00000100 | GPIO08 | | | | GPIO40 | T9-2, sfp-5 b-r274, B-r146 | I2C3-SCL |
| 00000200 | GPIO09 | |LEDx[^1] | | GPIO41 | T9-1, | SMI-MDO , B-r143 | | 00000200 | GPIO09 | |LEDx[^1] | | GPIO41 | T9-1, B-r143 | | I2C3-SDA (Unused) |
| 00000400 | GPIO10 | | | | GPIO42 | U6?8?-P6, T-R | SPI-MEMORY, CLK | | 00000400 | GPIO10 | | | | GPIO42 | U6?8?-P6, T-R | SPI-MEMORY, CLK |
| 00000800 | GPIO11 | |LEDx[^1] | | GPIO43 | U6?8?-P5, T-R | SPI-MEMORY, DI,IO0 | | 00000800 | GPIO11 | |LEDx[^1] | | GPIO43 | U6?8?-P5, T-R | SPI-MEMORY, DI,IO0 |
| 00001000 | GPIO12 | |LEDx[^1] | | GPIO44 | U6?8?-P2, T-R | SPI-MEMORY, DO,IO1 | | 00001000 | GPIO12 | |LEDx[^1] | | GPIO44 | U6?8?-P2, T-R | SPI-MEMORY, DO,IO1 |
| 00002000 | GPIO13 | |LEDx[^1] | | GPIO45 | U6?8?-P1, T-R | SPI-MEMORY, CS | | 00002000 | GPIO13 | |LEDx[^1] | | GPIO45 | U6?8?-P1, T-R | SPI-MEMORY, CS |
| 00004000 | GPIO14 | |LEDx[^1] | | GPIO46 | T10-6 | | | 00004000 | GPIO14 | |LEDx[^1] | | GPIO46 | T10-6 | SPI0-SCK |
| 00008000 | GPIO15 | |LEDx[^1] | | GPIO47 | T10-2 | | | 00008000 | GPIO15 | |LEDx[^1] | | GPIO47 | T10-2 | SPI0-SDA |
| 00010000 | GPIO16 | |LEDx[^1] | | GPIO48 | T10-4, J6 (BUTTON RESET) | | | 00010000 | GPIO16 | |LEDx[^1] | | GPIO48 | T10-4, J6 (BUTTON RESET) | SPI1-SCK |
| 00020000 | GPIO17 | |LEDx[^1] | | GPIO49 | T10-1 | | | 00020000 | GPIO17 | |LEDx[^1] | | GPIO49 | T10-1 | SPI1-SDA |
| 00040000 | GPIO18 | |LEDx[^1] | | GPIO50 | | | | 00040000 | GPIO18 | |LEDx[^1] | | GPIO50 | | |
| 00080000 | GPIO19 | |LEDx[^1] | | GPIO51 | | | | 00080000 | GPIO19 | |LEDx[^1] | | GPIO51 | | |
| 00100000 | GPIO20 | |LEDx[^1] | | GPIO52 | | | | 00100000 | GPIO20 | |LEDx[^1] | | GPIO52 | | |
@@ -96,7 +124,7 @@ Reset-line found at `T-D6-L`, `T-R83`, `T-R97`, `T-R94`, `T-R93` active-low.
| 08000000 | GPIO27 | |? | | GPIO59 | | | | 08000000 | GPIO27 | |? | | GPIO59 | | |
| 10000000 | GPIO28 | | | | GPIO60 | | | | 10000000 | GPIO28 | | | | GPIO60 | | |
| 20000000 | GPIO29 | | | | GPIO61 | | | | 20000000 | GPIO29 | | | | GPIO61 | | |
| 40000000 | GPIO30 | |SFP-DETE | | GPIO62 | To RTL8225 | Already driver INT? | | | 40000000 | GPIO30 | RTL8224N Reset |RTL8224 | | GPIO62 | To RTL8224 | Already driver | |
| 80000000 | GPIO31 | B-r129-r? |U0TXD | | GPIO63 | | | | 80000000 | GPIO31 | B-r129-r? |U0TXD | | GPIO63 | | |
## GPIO Register Input value ## GPIO Register Input value
+62
View File
@@ -0,0 +1,62 @@
# Hisource Hi-K0402WS
Following is documentation for unmanaged switch marked as `Hi-K0402WS`.
Original software is running UART on 9600 baud rate.
Using SPI clamp in-board is the only method for initial installation.
The board has two flash chips `BY25Q16BS` with 16M-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
- **Name**: 2.5G Ethernet Switch
- **Model**: Hi-K0402WS
- **Ports**:
- 4 × RJ45: 10/100/1000/2500 Mbps
- 2 × SFP: 1000 / 2500 / 10000 Mbps
### What works (expected from label + similar devices)
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
- Both SFP ports supporting 1G, 2.5G and 10G modules
- LEDs
### PCB overview
**Board markings**
- Top silkscreen: PCB-KO4022W-V3.0 / DIP-KO4022WS-V3.0
Top side
<img src="photos/K0402W-V3.0-unmanaged\PCB-top.jpg" width="300" />
Bottom
<img src="photos/K0402W-V3.0-unmanaged\PCB-bottom.jpg" width="300" />
### T2, serial console
| `J2` pin | Signal |
| -------- | ----------- |
| 1 | 3V3 |
| 2 | RX (Input) |
| 3 | TX (Output) |
| 4 | GND |
## Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
Board has two supply rails. `0.95` and `3.3` volt.
### `0.95` Core Voltage
Voltage is made by a `Techcode TD1720` .
### `3.3` Voltage
Voltage is created by chip marked as `Techcode TD1720`.
**There seems to have been a miscalculation when choosing the inductor and the device is ~25% more efficient with an 5V power supply.**
+54
View File
@@ -0,0 +1,54 @@
# SWTG018AS-A V2.0
The following is a documentation for the unmanaged switch marked as `SWTG018AS-A V2.0`.
It is e.g. sold under the Ampcom brand, but no branh-markings are found on the device.
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 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
- **Name**: 9-Ports 2.5G Ethernet Switch
- **Ports**:
- 8 × RJ45: 10/100/1000/2500 Mbps
- 1 × SFP+: 1000 / 2500 / 10000 Mbps
- **Power**: 12V DC, 1A barrel connector
<img src="photos/SWTG018AS_A_V_2_0/label.jpg" width="300" />
### What works
The device is fully supported:
- All 8 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
### PCB overview
**Board markings**
- Top silkscreen: SWTG018AS-A-V2.0.1_19649
Top side
<img src="photos/SWTG018AS_A_V_2_0/pcb_top.jpg" width="300" />
Bottom
<img src="photos/SWTG018AS_A_V_2_0/pcb_bottom.jpg" width="300" />
### J1, serial console
| `J1` pin | Signal |
| -------- | ----------- |
| 1 | 3V3 |
| 2 | GND |
| 3 | RX (Input) |
| 4 | TX (Output) |
## Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
+24
View File
@@ -0,0 +1,24 @@
### ZX-SWTGW218AS
## Brands
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|---|---|---|---|---|---|
| Mokerlink | ZX-SWTGW218AS | Yes| SWTG118AS-V2.0-16029 | 2MB (FM25Q16A)| 8273N + 8224N |
| Sodola | | | | | |
| Horaco | | | | | |
## Photos
<img src="photos/SWTGW218AS-managed/front.png" width="800" />
<img src="photos/SWTGW218AS-managed/label.jpg" width="800" />
## PCB
See up'n'atom's Repo:
https://github.com/up-n-atom/SWTG118AS/blob/main/photos/SWTG118AS-v2.0/SWTG118AS-v2.0-pcb-top.JPG
https://github.com/up-n-atom/SWTG118AS/blob/main/photos/SWTG118AS-v2.0/SWTG118AS-v2.0-pcb-bottom.JPG
+175
View File
@@ -0,0 +1,175 @@
# TrendNet TEG-S562
Following is documentation for unmanaged switch marked as `TEG-S563/EU H/W: V1.0R`.
Original software is running UART on 57600 baud rate. The software does not allow to
do anything fancy via serial. There is `IP` configuration which can be printed as well.
There might be also some flash upload procedure, but using SPI clamp in-board seems to
be easier method.
The memory chip is `Winbond W25Q16JV` with 16M-bit size.
## What does work
1. 2.5G ports on all advertised speeds.
2. SFP+ communication.
3. Serial, Web UI.
## Known issues
1. LEDs are not initialized properly.
## PCB
Manufacturer information be found [on the product page](https://www.trendnet.com/support/support-detail.asp?prod=105_TEG-S562).
Top side
<img src="photos/TEG-S562/TEG-S562-v1.0R-top.jpg" width="300" />
Bottom
<img src="photos/TEG-S562/TEG-S562-v1.0R-bottom.jpg" width="300" />
## Connectors
### Port overview
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ ┌──────────┐ ┌──────────┐ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ SFP │ │ SFP │ │
│ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ PORT 5 │ │ PORT 6 │ │
│ │ PORT 1 │ │ PORT 2 │ │ PORT 3 │ │ PORT 4 │ │ MAC ? │ │ MAC ? │ │
│ │ MAC 4 │ │ MAC 5 │ │ MAC 6 │ │ MAC 7 │ │ SerDes ? │ │ SerDes ? │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
```
### J2, serial console
| `J2` pin | Signal |
| -------- | ----------- |
| 1 | 3V3 |
| 2 | TX (Output) |
| 3 | RX (Input) |
| 4 | GND |
Note: 1 pin is square shaped, towards the power input.
### J5, power pass-thru
| `J5` pin | Signal |
| -------- | ------ |
| 1 | 12V |
| 2 | 12V |
| 3 | GND |
| 4 | GND |
Note: 1 pin is square shaped.
### U5, I2C eeprom placeholder
| `J5` pin | Signal |
| -------- | ------------- |
| 1 | GND |
| 2 | GND |
| 3 | GND |
| 4 | GND |
| 5 | 3V3 |
| 6 | ??? Logic Low |
| 7 | SCL |
| 8 | SDA |
SOC I2C address is 0x5c.
### SW1 GPIO switch?
Not populated but looks like a switch for selecting
GPIO level. Missing resistors in place.
GPIO mapping unknown.
### S2 Reset ciruit
Not populated but looks like a button can be added on `S2` connector,
requires additional `R571` resistor which will pull signal to ground.
GPIO mapping unknown.
### GPIO
| HEX VAL. | GPIO | When | GPIO | When |
| -------- | ------ | ----------------| ------ | -----------------------|
| 00000001 | GPIO00 | | GPIO32 | |
| 00000002 | GPIO01 | | GPIO33 | |
| 00000004 | GPIO02 | | GPIO34 | Random changes |
| 00000008 | GPIO03 | | GPIO35 | |
| 00000010 | GPIO04 | | GPIO36 | SFP1 Present |
| 00000020 | GPIO05 | | GPIO37 | SFP1 RX Los |
| 00000040 | GPIO06 | | GPIO38 | SFP2 Present |
| 00000080 | GPIO07 | | GPIO39 | |
| 00000100 | GPIO08 | | GPIO40 | |
| 00000200 | GPIO09 | | GPIO41 | |
| 00000400 | GPIO10 | | GPIO42 | Random changes |
| 00000800 | GPIO11 | | GPIO43 | |
| 00001000 | GPIO12 | PORT1 Link | GPIO44 | |
| 00002000 | GPIO13 | PORT1-LED-GREEN | GPIO45 | |
| 00004000 | GPIO14 | PORT1-LED-AMBER | GPIO46 | SFP1 I2C CLK |
| 00008000 | GPIO15 | PORT2 Link | GPIO47 | SFP1 I2C SDA |
| 00010000 | GPIO16 | PORT2-LED-GREEN | GPIO48 | SFP2 I2C CLK |
| 00020000 | GPIO17 | PORT2-LED-AMBER | GPIO49 | SFP2 I2C SDA |
| 00040000 | GPIO18 | PORT3 Link | GPIO50 | SFP2 Rx LOS |
| 00080000 | GPIO19 | PORT3-LED-GREEN | GPIO51 | SFP1 TX Disable |
| 00100000 | GPIO20 | PORT4-LED-AMBER | GPIO52 | |
| 00200000 | GPIO21 | PORT4 Link | GPIO53 | |
| 00400000 | GPIO22 | PORT4-LED-GREEN | GPIO54 | SFP2 TX Disable |
| 00800000 | GPIO23 | PORT4-LED-AMBER | GPIO55 | |
| 01000000 | GPIO24 | | GPIO56 | |
| 02000000 | GPIO25 | | GPIO57 | |
| 04000000 | GPIO26 | | GPIO58 | |
| 08000000 | GPIO27 | | GPIO59 | |
| 10000000 | GPIO28 | | GPIO60 | |
| 20000000 | GPIO29 | | GPIO61 | |
| 40000000 | GPIO30 | | GPIO62 | |
| 80000000 | GPIO31 | | GPIO63 | |
## LEDs
Leds are not yet working as in stock firmware. This will be handled later.
Ports 1-4 are amber for 100M/1G links, Green for 2.5G.
Port 5-6 are green for 10G/1G link. Both should flash on activity.
| NAME | When active |
| ---------------- | ---------------|
| PWR | 3V3 |
| SFP1 | |
| SFP2 | |
| PORT1-LED-GREEN | - |
| PORT2-LED-GREEN | PORT2 2.5G |
| PORT3-LED-GREEN | PORT3 2.5G |
| PORT4-LED-GREEN | PORT4 2.5G |
| PORT1-LED-AMBER | PORT1 1GB/100M |
| PORT2-LED-AMBER | PORT2 1GB/100M |
| PORT3-LED-AMBER | PORT3 1GB/100M |
| PORT4-LED-AMBER | PORT4 1GB/100M |
## Power supply
Input power is delivered via barell plug, `12V 1A` adapter was provided.
Board has two supply rails. `0.95` and `3.3` volt.
### `0.95` Core Voltage
Voltage is made by a `APW8713` (U3).
### `3.3` Voltage
Voltage is crated regulated by chip marke as `GoIAT` (U2).
## SFP SPI
There is separate clock and data lines for both SFP modules. MSDA/MSCK 0 and 1 need to be enabled.
SFP1 slot is connected to SPI0. SFP2 slot is connected to SPI1.
Binary file not shown.

After

Width:  |  Height:  |  Size: 754 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

+2 -2
View File
@@ -2,7 +2,7 @@
## SPI-Flash Memory ## SPI-Flash Memory
SPI-Flash memory can be replaced with an other type. Because the chip is defect, like #69 & #70 or you have an unmanaged-switch with a small flash size, and want to convert it to a managed-variant to run `RTLPlayground` software on it. Currently `RTLPlayground`-firmware expects `8 MBit / 2 MiB`. SPI-Flash memory can be replaced with an other type. Because the chip is defect, like #69 & #70 or you have an unmanaged-switch with a small flash size, and want to convert it to a managed-variant to run `RTLPlayground` software on it. Currently `RTLPlayground`-firmware expects `8 MBit / 1 MiB`.
### Size ### Size
@@ -25,7 +25,7 @@ Most use package are `SO8`-type may also called `SOIC8`-type. Which can also hav
### Specification ### Specification
1. Size: At least `16 MBit / 4 MiB` (theoretic max. `128 MBit / 32 MiB`, but is not *tested*!) 1. Size: At least `8 MBit / 1 MiB` (theoretic max. `128 MBit / 16 MiB`, but is not *tested*!)
2. Speed: `62.5 MHz` or better. 2. Speed: `62.5 MHz` or better.
3. Support for `DUAL SPI operation`. 3. Support for `DUAL SPI operation`.
Device need support for command `BBh`, `Dual I/O Fast Read` or `Fast Read Dual I/O`. Device need support for command `BBh`, `Dual I/O Fast Read` or `Fast Read Dual I/O`.
+1
View File
@@ -8,6 +8,7 @@ The following devices have been tested and are fully working:
- Lianguo LG-SWTGW218AS (RTL8373 + RTL8224 PHY: 8x 2.5GBit + 1x 10GBit SFP+) - Lianguo LG-SWTGW218AS (RTL8373 + RTL8224 PHY: 8x 2.5GBit + 1x 10GBit SFP+)
- No-Name ZX-SWTGW215AS, managed version of kp-9000-6hx-x, ordered on - No-Name ZX-SWTGW215AS, managed version of kp-9000-6hx-x, ordered on
AliExpress as keepLINK 5+1 port managed AliExpress as keepLINK 5+1 port managed
- TrendNet TEG-S562 (RTL8372: 4x 2.5GBit + 2x 10GBit SFP+)
Other device based on RTL8272/3 that may work are described here: [Up-N-Atoms 2.5 GBit RTL Switch hacking guide] Other device based on RTL8272/3 that may work are described here: [Up-N-Atoms 2.5 GBit RTL Switch hacking guide]
(https://github.com/up-n-atom/SWTG118AS) (https://github.com/up-n-atom/SWTG118AS)
+20
View File
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<script src="/main.js"></script>
<link rel="stylesheet" href="style.css">
<title>Ingress and Egress Bandwidth</title>
</head>
<body>
<nav id="sidebar"></nav>
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
<div id="ports"></div>
<h1>Ingress and Egress Bandwidth</h1>
<table id="bwtable">
<tr> <th> </th> <th colspan="3"> Ingress </th> <th colspan="2">Egress</th> <th></th></tr>
<tr> <th>Port</th> <th>Limit</th> <th>Bandwidth [kBit/s]</th> <th>Flow Control</th> <th>Limit</th> <th>Bandwidth [kBit/s]</th> <th>Apply</th></tr>
</table>
<script src="/bandwidth.js"></script>
</div>
<script src="/navigation.js"></script>
</body>
</html>
+136
View File
@@ -0,0 +1,136 @@
const iLayout = '" type="number" maxlength="10" size="10" onfocus="inputFocus(';
function createBW() {
var tbl = document.getElementById('bwtable');
const limit = '<input type="checkbox" id="limit_port" onchange="exec();">'
if (tbl.rows.length <= 2 && numPorts) {
clearInterval(createBWInterval);
console.log("CREATING TABLE ", tbl.rows.length);
for (let i = 2; i < 2 + numPorts; i++) {
const tr = tbl.insertRow();
let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i-1}`));
td = tr.insertCell();
td.innerHTML = limit.replaceAll("limit_port", "ilimit_port_" + i).replace("exec()", "iClicked(" + i + ")");
td = tr.insertCell();
td.innerHTML = 'UNLIMITED';
td = tr.insertCell();
td.innerHTML = limit.replaceAll("limit_port", "fc_port_" + i).replace("exec()", "document.getElementById('bwapply_" + i + "').disabled=false;");
td = tr.insertCell();
td.innerHTML = limit.replaceAll("limit_port", "elimit_port_" + i).replace("exec()", "eClicked(" + i + ")");
td = tr.insertCell();
td.innerHTML = 'UNLIMITED';
var button = '<button type="button" id="bwapply_' + i + '" style="margin: 0 0 0 24px" onclick="applyBandwidth(' + i + ');">Apply</button>';
td = tr.insertCell();
td.innerHTML = button;
document.getElementById("bwapply_" + i).disabled = true;
}
}
}
function iClicked(i)
{
document.getElementById("bwapply_" + i).disabled=false;
var tbl = document.getElementById('bwtable');
var tr = tbl.rows[i];
if (!document.getElementById("ilimit_port_" + i).checked) {
tr.cells[2].innerHTML = "UNLIMITED";
document.getElementById("fc_port_" + i).disabled = true;
document.getElementById("fc_port_" + i).checked = true;
} else {
tr.cells[2].innerHTML = '<input id="ibw_' + i + iLayout + i + ')" value="0"/>';
document.getElementById("fc_port_" + i).disabled = false;
document.getElementById("fc_port_" + i).checked = true;
}
}
function eClicked(i)
{
document.getElementById("bwapply_" + i).disabled=false;
var tbl = document.getElementById('bwtable');
var tr = tbl.rows[i];
if (!document.getElementById("elimit_port_" + i).checked) {
tr.cells[5].innerHTML = "UNLIMITED";
} else {
tr.cells[5].innerHTML = '<input id="ebw_' + i + iLayout + i + ')" value="0"/>';
}
}
function inputFocus(i)
{
document.getElementById("bwapply_" + i).disabled=false;
}
async function doCMD(cmd)
{
console.log("Sending >" + cmd + "<");
try {
const response = await fetch('/cmd', {
method: 'POST',
body: cmd
});
console.log('Completed!', response);
} catch(err) {
console.error(`Error: ${err}`);
}
}
async function applyBandwidth(i) {
var tbl = document.getElementById('bwtable');
var tr = tbl.rows[i];
var cmd = "bw in " + (i-1) + " off";
if (document.getElementById("ilimit_port_" + i).checked)
cmd = 'bw in ' + (i-1) + ' ' + parseInt(document.getElementById("ibw_" + i).value).toString(16).padStart(4, "0");;
doCMD(cmd);
if (document.getElementById("ilimit_port_" + i).checked) {
if (!document.getElementById("fc_port_" + i).checked)
cmd = "bw in " + (i-1) + " drop";
doCMD(cmd);
}
var cmd = "bw out " + (i-1) + " off";
if (document.getElementById("elimit_port_" + i).checked)
cmd = 'bw out ' + (i-1) + ' ' + parseInt(document.getElementById("ebw_" + i).value).toString(16).padStart(4, "0");;
doCMD(cmd);
}
function getBW() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
const s = JSON.parse(xhttp.responseText);
console.log("BW: ", JSON.stringify(s));
var tbl = document.getElementById('bwtable');
if (tbl.rows.length > 2 && numPorts) {
for (let i = 2; i < 2 + numPorts; i++) {
p = s[i-2];
let n = p.portNum;
let tr = tbl.rows[n+1];
if (!document.getElementById("bwapply_" + (n+1)).disabled)
continue;
console.log("Table Update row: " + i + " portNum is " + n + ", pState is " + pState[i-2] + ", row number is " + (n+1));
let iBW = parseInt(p.iBW,16) * 16; let eBW = parseInt(p.eBW,16) * 16;
document.getElementById("ilimit_port_" + (n+1)).checked = p.iLimited;
document.getElementById("elimit_port_" + (n+1)).checked = p.eLimited;
if (!p.iLimited) {
tr.cells[2].innerHTML = "UNLIMITED";
} else {
tr.cells[2].innerHTML = '<input id="ibw_' + (n+1) + iLayout + (n+1) + ')" value="' + iBW +'"/>';
}
if (!p.eLimited) {
tr.cells[5].innerHTML = "UNLIMITED";
} else {
tr.cells[5].innerHTML = '<input id="ebw_' + (n+1) + iLayout + (n+1) + ')" value="' + eBW +'"/>';
}
document.getElementById("fc_port_" + (n+1)).checked = p.iFC==1?true:false;
document.getElementById("fc_port_" + (n+1)).disabled = p.iLimited==1?false:true;
}
}
}
};
xhttp.open("GET", "/bandwidth.json", true);
xhttp.timeout = 1500; xhttp.send();
}
window.addEventListener("load", function() {
getBW();
const iCount = setInterval(getBW, 2000);
});
const createBWInterval = setInterval(createBW, 1010);
-1
View File
@@ -1 +0,0 @@
../config.txt
+2 -1
View File
@@ -49,7 +49,8 @@ async function fetchCmdLog() {
console.log("CMD-Log: ", response); console.log("CMD-Log: ", response);
const t = await response.text(); const t = await response.text();
return t; return t;
} catch(error) { } catch(err) {
console.error("Error: ", err); console.error("Error: ", err);
return "";
} }
} }
+1 -1
View File
@@ -2,7 +2,7 @@ var txG = new BigInt64Array(10);
var txB = new BigInt64Array(10); var txB = new BigInt64Array(10);
var rxG = new BigInt64Array(10); var rxG = new BigInt64Array(10);
var rxB = new BigInt64Array(10); var rxB = new BigInt64Array(10);
const linkS = ["Disabled", "No Link", "100M", "1000M", "500M", "10G", "2.5G", "5G"]; const linkS = ["Disabled", "Down", "10M", "100M", "1000M", "500M", "10G", "2.5G", "5G"];
var pState = new Int8Array(10); var pState = new Int8Array(10);
var pIsSFP = new Int8Array(10); var pIsSFP = new Int8Array(10);
var pAdvertised = new Int8Array(10); var pAdvertised = new Int8Array(10);
+1 -1
View File
@@ -51,7 +51,7 @@ function fetchMirror() {
for (let i = 1; i <= numPorts; i++) { for (let i = 1; i <= numPorts; i++) {
let p = i - 1; let p = i - 1;
if (numPorts < 9) if (numPorts < 9)
p = physToLogPort[p];members & (1<<p) p = physToLogPort[p];
setM("mPortsTX"+i, m_tx&(1<<p)); setM("mPortsRX"+i, m_rx&(1<<p)); setM("mPortsTX"+i, m_tx&(1<<p)); setM("mPortsRX"+i, m_rx&(1<<p));
} }
} }
+1
View File
@@ -7,5 +7,6 @@ document.getElementById('sidebar').innerHTML =
+ "<li><a href='mirror.html'>Mirroring</a></li>" + "<li><a href='mirror.html'>Mirroring</a></li>"
+ "<li><a href='lag.html'>Link Aggregation</a></li>" + "<li><a href='lag.html'>Link Aggregation</a></li>"
+ "<li><a href='eee.html'>EEE</a></li>" + "<li><a href='eee.html'>EEE</a></li>"
+ "<li><a href='bandwidth.html'>Bandwidth Limits</a></li>"
+ "<li><a href='system.html'>System Settings</a></li>" + "<li><a href='system.html'>System Settings</a></li>"
+ "<li><a href='update.html'>Firmware Update</a></li></ul>"; + "<li><a href='update.html'>Firmware Update</a></li></ul>";
+2 -1
View File
@@ -6,8 +6,9 @@ ul {
margin: 0; margin: 0;
padding: 0; padding: 0;
width: 12%; width: 12%;
height: 100%; height: calc(100% - 50px);
position: fixed; position: fixed;
top: 50px;
overflow: auto; overflow: auto;
} }
+49
View File
@@ -3,12 +3,27 @@
<head> <head>
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
<title>System Settings</title> <title>System Settings</title>
<style>
.tab-bar { display: flex; border-bottom: 2px solid #226; margin-bottom: 0; margin-left: 16%; padding: 1px 16px; padding-bottom: 0; }
.tab-btn { padding: 10px 20px; background-color: #ddf; border: none; cursor: pointer; font-size: 1em; border-radius: 8px 8px 0 0; margin-right: 4px; }
.tab-btn:hover { background-color: #aaf; }
.tab-btn.active { background-color: #aaf; font-weight: bold; border-bottom: 2px solid #aaf; margin-bottom: -2px; }
.tab-content { display: none; }
.tab-content.active { display: block; }
</style>
</head> </head>
<body> <body>
<div class="tab-bar">
<button class="tab-btn active" onclick="openTab(event, 'system-tab')">System</button>
<button class="tab-btn" onclick="openTab(event, 'advanced-tab')">Advanced</button>
</div>
<nav id="sidebar"></nav> <nav id="sidebar"></nav>
<div style="margin-left:16%;padding:1px 16px;height:1000px;"> <div style="margin-left:16%;padding:1px 16px;height:1000px;">
<div id="ports"></div> <div id="ports"></div>
<div id="system-tab" class="tab-content active">
<h1>System Settings</h1> <h1>System Settings</h1>
<label class="dhcpon">DHCP client endabled: <input id="dhcp" type="checkbox" onchange="dhcpClicked(this)"></label><br/><br/>
<div class="row"> <div class="row">
<div class="lcol"> <label for="ip">IP address:</label></div> <div class="lcol"> <label for="ip">IP address:</label></div>
<div class="rcol"> <input id="ip" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div> <div class="rcol"> <input id="ip" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
@@ -21,10 +36,36 @@
<div class="lcol"> <label for="gw">Gateway:</label></div> <div class="lcol"> <label for="gw">Gateway:</label></div>
<div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div> <div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
</div> </div>
<br/>
When updating the above settings, remember to point your browser to the new IP afterwards:<br/>
<input style="width:40%;" class="action" id="ip_sub" onclick="ipSub();" type="button" value="Update Settings"><br/>
<br/>
Save all current settings to Flash:<br/>
<input style="width:40%;" class="action" id="flash_sub" onclick="flashSave();" type="button" value="Save Settings to Flash">
</div>
<div id="advanced-tab" class="tab-content">
<h1>Advanced Settings</h1>
<div class="lcol"> <label for="config_display">Startup configuration:</label></div>
<textarea id="config_display" rows="8" cols="60"></textarea>
<br/><br/> <br/><br/>
Be careful when saving the directly edited startup configuration, you can lock yourself out:<br/>
<input style="width:40%;" class="action" id="clear_config" onclick="clearConfig();" type="button" value="Clear Startup Config">
<br/>
<input style="width:40%;" class="action" id="flash_startup_sub" onclick="flashStartupSave();" type="button" value="Save Startup Settings to Flash">
<br/>
<input style="width:40%;" class="action" id="switch_reset" onclick="resetSwitch();" type="button" value="Reset Switch">
</div>
<div class="row">
<div class="lcol"> <label for="gw">Gateway:</label></div>
<div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
</div><br/>
When updating the above settings, remember to point your browser to the new IP afterwards:<br/> When updating the above settings, remember to point your browser to the new IP afterwards:<br/>
<input style="width:40%;" class="action" id="ip_sub" onclick="ipSub();" type="button" value="Update Settings"><br/> <input style="width:40%;" class="action" id="ip_sub" onclick="ipSub();" type="button" value="Update Settings"><br/>
<br/><br/> <br/><br/>
<label class="dhcpdon">Enable DHCP Server: <input id="dhcpd" type="checkbox"></label><br/><br/>
<label class="dhcpdvlan">Limit DHCP Server to VLAN (0: serve all VLANs): <input type="number" min="0" max="2047" value="0" id="dhcpd_vid" name="dhcpd_vid"></label><br/>
<input style="width:40%;" class="action" id="dhcpd_sub" onclick="dhcpdSub();" type="button" value="Change DHCPD State"><br/><br/><br/>
Save all current settings to Flash:<br/> Save all current settings to Flash:<br/>
<input style="width:40%;" class="action" id="flash_sub" onclick="flashSave();" type="button" value="Save Settings to Flash"> <input style="width:40%;" class="action" id="flash_sub" onclick="flashSave();" type="button" value="Save Settings to Flash">
@@ -32,5 +73,13 @@
<script src="/config.js"></script> <script src="/config.js"></script>
<script src="/system.js"></script> <script src="/system.js"></script>
<script src="/navigation.js"></script> <script src="/navigation.js"></script>
<script>
function openTab(evt, tabId) {
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
document.getElementById(tabId).classList.add('active');
evt.currentTarget.classList.add('active');
}
</script>
</body> </body>
</html> </html>
+104 -2
View File
@@ -8,6 +8,20 @@ function checkIp(ip) {
} }
async function ipSub() { async function ipSub() {
if (document.getElementById('dhcp').checked) {
var cmd = "ip dhcp";
try {
const response = await fetch('/cmd', {
method: 'POST',
body: cmd
});
console.log('Completed!', response);
systemInterval = setInterval(fetchIP, 10000);
} catch(err) {
console.error(`Error: ${err}`);
}
return;
}
for (let i=0;i<3;i++) { for (let i=0;i<3;i++) {
if (!checkIp(document.getElementById(ips[i]).value)) if (!checkIp(document.getElementById(ips[i]).value))
return; return;
@@ -26,7 +40,39 @@ async function ipSub() {
} }
} }
} }
async function dhcpdSub() {
var dhcpd_cmd = "dhcpd off";
if (document.getElementById('dhcpd').checked) {
dhcpd_cmd = "dhcpd on";
var v=document.getElementById('dhcpd_vid').value
if (v && v!= 0)
dhcpd_cmd = dhcpd_cmd + " " + v;
}
try {
console.log("Sending: ", dhcpd_cmd);
const response = await fetch('/cmd', {
method: 'POST',
body: dhcpd_cmd
});
console.log('Completed!', response);
} catch(err) {
console.error(`Error: ${err}`);
}
}
function dhcpClicked(e)
{
console.log("dhcpClicked called");
if (e.checked) {
for (let i=0; i<3;i++)
document.getElementById(ips[i]).disabled = true;
document.getElementById('dhcpd').disabled = true;
} else {
console.log("dhcpClicked off");
for (let i=0; i<3;i++)
document.getElementById(ips[i]).disabled = false;
document.getElementById('dhcpd').disabled = false;
}
}
async function sendConfig(c) { async function sendConfig(c) {
const form = new FormData(); const form = new FormData();
form.append("MAX_FILE_SIZE", "4096"); form.append("MAX_FILE_SIZE", "4096");
@@ -42,6 +88,7 @@ async function sendConfig(c) {
} }
} }
async function flashSave() { async function flashSave() {
fetchConfig().then((s) => { fetchConfig().then((s) => {
parseConf(s); parseConf(s);
@@ -53,6 +100,39 @@ async function flashSave() {
sendConfig(body); sendConfig(body);
}); });
}); });
setTimeout(() => {
fetchIP();
}, 500);
}
async function flashStartupSave() {
var configContent = document.getElementById("config_display").value;
console.log("CONFIGURATION to save: ", configContent);
sendConfig(configContent);
// Clear the command log 1 second after initiating the config save
setTimeout(() => {
fetch('/cmd_log_clear', { method: 'GET' })
.then(response => console.log('Command log cleared', response))
.catch(err => console.error('Error clearing command log:', err));
}, 1000);
}
function clearConfig() {
document.getElementById("config_display").value = "";
// Validate and populate with current IP settings
for (let i=0; i<3; i++) {
if (!checkIp(document.getElementById(ips[i]).value))
return;
}
var configLines = "";
for (let i=0; i<3; i++){
var cmd = ips[i]+' '+document.getElementById(ips[i]).value;
configLines += cmd + "\n";
}
document.getElementById("config_display").value = configLines;
} }
function fetchIP() { function fetchIP() {
@@ -64,13 +144,35 @@ function fetchIP() {
document.getElementById("ip").value=s.ip_address; document.getElementById("ip").value=s.ip_address;
document.getElementById("netmask").value=s.ip_netmask; document.getElementById("netmask").value=s.ip_netmask;
document.getElementById("gw").value=s.ip_gateway; document.getElementById("gw").value=s.ip_gateway;
document.getElementById('dhcp').checked = s.dhcp_client;
document.getElementById('dhcpd').checked = s.dhcp_server;
clearInterval(systemInterval); clearInterval(systemInterval);
} // Fetch and populate the config textbox
fetchConfig().then((configText) => {
let fullConfig = configText;
// Fetch and append cmd_log
//return fetchCmdLog().then((cmdLogText) => {
// if (cmdLogText) {
// fullConfig = fullConfig + cmdLogText;
// }
document.getElementById("config_display").value = fullConfig;
});
};
} }
xhttp.open("GET", `/information.json`, true); xhttp.open("GET", `/information.json`, true);
xhttp.send(); xhttp.send();
} }
function resetSwitch() {
if (!confirm('Are you sure you want to reset the switch?')) {
return;
}
fetch('/reset', { method: 'GET' }).catch(() => {});
setTimeout(() => {
alert('Switch is resetting. Please wait and refresh the page.');
}, 3000);
}
window.addEventListener("load", function() { window.addEventListener("load", function() {
systemInterval = setInterval(fetchIP, 1000); systemInterval = setInterval(fetchIP, 1000);
}); });
+22 -4
View File
@@ -14,9 +14,6 @@
#define SESSION_ID_LENGTH 12 #define SESSION_ID_LENGTH 12
#define SESSION_TIMEOUT 200 #define SESSION_TIMEOUT 200
// Upload Firmware to 1M
#define FIRMWARE_UPLOAD_START 0x100000
// SPI FLASH MEMORY PAGE SIZE. // SPI FLASH MEMORY PAGE SIZE.
#define FLASHMEM_PAGE_SIZE 0x100 #define FLASHMEM_PAGE_SIZE 0x100
@@ -30,9 +27,10 @@ extern __code uint8_t * __code hex;
extern __code struct f_data f_data[]; extern __code struct f_data f_data[];
extern __code char * __code mime_strings[]; extern __code char * __code mime_strings[];
extern __xdata struct flash_region_t flash_region; extern __xdata struct flash_region_t flash_region;
extern __xdata uint32_t flash_size;
// Flash buffer to optimize flash writing speed, write_len is the current filling position // Flash buffer to optimize flash writing speed, write_len is the current filling position
extern __xdata uint8_t flash_buf[512]; extern __xdata uint8_t flash_buf[FLASH_BUF_SIZE];
__xdata uint32_t uptr; // Current flash write position __xdata uint32_t uptr; // Current flash write position
__xdata uint16_t write_len; __xdata uint16_t write_len;
@@ -301,6 +299,8 @@ uint8_t stream_upload(uint16_t bptr)
print_string("Checksum incorrect!"); print_string("Checksum incorrect!");
} }
print_string("\nUpload to flash done, will reset!\n"); print_string("\nUpload to flash done, will reset!\n");
// close connection to avoid retries by browser
uip_close();
reset_chip(); reset_chip();
} }
// Make sure there is a 0 at the end of the uploaded data // Make sure there is a 0 at the end of the uploaded data
@@ -310,6 +310,9 @@ uint8_t stream_upload(uint16_t bptr)
flash_write_bytes(flash_buf); flash_write_bytes(flash_buf);
if (bptr >= uip_len) if (bptr >= uip_len)
return 0; return 0;
if(!verify_crc)
//ugly hack to signal connection finished after config upload.
uip_close();
return 1; return 1;
} }
if (p[bptr] == boundary[bindex]) { if (p[bptr] == boundary[bindex]) {
@@ -424,6 +427,12 @@ void handle_post(void)
p += 4; // Skip \r\n\r\n sequence at end of preamble of part p += 4; // Skip \r\n\r\n sequence at end of preamble of part
if (is_word(request_path, "upload")) { if (is_word(request_path, "upload")) {
if (flash_size < FIRMWARE_UPLOAD_START*2)
{
print_string("Flash too small for firmware upload!\n");
send_bad_request();
return;
}
print_string("Firmware upload started."); print_string("Firmware upload started.");
uptr = FIRMWARE_UPLOAD_START; uptr = FIRMWARE_UPLOAD_START;
verify_crc = 1; verify_crc = 1;
@@ -577,6 +586,8 @@ void httpd_appcall(void)
send_counters(q[20]-'0'); send_counters(q[20]-'0');
} else if (is_word(q, "/eee.json")) { } else if (is_word(q, "/eee.json")) {
send_eee(); send_eee();
} else if (is_word(q, "/bandwidth.json")) {
send_bandwidth();
} else if (is_word(q, "/l2.json")) { } else if (is_word(q, "/l2.json")) {
parse_short(q + 13); // e.g.: /l2.json?idx=10 parse_short(q + 13); // e.g.: /l2.json?idx=10
send_l2(short_parsed); send_l2(short_parsed);
@@ -593,6 +604,13 @@ void httpd_appcall(void)
send_config(); send_config();
} else if (is_word(q, "/cmd_log")) { } else if (is_word(q, "/cmd_log")) {
send_cmd_log(); send_cmd_log();
} else if (is_word(q, "/cmd_log_clear")) {
clear_command_history();
send_mtu(); // dummy response
} else if (is_word(q, "/reset")) {
uip_close();
delay(1000); //wait for the close packet to be sent, otherwise the browser will retry
reset_chip();
} else { } else {
send_not_found(); send_not_found();
} }
+110 -17
View File
@@ -9,6 +9,7 @@
#include "uip.h" #include "uip.h"
#include "html_data.h" #include "html_data.h"
#include <stdint.h> #include <stdint.h>
#include "dhcp.h"
#include "phy.h" #include "phy.h"
#include "version.h" #include "version.h"
#include "machine.h" #include "machine.h"
@@ -17,6 +18,7 @@
// #define DEBUG // #define DEBUG
#include "debug.h" #include "debug.h"
#define L2_MAX_TRANSFER 30 #define L2_MAX_TRANSFER 30
#pragma codeseg BANK1 #pragma codeseg BANK1
@@ -29,7 +31,6 @@ extern __xdata uint16_t cont_len;
extern __xdata uint32_t cont_addr; extern __xdata uint32_t cont_addr;
extern __code uint8_t * __code hex; extern __code uint8_t * __code hex;
extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
extern __code struct uip_eth_addr uip_ethaddr;
extern __xdata uint8_t sfr_data[4]; extern __xdata uint8_t sfr_data[4];
extern __xdata uint8_t sfp_pins_last; extern __xdata uint8_t sfp_pins_last;
@@ -45,6 +46,8 @@ extern __xdata char sfp_module_model[2][17];
extern __xdata char sfp_module_serial[2][17]; extern __xdata char sfp_module_serial[2][17];
extern __xdata uint8_t sfp_options[2]; extern __xdata uint8_t sfp_options[2];
extern __xdata struct dhcp_state dhcp_state;
__code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"; __code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
__code uint8_t * __code HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"; __code uint8_t * __code HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
@@ -97,6 +100,10 @@ void itoa_html(uint8_t v)
char_to_html('0' + (v % 10)); char_to_html('0' + (v % 10));
} }
void string_to_html(register char *s)
{
while (*s) char_to_html(*s++);
}
uint16_t stat_content(void) uint16_t stat_content(void)
{ {
@@ -231,8 +238,13 @@ void send_basic_info(void)
byte_to_html(uip_ethaddr.addr[5]); byte_to_html(uip_ethaddr.addr[5]);
slen += strtox(outbuf + slen, "\",\"sw_ver\":\""); slen += strtox(outbuf + slen, "\",\"sw_ver\":\"");
slen += strtox(outbuf + slen, VERSION_SW); slen += strtox(outbuf + slen, VERSION_SW);
slen += strtox(outbuf + slen, "\",\"build_date\":\"");
slen += strtox(outbuf + slen, BUILD_DATE);
slen += strtox(outbuf + slen, "\",\"hw_ver\":\""); slen += strtox(outbuf + slen, "\",\"hw_ver\":\"");
slen += strtox(outbuf + slen, machine.machine_name); slen += strtox(outbuf + slen, machine.machine_name);
slen += strtox(outbuf + slen, "\",\"flash_size\":\"");
string_to_html(get_flash_size_str());
slen += strtox(outbuf + slen, "\",\"sfp_slot_0\":\""); slen += strtox(outbuf + slen, "\",\"sfp_slot_0\":\"");
send_sfp_info(0); send_sfp_info(0);
char_to_html('"'); char_to_html('"');
@@ -241,6 +253,12 @@ void send_basic_info(void)
send_sfp_info(1); send_sfp_info(1);
char_to_html('"'); char_to_html('"');
} }
if (dhcp_state.state != DHCP_OFF && dhcp_state.state != DHCP_SERVER)
slen += strtox(outbuf + slen, ",\"dhcp_client\":1,\"dhcp_server\":0");
else if (dhcp_state.state == DHCP_SERVER)
slen += strtox(outbuf + slen, ",\"dhcp_client\":0,\"dhcp_server\":1");
else
slen += strtox(outbuf + slen, ",\"dhcp_client\":0,\"dhcp_server\":0");
char_to_html('}'); char_to_html('}');
} }
@@ -537,6 +555,50 @@ void send_eee(void)
} }
} }
void send_bandwidth(void)
{
dbg_string("send_bandwidth called\n");
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
char_to_html('[');
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
slen += strtox(outbuf + slen, "{\"portNum\":");
itoa_html(machine.log_to_phys_port[i]);
slen += strtox(outbuf + slen, ",\"iLimited\":");
reg_read_m(RTL837X_IGBW_PORT_CTRL + i * 4);
if (sfr_data[1] & 0x10)
char_to_html('1');
else
char_to_html('0');
slen += strtox(outbuf + slen, ",\"iBW\":\"");
byte_to_html(sfr_data[1] & 0x0f);
byte_to_html(sfr_data[2]);
byte_to_html(sfr_data[3]);
slen += strtox(outbuf + slen, "\",\"iFC\":");
if (reg_bit_test(RTL837X_IGBW_PORT_FC_CTRL, i))
char_to_html('1');
else
char_to_html('0');
reg_read_m(RTL837X_EGBW_PORT_CTRL + i * 1024);
slen += strtox(outbuf + slen, ",\"eLimited\":");
if (sfr_data[1] & 0x10)
char_to_html('1');
else
char_to_html('0');
slen += strtox(outbuf + slen, ",\"eBW\":\"");
byte_to_html(sfr_data[1] & 0x0f);
byte_to_html(sfr_data[2]);
byte_to_html(sfr_data[3]);
char_to_html('"');
char_to_html('}');
if (i < machine.max_port)
char_to_html(',');
else
char_to_html(']');
}
}
void send_mtu(void) void send_mtu(void)
{ {
dbg_string("send_mtu called\n"); dbg_string("send_mtu called\n");
@@ -628,12 +690,24 @@ void send_status(void)
slen += strtox(outbuf + slen, ",\"link\":"); slen += strtox(outbuf + slen, ",\"link\":");
uint8_t b = 0;
// Determine link state
reg_read_m(RTL837X_REG_LINKS_STS);
if(!((sfr_data[(i / 8) + 1] >> (i % 8 ) & 1)))
{
b = 0; //link down
}
else
{
//Determine link speed
if (i < 8) if (i < 8)
reg_read_m(RTL837X_REG_LINKS); reg_read_m(RTL837X_REG_LINKS);
else else
reg_read_m(RTL837X_REG_LINKS_89); reg_read_m(RTL837X_REG_LINKS_89);
uint8_t b = sfr_data[3 - ((i & 7) >> 1)];
b = (i & 1) ? b >> 4 : b & 0xf; b = sfr_data[3 - ((i & 7) >> 1)];
b = ((i & 1) ? b >> 4 : b & 0xf) + 1;
}
char_to_html('0' + b); char_to_html('0' + b);
STAT_GET(STAT_COUNTER_TX_PKTS, i); STAT_GET(STAT_COUNTER_TX_PKTS, i);
@@ -665,26 +739,45 @@ void send_status(void)
void send_config(void) void send_config(void)
{ {
dbg_string("send_config called\n"); dbg_string("send_config called\n");
__xdata uint32_t pos = CONFIG_START; // 70000 , 6c000 / 0xc000 = 9 __xdata uint32_t pos = CONFIG_START;
__xdata uint16_t valid_len = 0;
__xdata uint16_t len_left = CONFIG_LEN;
__xdata uint8_t flash_buf[256];
extern __xdata uint16_t len_left = CONFIG_LEN;
slen = strtox(outbuf, HTTP_RESPONCE_TXT); slen = strtox(outbuf, HTTP_RESPONCE_TXT);
while (read_flash((CONFIG_START-CODE0_SIZE) / CODE_BANK_SIZE + 1,
(__code uint8_t *) (((CONFIG_START + len_left - CODE0_SIZE) % CODE_BANK_SIZE) + CODE0_SIZE + len_left)) == 0xff) {
dbg_short(len_left);
len_left--;
}
len_left++;
if (len_left > (TCP_OUTBUF_SIZE - slen)) { // Scan through config to find the end of valid data (null terminator)
cont_len = len_left - (TCP_OUTBUF_SIZE - slen); do {
len_left = TCP_OUTBUF_SIZE - slen; flash_region.addr = pos;
cont_addr = len_left; flash_region.len = (len_left > 256) ? 256 : len_left;
flash_read_bulk(flash_buf);
// Look for null terminator in this chunk
for (uint16_t i = 0; i < flash_region.len; i++) {
if (flash_buf[i] == 0) {
// Found end of valid data
valid_len += i;
goto found_end;
} }
}
valid_len += flash_region.len;
len_left -= flash_region.len;
pos += flash_region.len;
} while (len_left > 0);
found_end:
// Now send the valid data
if (valid_len > (TCP_OUTBUF_SIZE - slen)) {
cont_len = valid_len - (TCP_OUTBUF_SIZE - slen);
valid_len = TCP_OUTBUF_SIZE - slen;
cont_addr = valid_len;
}
flash_region.addr = CONFIG_START; flash_region.addr = CONFIG_START;
flash_region.len = len_left; flash_region.len = valid_len;
flash_read_bulk(outbuf + slen); flash_read_bulk(outbuf + slen);
slen += len_left; slen += valid_len;
} }
void send_cmd_log(void) void send_cmd_log(void)
+1
View File
@@ -5,6 +5,7 @@ void send_counters(char port);
void send_status(void); void send_status(void);
void send_vlan(uint16_t vlan); void send_vlan(uint16_t vlan);
void send_basic_info(void); void send_basic_info(void);
void send_bandwidth(void);
void send_eee(void); void send_eee(void);
void send_l2(uint16_t idx); void send_l2(uint16_t idx);
void l2_delete(uint16_t idx); void l2_delete(uint16_t idx);
+199 -40
View File
@@ -1,6 +1,8 @@
#include "machine.h" #include "machine.h"
#include "rtl837x_pins.h" #include "rtl837x_pins.h"
#include "rtl837x_leds.h" #include "rtl837x_leds.h"
#include "rtl837x_regs.h"
#include "rtl837x_common.h"
#ifdef MACHINE_KP_9000_6XHML_X2 #ifdef MACHINE_KP_9000_6XHML_X2
__code const struct machine machine = { __code const struct machine machine = {
@@ -11,18 +13,20 @@ __code const struct machine machine = {
.n_sfp = 2, .n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1}, .is_sfp = {0, 0, 0, 1, 0, 0, 0, 0, 2},
// Left SFP port (5)
.sfp_port[0].pin_detect = GPIO50_I2C_SCL2_UART1_TX, .sfp_port[0].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[0].pin_los = GPIO10_LED10, .sfp_port[0].pin_los = GPIO10_LED10,
.sfp_port[0].pin_tx_disable = GPIO_NA, .sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 0, .sfp_port[0].sds = 0,
.sfp_port[0].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 }, .sfp_port[0].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 },
// Right SFP port (6)
.sfp_port[1].pin_detect = GPIO30_ACL_BIT3_EN, .sfp_port[1].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[1].pin_los = GPIO37, .sfp_port[1].pin_los = GPIO37,
.sfp_port[1].pin_tx_disable = GPIO_NA, .sfp_port[1].pin_tx_disable = GPIO_NA,
.sfp_port[1].sds = 1, .sfp_port[1].sds = 1,
.sfp_port[1].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, .sfp_port[1].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
.reset_pin = GPIO46_I2C_SCL0, .reset_pin = GPIO54_ACL_BIT2_EN,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 }, .high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0}, .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0},
/* Conditions for LED on: /* Conditions for LED on:
@@ -35,14 +39,10 @@ __code const struct machine machine = {
LEDS_1G | LEDS_LINK, LEDS_1G | LEDS_LINK,
0 }, 0 },
}, },
.led_mux_custom = 0,
// LED0 LED1 LED2 LED3 LED4 LED5 LED6 LED7 LED8 LED9 LED10 LED11 LED12 LED13 LED14 LED15
// L-SFP R-SFP | PORT 1
// LED16 LED17 LED18 LED19 LED20 LED21 LED22 LED23 LED24 LED25 LED26 LED27
// | PORT 2 | PORT 3 | PORT 4
// .led_mux = { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x0f, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14,
// 0x15, 0x16, 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23 },
}; };
void machine_custom_init(void) { }
#elif defined MACHINE_KP_9000_6XH_X #elif defined MACHINE_KP_9000_6XH_X
__code const struct machine machine = { __code const struct machine machine = {
.machine_name = "keepLink KP-9000-6XH-X", .machine_name = "keepLink KP-9000-6XH-X",
@@ -57,7 +57,6 @@ __code const struct machine machine = {
.sfp_port[0].pin_los = GPIO37, .sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA, .sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1, .sfp_port[0].sds = 1,
.sfp_port[0].i2c_bus = { .sda = 4, .scl = 3 },
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
.reset_pin = GPIO_NA, .reset_pin = GPIO_NA,
/* Conditions for LED on: /* Conditions for LED on:
@@ -71,9 +70,12 @@ __code const struct machine machine = {
0 }, 0 },
}, },
}; };
void machine_custom_init(void) { }
#elif defined MACHINE_KP_9000_9XH_X_EU #elif defined MACHINE_KP_9000_9XH_X_EU
__code const struct machine machine = { __code const struct machine machine = {
.machine_name = "keepLink KP-9000-6XH-X-EU", .machine_name = "keepLink KP-9000-9XH-X-EU",
.isRTL8373 = 1, .isRTL8373 = 1,
.min_port = 0, .min_port = 0,
.max_port = 8, .max_port = 8,
@@ -96,6 +98,45 @@ __code const struct machine machine = {
}, },
}; };
void machine_custom_init(void) { }
#elif defined MACHINE_KP_9000_9XHML_X
__code const struct machine machine = {
.machine_name = "keepLink KP-9000-9XHML-X",
.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 = GPIO38,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
.reset_pin = GPIO48_I2C_SCL1,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = {
{ /* RJ45: First LED, yellow, second LED: green */
LEDS_2G5 | LEDS_LINK,
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
}, { /* SFP PORT, SINGLE GREEN LED */
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
0,
0,
0,
}},
.led_mux_custom = 1,
.led_mux = {0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0c, 0x09, 0x0d, 0x10,
0x11, 0x0e, 0x14, 0x11, 0x12, 0x15, 0x15, 0x16, 0x18, 0x19,
0x1a, 0x19, 0x1d, 0x1e, 0x1c, 0x1d, 0x20, 0x21},
};
void machine_custom_init(void) { }
#elif defined MACHINE_SWGT024_V2_0 #elif defined MACHINE_SWGT024_V2_0
__code const struct machine machine = { __code const struct machine machine = {
.machine_name = "SWGT024 V2.0", .machine_name = "SWGT024 V2.0",
@@ -133,6 +174,49 @@ __code const struct machine machine = {
}, },
}; };
void machine_custom_init(void) { }
#elif defined MACHINE_SWTG018AS_A_V_2_0
__code const struct machine machine = {
.machine_name = "SWTG018AS-A V2.0",
.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 = GPIO38,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = {
{ /* RJ45: First LED, yellow, second LED: green */
LEDS_2G5 | LEDS_LINK,
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
0,
0,
}, { /* SFP PORT, SINGLE GREEN LED */
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
0,
0,
0,
}},
.led_mux_custom = 1,
.led_mux = { 0x00, 0x01, 0x04, 0x05, 0x08, // 65e0
0x09, 0x0c, 0x09, 0x0d, 0x10, // 65e4
0x11, 0x0e, 0x14, 0x11, 0x12, // 65e8
0x15, 0x15, 0x16, 0x18, 0x19, // 65ec
0x1a, 0x19, 0x1d, 0x1e, 0x1c, // 65f0
0x1d, 0x20, 0x21 },
};
void machine_custom_init(void) { }
#elif defined MACHINE_HG0402XG_V1_1 #elif defined MACHINE_HG0402XG_V1_1
__code const struct machine machine = { __code const struct machine machine = {
.machine_name = "HG0402XG V1.1", .machine_name = "HG0402XG V1.1",
@@ -170,48 +254,44 @@ __code const struct machine machine = {
0 }, 0 },
}, },
}; };
#elif defined MACHINE_ZX_SWTGW215AS_HASIVO
void machine_custom_init(void) { }
#elif defined MACHINE_SWTGW218AS
__code const struct machine machine = { __code const struct machine machine = {
.machine_name = "ZX-SWTGW215AS HASIVO", .machine_name = "SWTGW218AS 8+1 Managed Switch",
.isRTL8373 = 0, .isRTL8373 = 1,
.min_port = 3, .min_port = 0,
.max_port = 8, .max_port = 8,
.n_sfp = 1, .n_sfp = 1,
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN, .sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
.sfp_port[0].pin_los = GPIO37, .sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO_NA, .sfp_port[0].pin_tx_disable = GPIO_NA,
.sfp_port[0].sds = 1, .sfp_port[0].sds = 1,
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
.sfp_port[1].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
.reset_pin = GPIO54_ACL_BIT2_EN, .reset_pin = GPIO54_ACL_BIT2_EN,
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 }, .high_leds = { .mux = LED_27 | LED_28 | LED_29, .enable = LED_28 | LED_29 },
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1}, .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1},
.led_sets = { .led_sets = { { LEDS_2G5 | LEDS_LINK | LEDS_ACT, // Green LED (right)
/* The Ethernet ports have 1 amber LED (bi-color left) and 2 green LED (left/right) 0, // unused
* The SFP port has 1 green LED LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // Amber LED (left)
* Ethernet ports use LED-set 0, SFP port uses LED-set 1 0
* Amber-LED: ledid0 & ledid1 & !ledid2 }, // unused
* Left-Green: ledid-2 { LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT, // SFP LED
* Right-Green: ledid-0 0, // unused
* ledid3 is not used 0, // unused
*/ 0
{ LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, }, // unused },
LEDS_2G5 | LEDS_LINK | LEDS_10G,
LEDS_1G | LEDS_LINK,
0 },
{
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_1G | LEDS_LINK,
LEDS_2G5 | LEDS_LINK,
LEDS_COL | LEDS_DUPLEX,
}
}, },
.led_mux_custom = 0,
}; };
#elif defined DEFAULT_8C_1SFP
void machine_custom_init(void) { }
#elif defined MACHINE_DEFAULT_8C_1SFP
__code const struct machine machine = { __code const struct machine machine = {
.machine_name = "8+1 SFP Port Switch", .machine_name = "8+1 SFP Port Switch",
.isRTL8373 = 1, .isRTL8373 = 1,
@@ -235,4 +315,83 @@ __code const struct machine machine = {
LEDS_2G5 | LEDS_LINK | LEDS_ACT }, LEDS_2G5 | LEDS_LINK | LEDS_ACT },
}, },
}; };
void machine_custom_init(void) { }
#elif defined MACHINE_TRENDNET_TEG_S562
__code const struct machine machine = {
.machine_name = "Trendnet TEG-S562",
.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, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = GPIO36_PWM_OUT,
.sfp_port[0].pin_los = GPIO37,
.sfp_port[0].pin_tx_disable = GPIO51_I2C_SDA2_UART1_RX,
.sfp_port[0].sds = 0,
.sfp_port[0].i2c = { .sda = GPIO47_I2C_SDA0, .scl = GPIO46_I2C_SCL0 },
.sfp_port[1].pin_detect = GPIO38,
.sfp_port[1].pin_los = GPIO50_I2C_SCL2_UART1_TX,
.sfp_port[1].pin_tx_disable = GPIO54_ACL_BIT2_EN,
.sfp_port[1].sds = 1,
.sfp_port[1].i2c = { .sda = GPIO49_I2C_SDA1, .scl = GPIO48_I2C_SCL1 },
.reset_pin = GPIO_NA,
};
void machine_custom_init(void) { }
#elif defined MACHINE_HI_K0402WS
__code const struct machine machine = {
.machine_name = "HiSource HI-K0402WS",
.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
.sfp_port[0].pin_detect = GPIO38,
.sfp_port[0].pin_los = GPIO_NA,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
// Right SFP port
.sfp_port[1].pin_detect = GPIO37,
.sfp_port[1].pin_los = GPIO_NA,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 },
.reset_pin = GPIO_NA,
.high_leds = { .mux = LED_28 | LED_29, .enable = LED_27 | LED_28 | LED_29 },
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
.led_sets = {
{
LEDS_2G5 | LEDS_LINK | LEDS_10M | LEDS_ACT,
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G,
LEDS_1G | LEDS_LINK,
0
},
{
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK,
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_ACT,
0,
0
},
},
.led_mux_custom = 1,
.led_mux = {
0x00,0x01,0x04,0x05,0x08,0x09,0x0c,0x3f,0x0d,0x10,0x11,0x0e,0x14,0x11,0x12,0x15,0x15,0x16,0x18,0x19,0x1a,0x19,0x1d,0x1e,0x1c,0x1d,0x20,0x21
},
};
void machine_custom_init(void) {
reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6);
}
#else
#error "Please select a machine type in machine.h"
#endif #endif
+9 -5
View File
@@ -9,13 +9,15 @@
// #define MACHINE_KP_9000_6XHML_X2 // #define MACHINE_KP_9000_6XHML_X2
// #define MACHINE_KP_9000_6XH_X // #define MACHINE_KP_9000_6XH_X
// #define MACHINE_KP_9000_9XH_X_EU // #define MACHINE_KP_9000_9XH_X_EU
// #define MACHINE_KP_9000_9XHML_X
// #define MACHINE_SWGT024_V2_0 // #define MACHINE_SWGT024_V2_0
// #define MACHINE_HORACO_ZX_SG4T2 // #define MACHINE_HORACO_ZX_SG4T2
// #define MACHINE_TRENDNET_TEG_S562
// #define MACHINE_HG0402XG_V1_1 // #define MACHINE_HG0402XG_V1_1
#define MACHINE_ZX_SWTGW215AS_HASIVO // #define MACHINE_SWTG018AS_A_V_2_0
// #define DEFAULT_8C_1SFP // #define MACHINE_SWTGW218AS
// #define MACHINE_HI_K0402WS
// #define DEFAULT_5C_1SFP // #define MACHINE_DEFAULT_8C_1SFP
typedef struct { typedef struct {
// GPIO pins for SDA/SCL // GPIO pins for SDA/SCL
@@ -55,7 +57,7 @@ typedef struct machine {
uint8_t is_sfp[9]; // 0 for non-SFP ports 1 or 2 for the I2C port number uint8_t is_sfp[9]; // 0 for non-SFP ports 1 or 2 for the I2C port number
// sfp_port[0] is the first SFP-port from the left on the device, sfp_port[1] the next if present // sfp_port[0] is the first SFP-port from the left on the device, sfp_port[1] the next if present
struct sfp_port sfp_port[2]; struct sfp_port sfp_port[2];
int8_t reset_pin; uint8_t reset_pin;
struct high_leds high_leds; struct high_leds high_leds;
uint8_t port_led_set[9]; uint8_t port_led_set[9];
uint32_t led_sets[4][4]; uint32_t led_sets[4][4];
@@ -69,4 +71,6 @@ typedef struct machine_runtime
uint8_t isN : 1; uint8_t isN : 1;
}; };
void machine_custom_init(void);
#endif #endif
+122
View File
@@ -0,0 +1,122 @@
// #define REGDBG
// #define DEBUG
#include "rtl837x_common.h"
#include "rtl837x_sfr.h"
#include "rtl837x_regs.h"
#include "rtl837x_bandwidth.h"
#include "machine.h"
#pragma codeseg BANK2
#pragma constseg BANK2
extern __xdata uint8_t sfr_data[4];
void bandwidth_setup(void) __banked
{
print_string("bandwidth_setup called\n");
// Exclude all packets possibly for the CPU port, but do not include bypassed packets or Inter-Frame-Gap into bandwidth
REG_SET(RTL837X_IGBW_CTRL, IGBW_ADM_DHCP | IGBW_ADM_ARPREQ | IGBW_ADM_RMA | IGBW_ADM_BPDU | IGBW_ADM_RTKPKT | IGBW_ADM_IGMP);
// We do not count IFG for Egress and allways allow CPU-traffic
REG_SET(RTL837X_EGBW_CTRL, EGBW_CPUMODE);
print_string("RTL837X_IGBW_CTRL: "); print_reg(RTL837X_IGBW_CTRL); write_char('\n');
print_string("RTL837X_EGBW_CTRL: "); print_reg(RTL837X_EGBW_CTRL); write_char('\n');
print_string("bandwidth_setup done\n");
}
/*
* Set the ingress bandwidth
* bw: Bandwidth in kb
*/
void bandwidth_ingress_set(uint8_t port, __xdata uint32_t bw) __banked
{
__xdata uint8_t * __xdata bwptr = &bw;
print_string("bandwidth_ingress_set called, port "); print_byte(port); write_char('\n');
sfr_data[0] = 0;
sfr_data[1] = 0x10 | (*(bwptr + 2) >> 4); // Set bit 20 to enable ingress bandwidth control
sfr_data[2] = (*(bwptr + 2) << 4) | (*(bwptr + 1) >> 4);
sfr_data[3] = (*(bwptr) >> 4) | (*(bwptr + 1) << 4);
reg_write_m(RTL837X_IGBW_PORT_CTRL + port * 4);
// We enable Flow Control instead of just dropping packets
reg_bit_set(RTL837X_IGBW_PORT_FC_CTRL, port);
}
void bandwidth_ingress_drop(uint8_t port) __banked
{
reg_bit_clear(RTL837X_IGBW_PORT_FC_CTRL, port);
print_string("RTL837X_IGBW_PORT_FC_CTRL:"); print_reg(RTL837X_IGBW_PORT_FC_CTRL); write_char('\n');
}
void bandwidth_ingress_fc(uint8_t port) __banked
{
reg_bit_set(RTL837X_IGBW_PORT_FC_CTRL, port);
print_string("RTL837X_IGBW_PORT_FC_CTRL:"); print_reg(RTL837X_IGBW_PORT_FC_CTRL); write_char('\n');
}
void bandwidth_ingress_disable(uint8_t port) __banked
{
print_string("Ingress bandwidth limit disabled, port "); print_byte(port); write_char('\n');
REG_SET(RTL837X_IGBW_PORT_CTRL + port * 4, 0x0fffff);
}
void bandwidth_egress_set(uint8_t port, __xdata uint32_t bw) __banked
{
__xdata uint8_t * __xdata bwptr = &bw;
print_string("bandwidth_egress_set called, port "); print_byte(port); write_char('\n');
sfr_data[0] = 0;
sfr_data[1] = 0x10 | (*(bwptr + 2) >> 4); // Set bit 20 to enable egress bandwidth control
sfr_data[2] = (*(bwptr + 2) << 4) | (*(bwptr + 1) >> 4);
sfr_data[3] = (*(bwptr) >> 4) | (*(bwptr + 1) << 4);
reg_write_m(RTL837X_EGBW_PORT_CTRL + port * 1024);
}
void bandwidth_egress_disable(uint8_t port) __banked
{
print_string("Egress bandwidth limit disabled, port "); print_byte(port); write_char('\n');
REG_SET(RTL837X_EGBW_PORT_CTRL + port * 1024, 0x0fffff);
}
void bandwidth_status(uint8_t port) __banked
{
print_string("ingress: ");
reg_read_m(RTL837X_IGBW_PORT_CTRL + port * 4);
if (sfr_data[1] & 0x10) {
print_string("enabled: ");
sfr_data[1] &= 0xef;
print_string("0x");
print_byte(sfr_data[1]);
print_byte(sfr_data[2]);
print_byte(sfr_data[3]);
write_char('0');
write_char('\n');
} else {
print_string("disabled\n");
}
print_string("egress: ");
reg_read_m(RTL837X_EGBW_PORT_CTRL + port * 1024);
if (sfr_data[1] & 0x10) {
print_string("enabled: ");
sfr_data[1] &= 0xef;
print_string("0x");
print_byte(sfr_data[1]);
print_byte(sfr_data[2]);
print_byte(sfr_data[3]);
write_char('0');
write_char('\n');
} else {
print_string("disabled\n");
}
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef _RTL837X_BANDWIDTH_H_
#define _RTL837X_BANDWIDTH_H_
#include <stdint.h>
void bandwidth_setup(void) __banked;
void bandwidth_ingress_set(uint8_t port, __xdata uint32_t bw) __banked;
void bandwidth_ingress_disable(uint8_t port) __banked;
void bandwidth_ingress_drop(uint8_t port) __banked;
void bandwidth_ingress_fc(uint8_t port) __banked;
void bandwidth_egress_set(uint8_t port, __xdata uint32_t bw) __banked;
void bandwidth_egress_disable(uint8_t port) __banked;
void bandwidth_status(uint8_t port) __banked;
#endif
+27 -5
View File
@@ -19,9 +19,19 @@
#define LOOKUP_MISS_DROP_9 0x00015555 #define LOOKUP_MISS_DROP_9 0x00015555
#define LOOKUP_MISS_FLOOD 0x00000000 #define LOOKUP_MISS_FLOOD 0x00000000
// The serial buffer. Defines the command line size /* Buffer for serial input, SBUF_SIZE must be power of 2 < 256
// Must be 2^x and <= 128 * Writing to this buffer is under the sole control of the serial ISR
#define SBUF_SIZE 128 * Note that key-presses such as <cursor-left> can create multiple
* keys (3 to 4) being sent via the serial line, so this must be
* sufficiently large */
#define SBUF_SIZE 16
#define SBUF_MASK (SBUF_SIZE - 1)
extern __xdata volatile uint8_t sbuf_ptr;
extern __xdata uint8_t sbuf[SBUF_SIZE];
// Define the command buffer size, Must be 2^x and <= 128
#define CMD_BUF_SIZE 128
// Size of the TCP Output buffer // Size of the TCP Output buffer
#define TCP_OUTBUF_SIZE 2500 #define TCP_OUTBUF_SIZE 2500
@@ -29,6 +39,9 @@
// Size of the memory area dedicated to VLAN-names // Size of the memory area dedicated to VLAN-names
#define VLAN_NAMES_SIZE 1024 #define VLAN_NAMES_SIZE 1024
// Size of the flash buffer used for writing to flash, must be a multiple of the flash page size (0x100)
#define FLASH_BUF_SIZE 512
// For RX data, a propriatary RTL FRAME is inserted. Instead of 0x0800 for IPv4, // For RX data, a propriatary RTL FRAME is inserted. Instead of 0x0800 for IPv4,
// the RTL_FRAME_TAG_ID is used as part of an 8-byte tag. When VLAN is activated, // the RTL_FRAME_TAG_ID is used as part of an 8-byte tag. When VLAN is activated,
// the VLAN tag is inserted after the RTL tag // the VLAN tag is inserted after the RTL tag
@@ -57,11 +70,15 @@ struct vlan_tag {
// This is the standard size of an Ethernet frame header // This is the standard size of an Ethernet frame header
#define ETHER_HEADER_SIZE 14 #define ETHER_HEADER_SIZE 14
#define DEFAULT_CONFIG_START 0x6f000
#define CONFIG_START 0x70000 #define CONFIG_START 0x70000
#define CONFIG_LEN 0x1000 #define CONFIG_LEN 0x1000
#define CODE0_SIZE 0x4000 #define CODE0_SIZE 0x4000
#define CODE_BANK_SIZE 0xc000 #define CODE_BANK_SIZE 0xc000
// Store update image after running image
#define FIRMWARE_UPLOAD_START 0x80000
// Constants for the circular command buffer, the size must be 2^n // Constants for the circular command buffer, the size must be 2^n
#define CMD_HISTORY_SIZE 0x400 #define CMD_HISTORY_SIZE 0x400
#define CMD_HISTORY_MASK (CMD_HISTORY_SIZE - 1) #define CMD_HISTORY_MASK (CMD_HISTORY_SIZE - 1)
@@ -79,10 +96,14 @@ struct flash_region_t {
}; };
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2]; extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
extern __xdata struct uip_eth_addr uip_ethaddr;
extern __xdata uint16_t rx_packet_vlan;
extern __xdata uint16_t dhcpd_vlan;
// Headers for calls in the common code area (HOME/BANK0) // Headers for calls in the common code area (HOME/BANK0)
void print_string(__code char *p); void print_string(__code char *p);
void print_long(__xdata uint32_t a); void print_string_x(__xdata char *p);
void print_long(uint32_t a);
void print_short(uint16_t a); void print_short(uint16_t a);
void print_byte(uint8_t a); void print_byte(uint8_t a);
void itoa(uint8_t v); void itoa(uint8_t v);
@@ -103,6 +124,7 @@ void print_reg(uint16_t reg);
uint8_t sfp_read_reg(uint8_t slot, uint8_t reg); uint8_t sfp_read_reg(uint8_t slot, uint8_t reg);
void reg_bit_set(uint16_t reg_addr, char bit); void reg_bit_set(uint16_t reg_addr, char bit);
void reg_bit_clear(uint16_t reg_addr, char bit); void reg_bit_clear(uint16_t reg_addr, char bit);
uint8_t reg_bit_test(uint16_t reg_addr, char bit);
void sfr_mask_data(uint8_t n, uint8_t mask, uint8_t set); void sfr_mask_data(uint8_t n, uint8_t mask, uint8_t set);
void sfr_set_zero(void); void sfr_set_zero(void);
void reset_chip(void); void reset_chip(void);
@@ -112,8 +134,8 @@ void memset(register __xdata uint8_t *dst, register __xdata uint8_t v, register
uint16_t strlen(register __code const char *s); uint16_t strlen(register __code const char *s);
uint16_t strlen_x(register __xdata const char *s); uint16_t strlen_x(register __xdata const char *s);
uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s); uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s);
uint16_t strcpy(register __xdata uint8_t *dst, register const char *s);
void tcpip_output(void); void tcpip_output(void);
void print_string_x(__xdata char *p);
uint8_t read_flash(uint8_t bank, __code uint8_t *addr); uint8_t read_flash(uint8_t bank, __code uint8_t *addr);
void get_random_32(void); void get_random_32(void);
void read_reg_timer(uint32_t * tmr); void read_reg_timer(uint32_t * tmr);
+28 -55
View File
@@ -10,6 +10,8 @@
__xdata uint8_t dio_enabled; __xdata uint8_t dio_enabled;
__xdata struct flash_region_t flash_region; __xdata struct flash_region_t flash_region;
__xdata uint32_t flash_size;
__xdata uint8_t flash_capacity_code;
// For the flash commands, see e.g. Windbond W25Q32JV datasheet // For the flash commands, see e.g. Windbond W25Q32JV datasheet
#define CMD_WRITE_STATUS 0x01 #define CMD_WRITE_STATUS 0x01
@@ -17,6 +19,7 @@ __xdata struct flash_region_t flash_region;
// Don't use command `READ 0x03`, because on many device this command can't run at maximum SPI-clock speed. // Don't use command `READ 0x03`, because on many device this command can't run at maximum SPI-clock speed.
// Use `Fast READ 0x0b` instead! // Use `Fast READ 0x0b` instead!
//#define CMD_READ 0x03 //#define CMD_READ 0x03
#define CMD_READ_STATUS 0x05
#define CMD_WRITE_ENABLE 0x06 #define CMD_WRITE_ENABLE 0x06
#define CMD_FREAD 0x0b #define CMD_FREAD 0x0b
#define CMD_SECTOR_ERASE 0x20 #define CMD_SECTOR_ERASE 0x20
@@ -87,7 +90,7 @@ uint8_t flash_read_status(void)
// setup status read command // setup status read command
SFR_FLASH_TCONF = 0x11; SFR_FLASH_TCONF = 0x11;
SFR_FLASH_CMD_R = 5; SFR_FLASH_CMD_R = CMD_READ_STATUS;
// execute and wait for controller done // execute and wait for controller done
SFR_FLASH_EXEC_GO = 1; SFR_FLASH_EXEC_GO = 1;
@@ -119,9 +122,10 @@ void flash_read_uid(void)
print_byte(SFR_FLASH_DATA8); print_byte(SFR_FLASH_DATA8);
print_byte(SFR_FLASH_DATA16); print_byte(SFR_FLASH_DATA16);
print_byte(SFR_FLASH_DATA24); print_byte(SFR_FLASH_DATA24);
write_char(' ');
SFR_FLASH_DUMMYCYCLES = 24; // Doesn't seem to work; we get the same data as for the first transfer
SFR_FLASH_EXEC_GO = 1; SFR_FLASH_EXEC_GO = 1;
SFR_FLASH_DUMMYCYCLES = 24;
while(SFR_FLASH_EXEC_BUSY); while(SFR_FLASH_EXEC_BUSY);
print_byte(SFR_FLASH_DATA0); print_byte(SFR_FLASH_DATA0);
@@ -132,6 +136,19 @@ void flash_read_uid(void)
flash_configure_mmio(); flash_configure_mmio();
} }
__code char* get_flash_size_str(void)
{
switch (flash_capacity_code) {
case 0x12: return "256 KB";
case 0x13: return "512 KB";
case 0x14: return "1 MB";
case 0x15: return "2 MB";
case 0x16: return "4 MB";
case 0x17: return "8 MB";
case 0x18: return "16 MB";
default: return "unknown";
}
}
void flash_read_jedecid(void) void flash_read_jedecid(void)
{ {
@@ -148,15 +165,16 @@ void flash_read_jedecid(void)
SFR_FLASH_EXEC_GO = 1; SFR_FLASH_EXEC_GO = 1;
while(SFR_FLASH_EXEC_BUSY); while(SFR_FLASH_EXEC_BUSY);
print_string("Flash information:\n");
print_string(" Manufacturer ID: 0x");
print_byte(SFR_FLASH_DATA0); print_byte(SFR_FLASH_DATA0);
print_string("\n Memory Type: 0x");
print_byte(SFR_FLASH_DATA8); print_byte(SFR_FLASH_DATA8);
print_byte(SFR_FLASH_DATA16); print_string("\n Capacity: 0x");
print_byte(SFR_FLASH_DATA24); flash_capacity_code = SFR_FLASH_DATA16;
flash_size = 1UL << flash_capacity_code;
// Reset slow read mode print_byte(flash_capacity_code);
SFR_FLASH_MODEB = 0x0; print_string(" = "); print_string(get_flash_size_str()); write_char('\n');
SFR_FLASH_CMD_R = CMD_FREAD;
SFR_FLASH_DUMMYCYCLES = 8;
flash_configure_mmio(); flash_configure_mmio();
} }
@@ -188,51 +206,6 @@ void flash_write_enable(void)
} while (!(status & 0x2)); } while (!(status & 0x2));
} }
void flash_dump(uint8_t len)
{
short status;
do {
status = flash_read_status();
print_short(status);
} while (status & 0x1);
// Set fast read mode
if (dio_enabled) {
SFR_FLASH_MODEB = 0x18;
SFR_FLASH_CMD_R = CMD_FREAD_DIO;
SFR_FLASH_DUMMYCYCLES = 4;
} else {
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = CMD_FREAD; // Fast read
SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks after read?
}
// Read 4 bytes
SFR_FLASH_TCONF = 4;
while (len) {
SFR_FLASH_ADDR16 = flash_region.addr >> 16;
SFR_FLASH_ADDR8 = flash_region.addr >> 8;
SFR_FLASH_ADDR0 = flash_region.addr;
flash_region.addr += 4;
SFR_FLASH_EXEC_GO = 1;
while(SFR_FLASH_EXEC_BUSY);
print_short(SFR_FLASH_DATA0);
if (len == 1)
return;
print_short(SFR_FLASH_DATA8);
if (len == 2)
return;
print_short(SFR_FLASH_DATA16);
if (len == 3)
return;
print_short(SFR_FLASH_DATA24);
len -= 4;
}
}
/* /*
* Reads bulk data of length len from the flash memory starging at address src * Reads bulk data of length len from the flash memory starging at address src
* and writes the data into a buffer pointed to by dst in XMEM * and writes the data into a buffer pointed to by dst in XMEM
@@ -315,7 +288,7 @@ void flash_read_security(void)
if (flash_region.len == 3) if (flash_region.len == 3)
break; break;
print_byte(SFR_FLASH_DATA24); print_byte(SFR_FLASH_DATA24);
write_char(' ');
flash_region.len -= 4; flash_region.len -= 4;
} while(flash_region.len); } while(flash_region.len);
+2
View File
@@ -10,4 +10,6 @@ void flash_read_security(void);
void flash_sector_erase(void); void flash_sector_erase(void);
void flash_read_bulk(__xdata uint8_t *dst); void flash_read_bulk(__xdata uint8_t *dst);
void flash_write_bytes(__xdata uint8_t *ptr); void flash_write_bytes(__xdata uint8_t *ptr);
__code char* get_flash_size_str(void);
#endif #endif
+97 -50
View File
@@ -24,6 +24,8 @@ extern __code uint16_t bit_mask[16];
extern __code const struct machine machine; extern __code const struct machine machine;
extern __xdata struct machine_runtime machine_detected; extern __xdata struct machine_runtime machine_detected;
__xdata struct phy_settings phy_settings;
// SDS-settings for RTL8224 first SerDes which is connected to the RTL837x-SOC. // SDS-settings for RTL8224 first SerDes which is connected to the RTL837x-SOC.
// Array contrains register-value, and SDS-CMD, which already encodes (sds_index, page, reg). // Array contrains register-value, and SDS-CMD, which already encodes (sds_index, page, reg).
// This array is used in phy_config_8224(). // This array is used in phy_config_8224().
@@ -186,106 +188,151 @@ void phy_config_8224(void) __banked
* See e.g. RTL8221B datasheet * See e.g. RTL8221B datasheet
* duplex: 0: half, 1: full, 2: both * duplex: 0: half, 1: full, 2: both
*/ */
void phy_set_speed(uint8_t port, uint8_t speed, uint8_t duplex) __banked void phy_set_speed(void) __banked
{ {
uint16_t v; uint16_t v;
phy_read(port, PHY_MMD31, 0xa610);
print_string("Setting port "); write_char(machine.log_to_phys_port[phy_settings.port] + '0');
if (phy_settings.speed == PHY_OFF) {
print_string(" to disabled");
} else {
print_string(" to speed ");
switch(phy_settings.speed) {
case PHY_SPEED_AUTO:
print_string("auto");
break;
case PHY_SPEED_10M:
print_string("10M");
if (phy_settings.duplex)
print_string(" full duplex");
else
print_string(" half duplex");
break;
case PHY_SPEED_100M:
print_string("100M");
if (phy_settings.duplex)
print_string(" full duplex");
else
print_string(" half duplex");
break;
case PHY_SPEED_1G:
print_string("1G");
break;
case PHY_SPEED_2G5:
print_string("2G5");
break;
default:
print_string("UNKNOWN");
break;
}
}
write_char('\n');
phy_read(phy_settings.port, PHY_MMD31, 0xa610);
v = SFR_DATA_U16; v = SFR_DATA_U16;
if (speed == PHY_OFF) { if (phy_settings.speed == PHY_OFF) {
phy_write(port, PHY_MMD31, 0xa610, v | 0x0800); phy_write(phy_settings.port, PHY_MMD31, 0xa610, v | 0x0800);
return; return;
} }
// Port is on, make sure of it: // Port is on, make sure of it:
if (v & 0x0800) if (v & 0x0800)
phy_write(port, PHY_MMD31, 0xa610, v & 0xf7ff); phy_write(phy_settings.port, PHY_MMD31, 0xa610, v & 0xf7ff);
if (speed == PHY_SPEED_AUTO) { if (phy_settings.speed == PHY_SPEED_AUTO) {
// AN Advertisement Register (MMD 7.0x0010) // AN Advertisement Register (MMD 7.0x0010)
// bits 0-4: 0x1 (802.3 supported), Extended Next Page format used // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x15e1); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x15e1);
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
// bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD
phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081);
// GBCR (1000Base-T Control Register, MMD 31.0xA412) // GBCR (1000Base-T Control Register, MMD 31.0xA412)
phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200); // Loop timing enabled phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200); // Loop timing enabled
phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x3200); // Restart AN phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x3200); // Restart AN
} else { } else {
// AN Control Register (MMD 7.0x0000) // AN Control Register (MMD 7.0x0000)
phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13) phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13)
if (speed == PHY_SPEED_10M) { if (phy_settings.speed == PHY_SPEED_10M) {
phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001);
if (!duplex) if (!phy_settings.duplex)
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1421); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1421);
else if (duplex == 1) else if (phy_settings.duplex == 1)
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1441); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1441);
else else
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1461); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1461);
phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000); phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
} else if (speed == PHY_SPEED_100M) { } else if (phy_settings.speed == PHY_SPEED_100M) {
phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001);
if (!duplex) if (!phy_settings.duplex)
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1481); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1481);
if (duplex == 1) if (phy_settings.duplex == 1)
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1501); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1501);
else else
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1581); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1581);
phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000); phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
} else { } else {
// AN Advertisement Register (MMD 7.0x0010) // AN Advertisement Register (MMD 7.0x0010)
// bits 0-4: 0x1 (802.3 supported), Extended Next Page format used // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1001); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1001);
if (speed == PHY_SPEED_1G) { if (phy_settings.speed == PHY_SPEED_1G) {
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
// bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed
phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001);
// GBCR (1000Base-T Control Register, MMD 31.0xA412) // GBCR (1000Base-T Control Register, MMD 31.0xA412)
phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200); phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200);
} else if (speed == PHY_SPEED_2G5) { } else if (phy_settings.speed == PHY_SPEED_2G5) {
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
// bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed
phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081);
// GBCR (1000Base-T Control Register, MMD 31.0xA412) // GBCR (1000Base-T Control Register, MMD 31.0xA412)
phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000); phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
} }
} }
phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x3000); // Enable AN phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x3000); // Enable AN
} }
} }
void phy_set_duplex(uint8_t port, uint8_t fullduplex) __banked void phy_set_duplex(void) __banked
{ {
uint16_t v; uint16_t v;
phy_read(port, PHY_MMD31, PHY_ANEG_CTRL);
print_string("Setting port "); write_char(machine.log_to_phys_port[phy_settings.port] + '0');
if (phy_settings.duplex)
print_string(" to full duplex");
else
print_string(" to half duplex");
write_char('\n');
phy_read(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL);
v = SFR_DATA_U16; v = SFR_DATA_U16;
if (!(v & 0x1000)) { // AN disabled, we are in forced mode if (!(v & 0x1000)) { // AN disabled, we are in forced mode
phy_read(port, PHY_MMD31, PHY_MMD31_FEDCR); phy_read(phy_settings.port, PHY_MMD31, PHY_MMD31_FEDCR);
v = SFR_DATA_U16; v = SFR_DATA_U16;
if (fullduplex) if (phy_settings.duplex)
v |= 0x0100; v |= 0x0100;
else else
v &= 0xfeff; v &= 0xfeff;
phy_write(port, PHY_MMD31, PHY_MMD31_FEDCR, v); phy_write(phy_settings.port, PHY_MMD31, PHY_MMD31_FEDCR, v);
return; return;
} }
// Disable AN // Disable AN
phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x2000); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x2000);
phy_read(port, PHY_MMD_AN, PHY_ANEG_ADV); phy_read(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV);
v = SFR_DATA_U16; v = SFR_DATA_U16;
if (v & 0x0060) { if (v & 0x0060) {
if (fullduplex) if (phy_settings.duplex)
phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffbf, 0x0040); phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffbf, 0x0040);
else else
phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffdf, 0x0020); phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffdf, 0x0020);
} }
if (v & 0x0180) { if (v & 0x0180) {
if (fullduplex) if (phy_settings.duplex)
phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xfeff, 0x0100); phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xfeff, 0x0100);
else else
phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xff7f, 0x0080); phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xff7f, 0x0080);
} }
// Restart AN // Restart AN
phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x3000); phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x3000);
} }
@@ -327,7 +374,7 @@ void phy_show(uint8_t port) __banked
else else
print_string(" half duplex"); print_string(" half duplex");
phy_read(port, PHY_MMD31, PHY_ANEG_CTRL); phy_read(port, PHY_MMD_AN, PHY_ANEG_CTRL);
v = SFR_DATA_U16; v = SFR_DATA_U16;
if (!(v & 0x1000)) { // AN disabled, we are in forced mode if (!(v & 0x1000)) { // AN disabled, we are in forced mode
phy_read(port, PHY_MMD_PMAPMD, 0); phy_read(port, PHY_MMD_PMAPMD, 0);
+10 -2
View File
@@ -10,11 +10,19 @@
#define PHY_SPEED_AUTO 0x10 #define PHY_SPEED_AUTO 0x10
#define PHY_OFF 0xff #define PHY_OFF 0xff
struct phy_settings {
uint8_t duplex;
uint8_t port;
uint8_t speed;
};
extern __xdata struct phy_settings phy_settings;
void rtl8224_phy_enable(void) __banked; void rtl8224_phy_enable(void) __banked;
void phy_config(uint8_t phy) __banked; void phy_config(uint8_t phy) __banked;
void phy_config_8224(void) __banked; void phy_config_8224(void) __banked;
void phy_set_speed(uint8_t port, uint8_t speed, uint8_t duplex) __banked; void phy_set_speed(void) __banked;
void phy_set_duplex(uint8_t port, uint8_t fullduplex) __banked; void phy_set_duplex(void) __banked;
void phy_show(uint8_t port) __banked; void phy_show(uint8_t port) __banked;
void phy_reset(uint8_t port) __banked; void phy_reset(uint8_t port) __banked;
void rtl8224_read_reg_u16(uint16_t reg) __banked; void rtl8224_read_reg_u16(uint16_t reg) __banked;
+72 -18
View File
@@ -28,6 +28,8 @@ extern __xdata struct machine_runtime machine_detected;
__xdata uint32_t l2_head; __xdata uint32_t l2_head;
__xdata struct vlan_settings vlan_settings;
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked
{ {
print_string("\nport_mirror_set called \n"); print_string("\nport_mirror_set called \n");
@@ -46,7 +48,7 @@ void port_mirror_del(void) __banked
} }
void port_ingress_filter(register uint8_t port, uint8_t type) __banked void port_ingress_filter(__xdata uint8_t port, __xdata uint8_t type) __banked
{ {
if (type & 0x1) if (type & 0x1)
reg_bit_set(RTL837x_REG_INGRESS, port << 1); reg_bit_set(RTL837x_REG_INGRESS, port << 1);
@@ -121,27 +123,31 @@ __xdata uint16_t vlan_name(register uint16_t vlan) __banked
/* /*
* Create a VLAN
* The arguments are passed in global structure vlan_settings
* A member that is not tagged, is untagged * A member that is not tagged, is untagged
*/ */
void vlan_create(register uint16_t vlan, register uint16_t members, register uint16_t tagged) __banked void vlan_create(void) __banked
{ {
// For now, the CPU-port is always a tagged member: // For now, the CPU-port is always a tagged member:
members |= 0x0200; // Set 10th bit vlan_settings.members |= 0x0200; // Set 10th bit
tagged |= 0x0200; vlan_settings.tagged |= 0x0200;
print_string("\nvlan_create called\nvlan: "); print_short(vlan);
print_string(", members: "); print_short(members); print_string("\nvlan_create called\nvlan: "); print_short(vlan_settings.vlan);
print_string(", tagged: "); print_short(tagged); write_char('\n'); print_string(", members: "); print_short(vlan_settings.members);
print_string(", tagged: "); print_short(vlan_settings.tagged); write_char('\n');
uint16_t a = (~vlan_settings.members) ^ vlan_settings.tagged ^ vlan_settings.members;
uint16_t a = (~members) ^ tagged ^ members;
// On RTL8372, port-bits 0-2 must be 0, although they are not members // On RTL8372, port-bits 0-2 must be 0, although they are not members
if (!machine_detected.isRTL8373) { if (!machine_detected.isRTL8373) {
a &= 0x1f8; a &= 0x1f8;
tagged &= 0x3f8; vlan_settings.tagged &= 0x3f8;
} }
// Initialize VLAN table with VLAN 1 // Initialize VLAN table with VLAN 1
REG_WRITE(RTL837x_TBL_DATA_IN_A, 0x02, (a >> 6) & 0x0f, (a << 2) | (members >> 8), members); REG_WRITE(RTL837x_TBL_DATA_IN_A, 0x02, (a >> 6) & 0x0f, (a << 2) | (vlan_settings.members >> 8), vlan_settings.members);
REG_WRITE(RTL837X_TBL_CTRL, vlan >> 8, vlan, TBL_VLAN, TBL_WRITE | TBL_EXECUTE); REG_WRITE(RTL837X_TBL_CTRL, vlan_settings.vlan >> 8, vlan_settings.vlan, TBL_VLAN, TBL_WRITE | TBL_EXECUTE);
do { do {
reg_read_m(RTL837X_TBL_CTRL); reg_read_m(RTL837X_TBL_CTRL);
} while (sfr_data[3] & TBL_EXECUTE); } while (sfr_data[3] & TBL_EXECUTE);
@@ -363,15 +369,28 @@ void port_stats_print(void) __banked
} }
} }
uint8_t b = 0;
// Determine link state
reg_read_m(RTL837X_REG_LINKS_STS);
if(!((sfr_data[(i / 8) + 1] >> ( i % 8 ) & 1)))
{
b = 99;
}
else
{
if (i < 8) if (i < 8)
reg_read_m(RTL837X_REG_LINKS); reg_read_m(RTL837X_REG_LINKS);
else else
reg_read_m(RTL837X_REG_LINKS_89); reg_read_m(RTL837X_REG_LINKS_89);
uint8_t b = sfr_data[3 - ((i & 7) >> 1)];
b = sfr_data[3 - ((i & 7) >> 1)];
b = (i & 1) ? b >> 4 : b & 0xf; b = (i & 1) ? b >> 4 : b & 0xf;
}
switch (b) { switch (b) {
case 0: case 0:
print_string("Down\t"); print_string("10M\t");
break; break;
case 1: case 1:
print_string("100M\t"); print_string("100M\t");
@@ -385,6 +404,9 @@ void port_stats_print(void) __banked
case 5: case 5:
print_string("2.5G\t"); print_string("2.5G\t");
break; break;
case 99:
print_string("Down\t");
break;
default: default:
print_string("Up\t"); print_string("Up\t");
break; break;
@@ -422,17 +444,49 @@ uint16_t port_isolation_get(register uint8_t port)
} }
void port_eee_enable(uint8_t port) __banked void port_eee_enable(__xdata uint8_t port,__xdata uint8_t speed) __banked
{ {
if (machine.is_sfp[port])
return;
if (machine.is_sfp[port])
{
print_string("EEE can't be enabled for SFP port "); print_byte(port); print_string("\n");
return;
}
print_string("EEE on for "); print_byte(port); print_string(" speed ");
// Enable all speeds up to the specified speed
if ((speed & (EEE_100 | EEE_1000 | EEE_2G5)) == EEE_100) {
print_string("100m\n");
REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100);
// Enable EEE advertisement for 100BASE-T via EEE Advertisement Reg
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_100M);
if (!(speed & EEE_NORESET))
phy_reset(port);
return;
}
if ((speed & (EEE_100 | EEE_1000 | EEE_2G5)) == EEE_1000) {
print_string("1g\n");
REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000);
// Disable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, 0);
// Enable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_1G | PHY_EEE_BIT_100M);
if (!(speed & EEE_NORESET))
phy_reset(port);
return;
}
if ((speed & (EEE_100 | EEE_1000 | EEE_2G5)) == EEE_2G5) {
print_string("2g5\n");
REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000 | EEE_2G5); REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000 | EEE_2G5);
// Enable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg // Enable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_1G | PHY_EEE_BIT_100M); phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_1G | PHY_EEE_BIT_100M);
// Enable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2 // Enable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, PHY_EEE_BIT_2G5); phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, PHY_EEE_BIT_2G5);
if (!(speed & EEE_NORESET))
phy_reset(port); phy_reset(port);
return;
}
} }
@@ -506,10 +560,10 @@ void port_eee_status(uint8_t port) __banked
} }
void port_eee_enable_all(void) __banked void port_eee_enable_all(__xdata uint8_t speed) __banked
{ {
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
port_eee_enable(i); port_eee_enable(i, speed);
} }
} }
+12 -4
View File
@@ -13,6 +13,14 @@
reg_read_m(RTL837X_STAT_GET); \ reg_read_m(RTL837X_STAT_GET); \
} while (sfr_data[3] & 0x1); } while (sfr_data[3] & 0x1);
struct vlan_settings {
uint16_t vlan;
uint16_t members;
uint16_t tagged;
};
extern __xdata struct vlan_settings vlan_settings;
uint8_t port_l2_forget(void) __banked; uint8_t port_l2_forget(void) __banked;
void port_l2_learned(void) __banked; void port_l2_learned(void) __banked;
void port_stats_print(void) __banked; void port_stats_print(void) __banked;
@@ -20,18 +28,18 @@ int8_t vlan_get(register uint16_t vlan) __banked;
__xdata uint16_t vlan_name(register uint16_t vlan) __banked; __xdata uint16_t vlan_name(register uint16_t vlan) __banked;
void vlan_setup(void) __banked; void vlan_setup(void) __banked;
void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked; void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked;
void vlan_create(register uint16_t vlan, register uint16_t members, register uint16_t tagged) __banked; void vlan_create(void) __banked;
void vlan_delete(uint16_t vlan) __banked; void vlan_delete(uint16_t vlan) __banked;
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked; void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked;
void port_mirror_del(void) __banked; void port_mirror_del(void) __banked;
void port_ingress_filter(register uint8_t port, uint8_t type) __banked; void port_ingress_filter(__xdata uint8_t port, __xdata uint8_t type) __banked;
void port_l2_setup(void) __banked; void port_l2_setup(void) __banked;
void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked; void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked;
void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash) __banked; void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash) __banked;
void port_eee_enable_all(void) __banked; void port_eee_enable_all(__xdata uint8_t speed) __banked;
void port_eee_disable_all(void) __banked; void port_eee_disable_all(void) __banked;
void port_eee_status_all(void) __banked; void port_eee_status_all(void) __banked;
void port_eee_enable(uint8_t port) __banked; void port_eee_enable(__xdata uint8_t port, __xdata uint8_t speed) __banked;
void port_eee_disable(uint8_t port) __banked; void port_eee_disable(uint8_t port) __banked;
void port_eee_status(uint8_t port) __banked; void port_eee_status(uint8_t port) __banked;
#endif #endif
+24
View File
@@ -3,6 +3,8 @@
#define RTL837X_REG_CHIP_ID 0x0004 #define RTL837X_REG_CHIP_ID 0x0004
#define RTL837X_REG_CHIP_INFO 0x000c #define RTL837X_REG_CHIP_INFO 0x000c
#define RTL837X_REG_CHIP_UUID 0x0010
#define RTL837X_REG_CHIP_LOT_NO 0x0014
#define RTL837X_REG_RESET 0x0024 #define RTL837X_REG_RESET 0x0024
#define RESET_SOC_BIT 0 #define RESET_SOC_BIT 0
#define RESET_NIC_BIT 2 #define RESET_NIC_BIT 2
@@ -78,6 +80,8 @@
#define RTL837X_REG_LINKS 0x63f0 #define RTL837X_REG_LINKS 0x63f0
#define RTL837X_REG_LINKS_89 0x63f4 #define RTL837X_REG_LINKS_89 0x63f4
#define RTL837X_REG_LINKS_STS 0x63E8
/* Each nibble encodes the link state of a port. /* Each nibble encodes the link state of a port.
Port 0 appears to be the CPU port Port 0 appears to be the CPU port
The RTL8372 serves ports 4-7, port 3 is the RTL8221 The RTL8372 serves ports 4-7, port 3 is the RTL8221
@@ -271,6 +275,7 @@
#define EEE_100 0x01 #define EEE_100 0x01
#define EEE_1000 0x04 #define EEE_1000 0x04
#define EEE_2G5 0x10 #define EEE_2G5 0x10
#define EEE_NORESET 0x80
/* /*
* RANDOM * RANDOM
@@ -280,6 +285,25 @@
#define RTL837X_RAND_NUM0 0x107C #define RTL837X_RAND_NUM0 0x107C
#define RTL837X_RAND_NUM1 0x1080 #define RTL837X_RAND_NUM1 0x1080
/*
* Bandwidth control
*/
#define RTL837X_IGBW_CTRL 0x4c10
#define IGBW_INC_BYPASS_PKT 0x100
#define IGBW_INC_IFG 0x80
#define IGBW_ADM_DHCP 0x20
#define IGBW_ADM_ARPREQ 0x10
#define IGBW_ADM_RMA 0x08
#define IGBW_ADM_BPDU 0x04
#define IGBW_ADM_RTKPKT 0x02
#define IGBW_ADM_IGMP 0x01
#define RTL837X_IGBW_PORT_CTRL 0x4C18
#define RTL837X_IGBW_PORT_FC_CTRL 0x4C8C
#define RTL837X_EGBW_PORT_CTRL 0x1c34
#define RTL837X_EGBW_CTRL 0x447c
#define EGBW_INC_IFG 0x02
#define EGBW_CPUMODE 0x01
#ifdef REGDBG #ifdef REGDBG
#define REG_SET(r, v) SFR_DATA_24 = (((uint32_t)v) >> 24) & 0xff; \ #define REG_SET(r, v) SFR_DATA_24 = (((uint32_t)v) >> 24) & 0xff; \
+3
View File
@@ -40,6 +40,9 @@ __sfr __at(0x91) EXIF;
__sfr __at(0xf8) EIP; __sfr __at(0xf8) EIP;
__sbit __at(0xf9) PX3; __sbit __at(0xf9) PX3;
/* MPAGE page (sdcc _XPAGE) register for "movx @Ri" */
__sfr __at(0x92) _XPAGE; /* _XPAGE is used by sdcc in xstack mode */
__sfr __at(0x92) MPAGE;
/* SFR Bank control register: 0x0-3f. A value of 0 is bank 1 */ /* SFR Bank control register: 0x0-3f. A value of 0 is bank 1 */
__sfr __at(0x96) PSBANK; __sfr __at(0x96) PSBANK;
// SFR used to store return bank for trampoline // SFR used to store return bank for trampoline
+4 -4
View File
@@ -17,7 +17,7 @@
extern __code struct machine machine; extern __code struct machine machine;
extern __xdata uint8_t sfr_data[4]; extern __xdata uint8_t sfr_data[4];
extern __code struct uip_eth_addr uip_ethaddr; extern __xdata struct uip_eth_addr uip_ethaddr;
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2]; extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2];
@@ -164,9 +164,9 @@ void stp_cnf_send(uint8_t port)
STP_O->bpdu_type = 0x00; // Config STP_O->bpdu_type = 0x00; // Config
STP_O->flags = 0x81; STP_O->flags = 0x81;
memcpyc(STP_O->src_addr, uip_ethaddr.addr, 6); memcpy(STP_O->src_addr, uip_ethaddr.addr, 6);
memcpy(STP_O->root.mac, root_bridge.mac, 6); memcpy(STP_O->root.mac, root_bridge.mac, 6);
memcpyc(STP_O->bridge.mac, uip_ethaddr.addr, 6); memcpy(STP_O->bridge.mac, uip_ethaddr.addr, 6);
STP_O->root.prio = root_bridge.prio; STP_O->root.prio = root_bridge.prio;
STP_O->root.ext = 0x00; STP_O->root.ext = 0x00;
@@ -221,7 +221,7 @@ void stp_setup(void) __banked
root_bridge.prio = 0x80; // This corresponds to 32768 root_bridge.prio = 0x80; // This corresponds to 32768
root_bridge.ext = 0x00; root_bridge.ext = 0x00;
memcpyc(root_bridge.mac, uip_ethaddr.addr, 6); memcpy(root_bridge.mac, uip_ethaddr.addr, 6);
} }
+260 -159
View File
@@ -14,25 +14,23 @@
#include "rtl837x_stp.h" #include "rtl837x_stp.h"
#include "rtl837x_igmp.h" #include "rtl837x_igmp.h"
#include "rtl837x_leds.h" #include "rtl837x_leds.h"
#include "rtl837x_bandwidth.h"
#include "dhcp.h" #include "dhcp.h"
#include "cmd_parser.h" #include "cmd_parser.h"
#include "cmd_editor.h"
#include "uip/uipopt.h" #include "uip/uipopt.h"
#include "uip/uip.h" #include "uip/uip.h"
#include "uip/uip_arp.h" #include "uip/uip_arp.h"
#include "machine.h" #include "machine.h"
#include "phy.h" #include "phy.h"
extern __code const struct machine machine; extern __code const struct machine machine;
extern __xdata uint32_t flash_size;
extern __xdata uint16_t crc_value; extern __xdata uint16_t crc_value;
__xdata uint8_t crc_testbytes[10];
__xdata struct machine_runtime machine_detected; __xdata struct machine_runtime machine_detected;
void crc16(__xdata uint8_t *v) __naked; void crc16(__xdata uint8_t *v) __naked;
// Upload Firmware to 1M
#define FIRMWARE_UPLOAD_START 0x100000
// See setup_serial_timer1() for valid baudrate settings! // See setup_serial_timer1() for valid baudrate settings!
#define SERIAL_BAUD_RATE 115200 #define SERIAL_BAUD_RATE 115200
@@ -77,10 +75,11 @@ void crc16(__xdata uint8_t *v) __naked;
__xdata uint8_t idle_ready; __xdata uint8_t idle_ready;
__code uint8_t ownIP[] = { 192, 168, 2, 2 }; __code uint8_t ownIP[] = { 192, 168, 2, 2 };
__code struct uip_eth_addr uip_ethaddr = {{ 0x1c, 0x2a, 0xa3, 0x23, 0x00, 0x02 }};
__code uint8_t gatewayIP[] = { 192, 168, 2, 22}; __code uint8_t gatewayIP[] = { 192, 168, 2, 22};
__code uint8_t netmask[] = { 255, 255, 255, 0}; __code uint8_t netmask[] = { 255, 255, 255, 0};
__xdata struct uip_eth_addr uip_ethaddr;
volatile __xdata uint32_t ticks; volatile __xdata uint32_t ticks;
volatile __xdata uint8_t sec_counter; volatile __xdata uint8_t sec_counter;
volatile __xdata uint16_t sleep_ticks; volatile __xdata uint16_t sleep_ticks;
@@ -89,10 +88,13 @@ extern __xdata struct dhcp_state dhcp_state;
#define STP_TICK_DIVIDER 3 #define STP_TICK_DIVIDER 3
/* Buffer for serial input, SBUF_SIZE must be power of 2 < 256
// Buffer for serial input, SBUF_SIZE must be power of 2 < 256 * Writing to this buffer is under the sole control of the serial ISR
* Note that key-presses such as <cursor-left> can create multiple
* keys being sent via the serial line */
__xdata volatile uint8_t sbuf_ptr; __xdata volatile uint8_t sbuf_ptr;
__xdata uint8_t sbuf[SBUF_SIZE]; __xdata uint8_t sbuf[SBUF_SIZE];
__xdata uint8_t sfr_data[4]; __xdata uint8_t sfr_data[4];
extern __xdata uint8_t gpio_last_value[8]; extern __xdata uint8_t gpio_last_value[8];
@@ -102,7 +104,7 @@ extern __xdata struct flash_region_t flash_region;
__code uint8_t * __code greeting = "\nA minimal prompt to explore the RTL8372:\n"; __code uint8_t * __code greeting = "\nA minimal prompt to explore the RTL8372:\n";
__code uint8_t * __code hex = "0123456789abcdef"; __code uint8_t * __code hex = "0123456789abcdef";
__xdata uint8_t flash_buf[512]; __xdata uint8_t flash_buf[FLASH_BUF_SIZE];
// NIC buffers for packet RX/TX // NIC buffers for packet RX/TX
__xdata uint8_t rx_headers[16]; // Packet header(s) on RX __xdata uint8_t rx_headers[16]; // Packet header(s) on RX
@@ -127,6 +129,8 @@ __xdata char sfp_module_vendor[2][17];
__xdata char sfp_module_model[2][17]; __xdata char sfp_module_model[2][17];
__xdata char sfp_module_serial[2][17]; __xdata char sfp_module_serial[2][17];
__xdata uint8_t sfp_options[2]; __xdata uint8_t sfp_options[2];
__xdata bool button_last;
__xdata uint8_t button_sec_counter_last;
__sbit tx_buf_empty; __sbit tx_buf_empty;
#define ETHERTYPE_OFFSET (12 + VLAN_TAG_SIZE + RTL_TAG_SIZE) #define ETHERTYPE_OFFSET (12 + VLAN_TAG_SIZE + RTL_TAG_SIZE)
@@ -237,6 +241,7 @@ uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s)
return dst - b; return dst - b;
} }
uint16_t strlen(register __code const char *s) uint16_t strlen(register __code const char *s)
{ {
uint16_t l = 0; uint16_t l = 0;
@@ -257,27 +262,44 @@ uint16_t strlen_x(register __xdata const char *s)
void print_short(uint16_t a) void print_short(uint16_t a)
{ {
// allocating the registers first improves the sdcc code here
uint8_t h = a >> 8;
uint8_t l = a;
print_string("0x"); print_string("0x");
for (signed char i = 12; i >= 0; i -= 4) { print_byte(h);
write_char(hex[(a >> i) & 0xf]); print_byte(l);
}
} }
void print_long(uint32_t a)
void print_long(__xdata uint32_t a)
{ {
// allocating the registers first improves the sdcc code here
uint8_t a24 = a >> 24;
uint8_t a16 = a >> 16;
uint8_t a8 = a >> 8;
uint8_t a0 = a;
print_string("0x"); print_string("0x");
for (signed char i = 28; i >= 0; i -= 4) { print_byte(a24);
write_char(hex[(a >> i) & 0xf]); print_byte(a16);
} print_byte(a8);
print_byte(a0);
} }
void print_byte(uint8_t a) void print_byte(uint8_t a)
{ {
write_char(hex[(a >> 4) & 0xf]); char high = (a >> 4) + '0';
write_char(hex[a & 0xf]); if (high > '9') {
high += 'a' - ('0' + 10);
} }
write_char(high);
char low = (a & 0xf) + '0';
if (low > '9') {
low += 'a' - ('0' + 10);
}
write_char(low);
}
/* /*
* External IRQ 0 Service Routine: Called on link change? * External IRQ 0 Service Routine: Called on link change?
@@ -435,6 +457,23 @@ void reg_bit_clear(uint16_t reg_addr, char bit)
reg_write_m(reg_addr); reg_write_m(reg_addr);
} }
/*
* This sets a bit in the 32bit wide switch register reg_addr
*/
uint8_t reg_bit_test(uint16_t reg_addr, char bit)
{
uint8_t bit_mask = 1 << (bit & 0x7);
bit >>= 3;
reg_read_m(reg_addr);
bit_mask = bit_mask;
if (sfr_data[3-bit] & bit_mask)
return 1;
return 0;
}
/* /*
* This masks the sfr data fields, first &-ing with ~mask, then setting the bits in set * This masks the sfr data fields, first &-ing with ~mask, then setting the bits in set
*/ */
@@ -545,16 +584,6 @@ uint8_t read_flash(uint8_t bank, __code uint8_t *addr)
return v; return v;
} }
void print_long_x(__xdata uint8_t v[])
{
write_char('0'); write_char('x');
for (uint8_t i=0; i < 4; i++) {
write_char(hex[v[i] >> 4]);
write_char(hex[v[i] & 0xf]);
}
}
/* /*
* Read a SerDes register in the SoC * Read a SerDes register in the SoC
* Input must be: sds_id = 0/1, page < 128, reg <= 0xff * Input must be: sds_id = 0/1, page < 128, reg <= 0xff
@@ -601,14 +630,10 @@ void print_sfr_data(void)
{ {
write_char('0'); write_char('0');
write_char('x'); write_char('x');
write_char(hex[sfr_data[0] >> 4]); print_byte(sfr_data[0]);
write_char(hex[sfr_data[0] & 0xf]); print_byte(sfr_data[1]);
write_char(hex[sfr_data[1] >> 4]); print_byte(sfr_data[2]);
write_char(hex[sfr_data[1] & 0xf]); print_byte(sfr_data[3]);
write_char(hex[sfr_data[2] >> 4]);
write_char(hex[sfr_data[2] & 0xf]);
write_char(hex[sfr_data[3] >> 4]);
write_char(hex[sfr_data[3] & 0xf]);
} }
@@ -616,10 +641,8 @@ void print_phy_data(void)
{ {
write_char('0'); write_char('0');
write_char('x'); write_char('x');
write_char(hex[SFR_DATA_8 >> 4]); print_byte(SFR_DATA_8);
write_char(hex[SFR_DATA_8 & 0xf]); print_byte(SFR_DATA_0);
write_char(hex[SFR_DATA_0 >> 4]);
write_char(hex[SFR_DATA_0 & 0xf]);
} }
@@ -926,13 +949,12 @@ void handle_rx(void)
if (uip_len) { if (uip_len) {
tcpip_output(); tcpip_output();
} }
} else if (uip_buf[ETHERTYPE_OFFSET] == 0x08 && uip_buf[ETHERTYPE_OFFSET + 1] == 0x00) { // TCP? } else if (uip_buf[ETHERTYPE_OFFSET] == 0x08 && uip_buf[ETHERTYPE_OFFSET + 1] == 0x00) { // IP packet?
if (!management_vlan || management_vlan == rx_packet_vlan) { if (!management_vlan || management_vlan == rx_packet_vlan) {
uip_arp_ipin(); // Learn MAC addresses in TCP packets uip_arp_ipin(); // Learn MAC addresses in TCP packets
uip_input(); uip_input();
if (uip_len) { if (uip_len) {
// Add ethernet frame uip_arp_out(); // Add ethernet frame
uip_arp_out();
tcpip_output(); tcpip_output();
} }
} }
@@ -1063,6 +1085,72 @@ void handle_sfp(void)
} }
} }
void flash_default_config(void)
{
__xdata uint32_t source = DEFAULT_CONFIG_START;
__xdata uint32_t dest = CONFIG_START;
flash_region.addr = CONFIG_START;
flash_sector_erase();
for (uint8_t i = 0; i < 8; i++) // 8 * 512 Byte = 4 kByte (1 sector)
{
flash_region.addr = source;
flash_region.len = FLASH_BUF_SIZE;
flash_read_bulk(flash_buf);
flash_region.addr = dest;
flash_region.len = FLASH_BUF_SIZE;
flash_write_bytes(flash_buf);
dest += FLASH_BUF_SIZE;
source += FLASH_BUF_SIZE;
}
print_string("Written default config to flash\n");
}
void handle_button(void)
{
if (machine.reset_pin == GPIO_NA) {
return;
}
bool button_pressed = !gpio_pin_test(machine.reset_pin);
if (button_last != button_pressed)
{
print_string(button_pressed ? "Button pressed\n" : "Button released\n");
reg_read_m(RTL837X_REG_SEC_COUNTER);
uint8_t diff_sec_counter = sfr_data[3] - button_sec_counter_last;
button_last = button_pressed;
button_sec_counter_last = sfr_data[3];
if (!button_pressed)
{
if (diff_sec_counter > 10)
{
print_string(">10s button detected; reverting to default settings:\n");
flash_default_config();
print_string("Now resetting...\n");
reset_chip();
}
else if (diff_sec_counter > 3)
{
print_string(">3s button detected; resetting chip...\n");
reset_chip();
}
else
{
print_string("Short button press detected; no action.\n");
set_sys_led_state(SYS_LED_ON);
}
}
else
{
// Give the user feedback for button press
set_sys_led_state(SYS_LED_SLOW);
}
}
}
// //
// An idle function that sleeps for 1 tick and does all the house-keeping // An idle function that sleeps for 1 tick and does all the house-keeping
// //
@@ -1095,6 +1183,10 @@ void idle(void)
} }
reg_write_m(RTL837X_REG_SEC_COUNTER); reg_write_m(RTL837X_REG_SEC_COUNTER);
reg_read_m(RTL837X_REG_SEC_COUNTER); reg_read_m(RTL837X_REG_SEC_COUNTER);
// Check for button presses once a second
handle_button();
#ifdef DEBUG #ifdef DEBUG
print_sfr_data(); print_sfr_data();
write_char('\n'); write_char('\n');
@@ -1134,11 +1226,6 @@ void idle(void)
// Check for changes with SFP modules // Check for changes with SFP modules
handle_sfp(); handle_sfp();
/* Button pressed on KL-8xhm-x2:
reg_read(RTL837X_REG_GPIO_32_63_INPUT);
if (!(sfr_data[2] & 0x40))
print_string("Button pressed\n");
*/
// Check new Packets RX // Check new Packets RX
handle_rx(); handle_rx();
// Check UIP for packets to transmit // Check UIP for packets to transmit
@@ -1553,6 +1640,9 @@ void rtl8373_init(void)
reg_bit_set(RTL837X_REG_HW_CONF, 0); reg_bit_set(RTL837X_REG_HW_CONF, 0);
// enable EEE for all ports at 2.5G and 10G, but don't reset the PHYs
port_eee_enable_all(EEE_2G5 | EEE_NORESET);
// TODO: patch the PHYs // TODO: patch the PHYs
// Re-enable PHY after configuration // Re-enable PHY after configuration
@@ -1614,6 +1704,10 @@ void rtl8372_init(void)
reg_bit_set(RTL837X_REG_HW_CONF, 0); reg_bit_set(RTL837X_REG_HW_CONF, 0);
// enable EEE for all ports at 2.5G and 10G, but don't reset the PHYs
port_eee_enable_all(EEE_2G5 | EEE_NORESET);
// TODO: patch the PHYs // TODO: patch the PHYs
// Re-enable PHY after configuration // Re-enable PHY after configuration
@@ -1792,7 +1886,92 @@ void setup_i2c(void)
} }
void bootloader(void) void check_and_flash_update_image(void)
{
flash_read_jedecid(); // This initializes also __xdata flash_size variable
print_string(get_flash_size_str()); print_string(" flash size detected. (1 MB is needed for image updating)\n");
if (flash_size < FIRMWARE_UPLOAD_START*2) {
print_string("Flash too small for updating; skipping update check\n");
return;
}
print_string("Checking for update image in flash... ");
// Check if an update image is in flash
flash_region.addr = FIRMWARE_UPLOAD_START;
flash_region.len = 0x100;
flash_read_bulk(flash_buf);
if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40)
{
// Yes, flash the new image to the start of flash and reset
__xdata uint32_t dest = 0x0;
__xdata uint32_t source = FIRMWARE_UPLOAD_START;
__xdata uint16_t i = 0;
__xdata uint16_t j = 0;
__xdata uint8_t * __xdata bptr;
print_string("found update image! Checking integrity");
flash_init(0); // Re-initialize flash for non-DIO operation, otherwise flashing will fail
set_sys_led_state(SYS_LED_FAST);
crc_value = 0x0000;
for (i = 0; i < 1024; i++) {
flash_region.addr = source;
flash_region.len = FLASH_BUF_SIZE;
flash_read_bulk(flash_buf);
bptr = flash_buf;
for (j = 0; j < FLASH_BUF_SIZE; j++) {
crc16(bptr++);
}
source += FLASH_BUF_SIZE;
if (i%16 == 0) write_char('.');
}
if (crc_value == 0xb001) {
print_string("Checksum OK.\nUpdate in progress, moving firmware to start of flash");
source = FIRMWARE_UPLOAD_START;
// Don't copy the config area at the end of flash
for (i = 0; i < CONFIG_START/FLASH_BUF_SIZE; i++) {
flash_region.addr = source;
flash_region.len = FLASH_BUF_SIZE;
flash_read_bulk(flash_buf);
if (i%8 == 0) {
flash_region.addr = dest;
flash_sector_erase();
if (i%16 == 0) write_char('.');
}
flash_region.addr = dest;
flash_region.len = FLASH_BUF_SIZE;
flash_write_bytes(flash_buf);
dest += FLASH_BUF_SIZE;
source += FLASH_BUF_SIZE;
}
print_string("Done.\nDeleting uploaded flash image");
dest = FIRMWARE_UPLOAD_START;
for (register uint8_t i=0; i < 128; i++) // TODO: Erasing the entire 512kByte upload area is probably not necessary
{
flash_region.addr = dest;
flash_sector_erase();
dest += 0x1000;
if (i%4 == 0) write_char('.');
}
print_string("Done.\nResetting now");
delay(200);
reset_chip();
}
print_string("Checksum incorrect, please upload the image again\n");
print_string("Erasing bad uploaded flash image\n");
dest = FIRMWARE_UPLOAD_START;
for (register uint8_t i=0; i < 128; i++) {
flash_region.addr = dest;
flash_sector_erase();
dest += 0x1000;
}
}
else
{
print_string("no update image found.\n");
}
}
void main(void)
{ {
ticks = 0; ticks = 0;
stp_clock = STP_TICK_DIVIDER; stp_clock = STP_TICK_DIVIDER;
@@ -1829,6 +2008,9 @@ void bootloader(void)
// We have not detected any link // We have not detected any link
linkbits_last[0] = linkbits_last[1] = linkbits_last[2] = linkbits_last[3] = linkbits_last_p89 = 0; linkbits_last[0] = linkbits_last[1] = linkbits_last[2] = linkbits_last[3] = linkbits_last_p89 = 0;
button_last = 0;
button_sec_counter_last = 0;
machine_detected.isRTL8373 = 0; machine_detected.isRTL8373 = 0;
machine_detected.isN = 0; machine_detected.isN = 0;
print_string("Detecting CPU: RTL837"); print_string("Detecting CPU: RTL837");
@@ -1865,97 +2047,44 @@ void bootloader(void)
uip_ipaddr(&uip_hostaddr, ownIP[0], ownIP[1], ownIP[2], ownIP[3]); uip_ipaddr(&uip_hostaddr, ownIP[0], ownIP[1], ownIP[2], ownIP[3]);
uip_ipaddr(&uip_draddr, gatewayIP[0], gatewayIP[1], gatewayIP[2], gatewayIP[3]); uip_ipaddr(&uip_draddr, gatewayIP[0], gatewayIP[1], gatewayIP[2], gatewayIP[3]);
uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]); uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]);
reg_read_m(RTL837X_REG_CHIP_UUID);
#ifdef DEBUG
print_string("SoC UUID: "); print_sfr_data();
#endif
uip_ethaddr.addr[0] = 0x06; // LAA prefix
uip_ethaddr.addr[3] = sfr_data[0] ^ sfr_data[3];
uip_ethaddr.addr[4] = sfr_data[1] ^ sfr_data[3];
uip_ethaddr.addr[5] = sfr_data[2] ^ sfr_data[3];
reg_read_m(RTL837X_REG_CHIP_LOT_NO);
#ifdef DEBUG
print_string(", LOT: "); print_sfr_data(); write_char(' ');
#endif
uip_ethaddr.addr[1] = sfr_data[0] ^ sfr_data[2];
uip_ethaddr.addr[2] = sfr_data[1] ^ sfr_data[3];
print_string("Setting MAC to: ");
print_byte(uip_ethaddr.addr[0]); write_char(':'); print_byte(uip_ethaddr.addr[1]); write_char(':');
print_byte(uip_ethaddr.addr[2]); write_char(':'); print_byte(uip_ethaddr.addr[3]); write_char(':');
print_byte(uip_ethaddr.addr[4]); write_char(':'); print_byte(uip_ethaddr.addr[5]); write_char('\n');
REG_SET(RTL837X_PIN_MUX_2, 0x0); // Disable pins for ACL REG_SET(RTL837X_PIN_MUX_2, 0x0); // Disable pins for ACL
init_smi(); init_smi();
rtl8373_revision(); rtl8373_revision();
leds_setup(); leds_setup();
machine_custom_init();
leds_dump(); leds_dump();
set_sys_led_state(SYS_LED_SLOW);
if (machine_detected.isRTL8373) if (machine_detected.isRTL8373)
rtl8373_init(); rtl8373_init();
else else
rtl8372_init(); rtl8372_init();
delay(1000); delay(1000);
// Check update in progress and move blocks check_and_flash_update_image();
flash_region.addr = FIRMWARE_UPLOAD_START;
flash_region.len = 0x100;
flash_read_bulk(flash_buf);
#ifndef MACHINE_HG0402XG_V1_1
if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40) {
__xdata uint32_t dest = 0x0;
__xdata uint32_t source = FIRMWARE_UPLOAD_START;
__xdata uint16_t i = 0;
__xdata uint16_t j = 0;
__xdata uint8_t * __xdata bptr;
print_string("Identified update image. Checking integrity...");
flash_init(0); // Re-initialize flash for non-DIO operation, otherwise flashing will fail
set_sys_led_state(SYS_LED_FAST);
crc_value = 0x0000;
for (i = 0; i < 1024; i++) {
flash_region.addr = source;
flash_region.len = 0x200;
flash_read_bulk(flash_buf);
bptr = flash_buf;
for (j = 0; j < 0x200; j++) {
// print_byte(*bptr); write_char(' ');
crc16(bptr++);
// print_short(crc_value); write_char(':');
}
source += 0x200;
// write_char('\n'); print_short(crc_value); write_char(' ');
if (i%16 == 0)
write_char('.');
}
if (crc_value == 0xb001) {
print_string("\nChecksum OK\n");
print_string("Update in progress, moving firmware to start of FLASH.");
source = FIRMWARE_UPLOAD_START;
// A 512kByte = 4MBit Flash has 128*8=1024 512byte blocks, we copy only 896
// (don't overwrite config @ 0x700000)
for (i = 0; i < 896; i++) {
// print_string("Writing block: ");
// print_short(dest);
flash_region.addr = source;
flash_region.len = 0x200;
flash_read_bulk(flash_buf);
if (!(i & 0x7)) {
flash_region.addr = dest;
flash_sector_erase();
write_char('.');
}
flash_region.addr = dest;
flash_region.len = 0x200;
flash_write_bytes(flash_buf);
dest += 0x200;
source += 0x200;
}
print_string("\nDeleting uploaded flash image\n");
dest = FIRMWARE_UPLOAD_START;
for (register uint8_t i=0; i < 128; i++) {
flash_region.addr = dest;
flash_sector_erase();
dest += 0x1000;
}
print_string("Resetting now");
delay(200);
reset_chip();
}
print_string("Checksum incorrect, please upload the image again\n");
print_string("Erasing bad uploaded flash image\n");
dest = FIRMWARE_UPLOAD_START;
for (register uint8_t i=0; i < 128; i++) {
flash_region.addr = dest;
flash_sector_erase();
dest += 0x1000;
}
}
#endif
set_sys_led_state(SYS_LED_SLOW);
#ifdef DEBUG #ifdef DEBUG
// This register seems to work on the RTL8373 only if also the SDS // This register seems to work on the RTL8373 only if also the SDS
@@ -1979,6 +2108,7 @@ void bootloader(void)
vlan_setup(); vlan_setup();
port_l2_setup(); port_l2_setup();
igmp_setup(); igmp_setup();
bandwidth_setup();
uip_init(); uip_init();
uip_arp_init(); uip_arp_init();
httpd_init(); httpd_init();
@@ -1986,6 +2116,7 @@ void bootloader(void)
management_vlan = 0; // Disabled management_vlan = 0; // Disabled
setup_i2c(); setup_i2c();
setup_sfp_gpio();
print_string(greeting); print_string(greeting);
@@ -2004,39 +2135,9 @@ void bootloader(void)
set_sys_led_state(SYS_LED_ON); set_sys_led_state(SYS_LED_ON);
// Wait for commands on serial connection cmd_editor_init();
// sbuf_ptr is moved forward by serial interrupt, l is the position until we have already
// printed out the entered characters
__xdata uint8_t l = sbuf_ptr; // We have printed out entered characters until l
__xdata uint8_t line_start = sbuf_ptr; // This is where the current line starts
cmd_available = 0;
while (1) { while (1) {
while (l != sbuf_ptr) { cmd_edit();
// If the command buffer is currently in use, we cannot copy to it
if (cmd_available)
break;
write_char(sbuf[l]);
// Check whether there is a full line:
if (sbuf[l] == '\n' || sbuf[l] == '\r') {
write_char('\n');
register uint8_t i = 0;
while (line_start != l) {
cmd_buffer[i++] = sbuf[line_start++];
line_start &= (SBUF_SIZE - 1);
}
line_start++;
line_start &= (SBUF_SIZE - 1);
cmd_buffer[i] = '\0';
// If there is a command we print the prompt after execution
// otherwise immediately because there is nothing to execute
if (i)
cmd_available = 1;
else
print_string("\n> ");
}
l++;
l &= (SBUF_SIZE - 1);
}
idle(); // Enter Idle mode until interrupt occurs idle(); // Enter Idle mode until interrupt occurs
} }
} }
+61 -4
View File
@@ -15,7 +15,7 @@
#define PASSWORD "1234" #define PASSWORD "1234"
#define SESSION_TIMEOUT 2000 #define SESSION_TIMEOUT 2000
#define PORTS 9 #define PORTS 6
#define NSFP 1 #define NSFP 1
#define N_COUNTERS 52 #define N_COUNTERS 52
@@ -121,7 +121,8 @@ void send_basic_info(int socket)
{ {
char *response = "HTTP/1.1 200 OK\r\n" char *response = "HTTP/1.1 200 OK\r\n"
"Content-Type: application/json; charset=UTF-8\r\n\r\n" "Content-Type: application/json; charset=UTF-8\r\n\r\n"
"{\"ip_address\":\"192.168.10.247\",\"ip_gateway\":\"192.168.2.22\",\"ip_netmask\":\"255.255.255.0\",\"mac_address\":\"1c:2a:a3:23:00:02\",\"sw_ver\":\"" VERSION_SW "\",\"hw_ver\":\"SWGT024-V2.0\"}"; "{\"ip_address\":\"192.168.10.247\",\"ip_gateway\":\"192.168.2.22\",\"ip_netmask\":\"255.255.255.0\",\"mac_address\":\"1c:2a:a3:23:00:02\",\"sw_ver\":\"" VERSION_SW "\",\"hw_ver\":\"SWGT024-V2.0\""
",\"dhcp_client\":1,\"dhcp_server\":0}";
write(socket, response, strlen(response)); write(socket, response, strlen(response));
} }
@@ -229,7 +230,7 @@ void send_status(int s)
void send_counters(int s, int port) void send_counters(int s, int port)
{ {
struct json_object *v, *counters; struct json_object *counters;
const char *jstring; const char *jstring;
char *header = "HTTP/1.1 200 OK\r\n" char *header = "HTTP/1.1 200 OK\r\n"
"Cache-Control: no-cache\r\n" "Cache-Control: no-cache\r\n"
@@ -239,7 +240,6 @@ void send_counters(int s, int port)
counters = json_object_new_array_ext(N_COUNTERS); counters = json_object_new_array_ext(N_COUNTERS);
for (int i = 0; i < N_COUNTERS; i++) { for (int i = 0; i < N_COUNTERS; i++) {
v = json_object_new_object();
sprintf(counter_buf, "0x%016lx", 0x1234UL + i); sprintf(counter_buf, "0x%016lx", 0x1234UL + i);
json_object_array_add(counters, json_object_new_string(counter_buf)); json_object_array_add(counters, json_object_new_string(counter_buf));
} }
@@ -283,6 +283,56 @@ void send_eee(int s)
} }
void send_bandwidth(int s)
{
struct json_object *ports, *v;
const char *jstring;
uint32_t bw;
int limited, fcEnabled;
char *header = "HTTP/1.1 200 OK\r\n"
"Content-Type: application/json; charset=UTF-8\r\n\r\n";
ports = json_object_new_array_ext(PORTS);
for (int i = 1; i <= PORTS; i++) {
v = json_object_new_object();
json_object_object_add(v, "portNum", json_object_new_int(i));
if (i % 2) {
limited = 1;
fcEnabled = i % 4 ? 1 : 0;
bw = 0x100;
} else {
limited = 0;
fcEnabled = 0;
bw = 0xfffff;
}
char bw_buf[20];
sprintf(bw_buf, "%08x", bw);
json_object_object_add(v, "iLimited", json_object_new_int(limited));
json_object_object_add(v, "iFC", json_object_new_int(fcEnabled));
json_object_object_add(v, "iBW", json_object_new_string(bw_buf));
if (i % 4) {
limited = 1;
bw = 0x1000;
} else {
limited = 0;
bw = 0xfffff;
}
sprintf(bw_buf, "%08x", bw);
json_object_object_add(v, "eLimited", json_object_new_int(limited));
json_object_object_add(v, "eBW", json_object_new_string(bw_buf));
json_object_array_add(ports, v);
}
write(s, header, strlen(header));
jstring = json_object_to_json_string_ext(ports, JSON_C_TO_STRING_PLAIN);
write(s, jstring, strlen(jstring));
json_object_put(ports);
}
void send_mirror(int s) void send_mirror(int s)
{ {
uint16_t mirror_tx, mirror_rx = 0; uint16_t mirror_tx, mirror_rx = 0;
@@ -593,6 +643,13 @@ void launch(struct Server *server)
else else
send_eee(new_socket); send_eee(new_socket);
goto done; goto done;
} else if (!strncmp(&buffer[4], "/bandwidth.json", 15)) {
printf("Bandwidth request\n");
if (!authenticated)
send_unauthorized(new_socket);
else
send_bandwidth(new_socket);
goto done;
} else if (!strncmp(&buffer[4], "/information.json", 17)) { } else if (!strncmp(&buffer[4], "/information.json", 17)) {
printf("Status request\n"); printf("Status request\n");
if (!authenticated) if (!authenticated)
+4
View File
@@ -106,6 +106,10 @@ int main(int argc, char **argv)
printf("Error reading input file.\n"); printf("Error reading input file.\n");
return 5; return 5;
} }
if (buffer[0] != 2) {
printf("Expected LJMP at offset 0.\n");
return 5;
}
for (int b = BANK0_SIZE; b < BANK_STRIDE + BANK0_SIZE; b ++) { for (int b = BANK0_SIZE; b < BANK_STRIDE + BANK0_SIZE; b ++) {
if (buffer[b]) { if (buffer[b]) {
printf("WARNING: Bank 0: code segment too large at 0x%x!\n", b); printf("WARNING: Bank 0: code segment too large at 0x%x!\n", b);
+1 -1
View File
@@ -5,7 +5,7 @@ AFLAGS= -plosgff
BUILDDIR = output/ BUILDDIR = output/
SRCS = timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-neighbor.c uip-split.c SRCS = timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-split.c
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel} OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
all: create_build_dir $(OBJS) all: create_build_dir $(OBJS)
+6 -4
View File
@@ -132,8 +132,6 @@ static __code const uip_ipaddr_t all_zeroes_addr =
{0x0000,0x0000}; {0x0000,0x0000};
#endif /* UIP_CONF_IPV6 */ #endif /* UIP_CONF_IPV6 */
extern __code struct uip_eth_addr uip_ethaddr;
#ifndef UIP_CONF_EXTERNAL_BUFFER #ifndef UIP_CONF_EXTERNAL_BUFFER
u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains
incoming packets. */ incoming packets. */
@@ -921,7 +919,7 @@ uip_process(u8_t flag) __banked
/* Check if we have a DHCP packet, otherwise check if the packet is destined for our IP address. */ /* Check if we have a DHCP packet, otherwise check if the packet is destined for our IP address. */
#if !UIP_CONF_IPV6 #if !UIP_CONF_IPV6
if(!(BUF->proto == UIP_PROTO_UDP && UDPBUF->destport == HTONS(DHCPC_CLIENT_PORT))) { if(!(BUF->proto == UIP_PROTO_UDP && (UDPBUF->destport == HTONS(DHCP_CLIENT_PORT) || UDPBUF->destport == HTONS(DHCP_SERVER_PORT)) )) {
if(!uip_ipaddr_cmpx(BUF->destipaddr, uip_hostaddr)) { if(!uip_ipaddr_cmpx(BUF->destipaddr, uip_hostaddr)) {
UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.drop);
goto drop; goto drop;
@@ -940,7 +938,11 @@ uip_process(u8_t flag) __banked
} }
#endif /* UIP_CONF_IPV6 */ #endif /* UIP_CONF_IPV6 */
} }
// If we serve only the designated DHCPD-VLAN, we drop the packet if not in that VLAN
if(BUF->proto == UIP_PROTO_UDP && dhcpd_vlan && UDPBUF->destport == HTONS(DHCP_SERVER_PORT) && dhcpd_vlan != rx_packet_vlan) {
UIP_STAT(++uip_stat.ip.drop);
goto drop;
}
#if !UIP_CONF_IPV6 #if !UIP_CONF_IPV6
// if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header // if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
// checksum. */ // checksum. */
+43 -21
View File
@@ -93,7 +93,7 @@ struct arp_hdr_o {
u16_t dipaddr[2]; u16_t dipaddr[2];
}; };
struct ethip_hdr { struct ethip_hdr_o {
struct uip_eth_hdr ethhdr; struct uip_eth_hdr ethhdr;
/* IP header. */ /* IP header. */
u8_t vhl, u8_t vhl,
@@ -106,6 +106,24 @@ struct ethip_hdr {
u16_t ipchksum; u16_t ipchksum;
u16_t srcipaddr[2], u16_t srcipaddr[2],
destipaddr[2]; destipaddr[2];
u16_t sport, dport;
};
struct ethip_hdr_i {
struct uip_eth_hdr ethhdr;
struct rtl_tag rtl_tag;
/* IP header. */
u8_t vhl,
tos,
len[2],
ipid[2],
ipoffset[2],
ttl,
proto;
u16_t ipchksum;
u16_t srcipaddr[2],
destipaddr[2];
u16_t sport, dport;
}; };
#define ARP_REQUEST 1 #define ARP_REQUEST 1
@@ -132,7 +150,8 @@ static __xdata u8_t tmpage;
#define BUF ((__xdata struct arp_hdr_i *)&uip_buf[0]) #define BUF ((__xdata struct arp_hdr_i *)&uip_buf[0])
#define BUF_O ((__xdata struct arp_hdr_o *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE]) #define BUF_O ((__xdata struct arp_hdr_o *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE])
#define IPBUF ((__xdata struct ethip_hdr *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE]) #define IPBUF_I ((__xdata struct ethip_hdr_i *)&uip_buf[0])
#define IPBUF_O ((__xdata struct ethip_hdr_o *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE])
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/** /**
* Initialize the ARP module. * Initialize the ARP module.
@@ -238,27 +257,26 @@ uip_arp_update(__xdata u16_t *ipaddr, __xdata struct uip_eth_addr *ethaddr)
* variable uip_len. * variable uip_len.
*/ */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
#if 0
void void
uip_arp_ipin(void) uip_arp_ipin(void) __banked
{ {
uip_len -= sizeof(struct uip_eth_hdr); uip_len -= sizeof(struct uip_eth_hdr);
/* Only insert/update an entry if the source IP address of the /* Only insert/update an entry if the source IP address of the
incoming IP packet comes from a host on the local network. */ incoming IP packet comes from a host on the local network. */
if((IPBUF->srcipaddr[0] & uip_netmask[0]) != if((IPBUF_I->srcipaddr[0] & uip_netmask[0]) !=
(uip_hostaddr[0] & uip_netmask[0])) { (uip_hostaddr[0] & uip_netmask[0])) {
return; return;
} }
if((IPBUF->srcipaddr[1] & uip_netmask[1]) != if((IPBUF_I->srcipaddr[1] & uip_netmask[1]) !=
(uip_hostaddr[1] & uip_netmask[1])) { (uip_hostaddr[1] & uip_netmask[1])) {
return; return;
} }
uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); uip_arp_update(IPBUF_I->srcipaddr, &(IPBUF_I->ethhdr.src));
return; return;
} }
#endif /* 0 */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/** /**
* ARP processing for incoming ARP packets. * ARP processing for incoming ARP packets.
@@ -302,12 +320,11 @@ uip_arp_arpin(void) __banked
with this host in the future. */ with this host in the future. */
uip_arp_update(BUF->sipaddr, &BUF->shwaddr); uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
/* The reply opcode is 2. */ BUF_O->opcode = HTONS(ARP_REPLY);
BUF_O->opcode = HTONS(2);
memcpy(BUF_O->dhwaddr.addr, BUF->shwaddr.addr, 6); memcpy(BUF_O->dhwaddr.addr, BUF->shwaddr.addr, 6);
memcpyc(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6); memcpy(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6);
memcpyc(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6); memcpy(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6);
memcpy(BUF_O->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); memcpy(BUF_O->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
BUF_O->dipaddr[0] = BUF->sipaddr[0]; BUF_O->dipaddr[0] = BUF->sipaddr[0];
@@ -371,19 +388,24 @@ uip_arp_out(void) __banked
If not ARP table entry is found, we overwrite the original IP If not ARP table entry is found, we overwrite the original IP
packet with an ARP request for the IP address. */ packet with an ARP request for the IP address. */
if (IPBUF_O->sport == 0x4300 && !IPBUF_O->destipaddr[0] && !IPBUF_O->destipaddr[1]) {
IPBUF_O->destipaddr[0] = 0xffff;
IPBUF_O->destipaddr[1] = 0xffff;
IPBUF_O->dport = 0x4400;
}
/* First check if destination is a local broadcast. */ /* First check if destination is a local broadcast. */
if(uip_ipaddr_cmpc(IPBUF->destipaddr, broadcast_ipaddr)) { if(uip_ipaddr_cmpc(IPBUF_O->destipaddr, broadcast_ipaddr)) {
memcpyc(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6); memcpyc(IPBUF_O->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
} else { } else {
/* Check if the destination address is on the local network. */ /* Check if the destination address is on the local network. */
if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) { if(!uip_ipaddr_maskcmp(IPBUF_O->destipaddr, uip_hostaddr, uip_netmask)) {
/* Destination address was not on the local network, so we need to /* Destination address was not on the local network, so we need to
use the default router's IP address instead of the destination use the default router's IP address instead of the destination
address when determining the MAC address. */ address when determining the MAC address. */
uip_ipaddr_copy(ipaddr, uip_draddr); uip_ipaddr_copy(ipaddr, uip_draddr);
} else { } else {
/* Else, we use the destination IP address. */ /* Else, we use the destination IP address. */
uip_ipaddr_copy(ipaddr, IPBUF->destipaddr); uip_ipaddr_copy(ipaddr, IPBUF_O->destipaddr);
} }
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
@@ -399,8 +421,8 @@ uip_arp_out(void) __banked
memset(BUF_O->ethhdr.dest.addr, 0xff, 6); memset(BUF_O->ethhdr.dest.addr, 0xff, 6);
memset(BUF_O->dhwaddr.addr, 0x00, 6); memset(BUF_O->dhwaddr.addr, 0x00, 6);
memcpyc(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6); memcpy(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6);
memcpyc(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6); memcpy(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6);
uip_ipaddr_copy(BUF_O->dipaddr, ipaddr); uip_ipaddr_copy(BUF_O->dipaddr, ipaddr);
uip_ipaddr_copy(BUF_O->sipaddr, uip_hostaddr); uip_ipaddr_copy(BUF_O->sipaddr, uip_hostaddr);
@@ -418,11 +440,11 @@ uip_arp_out(void) __banked
} }
/* Build an ethernet header. */ /* Build an ethernet header. */
memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); memcpy(IPBUF_O->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
} }
memcpyc(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); memcpy(IPBUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6);
IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); IPBUF_O->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
uip_len += sizeof(struct uip_eth_hdr); uip_len += sizeof(struct uip_eth_hdr);
} }
+2 -4
View File
@@ -55,8 +55,6 @@
#include "uip.h" #include "uip.h"
#include "../rtl837x_common.h" #include "../rtl837x_common.h"
extern __code struct uip_eth_addr uip_ethaddr;
/** /**
* The Ethernet header. * The Ethernet header.
*/ */
@@ -80,8 +78,8 @@ void uip_arp_init(void) __banked;
inserts a new mapping if none exists. The function assumes that an inserts a new mapping if none exists. The function assumes that an
IP packet with an Ethernet header is present in the uip_buf buffer IP packet with an Ethernet header is present in the uip_buf buffer
and that the length of the packet is in the uip_len variable. */ and that the length of the packet is in the uip_len variable. */
/*void uip_arp_ipin(void);*/ void uip_arp_ipin(void) __banked;
#define uip_arp_ipin() // #define uip_arp_ipin()
/* The uip_arp_arpin() should be called when an ARP packet is received /* The uip_arp_arpin() should be called when an ARP packet is received
by the Ethernet driver. This function also assumes that the by the Ethernet driver. This function also assumes that the