Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1400431337 | ||
|
|
119b5ddf13 | ||
|
|
231b43b264 | ||
|
|
e53ebddc21 | ||
|
|
f23eb6bebb | ||
|
|
cd51cffb1d | ||
|
|
01fc5db9a3 | ||
|
|
bdca888ecd | ||
|
|
e8431999e5 | ||
|
|
7ca4d2c8dc | ||
|
|
32dd21bbd3 | ||
|
|
92f9025109 | ||
|
|
b65aa82d78 | ||
|
|
851eb39344 | ||
|
|
970e98f4c5 | ||
|
|
4d009bc8e8 | ||
|
|
eb51128ec7 | ||
|
|
b86fd37eaa | ||
|
|
b92a773cad | ||
|
|
068e7467af | ||
|
|
da4f5058a7 | ||
|
|
fee4f17bff | ||
|
|
e19271fc44 | ||
|
|
aff6ac0923 | ||
|
|
7e11be0d97 | ||
|
|
23862bc648 | ||
|
|
6c62791d23 | ||
|
|
413690a748 | ||
|
|
3910888052 | ||
|
|
a0cb3c1850 | ||
|
|
73bb4c8af2 | ||
|
|
0443ba428b | ||
|
|
62abd08aa2 | ||
|
|
70426ff24a | ||
|
|
2d62cc493d | ||
|
|
bbce2d6727 | ||
|
|
36de7b7241 | ||
|
|
ea320d813d | ||
|
|
ca2abcc4e1 | ||
|
|
4d7159092c | ||
|
|
98763e3bff | ||
|
|
80a30b705e | ||
|
|
4c3e1fde81 | ||
|
|
5cd14e6227 | ||
|
|
5105018d90 | ||
|
|
5bc7cf43db | ||
|
|
c776d10129 | ||
|
|
7b4d0d55d2 | ||
|
|
e95e450813 | ||
|
|
fe1d4119d0 | ||
|
|
c5f62bff95 | ||
|
|
7535c0d9b7 | ||
|
|
a57319557d | ||
|
|
1b29fb687f | ||
|
|
2e62f9eea7 | ||
|
|
5c6a82d50f | ||
|
|
1d158d21d1 | ||
|
|
26c420d26a | ||
|
|
eb394af95f | ||
|
|
4a4caeffd7 | ||
|
|
391360f517 | ||
|
|
ed8e4b1a56 | ||
|
|
78f28488c1 | ||
|
|
e1c79ec4cd | ||
|
|
a7db0ca8b6 | ||
|
|
70f59b64f5 | ||
|
|
f0cbaba7b1 | ||
|
|
2d5424fedc | ||
|
|
23c8b2a8b3 | ||
|
|
c9f6362da5 | ||
|
|
742aef5461 | ||
|
|
a77d219baf | ||
|
|
f94204e56f | ||
|
|
8d6adedb56 | ||
|
|
c3f9acea10 | ||
|
|
c46261e052 | ||
|
|
834403b97b | ||
|
|
48087d3520 | ||
|
|
1d359afba5 | ||
|
|
ec14dbf323 | ||
|
|
deedb92c5d | ||
|
|
a18c334139 | ||
|
|
337b171ac4 | ||
|
|
53eb3f5486 | ||
|
|
241edfdbda | ||
|
|
714c9eb343 | ||
|
|
f2c89fd75b | ||
|
|
ca2f1d101d | ||
|
|
9cc859ad30 | ||
|
|
0181276ec6 | ||
|
|
905e588071 | ||
|
|
bb16302a80 | ||
|
|
50fda40fd9 | ||
|
|
9c65039bab | ||
|
|
7e0bc93b55 | ||
|
|
e1e1292ab0 | ||
|
|
975caaff02 | ||
|
|
cffe4793b1 | ||
|
|
9ed1e89c8b | ||
|
|
ba2f759df3 | ||
|
|
884a1ac016 | ||
|
|
51ed063dcb | ||
|
|
0da6318777 | ||
|
|
d13a5d125d | ||
|
|
889c94404c | ||
|
|
0f98734ae2 | ||
|
|
2d0abbbca0 | ||
|
|
fdcdfa9b45 | ||
|
|
c043c671d7 | ||
|
|
11a24783e4 | ||
|
|
e864c32980 | ||
|
|
bb329daab0 | ||
|
|
89c8903454 | ||
|
|
63a3bc50d6 | ||
|
|
a94be7d524 | ||
|
|
50be5308d9 | ||
|
|
9731a33fa9 | ||
|
|
c3dddd9c90 | ||
|
|
6e5617c82f | ||
|
|
6638748e3c | ||
|
|
98965b73f6 | ||
|
|
ef0d9d872e | ||
|
|
7d7585fa6d | ||
|
|
13801241ca | ||
|
|
94ca35f65e | ||
|
|
69714c8a75 | ||
|
|
2bc6939f86 | ||
|
|
aea537f8e7 | ||
|
|
7346977f91 | ||
|
|
7b0a07efaa | ||
|
|
3c00ab0ae9 | ||
|
|
7673ef8322 | ||
|
|
c9e8403c6e | ||
|
|
3deee14f94 | ||
|
|
6d539bfb1b | ||
|
|
7a44d8181f | ||
|
|
d698e180e4 | ||
|
|
566e26ace2 | ||
|
|
674dc23a27 | ||
|
|
620edafd62 | ||
|
|
413d10bbcc | ||
|
|
0faceab1d0 | ||
|
|
7e12f0a62c | ||
|
|
491a919105 | ||
|
|
2588965eee | ||
|
|
827d3b389c | ||
|
|
ef224ec8f4 | ||
|
|
0a3d7d360a | ||
|
|
9561f239b4 | ||
|
|
b06ff76a21 | ||
|
|
b28ead65dc | ||
|
|
a079c803d9 | ||
|
|
cc3ae654a0 | ||
|
|
2a9f9b2508 | ||
|
|
57d6337940 | ||
|
|
3b58eb36e5 | ||
|
|
34c0ef77d0 | ||
|
|
e6182dbe0d | ||
|
|
1d5e4cd722 | ||
|
|
a02116a24b | ||
|
|
98369c37fe | ||
|
|
d104b3129d | ||
|
|
138acfadb1 | ||
|
|
08f8498b39 | ||
|
|
dd521cc79d | ||
|
|
723d16b4cb | ||
|
|
2c2349dcef | ||
|
|
6d1380fb36 | ||
|
|
eacf13690c | ||
|
|
a1998c70d7 | ||
|
|
4ed74f05db | ||
|
|
0de18ff457 | ||
|
|
3195a14870 | ||
|
|
3ffb311e95 | ||
|
|
f0c672418c | ||
|
|
41ed689ae0 | ||
|
|
11eadc5a49 | ||
|
|
24d2cd7bab | ||
|
|
28c09737b2 | ||
|
|
3e1d3f40d2 | ||
|
|
389dc2af76 | ||
|
|
4963fbe50a | ||
|
|
44b5ab0e64 | ||
|
|
088321deaf | ||
|
|
3af1b049ee | ||
|
|
6a5d3cdf2c | ||
|
|
d21ea52c46 | ||
|
|
c6cc3ee595 | ||
|
|
424a963301 | ||
|
|
1344e02fb7 | ||
|
|
2ae297bc20 | ||
|
|
ce77cc273d | ||
|
|
6376a10288 | ||
|
|
a202842107 | ||
|
|
6fad2836ae | ||
|
|
2415015a87 | ||
|
|
d9fc20addf | ||
|
|
c15b2d48da | ||
|
|
f17ca1c9fc | ||
|
|
be5dee04e3 | ||
|
|
196d22d7c3 | ||
|
|
496ac8b757 | ||
|
|
bf670aed0b | ||
|
|
6af5580433 | ||
|
|
6194356f66 | ||
|
|
bd56c1a8c5 | ||
|
|
d562fd661e | ||
|
|
0b6b613c03 | ||
|
|
f325bdbd11 | ||
|
|
680a40dab5 | ||
|
|
97b15f4022 | ||
|
|
c263a8ab64 | ||
|
|
d5ccd38dd3 | ||
|
|
adecc26ae2 | ||
|
|
44ae7a8d3b | ||
|
|
c3fc541339 | ||
|
|
6fdb19f18c | ||
|
|
70f8964918 | ||
|
|
aba58e7f99 | ||
|
|
2404e7a9b6 | ||
|
|
6a31b4a279 | ||
|
|
6cd1f683bb | ||
|
|
7e90f6a126 | ||
|
|
9bd301447b | ||
|
|
9745dfe6ae | ||
|
|
d4345c1bf8 | ||
|
|
fcaacd4429 | ||
|
|
0f63244ca1 | ||
|
|
913e9780b8 | ||
|
|
0d748fa808 | ||
|
|
bd974e0aaf | ||
|
|
56686185ce | ||
|
|
ed069b67fd | ||
|
|
b1026490a8 | ||
|
|
28ea2184c2 | ||
|
|
d5f84cc2fb | ||
|
|
682ac462c4 | ||
|
|
ecc8356f4d | ||
|
|
3a8d1d323f | ||
|
|
e125ebd097 | ||
|
|
4050555667 | ||
|
|
8224b06f9e | ||
|
|
69151362a0 | ||
|
|
24e83d5b74 | ||
|
|
e890e429a5 | ||
|
|
813a62ca7d | ||
|
|
b096efd63a | ||
|
|
3d81df0cad | ||
|
|
2481810906 | ||
|
|
03311debe6 | ||
|
|
e4adec9c11 | ||
|
|
8a7c847ad9 | ||
|
|
b94d2aeabc | ||
|
|
d525229b42 | ||
|
|
73b23808cf | ||
|
|
4a14f50932 | ||
|
|
1bfe632174 | ||
|
|
265a80bb25 | ||
|
|
64efd3fb9f | ||
|
|
2e6425f5e6 | ||
|
|
6bae5c5c90 | ||
|
|
c2980e42d8 | ||
|
|
1856aeba28 | ||
|
|
4e4a2ea4db | ||
|
|
4ccbf51976 | ||
|
|
0df48fbb1c | ||
|
|
25040070e5 | ||
|
|
edf6351d85 | ||
|
|
c3b4cc893b | ||
|
|
b83b67d234 | ||
|
|
efd61be64e | ||
|
|
875933b9f9 | ||
|
|
0e85137e7a | ||
|
|
da7909f422 | ||
|
|
14b2ce1c49 | ||
|
|
84d9408151 | ||
|
|
c02f660c08 | ||
|
|
05c0571154 | ||
|
|
8790f0dca4 | ||
|
|
98af999304 | ||
|
|
0a996fa6d0 | ||
|
|
441e575661 | ||
|
|
a27118a428 | ||
|
|
01709431dc | ||
|
|
de0d413c0c | ||
|
|
b3ac10cae7 | ||
|
|
4e00f5a592 | ||
|
|
eff3f42ae1 | ||
|
|
dda873a633 | ||
|
|
9b2bd7f1b8 | ||
|
|
2dfe531fe0 | ||
|
|
72c2625121 | ||
|
|
58fd1a3ccc | ||
|
|
4f1a2f04d8 | ||
|
|
cedc795b82 | ||
|
|
ccf541a06b | ||
|
|
d5124df89e | ||
|
|
3eacc9c8a5 | ||
|
|
735672ccf1 | ||
|
|
1ebee4d6e9 | ||
|
|
24c0a95734 | ||
|
|
706dea63a2 | ||
|
|
f88f655f5a | ||
|
|
a6b0918885 | ||
|
|
1d6fe690a4 | ||
|
|
e67c928eb7 | ||
|
|
46f8ea8712 | ||
|
|
b0eab52a2e | ||
|
|
8ce062c349 | ||
|
|
f768220a73 | ||
|
|
eab2e26510 | ||
|
|
b0ed56d423 | ||
|
|
36a064d03d | ||
|
|
2d01b8b7d7 | ||
|
|
fa632cdc6e | ||
|
|
177fb76e1b | ||
|
|
ff57084799 | ||
|
|
2dc5520928 | ||
|
|
7c11142a04 | ||
|
|
957a5b0e23 | ||
|
|
c773230a9b | ||
|
|
4f009539b0 | ||
|
|
bb90e0c9ba | ||
|
|
0e9c997d06 | ||
|
|
5ab247e996 | ||
|
|
d80717f3f0 | ||
|
|
24069439b0 | ||
|
|
4117f549cc | ||
|
|
2e24b24426 | ||
|
|
b71239f394 | ||
|
|
6e69f5bba3 | ||
|
|
1224335b66 | ||
|
|
e5b19bc594 | ||
|
|
89fcc6836d | ||
|
|
f9d4ab0074 | ||
|
|
6f68ccef28 | ||
|
|
8e687ef28e | ||
|
|
87db2dd4b8 | ||
|
|
aac1aed4c8 | ||
|
|
f0aea3dcac | ||
|
|
f10ab30f6d | ||
|
|
de431c6d84 | ||
|
|
3cd6d60e0b | ||
|
|
67b8c718fb | ||
|
|
26547f3e01 | ||
|
|
13b75a73c9 | ||
|
|
c6fceae724 | ||
|
|
068ec4c510 | ||
|
|
3a92459190 | ||
|
|
5ffeb3d16a | ||
|
|
de705380c9 | ||
|
|
e4f3315af3 | ||
|
|
07ab04e668 | ||
|
|
c5ce24ff78 | ||
|
|
bcb237158f | ||
|
|
f103daaafa | ||
|
|
168add47a3 | ||
|
|
423886dc54 | ||
|
|
4a9137387c | ||
|
|
2fc08f40d2 | ||
|
|
4a7fd7a098 | ||
|
|
19cd1200b4 | ||
|
|
333adbaf19 | ||
|
|
8051061fd7 | ||
|
|
8ae3f5e70f | ||
|
|
9ce328d155 | ||
|
|
2e463a2f30 | ||
|
|
d0374541c5 | ||
|
|
422dc3f24d | ||
|
|
4b01ff9f8a | ||
|
|
456a4d9d3f | ||
|
|
02e9189f5f | ||
|
|
aff7d9c098 | ||
|
|
770926abd1 | ||
|
|
13f04d8acb | ||
|
|
49284fee15 | ||
|
|
db9ce7543e | ||
|
|
7a14c2d4a5 | ||
|
|
92948079a9 | ||
|
|
e406a3e82b | ||
|
|
c43b955db0 | ||
|
|
0321763e91 | ||
|
|
4bbbcd7d04 | ||
|
|
682ed861fa | ||
|
|
3a9045b97e | ||
|
|
4b9f6c319f | ||
|
|
6e2701bc8c | ||
|
|
ac3b4b17ae | ||
|
|
f87eb70c6a | ||
|
|
214cc6b737 | ||
|
|
40177f6318 | ||
|
|
d3dda09079 | ||
|
|
277e729f2c | ||
|
|
f778b9159b | ||
|
|
b6d6d2391d | ||
|
|
2c231fdf69 | ||
|
|
689751ffe6 | ||
|
|
fa93340c24 | ||
|
|
e9523a2f67 | ||
|
|
088be074f5 | ||
|
|
340fdd97e5 | ||
|
|
09ce4b391b | ||
|
|
7e6577a811 | ||
|
|
675faf0471 | ||
|
|
175ca9464a | ||
|
|
38241f0a08 | ||
|
|
0fe323b12f | ||
|
|
94187461c6 | ||
|
|
fa0eb91586 | ||
|
|
2f872ea08e | ||
|
|
ab2d30a05b | ||
|
|
d37ce07119 | ||
|
|
4bd6ffd083 | ||
|
|
94cfec8693 | ||
|
|
a4bb3f1725 | ||
|
|
931e6da0ab | ||
|
|
88454ec7d7 | ||
|
|
f0efb84abb | ||
|
|
62d3424a92 | ||
|
|
a3860c29cb | ||
|
|
b1961c6955 | ||
|
|
bb84bdc55a | ||
|
|
9733ff61a0 | ||
|
|
1b5243714e | ||
|
|
36459fdd76 | ||
|
|
ce11790a0d | ||
|
|
55431b39f6 | ||
|
|
46e1c955ba | ||
|
|
7b728cec6f | ||
|
|
0d17dd563f | ||
|
|
d556d634ca | ||
|
|
2844a1ed6d | ||
|
|
7b5e365d5e | ||
|
|
45fb382b07 | ||
|
|
8973774594 | ||
|
|
48c5b0c9cf | ||
|
|
1557a7cf3c | ||
|
|
131bc106af | ||
|
|
19ccc4003d | ||
|
|
b5fe9f217f | ||
|
|
f65d14f452 | ||
|
|
b92fba870c | ||
|
|
4deee377a7 | ||
|
|
fe42b07e2b | ||
|
|
9984649177 | ||
|
|
7d47edb649 | ||
|
|
fdb19fe0ee | ||
|
|
b9b50f9a70 | ||
|
|
c31b67572b | ||
|
|
a4e3b4368b | ||
|
|
93003c8cb8 | ||
|
|
fd058ea74d | ||
|
|
edc469fe29 | ||
|
|
a71c5359a5 | ||
|
|
9e3863cc4e | ||
|
|
d22ec04b5b | ||
|
|
0a65536a7f | ||
|
|
0631c813e2 | ||
|
|
eaebeba528 | ||
|
|
b36fd95356 | ||
|
|
52b1d1a4ea | ||
|
|
48f28ae7ff | ||
|
|
a7fc8303e9 | ||
|
|
a62866a93a | ||
|
|
42bbed9661 | ||
|
|
3c8de6da87 | ||
|
|
3a6f62b1d5 | ||
|
|
530e2683f0 | ||
|
|
9fedc6dd3d | ||
|
|
5e23d13771 | ||
|
|
09d5857fdd | ||
|
|
be309853c9 | ||
|
|
072edb36a8 | ||
|
|
10dd330e3c | ||
|
|
c514eb8bf3 | ||
|
|
e2c4ed6be3 | ||
|
|
56ee56af2e | ||
|
|
8626b4c1d4 | ||
|
|
0cc09e4015 | ||
|
|
674dc1f35d | ||
|
|
7e6b443e07 | ||
|
|
73ec184c23 | ||
|
|
bf41fbd202 | ||
|
|
04ab442c6d | ||
|
|
c02623a610 | ||
|
|
c69bf4c5ec | ||
|
|
575274786a | ||
|
|
7f4f6dae03 | ||
|
|
4eeb12c020 | ||
|
|
7d81b15b6e | ||
|
|
d6253ddc25 | ||
|
|
8cac67cdf7 | ||
|
|
5620e950ce | ||
|
|
83491bc9e3 | ||
|
|
eb83b8be09 | ||
|
|
bece4a20a1 | ||
|
|
cdc84c75e4 | ||
|
|
6be1871bb4 | ||
|
|
4686515de3 | ||
|
|
c39cc421a7 | ||
|
|
c1df7c23d1 | ||
|
|
9bae4052a3 | ||
|
|
0d115e0e0b | ||
|
|
8e78d1e629 | ||
|
|
13cc9db1ce | ||
|
|
3dcab09047 | ||
|
|
94992562fd | ||
|
|
6150ada5f8 | ||
|
|
8116ef0a5b | ||
|
|
0cd56b1196 | ||
|
|
3b3f36256c | ||
|
|
18b28edcbb | ||
|
|
6ea9503ab2 | ||
|
|
e0df37f359 | ||
|
|
c04a5fc3a4 | ||
|
|
f0b311fc43 | ||
|
|
2f005d2993 | ||
|
|
974052877d | ||
|
|
ae77ffe495 | ||
|
|
f65416f0d1 | ||
|
|
ffde4eaf60 | ||
|
|
c05d83132b | ||
|
|
dcd3cd5a98 | ||
|
|
9f107b6e60 | ||
|
|
15b10d9ed0 | ||
|
|
abf1cd1344 | ||
|
|
b5b52776bc | ||
|
|
0486c34bfd | ||
|
|
690092d564 | ||
|
|
115ea09ebb | ||
|
|
f3e1a393b5 | ||
|
|
206c72b5ef | ||
|
|
472811cc9a | ||
|
|
80552816b9 | ||
|
|
c1caf6f569 | ||
|
|
ddad65fe90 | ||
|
|
ff7b517491 | ||
|
|
65417433eb | ||
|
|
b7621fad31 | ||
|
|
82f78cb8f2 | ||
|
|
75f2ade1a1 | ||
|
|
3e91b05a42 | ||
|
|
ec1cb4106d | ||
|
|
62c6c65f1c | ||
|
|
c691591295 | ||
|
|
eb4bae278b | ||
|
|
7908044a44 | ||
|
|
0ec1a5e63f | ||
|
|
114af559c7 | ||
|
|
3ec9319d77 | ||
|
|
8d7faf5312 | ||
|
|
552bd1cb18 |
No files matched your search
@@ -3,6 +3,7 @@
|
||||
.gitattributes
|
||||
.github/
|
||||
output/
|
||||
toolchain/
|
||||
installer/output/
|
||||
*.bin
|
||||
html_data.c
|
||||
|
||||
@@ -3,6 +3,12 @@ name: Build firmware
|
||||
on:
|
||||
push:
|
||||
branches: ['**']
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -12,12 +18,41 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: branch
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: main
|
||||
ref: main
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt update
|
||||
apt install make gcc sdcc xxd python-is-python3 libjson-c-dev zlib1g-dev -y
|
||||
- name: Check if machine.c can be compiled for all machines
|
||||
run: make machine_check
|
||||
- name: Make project
|
||||
run: make MACHINE="KP_9000_6XHML_X2"
|
||||
apt install make gcc g++ bison flex libboost-dev patch bzip2 curl ca-certificates xxd python-is-python3 libjson-c-dev zlib1g-dev -y
|
||||
- name: Cache the patched SDCC
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: branch/toolchain
|
||||
key: sdcc-${{ hashFiles('branch/sdcc/*') }}
|
||||
- name: Run the host-side unit tests
|
||||
run: cd branch && make -C test
|
||||
- name: Check that every machine definition can be compiled
|
||||
run: cd branch && make machine_check
|
||||
- name: Make project (4x2/RTL8372)
|
||||
run: cd branch && make CI=1 MACHINE="KP_9000_6XHML_X2" && cp output/KP_9000_6XHML_X2/rtlplayground.map /tmp/branch.map
|
||||
- name: Make project (8x1/RTL8373)
|
||||
run: cd branch && make CI=1 MACHINE="KP_9000_9XHML_X_V3_1"
|
||||
- name: Make project with the health instrumentation
|
||||
run: cd branch && make clean && make CI=1 MACHINE="KP_9000_6XHML_X2" HEALTH=1
|
||||
- name: Make main
|
||||
run: |
|
||||
ln -s ../branch/toolchain main/toolchain
|
||||
PATH="$(echo "$PWD"/branch/toolchain/sdcc-*/bin):$PATH"
|
||||
cd main && make CI=1 MACHINE="KP_9000_6XHML_X2" && cp output/KP_9000_6XHML_X2/rtlplayground.map /tmp/main.map
|
||||
- name: Calculate bank growth
|
||||
run: |
|
||||
sed -rn 's/^([XCD]SEG|(BANK[0-9])).*=\s+([0-9]+)\. bytes.*$/MAIN_\1=\3/p' /tmp/main.map | sort -u >> "$GITHUB_ENV"
|
||||
sed -rn 's/^([XCD]SEG|(BANK[0-9])).*=\s+([0-9]+)\. bytes.*$/BRANCH_\1=\3/p' /tmp/branch.map | sort -u >> "$GITHUB_ENV"
|
||||
du -sb main/output/KP_9000_6XHML_X2/html_min | awk '{print "MAIN_WEB="$1}' >> "$GITHUB_ENV"
|
||||
du -sb branch/output/KP_9000_6XHML_X2/html_min | awk '{print "BRANCH_WEB="$1}' >>"$GITHUB_ENV"
|
||||
@@ -1,9 +1,17 @@
|
||||
.gitignore
|
||||
.idea/
|
||||
output/
|
||||
output-main/
|
||||
toolchain/
|
||||
html_data.c
|
||||
html_data.h
|
||||
version.h
|
||||
tools/httpd_sim
|
||||
tools/injector
|
||||
tools/fileadder
|
||||
build/
|
||||
|
||||
# host-test stand-ins for the two generated headers
|
||||
!test/stub/html_data.h
|
||||
!test/stub/version.h
|
||||
.vscode
|
||||
@@ -4,13 +4,55 @@
|
||||
|
||||
## Added
|
||||
|
||||
- Devices
|
||||
- Support the hongyavision HYWS-SGT0204S (PCB marking `2G5F4_10G2_V1.01`), an
|
||||
RTL8372 based 4x2.5G + 2xSFP+ unmanaged switch with a 512 KB Bright Moon
|
||||
`T25S40` flash. It is a sibling of the KP-9000-6XH-X2 (2M-PCB43-V1.1) with
|
||||
the two SFP+ cages wired the other way round (physical 5 is on SDS1,
|
||||
physical 6 on SDS0), no reset button fitted, wrong silkscreen labels on the
|
||||
serial header, `LED_GLB_IO_EN` bit 6 has to be set for the port LEDs to
|
||||
work, and the fitted T25S40 cannot be read in DIO mode on this board, so the
|
||||
target selects single-IO flash reads (`flash_sio`). New machine target
|
||||
`MACHINE_2G5F4_10G2_V1_01`, see `doc/devices/2G5F4_10G2_V1.01.md`.
|
||||
|
||||
- Web UI
|
||||
- Compress the embedded assets (minify + gzip) and switch to a single-page layout. #315
|
||||
- Replace the multi-page UI with a themed single-page app: light, dark and Selenized themes following the browser by default,
|
||||
English, Japanese and Chinese, save to flash merges the command log into the startup config and verifies the write,
|
||||
firmware images are checked in the browser before upload. #429
|
||||
|
||||
## Changed
|
||||
|
||||
## Fixed
|
||||
|
||||
- Time
|
||||
- `rtl8372_init()` sets SDS 0 to SGMII as the stock firmware does. The masks were 0, so on RTL8372
|
||||
boards without 10G ports both SerDes stayed off, and with SDS 0 off `RTL837X_REG_SEC_COUNTER`
|
||||
does not hold a written value: NTP never retried after a failed first attempt at boot and
|
||||
froze the clock after a sync.
|
||||
|
||||
- Web UI
|
||||
- Firefox no longer fills a saved login into the new admin password fields. It also put the
|
||||
user name into the NTP poll interval, which marked the Time card as edited, so it kept its
|
||||
defaults (NTP off, no server, UTC-12:00) instead of the switch's settings.
|
||||
- Accept firmware uploads regardless of the file part's MIME type, including
|
||||
`application/macbinary` sent by Chrome on macOS for `.bin` files.
|
||||
|
||||
- Health
|
||||
- `HEALTH=1` builds no longer write past the phase timing arrays at the LLDP checkpoint, which
|
||||
corrupted the `link` slow counter and the DHCP client state. #658
|
||||
- Config
|
||||
- A startup configuration line longer than the command buffer no longer stops the replay:
|
||||
the offending line is skipped and the following lines are still applied.
|
||||
- The web UI and the configuration upload now refuse a line the replay cannot take,
|
||||
instead of writing it to flash.
|
||||
|
||||
- Startup
|
||||
- Initialised and zero-initialised globals above xdata 0x4000 now get their values at boot.
|
||||
Hardware reset leaves SFR 0x97 at 1, which maps xdata 0x4000-0xbfff to the flash image,
|
||||
and it was cleared only in `main()`, after the C startup code had copied and cleared them.
|
||||
This showed as a random web session timeout and LLDP blocked on some ports without config.
|
||||
|
||||
## Breaking changes
|
||||
|
||||
- Config
|
||||
|
||||
@@ -3,11 +3,19 @@ FROM debian:13-slim
|
||||
RUN apt-get update && apt-get install -y \
|
||||
make \
|
||||
gcc \
|
||||
sdcc \
|
||||
g++ \
|
||||
bison \
|
||||
flex \
|
||||
libboost-dev \
|
||||
patch \
|
||||
bzip2 \
|
||||
curl \
|
||||
ca-certificates \
|
||||
xxd \
|
||||
python3 \
|
||||
libjson-c-dev \
|
||||
git \
|
||||
zlib1g-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# git safe.directory for mounted repos (Makefile uses git describe)
|
||||
|
||||
@@ -4,23 +4,63 @@ DEFAULT_CONFIG_LOCATION = 454656
|
||||
CONFIG_LOCATION = 458752
|
||||
HTML_LOCATION = 262144
|
||||
|
||||
# Startup configuration embedded in the image. Override it to build a specific
|
||||
# machine with its own configuration: make MACHINE=<name> CONFIG=<file>
|
||||
CONFIG ?= config.txt
|
||||
|
||||
SDCC_TOOLCHAIN = sdcc-$(shell cat sdcc/* | cksum | cut -d' ' -f1)
|
||||
SDCC_PREFIX = toolchain/$(SDCC_TOOLCHAIN)
|
||||
ifeq ($(origin CC),default)
|
||||
CC = sdcc
|
||||
SDCC = $(SDCC_PREFIX)/bin/sdcc
|
||||
CC = $(SDCC)
|
||||
ASM = $(SDCC_PREFIX)/bin/sdas8051
|
||||
SDCC_REV := $(shell git log -1 --format=%h -- sdcc 2>/dev/null)
|
||||
ifneq ($(SDCC_REV),)
|
||||
ifneq ($(shell git status --porcelain --untracked-files=no -- sdcc 2>/dev/null),)
|
||||
SDCC_REV := $(SDCC_REV)-dirty
|
||||
endif
|
||||
CC_FLAGS = -mmcs51 -I. -Ihttpd -Iuip
|
||||
endif
|
||||
SDCC_BANNER = $(if $(SDCC_REV),sdcc/ at $(SDCC_REV),$(SDCC_TOOLCHAIN)) ($(words $(wildcard sdcc/*.patch)) patches)
|
||||
else
|
||||
SDCC_BANNER = system
|
||||
endif
|
||||
CC_FLAGS = -mmcs51 -I. -Imachine -Ihttpd -Iuip
|
||||
ASM ?= sdas8051
|
||||
AFLAGS= -plosgff
|
||||
|
||||
SUBDIRS := tools
|
||||
SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS))
|
||||
|
||||
ifeq ($(MACHINE),)
|
||||
MACHINE:= $(shell grep "^\s*#define MACHINE_" machine.h | sed "s/^\s*#define MACHINE_//")
|
||||
else
|
||||
CC_FLAGS += -DMACHINE_$(MACHINE)
|
||||
# $MACHINE selects machine/$(MACHINE).c as the board definition and is passed
|
||||
# on as -DMACHINE_NAME, which machine.h uses to include machine/$(MACHINE).h.
|
||||
# Board selection itself needs no MACHINE_* symbol for #if chains, so the
|
||||
# definition is all the compiler has to know.
|
||||
ifneq ($(MACHINE),)
|
||||
CC_FLAGS += -DMACHINE_NAME=$(MACHINE)
|
||||
endif
|
||||
# Health instrumentation and the "health" console command: HEALTH=1 gmake ...
|
||||
ifneq ($(HEALTH),)
|
||||
CC_FLAGS += -DHEALTH
|
||||
endif
|
||||
|
||||
BUILDDIR = output/$(MACHINE)
|
||||
ifeq ($(CI),1)
|
||||
CC_FLAGS += --Werror
|
||||
endif
|
||||
|
||||
# The board definition being built: one file per MACHINE_* symbol in machine.h.
|
||||
MACHINE_SRC = machine/$(MACHINE).c
|
||||
|
||||
MACHINE_INIT_DEFAULT := machine/default_machine_init.c
|
||||
MACHINE_INIT_SRC := $(wildcard machine/$(MACHINE)_init.c)
|
||||
ifeq ($(MACHINE_INIT_SRC),)
|
||||
MACHINE_INIT_SRC := $(MACHINE_INIT_DEFAULT)
|
||||
endif
|
||||
|
||||
ifndef BUILDDIR
|
||||
BUILDDIR = output/$(MACHINE)
|
||||
endif
|
||||
|
||||
CONFIG_STAMP := $(BUILDDIR)/.config
|
||||
VERSION_HEADER := version.h
|
||||
|
||||
GIT_VERSION := $(shell git rev-parse --short HEAD)
|
||||
@@ -43,17 +83,41 @@ BUILD_DATE := $(shell date -u -d @$(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S" 2>/d
|
||||
|| date -u -r $(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S")
|
||||
endif
|
||||
|
||||
all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
|
||||
# $(MACHINE_SRC) and $(CONFIG) are listed here so an unknown $MACHINE or a
|
||||
# missing config file fails before anything else is built, including the tools/
|
||||
# subdirectory.
|
||||
all: create_build_dir $(VERSION_HEADER) $(MACHINE_SRC) $(CONFIG) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
|
||||
|
||||
create_build_dir:
|
||||
bank_size:
|
||||
tools/bank_occupancy.sh "$(MACHINE)"
|
||||
|
||||
create_build_dir: $(SDCC)
|
||||
mkdir -p "$(BUILDDIR)"
|
||||
mkdir -p "$(BUILDDIR)/uip"
|
||||
mkdir -p "$(BUILDDIR)/httpd"
|
||||
mkdir -p "$(BUILDDIR)/machine"
|
||||
|
||||
# Keep machine.c in first position to fail immediately on invalid $MACHINE value
|
||||
# Every machine is a pair machine/<MACHINE>.c + machine/<MACHINE>.h. Selecting
|
||||
# them by name means no #if/#elif chain, so an unknown or empty $MACHINE is
|
||||
# caught here instead of by a #error further down the build.
|
||||
$(MACHINE_SRC):
|
||||
@echo "ERROR: MACHINE='$(MACHINE)' has no definition (expected $(MACHINE_SRC))." >&2
|
||||
@echo " Every machine is one file pair under machine/, named after the" >&2
|
||||
@echo " MACHINE_* symbol it defines; see machine/*.c for the full list." >&2
|
||||
@echo " Example: make MACHINE=KP_9000_6XHML_X2" >&2
|
||||
@false
|
||||
|
||||
# Fail with a clear message when CONFIG names a file that does not exist.
|
||||
$(CONFIG):
|
||||
@echo "ERROR: CONFIG='$(CONFIG)' does not exist." >&2
|
||||
@echo " Point CONFIG at a configuration file, or omit it to use config.txt." >&2
|
||||
@false
|
||||
|
||||
# Keep the per-machine definition in first position to fail immediately on an
|
||||
# invalid $MACHINE value
|
||||
SRCS = \
|
||||
machine.c \
|
||||
machine_init.c \
|
||||
$(MACHINE_SRC) \
|
||||
$(MACHINE_INIT_SRC) \
|
||||
cmd_editor.c \
|
||||
cmd_parser.c \
|
||||
dhcp.c \
|
||||
@@ -61,23 +125,37 @@ SRCS = \
|
||||
rtlplayground.c \
|
||||
boot.c \
|
||||
sfp.c \
|
||||
dns.c \
|
||||
dns_cli.c \
|
||||
sessions.c \
|
||||
ntp.c \
|
||||
ntp_cli.c \
|
||||
syslog.c \
|
||||
udp_apps.c
|
||||
|
||||
# RTL837x
|
||||
SRCS += \
|
||||
rtl837x_bandwidth.c \
|
||||
rtl837x_cabletest.c \
|
||||
rtl837x_flash.c \
|
||||
rtl837x_igmp.c \
|
||||
rtl837x_init.c \
|
||||
rtl837x_nic.c \
|
||||
rtl837x_leds.c \
|
||||
rtl837x_leds_dump.c \
|
||||
rtl837x_phy.c \
|
||||
rtl837x_pins.c\
|
||||
rtl837x_port.c \
|
||||
rtl837x_stp.c
|
||||
rtl837x_stp.c \
|
||||
rtl837x_lldp.c \
|
||||
rtl837x_storm.c \
|
||||
rtl837x_lacp.c \
|
||||
rtl837x_trap.c \
|
||||
rtl837x_stp_cli.c
|
||||
SRCS += \
|
||||
httpd/httpd.c \
|
||||
httpd/page_impl.c
|
||||
httpd/page_impl.c \
|
||||
httpd/page_stp.c
|
||||
SRCS += \
|
||||
uip/timer.c \
|
||||
uip/uip.c \
|
||||
@@ -94,71 +172,120 @@ HTML := $(shell find html -name '*.js' -or -name '*.html' -or -name '*.svg' -or
|
||||
# Minified copy of the web UI sources, used as the fileadder input.
|
||||
# The raw html/ sources stay untouched for development; the minified
|
||||
# copy is a build artifact under output/.
|
||||
HTML_MIN := output/html_min
|
||||
HTML_MIN := $(BUILDDIR)/html_min
|
||||
HTML_MIN_LIST := $(BUILDDIR)/html_min.list
|
||||
HTML_MIN_STAMP := $(BUILDDIR)/html_min.stamp
|
||||
.PHONY: html_min
|
||||
html_min: $(HTML)
|
||||
html_min: $(HTML_MIN_STAMP)
|
||||
|
||||
$(HTML_MIN_LIST): FORCE
|
||||
@mkdir -p $(BUILDDIR)
|
||||
@echo $(sort $(HTML)) > $@.tmp
|
||||
@cmp -s $@.tmp $@ && rm -f $@.tmp || mv $@.tmp $@
|
||||
|
||||
$(HTML_MIN_STAMP): $(HTML) $(HTML_MIN_LIST) tools/minify.py $(if $(wildcard $(HTML_MIN)),,FORCE)
|
||||
rm -rf $(HTML_MIN)
|
||||
mkdir -p $(HTML_MIN)
|
||||
@for f in $(HTML); do python3 tools/minify.py $$f $(HTML_MIN)/$$(basename $$f) || exit 1; done
|
||||
@touch $@
|
||||
|
||||
html_data.c html_data.h &: $(HTML) | tools html_min
|
||||
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -z -d $(HTML_MIN) -p html_data
|
||||
html_data.c html_data.h &: $(HTML_MIN_STAMP) | tools
|
||||
tools/$(BUILDDIR)/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -z -d $(HTML_MIN) -p html_data
|
||||
|
||||
$(VERSION_HEADER):
|
||||
$(VERSION_HEADER): FORCE
|
||||
@printf '%s\n' "#ifndef VERSION_H" "#define VERSION_H" \
|
||||
"#define VERSION_SW \"$(VERSION_EXTENSION)\"" \
|
||||
"#define BUILD_DATE \"$(BUILD_DATE)\"" \
|
||||
"#endif" > $(VERSION_HEADER)
|
||||
"#define SDCC_TOOLCHAIN \"$(SDCC_BANNER)\"" \
|
||||
"#endif" > $(VERSION_HEADER).tmp
|
||||
@cmp -s $(VERSION_HEADER).tmp $(VERSION_HEADER) \
|
||||
&& rm -f $(VERSION_HEADER).tmp \
|
||||
|| mv $(VERSION_HEADER).tmp $(VERSION_HEADER)
|
||||
|
||||
httpd: html_data.h
|
||||
|
||||
$(SUBDIRS):
|
||||
$(MAKE) -C $@
|
||||
$(MAKE) -C $@ BUILDDIR=$(BUILDDIR)
|
||||
|
||||
clean: $(SUBDIRSCLEAN)
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER)
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER) $(HTML_MIN_LIST) $(HTML_MIN_STAMP)
|
||||
-if [ -d $(BUILDDIR) ]; then find $(BUILDDIR) -type f ! -name "*.bin" -delete; fi
|
||||
|
||||
distclean: $(SUBDIRSCLEAN)
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER)
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER) $(HTML_MIN_LIST) $(HTML_MIN_STAMP)
|
||||
-rm -rf $(BUILDDIR)
|
||||
-rm -rf toolchain
|
||||
|
||||
ifneq ($(SDCC),)
|
||||
$(SDCC):
|
||||
sh sdcc/build.sh $(abspath $(SDCC_PREFIX))
|
||||
endif
|
||||
|
||||
$(SUBDIRSCLEAN):
|
||||
$(MAKE) -C $(@:clean=) clean
|
||||
|
||||
$(BUILDDIR)/%.rel: %.c | create_build_dir html_data.h
|
||||
# Objects depend on the flags they were built with, through a stamp file that
|
||||
# is rewritten only when CC_FLAGS actually changes.
|
||||
CCFLAGS_STAMP := $(BUILDDIR)/.ccflags
|
||||
|
||||
.PHONY: FORCE
|
||||
FORCE:
|
||||
|
||||
$(CCFLAGS_STAMP): FORCE | create_build_dir
|
||||
@echo '$(CC_FLAGS)' | cmp -s - $@ 2>/dev/null || echo '$(CC_FLAGS)' > $@
|
||||
|
||||
# The same for $(CONFIG): its path is stamped so switching to a config file
|
||||
# older than the image still rebuilds it, while $(CONFIG) itself as a normal
|
||||
# prerequisite covers edits to the selected file.
|
||||
$(CONFIG_STAMP): FORCE | create_build_dir
|
||||
@echo '$(CONFIG)' | cmp -s - $@ 2>/dev/null || echo '$(CONFIG)' > $@
|
||||
|
||||
$(BUILDDIR)/%.rel: %.c $(CCFLAGS_STAMP) | create_build_dir html_data.h
|
||||
$(CC) -MMD $(CC_FLAGS) -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)/%.rel: %.asm | create_build_dir
|
||||
$(BUILDDIR)/%.rel: %.asm $(CCFLAGS_STAMP) | create_build_dir
|
||||
${ASM} ${AFLAGS} -o $@ $<
|
||||
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
|
||||
|
||||
$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtbank.rel $(BUILDDIR)/crc16.rel
|
||||
$(CC) $(CC_FLAGS) -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-bBANK3=0x34000 -Wl-r -o $@ $^
|
||||
$(CC) $(CC_FLAGS) --xram-size 49151 -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-bBANK3=0x34000 -Wl-bBANK4=0x44000 -Wl-r -o $@ $^
|
||||
|
||||
$(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx
|
||||
objcopy --input-target=ihex -O binary $< $@
|
||||
|
||||
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img | tools
|
||||
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img $(CONFIG) $(CONFIG_STAMP) | tools
|
||||
if [ -e $@ ]; then rm $@; fi
|
||||
tools/output/imagebuilder -i $^ $@
|
||||
tools/output/fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
|
||||
tools/output/fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
|
||||
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -z -d $(HTML_MIN) -p html_data -b BANK1 $@
|
||||
tools/output/crc_calculator -u $@
|
||||
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin output/rtlplayground.bin
|
||||
tools/$(BUILDDIR)/imagebuilder -i $(BUILDDIR)/rtlplayground.img $@
|
||||
tools/$(BUILDDIR)/fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d "$(CONFIG)" $@
|
||||
tools/$(BUILDDIR)/fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d "$(CONFIG)" $@
|
||||
tools/$(BUILDDIR)/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -z -d $(HTML_MIN) -b BANK1 $@
|
||||
tools/$(BUILDDIR)/crc_calculator -u $@
|
||||
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin $(BUILDDIR)/../rtlplayground.bin
|
||||
|
||||
.PHONY: clean distclean all $(SUBDIRS) $(SUBDIRSCLEAN) $(VERSION_HEADER) create_build_dir
|
||||
.PHONY: clean distclean all $(SUBDIRS) $(SUBDIRSCLEAN) create_build_dir
|
||||
|
||||
.PHONY:
|
||||
machine_check:
|
||||
# Every machine/ definition is compiled, so a machine added to machine/ is
|
||||
# covered without registering it anywhere. A board only counts once both its
|
||||
# <machine>.c and its <machine>.h are present: the header is what the rest of
|
||||
# the build includes, so a .c without one is an incomplete board. The _init.c
|
||||
# files are excluded here: they are the boot hooks, compiled separately below
|
||||
# (the board's own if it exists, otherwise default_machine_init.c). The
|
||||
# machine-specific defines are filtered out of $(CC_FLAGS) and supplied per
|
||||
# iteration instead, so this also works as "make machine_check MACHINE=...".
|
||||
MACHINE_DEFS := $(sort $(filter $(patsubst machine/%.h,%,$(wildcard machine/*.h)),$(patsubst machine/%.c,%,$(filter-out machine/%_init.c,$(wildcard machine/*.c)))))
|
||||
MACHINE_LESS_CC_FLAGS = $(filter-out -DMACHINE_%,$(CC_FLAGS))
|
||||
|
||||
.PHONY: machine_check
|
||||
machine_check: $(SDCC)
|
||||
@mkdir -p $(BUILDDIR)/tmp
|
||||
@set -eo pipefail; \
|
||||
for MACHINE in `grep -E '^[[:space:]]*(//[[:space:]]*)?#define MACHINE_' machine.h | sed -E 's%^[[:space:]]*(//[[:space:]]*)?#define MACHINE_%%' | awk '{print $$1}' | sort -u`; \
|
||||
for MACHINE in $(MACHINE_DEFS); \
|
||||
do \
|
||||
echo "Checking $${MACHINE}"; \
|
||||
$(CC) $(CC_FLAGS) -DMACHINE_$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine.c; \
|
||||
$(CC) $(CC_FLAGS) -DMACHINE_$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine_init.c; \
|
||||
$(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine/$${MACHINE}.c; \
|
||||
INIT=machine/$${MACHINE}_init.c; \
|
||||
if [ ! -e $$INIT ] && [ ! -L $$INIT ]; then INIT=$(MACHINE_INIT_DEFAULT); fi; \
|
||||
$(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c $$INIT; \
|
||||
done
|
||||
@rm -rf $(BUILDDIR)/tmp
|
||||
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
A Playground for Firmware development for advanced user of RTL8372/RTL8373 based 2.5GBit Switches.
|
||||
|
||||
For each hardware configuration of these devices, there is usually a managed and an
|
||||
umanaged version sold, with mostly identical hardware. The aim is to provide management
|
||||
unmanaged version sold, with mostly identical hardware. The aim is to provide management
|
||||
features also for unmanaged devices with additional features such as Management VLAN,
|
||||
dhcp servers, multi-language support, IPv6 and TLS-encrypted web-pages. At present, however
|
||||
DHCP servers, multi-language support, IPv6 and TLS-encrypted web-pages. At present, however
|
||||
only the following features are provided:
|
||||
- A modern web-interface with mouse-over to display further information
|
||||
- A serial console interface to configure all features
|
||||
- IGMP to configure Multicast streaming
|
||||
- Port configuration showing detailed informtion about own and Link-partner advertised
|
||||
Speed settins and configuration of these settings on the local side
|
||||
- Port configuration showing detailed information about own and Link-partner advertised
|
||||
Speed settings and configuration of these settings on the local side
|
||||
- Per-port configuration of frame sizes (MTUs) for Jumbo-Frame support or limiting MTUs
|
||||
for particular devices
|
||||
- EEE (Energy Efficient Ethernet) can be configured per-port. Detailed information is
|
||||
@@ -25,7 +25,7 @@ only the following features are provided:
|
||||
- Firmware updates via the web
|
||||
- Installation as a firmware upgrade from the original web-interface
|
||||
|
||||
<img width="1420" height="623" alt="GUI" src="doc/images/gui.png" />
|
||||
<img width="1673" height="977" alt="GUI" src="doc/images/gui.png" />
|
||||
|
||||
While the firmware provides already considerable improvements over the original managed firmware,
|
||||
the firmware still lacks support for the proprietary loop prevention
|
||||
@@ -37,7 +37,7 @@ a backup of the original flash content via a SOIC clamp such as also used for BI
|
||||
backups and can re-install that firmware in case something is wrong. For this no soldering
|
||||
skills are necessary.
|
||||
|
||||
The firmware supports all hardware featues of devices with
|
||||
The firmware supports all hardware features of devices with
|
||||
- 4 2.5GBit ports + 2 SFP+ ports
|
||||
- 5 2.5GBIT + 1 SFP+ port
|
||||
- 8 2.5GBit + 1 SFP+ port
|
||||
@@ -56,12 +56,19 @@ device simulator is provided, which runs entirely under Linux as a local webserv
|
||||
|
||||
## (0) Compiling Requirements
|
||||
|
||||
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:
|
||||
Install the following particular build requisites (Debian 12/13):
|
||||
```
|
||||
sudo apt install make gcc sdcc xxd python-is-python3 libjson-c-dev zlib1g-dev
|
||||
sudo apt install make gcc g++ bison flex libboost-dev patch bzip2 curl xxd python-is-python3 libjson-c-dev zlib1g-dev
|
||||
```
|
||||
|
||||
The first `make` downloads SDCC 4.6.0, applies the fixes in `sdcc/` and builds it into
|
||||
`toolchain/`, which takes a few minutes. Later builds reuse it. The released SDCC 4.5.0
|
||||
and 4.6.0 miscompile parts of this code, see [SDCC bug #4153](https://sourceforge.net/p/sdcc/bugs/4153/)
|
||||
and [#4154](https://sourceforge.net/p/sdcc/bugs/4154/); both fixes are in SDCC trunk since
|
||||
r17039. The third patch is for [#4070](https://sourceforge.net/p/sdcc/bugs/4070/), where the
|
||||
assembler drops the top byte of a `__sfr32` address list; it is proposed upstream and lets
|
||||
`SFR_DATA_U32` be used again. To use an SDCC you installed yourself instead, run `make CC=sdcc ...`.
|
||||
|
||||
<details>
|
||||
<summary>If using Docker (click to expand)</summary>
|
||||
|
||||
@@ -90,6 +97,14 @@ docker run --rm -v $(pwd):/workspace rtlplayground-dev make MACHINE=DEFAULT_8C_1
|
||||
|
||||
The resulting `.bin` file appears in `output/` on your host.
|
||||
|
||||
Build the OEM web upgrade bin (after building the firmware bin)
|
||||
|
||||
```
|
||||
docker run --rm -v $(pwd):/workspace rtlplayground-dev make -C installer
|
||||
```
|
||||
|
||||
The resulting `rtlplayground_oem_upgrade.bin` file appears in `installer/output/` on your host.
|
||||
|
||||
Build host tools only:
|
||||
|
||||
```
|
||||
@@ -103,24 +118,36 @@ docker run --rm -p 8080:8080 -v $(pwd):/workspace rtlplayground-dev \
|
||||
tools/output/httpd_sim /workspace/html
|
||||
```
|
||||
|
||||
Edit `machine.h` or `config.txt` on your host, then re-run `make` — the
|
||||
Edit `config.txt` on your host, then re-run `make` — the
|
||||
source directory is mounted into the container, so changes take effect
|
||||
immediately. To build for a different machine, pass `MACHINE=...`.
|
||||
immediately. To build for a different machine, pass `MACHINE=<name>`, which
|
||||
selects `machine/<name>.c` (see [Adding a new device](doc/adding-a-device.md)).
|
||||
|
||||
</details>
|
||||
|
||||
## (1) Compiling for direct chip flashing AND upgrading an existing RTLPlayground running device
|
||||
|
||||
Edit machine.h with an editor like vi or nano. Select the correct machine the firmware should build for.
|
||||
Pass the machine that matches your device, for example:
|
||||
```
|
||||
make MACHINE=DEFAULT_8C_1SFP
|
||||
```
|
||||
The name selects the board definition `machine/<name>.c`; `make` without a
|
||||
`MACHINE` value stops with an error listing what is expected. If your board is
|
||||
not in the list yet, see [Adding a new device](doc/adding-a-device.md).
|
||||
|
||||
To embed a machine-specific startup configuration, pass `CONFIG`:
|
||||
```
|
||||
make MACHINE=DEFAULT_8C_1SFP CONFIG=configs/DEFAULT_8C_1SFP.txt
|
||||
```
|
||||
`CONFIG` defaults to `config.txt`; the selected file is embedded in the image
|
||||
and changing it triggers a rebuild.
|
||||
|
||||
> [!TIP]
|
||||
> You can write configuration parameters in config.txt (see below) in order your switch to get
|
||||
> straight at the first boot, a correct IP configuration.
|
||||
|
||||
Now, building the firmware image should work:
|
||||
```
|
||||
make
|
||||
```
|
||||
Now, building the firmware image should work.
|
||||
|
||||
Note, that the image generated ends in .bin, not .img, in order to make IMSProg happy.
|
||||
|
||||
image location is stored in `RTLPlayground/output/rtlplayground_version_machine.bin`
|
||||
@@ -131,7 +158,7 @@ rtlplayground-v0.1.0-12c98ba-dirty-LIANGUO_ZX_SWTGW215AS.bin
|
||||
|
||||
> [!CAUTION]
|
||||
> This image can be flashed directly to the chip OR through the firmware update/upgrade
|
||||
> interface of RTLPlaygound interface
|
||||
> interface of RTLPlayground interface
|
||||
|
||||
## (2) Compiling for OEM running device with management options (web upgrade)
|
||||
|
||||
@@ -158,9 +185,9 @@ example of compilation console output
|
||||
RTLPlayground/installer$ make
|
||||
mkdir -p output
|
||||
gcc updatebuilder.c -o output/updatebuilder
|
||||
sdas8051 -plosgff -o output/crtstart.rel crtstart.asm
|
||||
sdcc -mmcs51 --code-loc 0x1000 -o output/installer.rel -c installer.c
|
||||
sdcc -mmcs51 -Wl-bHOME=0x1100 -Wl-r -o output/rtlinstaller.ihx output/crtstart.rel output/installer.rel
|
||||
../toolchain/sdcc-3390765201/bin/sdas8051 -plosgff -o output/crtstart.rel crtstart.asm
|
||||
../toolchain/sdcc-3390765201/bin/sdcc -mmcs51 --code-loc 0x1000 -o output/installer.rel -c installer.c
|
||||
../toolchain/sdcc-3390765201/bin/sdcc -mmcs51 -Wl-bHOME=0x1100 -Wl-r -o output/rtlinstaller.ihx output/crtstart.rel output/installer.rel
|
||||
./output/updatebuilder -i output/rtlinstaller.ihx -o output/rtlplayground_oem_upgrade.bin ../output/rtlplayground.bin
|
||||
Input file size: 524288
|
||||
Bytes read: 524288
|
||||
@@ -179,18 +206,18 @@ ghidra see this information about [Ghidra images](doc/ghidra.md).
|
||||
|
||||
## (4) Installation through the Web interface (software way)
|
||||
|
||||
Managed switches (OEM firmware of RTLplaygroud firmware) can be upgraded via the web interface.
|
||||
Managed switches (OEM firmware of RTLplayground firmware) can be upgraded via the web interface.
|
||||
Unmanaged switch cannot be flashed this way (see 5).
|
||||
|
||||
Go to "Firmware update" tab, select the correct file.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If your device already runs RTLPlayground, you must upload the binary file /RTLPlayground/output/rtlplayground_Version_Machine.bin
|
||||
> If your device is OEM, you must upload the binary file /RTLPlayground/installer/outputrtlplayground_oem_upgrade.bin
|
||||
> If your device is OEM, you must upload the binary file /RTLPlayground/installer/output/rtlplayground_oem_upgrade.bin
|
||||
|
||||
> [!CAUTION]
|
||||
> Check one more time that your device matches the machine type before flashing.
|
||||
> Be shure you have a backup of the original firmware before diving in RTLPlaygroung.
|
||||
> Be sure you have a backup of the original firmware before diving in RTLPlayground.
|
||||
|
||||
Finally, push the Upload File Button and you're done !
|
||||
|
||||
@@ -198,7 +225,7 @@ Finally, push the Upload File Button and you're done !
|
||||
## (5) Flashing the ROM directly (hardware way, but also only way to rescue)
|
||||
|
||||
This procedure is the only way to flash unmanaged switches, if the ROM chip is large enough.
|
||||
This is also the only way to unbrick your device if something went wroong.
|
||||
This is also the only way to unbrick your device if something went wrong.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> You need a SOIC-8 clip to flash the ROM chip directly onboard.
|
||||
@@ -218,7 +245,7 @@ This is also the only way to unbrick your device if something went wroong.
|
||||
- ERASE THE ROM (BLANK) !
|
||||
- Load the firmware into IMSProg.
|
||||
- Flash is to the ROM chip.
|
||||
- Disconect the clip from the ROM chip.
|
||||
- Disconnect the clip from the ROM chip.
|
||||
- You're done, ready for the first boot.
|
||||
|
||||
## (6) Connecting a serial interface (optional)
|
||||
@@ -233,7 +260,7 @@ When you power up the switch, the device will perform some examples and provide
|
||||
## (8) The web-interface
|
||||
|
||||
The web-interface can be reached under the [default 192.168.10.247](http://192.168.10.247) unless you
|
||||
specified an IP adress in the config.txt before compilation.
|
||||
specified an IP address in the config.txt before compilation.
|
||||
|
||||
> [!TIP]
|
||||
> The default password is `1234`.
|
||||
@@ -333,17 +360,18 @@ While in compilation part, you might write directly to config.txt file before ma
|
||||
nano config.txt
|
||||
```
|
||||
|
||||
If you want to modify settings after the flash is done, go to the Advanced Settings tab in System Settings
|
||||
If you want to modify settings after the flash is done, go to the System tab and find the Startup Configuration.
|
||||
|
||||
<img width="1085" height="646" alt="ADVANCED SETTINGS" src="doc/images/advanced_settings.png" />
|
||||
<img width="1673" height="978" alt="ADVANCED SETTINGS" src="doc/images/advanced_settings.png" />
|
||||
|
||||
```
|
||||
ip xxx.xxx.xxx.xxx = IP adress of the switch
|
||||
gw yyy.yyy.yyy.yyy = IP adress of the gateway
|
||||
ip xxx.xxx.xxx.xxx = IP address of the switch
|
||||
gw yyy.yyy.yyy.yyy = IP address of the gateway
|
||||
netmask zzz.zzz.zzz.zzz = Network mask of the switch
|
||||
port x name xxx = Name xxx the port number x
|
||||
port z 1g = Set 1g speed for port z
|
||||
igmp on/off = Turn IGMP on or off
|
||||
session xxxx = Web session timeout in seconds (default 200)
|
||||
```
|
||||
[To be continue]
|
||||
|
||||
@@ -352,11 +380,14 @@ Enjoy playing!
|
||||
## (11) Other documents
|
||||
|
||||
The following documents give further documentation on specific features of the RTL837x SoCs:
|
||||
- [Adding a new device](doc/adding-a-device.md)
|
||||
- [RTL8372/3 Feature support](doc/hardware.md)
|
||||
- [CPU Port](doc/CpuPort.md)
|
||||
- [L2 learning](doc/l2.md)
|
||||
- [IGMP (IP-MC streaming)](doc/igmp.md)
|
||||
- [SFP+ ports](doc/sfp.md)
|
||||
- [Trunking aka. port aggregation](doc/trunking.md)
|
||||
- [Trunking aka. port aggregation](doc/link_aggregation.md)
|
||||
- [LACP (802.3ad link aggregation)](doc/lacp.md)
|
||||
- [VLAN](doc/vlan.md)
|
||||
- [Storm control](doc/storm_control.md)
|
||||
- [Modifications and Flash replacement](doc/mods.md)
|
||||
@@ -21,8 +21,9 @@ extern __code const struct machine machine;
|
||||
extern __xdata struct machine_runtime machine_detected;
|
||||
extern __xdata uint8_t sfr_data[4];
|
||||
extern volatile __xdata uint32_t ticks;
|
||||
__xdata uint32_t rtl8224_release_tick;
|
||||
extern __xdata uint8_t tx_seq;
|
||||
extern __code uint8_t * __code hex;
|
||||
extern __code const uint8_t * __code const hex;
|
||||
|
||||
|
||||
|
||||
@@ -124,18 +125,6 @@ void early_boot_handle_button(void) __banked
|
||||
void sds_config(uint8_t sds, uint8_t mode) __banked
|
||||
{
|
||||
print_string("sds_config sds: "); print_byte(sds); print_string(", mode: "); print_byte(mode); write_char('\n');
|
||||
sds_config_mac(sds, mode);
|
||||
|
||||
if (mode == SDS_10GR || mode == SDS_QXGMII)
|
||||
sds_write_v(sds, 0x21, 0x10, 0x4480); // Q002110:6480
|
||||
else
|
||||
sds_write_v(sds, 0x21, 0x10, 0x6480); // Q002110:6480
|
||||
sds_write_v(sds, 0x21, 0x13, 0x0400); // Q002113:0400
|
||||
sds_write_v(sds, 0x21, 0x18, 0x6d02); // Q002118:6d02
|
||||
sds_write_v(sds, 0x21, 0x1b, 0x424e); // Q00211b:424e
|
||||
sds_write_v(sds, 0x21, 0x1d, 0x0002); // Q00211d:0002
|
||||
sds_write_v(sds, 0x36, 0x1c, 0x1390); // Q00361c:1390
|
||||
sds_write_v(sds, 0x36, 0x14, 0x003f); // Q003614:003f
|
||||
|
||||
uint8_t page = 0;
|
||||
uint16_t v = 0;
|
||||
@@ -164,6 +153,21 @@ void sds_config(uint8_t sds, uint8_t mode) __banked
|
||||
print_string("Error in SDS Mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sds_config_mac(sds, mode);
|
||||
|
||||
if (mode == SDS_10GR || mode == SDS_QXGMII)
|
||||
sds_write_v(sds, 0x21, 0x10, 0x4480); // Q002110:6480
|
||||
else
|
||||
sds_write_v(sds, 0x21, 0x10, 0x6480); // Q002110:6480
|
||||
|
||||
sds_write_v(sds, 0x21, 0x13, 0x0400); // Q002113:0400
|
||||
sds_write_v(sds, 0x21, 0x18, 0x6d02); // Q002118:6d02
|
||||
sds_write_v(sds, 0x21, 0x1b, 0x424e); // Q00211b:424e
|
||||
sds_write_v(sds, 0x21, 0x1d, 0x0002); // Q00211d:0002
|
||||
sds_write_v(sds, 0x36, 0x1c, 0x1390); // Q00361c:1390
|
||||
sds_write_v(sds, 0x36, 0x14, 0x003f); // Q003614:003f
|
||||
|
||||
sds_write_v(sds, 0x36, 0x10, v); // Q003610:0200
|
||||
|
||||
if (page == 0x2e) { // 10G Fiber / SDS_QXGMII
|
||||
@@ -240,10 +244,10 @@ void rtl8224_enable(void) __banked
|
||||
reg_bit_clear(RTL837X_REG_GPIO_32_63_OUTPUT, 4);
|
||||
// Configure Pin as output
|
||||
reg_bit_set(RTL837X_REG_GPIO_32_63_DIRECTION, 4);
|
||||
delay(100);
|
||||
delay(4);
|
||||
// Set pin 4 high
|
||||
reg_bit_set(RTL837X_REG_GPIO_32_63_OUTPUT, 4);
|
||||
delay(500);
|
||||
rtl8224_release_tick = ticks;
|
||||
}
|
||||
|
||||
|
||||
@@ -256,7 +260,7 @@ void nic_setup(void) __banked
|
||||
|
||||
// This sets the size of the RX buffer, the filling level is in 0x7874
|
||||
// R7848-000004ff
|
||||
REG_SET(RTL837X_REG_NIC_RXBUFF_RX, 0x4ff);
|
||||
REG_SET(RTL837X_REG_NIC_RXBUFF_RX, RTL837X_NIC_RX_LAST_SLOT);
|
||||
|
||||
// R7844-000007fe
|
||||
REG_SET(RTL837X_REG_NIC_BUFFSIZE_TX, 0x7fe);
|
||||
@@ -295,6 +299,7 @@ void nic_setup(void) __banked
|
||||
|
||||
// Sequence number of TX packets
|
||||
tx_seq = 0;
|
||||
REG_SET(RTL837X_NIC_INT_MSK, NIC_INT_RXIE);
|
||||
}
|
||||
|
||||
|
||||
@@ -397,10 +402,12 @@ void setup_i2c(void) __banked
|
||||
// HW Control register, enable I2C depending on PIN configuration
|
||||
reg_read_m(RTL837X_PIN_MUX_1);
|
||||
for (uint8_t sfp = 0; sfp < machine.n_sfp; sfp++) {
|
||||
const uint8_t scl_bus = i2c_bus_from_scl_pin(machine.sfp_port[sfp].i2c.scl);
|
||||
const uint8_t sda_bus = i2c_bus_from_sda_pin(machine.sfp_port[sfp].i2c.sda);
|
||||
uint8_t i2c = machine.sfp_port[sfp].i2c;
|
||||
uint8_t scl_bus = (i2c >> RTL837X_REG_I2C_SCL_SHIFT) & RTL837X_REG_I2C_SCL_MASK;
|
||||
uint8_t sda_bus = (i2c >> RTL837X_REG_I2C_SDA_SHIFT) & RTL837X_REG_I2C_SDA_MASK;
|
||||
print_string("Configuring I2C for SFP idx="); print_byte(sfp); print_string(" SCL="); print_byte(scl_bus); print_string(", SDA="); print_byte(sda_bus); write_char('\n');
|
||||
switch (scl_bus) {
|
||||
// `& RTL837X_REG_I2C_SCL_MASK` is needed to silens a compiler warning 110.
|
||||
switch (scl_bus & RTL837X_REG_I2C_SCL_MASK) {
|
||||
case 3:
|
||||
// Bit 5-6 0b10 -> SCL (implies enabled SDA on bus 3)
|
||||
sfr_mask_data(0, 0x60, 0x40);
|
||||
@@ -419,8 +426,6 @@ void setup_i2c(void) __banked
|
||||
sfr_mask_data(0, 0x80, 0x80);
|
||||
sfr_mask_data(1, 0x01, 0x00);
|
||||
break;
|
||||
default:
|
||||
print_string("Invalid SCL bus number: "); print_byte(scl_bus); write_char('\n');
|
||||
}
|
||||
|
||||
switch (sda_bus) {
|
||||
@@ -444,8 +449,6 @@ void setup_i2c(void) __banked
|
||||
// Bit 9-10 0b01 -> SDA
|
||||
sfr_mask_data(1, 0x06, 0x02);
|
||||
break;
|
||||
default:
|
||||
print_string("Invalid SDA bus number: "); print_byte(sda_bus); write_char('\n');
|
||||
}
|
||||
}
|
||||
reg_write_m(RTL837X_PIN_MUX_1);
|
||||
|
||||
@@ -6,9 +6,36 @@
|
||||
#include "rtl837x_common.h"
|
||||
|
||||
extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
|
||||
extern __xdata uint8_t cmd_available;
|
||||
extern __bit __at(0x03) cmd_available;
|
||||
extern __xdata uint8_t err_status;
|
||||
|
||||
/* Health instrumentation, built with HEALTH=1. Without it the hooks below
|
||||
* compile to nothing and the "health" command does not exist. */
|
||||
#ifdef HEALTH
|
||||
/* Phase ids, in main-loop order */
|
||||
#define HEALTH_PH_LINK 0
|
||||
#define HEALTH_PH_SFP 1
|
||||
#define HEALTH_PH_RX 2
|
||||
#define HEALTH_PH_TX 3
|
||||
#define HEALTH_PH_STP 4
|
||||
#define HEALTH_PH_CMD 5
|
||||
#define HEALTH_PH_LLDP 6
|
||||
#define HEALTH_PHASES (HEALTH_PH_LLDP + 1) /* last id + 1: sizes the arrays in cmd_parser.c */
|
||||
|
||||
extern __xdata uint16_t health_rx_frames;
|
||||
#define health_rx_frame() health_rx_frames++
|
||||
|
||||
void health_loop_start(void) __banked; /* once per idle() pass, resets the phase baseline */
|
||||
void health_phase(uint8_t id) __banked; /* after each phase; accounts ticks since last checkpoint */
|
||||
void health_stack_paint(void) __banked; /* paint the unused stack area once at boot */
|
||||
void health_show(void) __banked; /* "health" CLI dump */
|
||||
#else
|
||||
#define health_rx_frame()
|
||||
#define health_loop_start()
|
||||
#define health_phase(id)
|
||||
#define health_stack_paint()
|
||||
#endif
|
||||
|
||||
void cmd_tokenize(void) __banked;
|
||||
void cmd_parser(void) __banked;
|
||||
void execute_config(void) __banked;
|
||||
|
||||
@@ -50,8 +50,8 @@ __xdata uip_ipaddr_t server;
|
||||
#define DHCP_PARAM_DNS 6
|
||||
#define DHCP_END 255
|
||||
|
||||
#pragma codeseg BANK2
|
||||
#pragma constseg BANK2
|
||||
#pragma codeseg BANK3
|
||||
#pragma constseg BANK3
|
||||
|
||||
struct dhcp_pkt {
|
||||
uint8_t type;
|
||||
@@ -139,7 +139,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[2];
|
||||
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[3];
|
||||
memcpy(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4);
|
||||
}
|
||||
|
||||
|
||||
@@ -151,13 +150,11 @@ 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[2];
|
||||
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[3];
|
||||
memcpy(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4);
|
||||
}
|
||||
|
||||
|
||||
void dhcp_send_discover(void)
|
||||
{
|
||||
print_string("dhcp_send_discover called\n");
|
||||
dhcp_prepare_request();
|
||||
|
||||
dhcp_state.opt_ptr = 0;
|
||||
@@ -193,7 +190,6 @@ void dhcp_send_discover(void)
|
||||
|
||||
void dhcp_send_request(void)
|
||||
{
|
||||
print_string("dhcp_send_request called\n");
|
||||
dhcp_prepare_request();
|
||||
|
||||
dhcp_state.opt_ptr = 0;
|
||||
@@ -232,19 +228,21 @@ void ip_opt(__xdata uint8_t * ip)
|
||||
{
|
||||
dhcp_state.opt_ptr++;
|
||||
uint8_t len = DHCP_OPT[dhcp_state.opt_ptr++];
|
||||
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
|
||||
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
|
||||
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
|
||||
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
|
||||
if (len >= 4)
|
||||
memcpy(ip, &DHCP_OPT[dhcp_state.opt_ptr], 4);
|
||||
// There may be more than one IP option, such as 2 DNS servers advertised
|
||||
dhcp_state.opt_ptr += len - 4;
|
||||
dhcp_state.opt_ptr += len;
|
||||
}
|
||||
|
||||
|
||||
void long_opt(void)
|
||||
uint8_t long_opt(void)
|
||||
{
|
||||
dhcp_state.opt_ptr++;
|
||||
dhcp_state.opt_ptr++;
|
||||
uint8_t len = DHCP_OPT[dhcp_state.opt_ptr++];
|
||||
if (len < 4) {
|
||||
dhcp_state.opt_ptr += len;
|
||||
return 0;
|
||||
}
|
||||
long_value = DHCP_OPT[dhcp_state.opt_ptr++];
|
||||
long_value <<= 8;
|
||||
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
|
||||
@@ -252,6 +250,8 @@ void long_opt(void)
|
||||
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
|
||||
long_value <<= 8;
|
||||
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
|
||||
dhcp_state.opt_ptr += len - 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -275,16 +275,16 @@ void parse_opts(void)
|
||||
ip_opt(&dhcp_state.broadcast[0]);
|
||||
break;
|
||||
case DHCP_LEASE:
|
||||
long_opt();
|
||||
dhcp_state.lease = long_value;
|
||||
if (long_opt())
|
||||
dhcp_state.lease = long_value;
|
||||
break;
|
||||
case DHCP_REBIND:
|
||||
long_opt();
|
||||
dhcp_state.rebind = long_value;
|
||||
if (long_opt())
|
||||
dhcp_state.rebind = long_value;
|
||||
break;
|
||||
case DHCP_RENEWAL:
|
||||
long_opt();
|
||||
dhcp_state.renewal = long_value;
|
||||
if (long_opt())
|
||||
dhcp_state.renewal = long_value;
|
||||
break;
|
||||
case DHCP_END:
|
||||
break;
|
||||
@@ -376,13 +376,11 @@ void dhcp_start(void) __banked
|
||||
*tid++ = SFR_DATA_8;
|
||||
*tid = SFR_DATA_0;
|
||||
dhcp_state.state = DHCP_START;
|
||||
print_string("dhcp_start done\n");
|
||||
}
|
||||
|
||||
|
||||
void dhcp_stop(void) __banked
|
||||
{
|
||||
print_string("dhcp_stop called\n");
|
||||
uip_udp_remove(dhcp_state.conn);
|
||||
dhcp_state.state = DHCP_OFF;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* DNS resolver for the RTL837x platform
|
||||
* This code is in the Public Domain
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rtl837x_common.h"
|
||||
#include "cmd_parser.h"
|
||||
#include "uip/uip.h"
|
||||
#include "dhcp.h"
|
||||
#include "dns.h"
|
||||
|
||||
#pragma codeseg BANK3
|
||||
#pragma constseg BANK3
|
||||
|
||||
#define DNS_PORT 53
|
||||
#define DNS_TRIES 6
|
||||
#define DNS_TIMEOUT (2 * SYS_TICK_HZ)
|
||||
|
||||
extern __xdata struct dhcp_state dhcp_state;
|
||||
extern volatile __xdata uint32_t ticks;
|
||||
|
||||
__xdata struct dns_state dns_state;
|
||||
__xdata uip_ipaddr_t dns_ip;
|
||||
uint8_t * __xdata dns_cand[3];
|
||||
|
||||
|
||||
static uint8_t dns_used(__xdata uint8_t *a) __reentrant
|
||||
{
|
||||
return a[0] | a[1] | a[2] | a[3];
|
||||
}
|
||||
|
||||
|
||||
static uint8_t dns_name_is_ip(void) __reentrant
|
||||
{
|
||||
__xdata char *s = dns_state.name;
|
||||
uint8_t i, n;
|
||||
uint16_t v;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
v = 0;
|
||||
n = 0;
|
||||
while (*s >= '0' && *s <= '9') {
|
||||
v = v * 10 + (*s++ - '0');
|
||||
if (++n > 3 || v > 255)
|
||||
return 0;
|
||||
}
|
||||
if (!n)
|
||||
return 0;
|
||||
dns_state.addr[i] = v;
|
||||
if (i < 3 && *s++ != '.')
|
||||
return 0;
|
||||
}
|
||||
return !*s;
|
||||
}
|
||||
|
||||
|
||||
static void dns_next(void) __reentrant
|
||||
{
|
||||
uint8_t k = 0;
|
||||
|
||||
if (dns_state.conn) {
|
||||
uip_udp_remove(dns_state.conn);
|
||||
dns_state.conn = 0;
|
||||
}
|
||||
if (dns_used(dns_state.server[0]))
|
||||
dns_cand[k++] = dns_state.server[0];
|
||||
if (dns_used(dns_state.server[1]))
|
||||
dns_cand[k++] = dns_state.server[1];
|
||||
if (dns_used(dhcp_state.dns))
|
||||
dns_cand[k++] = dhcp_state.dns;
|
||||
if (!k || dns_state.tries >= DNS_TRIES) {
|
||||
dns_state.status = DNS_FAILED;
|
||||
if (dns_state.verbose)
|
||||
print_string(k ? "DNS: no answer\n" : "DNS: no server\n");
|
||||
return;
|
||||
}
|
||||
k = dns_state.tries % k;
|
||||
uip_ipaddr(dns_ip, dns_cand[k][0], dns_cand[k][1], dns_cand[k][2], dns_cand[k][3]);
|
||||
dns_state.conn = uip_udp_new(&dns_ip, HTONS(DNS_PORT));
|
||||
if (!dns_state.conn) {
|
||||
dns_state.status = DNS_FAILED;
|
||||
print_string("DNS: no free UDP connection\n");
|
||||
return;
|
||||
}
|
||||
dns_state.send = 1;
|
||||
}
|
||||
|
||||
|
||||
static void dns_query(void) __reentrant
|
||||
{
|
||||
__xdata uint8_t *p = (__xdata uint8_t *)uip_appdata;
|
||||
__xdata char *n = dns_state.name;
|
||||
__xdata uint8_t *label;
|
||||
uint16_t len = 12;
|
||||
|
||||
dns_state.id++;
|
||||
p[0] = dns_state.id >> 8;
|
||||
p[1] = dns_state.id;
|
||||
p[2] = 0x01;
|
||||
p[3] = 0x00;
|
||||
p[4] = 0;
|
||||
p[5] = 1;
|
||||
p[6] = p[7] = p[8] = p[9] = p[10] = p[11] = 0;
|
||||
while (*n) {
|
||||
label = p + len++;
|
||||
*label = 0;
|
||||
while (*n && *n != '.') {
|
||||
p[len++] = *n++;
|
||||
(*label)++;
|
||||
}
|
||||
if (*n)
|
||||
n++;
|
||||
}
|
||||
p[len++] = 0;
|
||||
p[len++] = 0;
|
||||
p[len++] = 1;
|
||||
p[len++] = 0;
|
||||
p[len++] = 1;
|
||||
uip_udp_send(len);
|
||||
}
|
||||
|
||||
|
||||
static uint16_t dns_skip_name(__xdata uint8_t *p, uint16_t i, uint16_t len) __reentrant
|
||||
{
|
||||
while (i < len) {
|
||||
if (!p[i])
|
||||
return i + 1;
|
||||
if ((p[i] & 0xc0) == 0xc0)
|
||||
return i + 2;
|
||||
i += p[i] + 1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static void dns_answer(void) __reentrant
|
||||
{
|
||||
__xdata uint8_t *p = (__xdata uint8_t *)uip_appdata;
|
||||
uint16_t len = uip_datalen();
|
||||
uint16_t i, an;
|
||||
|
||||
if (dns_state.status != DNS_PENDING || len < 12 || !(p[2] & 0x80)
|
||||
|| p[0] != (uint8_t)(dns_state.id >> 8) || p[1] != (uint8_t)dns_state.id)
|
||||
return;
|
||||
an = ((uint16_t)p[6] << 8) | p[7];
|
||||
i = dns_skip_name(p, 12, len) + 4;
|
||||
while (!(p[3] & 0x0f) && an-- && i + 10 <= len) {
|
||||
i = dns_skip_name(p, i, len);
|
||||
if (i + 10 > len)
|
||||
break;
|
||||
if (!p[i] && p[i + 1] == 1 && !p[i + 8] && p[i + 9] == 4 && i + 14 <= len) {
|
||||
memcpy(dns_state.addr, p + i + 10, 4);
|
||||
dns_state.status = DNS_DONE;
|
||||
uip_udp_remove(dns_state.conn);
|
||||
dns_state.conn = 0;
|
||||
if (dns_state.verbose) {
|
||||
print_string("DNS: ");
|
||||
print_string_x(dns_state.name);
|
||||
print_string(" is ");
|
||||
print_ip(dns_state.addr);
|
||||
write_char('\n');
|
||||
}
|
||||
return;
|
||||
}
|
||||
i += 10 + (((uint16_t)p[i + 8] << 8) | p[i + 9]);
|
||||
}
|
||||
dns_state.tries = DNS_TRIES;
|
||||
dns_next();
|
||||
}
|
||||
|
||||
|
||||
void dns_init(void) __banked
|
||||
{
|
||||
memset(dns_state.server, 0, sizeof(dns_state.server));
|
||||
dns_state.name[0] = 0;
|
||||
dns_state.status = DNS_IDLE;
|
||||
dns_state.conn = 0;
|
||||
}
|
||||
|
||||
|
||||
void dns_lookup(void) __banked
|
||||
{
|
||||
if (dns_name_is_ip()) {
|
||||
dns_state.status = DNS_DONE;
|
||||
return;
|
||||
}
|
||||
dns_state.tries = 0;
|
||||
dns_state.status = DNS_PENDING;
|
||||
dns_next();
|
||||
}
|
||||
|
||||
|
||||
void dns_show(void) __banked
|
||||
{
|
||||
print_string("DNS servers ");
|
||||
print_ip(dns_state.server[0]);
|
||||
write_char(' ');
|
||||
print_ip(dns_state.server[1]);
|
||||
print_string(", from DHCP ");
|
||||
print_ip(dhcp_state.dns);
|
||||
write_char('\n');
|
||||
if (!dns_state.name[0])
|
||||
return;
|
||||
print_string("Last lookup ");
|
||||
print_string_x(dns_state.name);
|
||||
print_string(": ");
|
||||
if (dns_state.status == DNS_DONE)
|
||||
print_ip(dns_state.addr);
|
||||
else if (dns_state.status == DNS_PENDING)
|
||||
print_string("pending");
|
||||
else
|
||||
print_string("failed");
|
||||
write_char('\n');
|
||||
}
|
||||
|
||||
|
||||
void dns_callback(uint16_t lport) __banked __reentrant
|
||||
{
|
||||
if (!dns_state.conn || lport != dns_state.conn->lport)
|
||||
return;
|
||||
if (uip_newdata()) {
|
||||
dns_answer();
|
||||
return;
|
||||
}
|
||||
if (dns_state.status != DNS_PENDING)
|
||||
return;
|
||||
if (dns_state.send) {
|
||||
dns_state.send = 0;
|
||||
dns_state.sent = ticks;
|
||||
dns_query();
|
||||
return;
|
||||
}
|
||||
if (ticks - dns_state.sent >= DNS_TIMEOUT) {
|
||||
dns_state.tries++;
|
||||
dns_next();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef _DNS_H_
|
||||
#define _DNS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define DNS_NAME_LEN 48
|
||||
|
||||
#define DNS_IDLE 0
|
||||
#define DNS_PENDING 1
|
||||
#define DNS_DONE 2
|
||||
#define DNS_FAILED 3
|
||||
|
||||
struct uip_udp_conn;
|
||||
|
||||
struct dns_state {
|
||||
uint8_t server[2][4]; /* configured servers, 0.0.0.0 = unused */
|
||||
char name[DNS_NAME_LEN]; /* name of the current or last lookup */
|
||||
uint8_t addr[4]; /* address found by the last lookup */
|
||||
uint8_t status; /* DNS_* */
|
||||
uint8_t verbose; /* print the result of the lookup */
|
||||
uint8_t tries; /* queries sent for the current lookup */
|
||||
uint8_t send; /* a query is due on the connection */
|
||||
uint16_t id;
|
||||
uint32_t sent; /* ticks when the last query went out */
|
||||
struct uip_udp_conn *conn;
|
||||
};
|
||||
|
||||
extern __xdata struct dns_state dns_state;
|
||||
|
||||
void dns_init(void) __banked;
|
||||
void dns_lookup(void) __banked;
|
||||
void dns_show(void) __banked;
|
||||
void dns_callback(uint16_t lport) __banked __reentrant;
|
||||
void dns_parse(void) __banked __reentrant;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Command line interface of the DNS resolver for the RTL837x platform
|
||||
* This code is in the Public Domain
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rtl837x_common.h"
|
||||
#include "cmd_parser.h"
|
||||
#include "dns.h"
|
||||
|
||||
#pragma codeseg BANK2
|
||||
#pragma constseg BANK2
|
||||
|
||||
extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
|
||||
extern __xdata uint8_t cmd_words_len;
|
||||
extern __xdata uint8_t cmd_words_b[15];
|
||||
extern __xdata uint8_t ip[4];
|
||||
uint8_t cmd_compare(uint8_t start, __code const uint8_t * cmd);
|
||||
uint8_t parse_ip(uint8_t idx);
|
||||
|
||||
|
||||
void dns_parse(void) __banked __reentrant
|
||||
{
|
||||
__xdata uint8_t *s;
|
||||
uint8_t n;
|
||||
|
||||
if (cmd_words_len < 2) {
|
||||
dns_show();
|
||||
return;
|
||||
}
|
||||
if (cmd_compare(1, "server") && cmd_words_len >= 3 && parse_ip(cmd_words_b[2])) {
|
||||
memcpy(dns_state.server[0], ip, 4);
|
||||
memset(dns_state.server[1], 0, 4);
|
||||
if (cmd_words_len >= 4) {
|
||||
if (!parse_ip(cmd_words_b[3]))
|
||||
goto err;
|
||||
memcpy(dns_state.server[1], ip, 4);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (cmd_compare(1, "lookup") && cmd_words_len >= 3) {
|
||||
if (dns_state.status == DNS_PENDING) {
|
||||
print_string("DNS: a lookup is already running\n");
|
||||
return;
|
||||
}
|
||||
s = &cmd_buffer[cmd_words_b[2]];
|
||||
for (n = 0; s[n] && s[n] != ' '; n++) {
|
||||
if (n == DNS_NAME_LEN - 1)
|
||||
goto err;
|
||||
dns_state.name[n] = s[n];
|
||||
}
|
||||
dns_state.name[n] = 0;
|
||||
dns_state.verbose = 1;
|
||||
dns_lookup();
|
||||
if (dns_state.status == DNS_DONE) {
|
||||
print_ip(dns_state.addr);
|
||||
write_char('\n');
|
||||
}
|
||||
return;
|
||||
}
|
||||
err:
|
||||
print_string("Error: dns [server <ip> [<ip>]|lookup <name>]\n");
|
||||
}
|
||||
@@ -34,6 +34,21 @@ Next, transfer the actual packet over by repeating the SFR function with a
|
||||
pointer to the frame on the ASIC directly after the frame header and a
|
||||
length as given by the length in the frame header + 7, again divided by 8.
|
||||
|
||||
The RX ring's inclusive last slot is configured as `0x4ff`, giving a byte
|
||||
range of `0x0000` through `0x27ff`. If the descriptor occupies the last slot
|
||||
at `0x27f8`, its payload starts at `0x0000`, not `0x2800`. The RX copy code
|
||||
normalizes that starting address before DMA. It relies on the hardware to
|
||||
wrap transfers that start inside the ring and cross its end, as observed
|
||||
on SWTGW218AS. Programming an initial address of `0x2800` does not wrap
|
||||
and can instead read zeros or stale TX data outside the RX ring.
|
||||
|
||||
Frame lengths are checked against `UIP_CONF_BUFFER_SIZE` before copying.
|
||||
DMA works in whole eight-byte units. `UIP_CONF_BUFFER_ALLOC_SIZE` rounds
|
||||
the backing storage up to the next complete word: 1,560 bytes for the
|
||||
1,556-byte logical frame limit. This padding allows a maximum-size frame
|
||||
to be transferred directly without a separate tail copy. The logical
|
||||
frame limit and advertised MSS are unchanged.
|
||||
|
||||
The received frame will have an RTL proprietary Ethernet frame type of
|
||||
0x8899 (RRPC) where normally the frame type 0x0800 for IPv4 would be located.
|
||||
Further 6 bytes follow describing the frame, before the normal IPv4 data
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
# Adding a new device
|
||||
|
||||
A device is supported by adding one board header `.h` and board definition `.c` file
|
||||
under `machine/`.
|
||||
the build selects the definition by name, and CI compiles every file it finds.
|
||||
|
||||
To compile for your added device, do:
|
||||
```
|
||||
make MACHINE=<NAME>
|
||||
```
|
||||
|
||||
## What a new device consists of
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `machine/<NAME>.c` | the `struct machine machine` board definition |
|
||||
| `machine/<NAME>.h` | `MACHINE_MODEL` (the model string shown in the UI and the CLI) and `MACHINE_CHIPSET` (`RTL8372` or `RTL8373`) |
|
||||
| `machine/<NAME>_init.c` | optional `machine_custom_init()` boot hook, for registers the machine definition cannot express |
|
||||
| `doc/devices/<name>.md` + `doc/supported_devices.md` | (only if the board is verified and you want to support it publicly) user-facing documentation |
|
||||
|
||||
`<NAME>` is the machine symbol without its `MACHINE_` prefix, so `MACHINE` is
|
||||
passed exactly as spelled on the command line: `make MACHINE=MY_BOARD_1_0`
|
||||
needs `machine/MY_BOARD_1_0.c` and `machine/MY_BOARD_1_0.h`.
|
||||
|
||||
## Step 1: the board header
|
||||
|
||||
`machine/<NAME>.h` carries the product string and the SoC family. Use the
|
||||
existing files as the template:
|
||||
|
||||
```c
|
||||
#ifndef _MACHINE_MY_BOARD_1_0_H_
|
||||
#define _MACHINE_MY_BOARD_1_0_H_
|
||||
|
||||
#define MACHINE_MODEL "Brand Model V1.0"
|
||||
#define MACHINE_CHIPSET RTL8373
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
`MACHINE_CHIPSET` is `RTL8373` or `RTL8372`; a build without it will fail. It selects the default
|
||||
logical port range: `MACHINE_MIN_PORT` is `0` for RTL8373 and `3` for RTL8372, while
|
||||
`MACHINE_MAX_PORT` is `8`, the highest logical port index. A board with a different range defines
|
||||
`MACHINE_MIN_PORT` and/or `MACHINE_MAX_PORT` in its header to override the
|
||||
defaults.
|
||||
|
||||
The device product string is what the CLI or the Web-Interface will print to identify the device; `machine.h` includes it by name.
|
||||
|
||||
> [!NOTE]
|
||||
> `machine_name` is a `char[30]` and `MACHINE_MODEL` is copied into it at
|
||||
> compile time. A longer model string still builds, but SDCC emits
|
||||
> `warning 147: excess elements in array of chars initializer` and the name is
|
||||
> truncated in the UI. Keep it to 29 characters or less.
|
||||
|
||||
## Step 2: the board definition
|
||||
|
||||
`machine/<NAME>.c` starts with the shared prelude and then defines the single
|
||||
`machine` object. Copy the closest existing board and adjust it — do not start
|
||||
from a blank file, the field meanings are easier to see in a real example.
|
||||
The best choice is usually a device that has the same number and type of Ethernet
|
||||
ports and the same number of SFP+ cages.
|
||||
|
||||
```c
|
||||
#include "machine_defs.h"
|
||||
|
||||
__code const struct machine machine = {
|
||||
MACHINE_COMMON_SETTING,
|
||||
.n_sfp = 1,
|
||||
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
|
||||
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
|
||||
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
|
||||
.sfp_port[0].pin_los = GPIO37,
|
||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||
.sfp_port[0].sds = 1,
|
||||
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
|
||||
.reset_pin = GPIO_NA,
|
||||
|
||||
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
|
||||
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
||||
.led_sets = {
|
||||
{ /* RJ45 ports */
|
||||
LEDS_2G5 | LEDS_LINK,
|
||||
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
0
|
||||
}, { /* SFP port, single green LED */
|
||||
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
`MACHINE_COMMON_SETTING` (from `machine_defs.h`) initializes `machine_name` and
|
||||
`isRTL8373` from the header's `MACHINE_MODEL` and `MACHINE_CHIPSET`. The logical
|
||||
port range comes from `MACHINE_MIN_PORT` and `MACHINE_MAX_PORT` in `machine.h`.
|
||||
Keep it as the first initializer and list the board-specific fields after it.
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | Meaning |
|
||||
|-------|---------|
|
||||
| `MACHINE_COMMON_SETTING` | expands to `machine_name` (`MACHINE_MODEL`) and `isRTL8373` (`1` for `RTL8373`, `0` for `RTL8372`); both are derived from the header's `MACHINE_CHIPSET` (see Step 1) |
|
||||
| `n_sfp` | number of SFP+ cages |
|
||||
| `n_10g` | SerDes 10G capability used by the RTL837xN init: `0` none, `1` one, `2` two 10G-capable SerDes |
|
||||
| `log_to_phys_port[9]` | logical port (0-based index) → physical front-panel port number |
|
||||
| `phys_to_log_port[9]` | the inverse, physical port 1 is index 0, unused slots are 0 |
|
||||
| `is_sfp[9]` | `0` for copper, `1` for left slot and `2` for right slot |
|
||||
| `sfp_port[2]` | per-cage wiring, `sfp_port[0]` is the leftmost cage |
|
||||
| `reset_pin` | GPIO of the reset button, `GPIO_NA` if unpopulated |
|
||||
| `high_leds` | mux/enable for the LED pins 27–29 (`LED_27`, `LED_28_SYS`, `LED_29`) |
|
||||
| `port_led_set[9]` | which LED set (0–3) each logical port uses |
|
||||
| `led_sets[4][4]` | Each port can have up to 4 GPIO output pins assigned. 4 sets of LEDs with 4 LED-conditions per set; the conditions define which GPIO pins become active for a port given a port link-state. Which LEDs are then enabled depends on the wiring of the pins to up to 3 LEDs for that port, which can make a logical combination of the 4 LED output-pins. |
|
||||
| `led_mux_custom` / `led_mux[28]` | `1` plus the 28 mux values when the stock LED muxing does not fit the board |
|
||||
| `mac_flash_offset` | flash offset of the factory MAC address, omit or `0` if the board does not store one |
|
||||
|
||||
Each `struct sfp_port` entry holds `pin_detect`, `pin_los`, `pin_tx_disable`,
|
||||
`sds` (which SerDes drives the cage) and `i2c` (built with `I2CBUS(sda, scl)`,
|
||||
or `GPIO_NA`-based values where a cage has no such pin).
|
||||
|
||||
`I2CBUS(...)` only accepts the pin pairs listed in `machine_defs.h`. A wrong
|
||||
pair is caught at compile time: SDCC reports
|
||||
`error 176: sizeof applied to an incomplete type` pointing at the offending
|
||||
`.i2c` line, because the macro deliberately turns an invalid bus number into an
|
||||
array of size 0.
|
||||
|
||||
### Reusing an existing definition
|
||||
|
||||
If the new board is electrically identical to one that already exists — same
|
||||
port mapping, same SFP wiring, same LEDs — do not copy the file. Make the new
|
||||
`.c` a symlink and keep only a distinct `.h`, so the two boards cannot drift
|
||||
apart:
|
||||
|
||||
```
|
||||
ln -s KP_9000_6XHML_X2.c machine/MY_BOARD_1_0.c
|
||||
```
|
||||
|
||||
The new board still needs `machine/MY_BOARD_1_0.h` (pick the version number on
|
||||
the PCB) with its own `MACHINE_MODEL` and `MACHINE_CHIPSET`: `MACHINE_MODEL` is
|
||||
what distinguishes the products, and `MACHINE_CHIPSET` must match the SoC of
|
||||
the board definition being reused.
|
||||
Existing examples: `machine/PCB_K0402WS_V3.c`, `machine/KP_9000_9XHML_X_V3_2.c`
|
||||
and the six `KP_9000_*` revision variants.
|
||||
|
||||
Two files that differ only in whitespace or comments are duplicates and should
|
||||
be collapsed this way.
|
||||
|
||||
### Optional custom init hook
|
||||
|
||||
If the board needs custom initialization, add
|
||||
`machine/<NAME>_init.c` defining `machine_custom_init()`. The Makefile picks the
|
||||
file up by name and compiles it.
|
||||
|
||||
Boards that need the same hook share one file: keep the code in a single
|
||||
`machine/<NAME>_init.c` whose `machine/<NAME>.c` is a real file (not a symlink),
|
||||
and make the other boards' `_init.c` symlinks to it, for example:
|
||||
|
||||
```
|
||||
ln -s KP_9000_6XH_X2_init.c machine/MY_BOARD_1_0_init.c
|
||||
```
|
||||
|
||||
## Step 3: build and verify
|
||||
|
||||
```
|
||||
make MACHINE=MY_BOARD_1_0
|
||||
```
|
||||
|
||||
The generated flash image appears as `output/rtlplayground-<version>-MY_BOARD_1_0.bin`. An
|
||||
unknown or empty `MACHINE` fails immediately with a message naming the expected
|
||||
file, before anything is compiled.
|
||||
|
||||
Then run the checks CI runs:
|
||||
|
||||
```
|
||||
make machine_check # compiles machine/<NAME>.c and its optional _init.c for every machine
|
||||
make -C test # host-side unit tests
|
||||
```
|
||||
|
||||
`make machine_check` discovers the definitions with
|
||||
`$(wildcard machine/*.c)`, so a new file is covered without registering it
|
||||
anywhere. CI (`.github/workflows/build.yml`) runs it on every push and pull
|
||||
request, alongside full builds for a 4+2 and an 8+1 board.
|
||||
|
||||
A successful compile only proves the definition is syntactically valid. The
|
||||
actual behaviour — port numbering, SFP detection, LEDs — has to be confirmed on
|
||||
hardware, and the console commands (`port`, `stat`, `sfp`, `leds`) are the
|
||||
tools for that.
|
||||
|
||||
## Step 4: documentation
|
||||
|
||||
Once the board has been tested on hardware:
|
||||
|
||||
1. Add a row to the table in [Supported devices](supported_devices.md).
|
||||
2. Add `doc/devices/<name>.md` describing the board, the build target
|
||||
(`make MACHINE=MY_BOARD_1_0`), what works and what is unverified, plus
|
||||
photos and the PCB silkscreen marking.
|
||||
3. If the board shares a PCB with other revisions, follow
|
||||
`doc/devices/KP-9000-6XH-X2.md` and document which `MACHINE` to pick for
|
||||
which silkscreen.
|
||||
|
||||
### Identifying the CPU variant
|
||||
|
||||
For RTL8373-based devices, use the read-only console command below to distinguish
|
||||
the N and non-N CPU variants:
|
||||
|
||||
```text
|
||||
regget 4
|
||||
```
|
||||
|
||||
| Register 0x0004 value | CPU |
|
||||
|---|---|
|
||||
| `0x83730000` | RTL8373 (non-N) |
|
||||
| `0x83737000` | RTL8373N |
|
||||
|
||||
Record the identified CPU in the device documentation. These values identify
|
||||
only the CPU variant; document PHY and flash-chip models separately when verified.
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
hongyavision HYWS-SGT0204S
|
||||
|
||||
RTL8372-based 4×2.5G + 2×SFP+ unmanaged switch.
|
||||
|
||||
Also marked on the PCB as `2G5F4_10G2_V1.01`.
|
||||
|
||||
Stock firmware runs a factory test console on UART at 9600 baud 8N1 (banner
|
||||
`RTL8371B start`, prompt `RTL8371B:`). There is no management CLI and no Web
|
||||
interface.
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation and update.
|
||||
Erase the whole chip and verify the write (`flashrom -v`) before powering the
|
||||
board, so an incomplete write is caught before the board is powered up.
|
||||
|
||||
Stock flash chip is 512 KB (Bright Moon `T25S40`, 4 Mbit, SOP-8), which the
|
||||
RTLPlayground image fills exactly.
|
||||
|
||||
### Label specifications
|
||||
|
||||
Case, top / front / nameplate:
|
||||
|
||||
<img src="photos/2G5F4_10G2_V1.01/assembled-top.jpg" width="300" />
|
||||
<img src="photos/2G5F4_10G2_V1.01/assembled-front.jpg" width="300" />
|
||||
<img src="photos/2G5F4_10G2_V1.01/assembled-bottom.jpg" width="300" />
|
||||
|
||||
- **Manufacturer**: hongyavision (Shenzhen Hongyavision Electronic Technology
|
||||
Co., Ltd.)
|
||||
- **Model**: HYWS-SGT0204S — the nameplate is printed in Chinese and reads
|
||||
"10/100/1000/2500M fibre switch" and "4x 2.5G copper port + 2x 10G SFP+
|
||||
optical port"
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1G / 2.5G / 10G
|
||||
- **Power**: 12 V DC, 2 A
|
||||
- **Serial number**: `S/N-YYYYMMDDNNNN`, e.g. `S/N-202312010028`
|
||||
|
||||
The top of the case only carries generic printing ("2.5G+10G High Speed Fiber
|
||||
Transceiver / 4-Port 2.5G Ethernet Switch+10G Fiber"), so the nameplate on the
|
||||
bottom is what identifies the device.
|
||||
|
||||
### What works
|
||||
|
||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- Both SFP+ ports supporting 1G, 2.5G and 10G modules
|
||||
- Copper LEDs: white (2.5G) and blue (link/activity)
|
||||
- SFP LEDs: one single LED per port (link/activity)
|
||||
- SFP EEPROM and DDM readable on both cages, verified with a 10G module
|
||||
(`Rate: 0x67`, module identity and DDM values via the `sfp` console command)
|
||||
- Serial console at 115200 8N1 (RTLPlayground) / 9600 8N1 (stock)
|
||||
|
||||
### Not verified
|
||||
|
||||
- The reset button footprint is unpopulated and the case has no opening for it,
|
||||
so it could not be tested.
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: `2G5F4_10G2_V1.01`
|
||||
|
||||
**Key components**
|
||||
- Main switch: RTL8372 (RTL8371B family), reported as `RTL8372` (non-N) by
|
||||
RTLPlayground. The chip sits under a heatsink and its package marking is not
|
||||
readable.
|
||||
- U1: SPI NOR flash, Bright Moon `T25S40`, 4 Mbit / 512 KB, SOP-8
|
||||
- A 3-hole reset button footprint is present but unpopulated, and the case has
|
||||
no opening for it, so there is no usable reset button
|
||||
|
||||
Top side:
|
||||
|
||||
<img src="photos/2G5F4_10G2_V1.01/pcb_top.jpg" width="600" />
|
||||
|
||||
Bottom:
|
||||
|
||||
<img src="photos/2G5F4_10G2_V1.01/pcb_bottom.jpg" width="600" />
|
||||
|
||||
The stock flash chip, Bright Moon `T25S40` (SOP-8, 4 Mbit / 512 KB):
|
||||
|
||||
<img src="photos/2G5F4_10G2_V1.01/flash_t25s40.jpg" width="300" />
|
||||
|
||||
### Port layout
|
||||
|
||||
| Front panel position | Logical port | Physical port | Type |
|
||||
|----------------------|--------------|---------------|---------|
|
||||
| SFP left | 8 | 5 | SFP+ |
|
||||
| RJ45 1 | 4 | 1 | Copper |
|
||||
| RJ45 2 | 5 | 2 | Copper |
|
||||
| RJ45 3 | 6 | 3 | Copper |
|
||||
| RJ45 4 | 7 | 4 | Copper |
|
||||
| SFP right | 3 | 6 | SFP+ |
|
||||
|
||||
Copper ports 1–4 match the KP-9000-6XH-X2 (2M-PCB43-V1.1) layout, which this
|
||||
board is a sibling of. The two SFP+ cages are wired the other way round
|
||||
compared to that board: physical port 5 is on SDS1 and physical port 6 is on
|
||||
SDS0.
|
||||
|
||||
### Serial console
|
||||
|
||||
The board has three through-holes used as the serial console, next to the
|
||||
heatsink in the middle of the board and visible in the top side photo above (the
|
||||
silkscreen labels are printed rotated by 90°). **The silkscreen labels are
|
||||
wrong**: they are shifted relative to the actual signals.
|
||||
|
||||
| Silkscreen label | Actual signal |
|
||||
|------------------|---------------|
|
||||
| TX | GND |
|
||||
| RX | TX |
|
||||
| GND | RX |
|
||||
|
||||
Wiring (following the measured signals, not the labels):
|
||||
|
||||
| USB-TTL adapter | Board pad |
|
||||
|-----------------|----------------------|
|
||||
| GND | pad labelled `TX` |
|
||||
| RX | pad labelled `RX` |
|
||||
| TX | pad labelled `GND` |
|
||||
|
||||
- **Settings**: 115200 baud / 8N1 / 3.3V TTL (RTLPlayground), 9600 baud for the
|
||||
stock firmware
|
||||
- The stock firmware only prints a few bytes and a factory test menu
|
||||
(`?`, `rst`, `f`, `r`, `10`, `100`, `g1`, `sd`, `eye`, …); it is not an
|
||||
interactive management console
|
||||
|
||||
### LED configuration
|
||||
|
||||
Case silkscreen, below the RJ45 ports:
|
||||
|
||||
```
|
||||
White : 2.5G Blue : 1000M/2500M L/A
|
||||
```
|
||||
|
||||
The front panel also carries a `PWR` LED and one LED per SFP cage (`SFP1`,
|
||||
`SFP2`) on the right hand side.
|
||||
|
||||
| Port | LED | Linked, idle | With traffic |
|
||||
|------------|--------------|--------------|--------------|
|
||||
| Copper | white | 2.5G only | same |
|
||||
| Copper | blue | solid | blinks (L/A) |
|
||||
| SFP | single LED | solid | blinks (L/A) |
|
||||
|
||||
Measured LED-ID mapping (from the RTL837x LED set registers):
|
||||
|
||||
| LED-ID | Function |
|
||||
|--------|---------------------------------|
|
||||
| LED-ID0| copper blue LED |
|
||||
| LED-ID1| copper white LED |
|
||||
| LED-ID2| SFP single LED |
|
||||
|
||||
**Important**: `RTL837X_REG_LED_GLB_IO_EN` bit 6 must be set in
|
||||
`machine_custom_init()`. Without it the RTL837x "solid" conditions (LINK/speed)
|
||||
do not drive the LEDs at all and only `ACT` does, which makes the white LED
|
||||
glow faintly at non-2.5G speeds.
|
||||
|
||||
### SFP GPIO assignments
|
||||
|
||||
| SFP | pin\_detect (ModAbs) | pin\_los | SerDes | I2C SDA | I2C SCL |
|
||||
|-------------------|-------------------------------|------------------|--------|-------------------------|--------------------------|
|
||||
| Left (logical 8, physical 5) | GPIO30\_ACL\_BIT3\_EN | GPIO37 | SDS1 | GPIO39\_I2C\_SDA4 | GPIO40\_I2C\_SCL3\_MDC1 |
|
||||
| Right (logical 3, physical 6)| GPIO50\_I2C\_SCL2\_UART1\_TX | GPIO10\_LED10 | SDS0 | GPIO41\_I2C\_SDA3\_MDIO1 | GPIO40\_I2C\_SCL3\_MDC1 |
|
||||
|
||||
`pin_tx_disable` is GPIO\_NA on both ports. Both I2C buses are confirmed
|
||||
working: with the same 10G module inserted, the `sfp` console command reads its
|
||||
vendor and model from the left cage (`Slot 1`) and from the right cage
|
||||
(`Slot 2`), DDM values included. The insertion also shows which SerDes drives
|
||||
each cage - the left cage reports `sds_config sds: 01` and the right cage
|
||||
`sds: 00`, which matches the table above.
|
||||
|
||||
### Machine target
|
||||
|
||||
Build for this device with `make MACHINE=2G5F4_10G2_V1_01`, which selects the
|
||||
`machine/2G5F4_10G2_V1_01.c` board definition. It is derived from
|
||||
`machine/KP_9000_6XHML_X2.c` with the SFP cage order and the reset pin changed.
|
||||
The fitted T25S40 cannot be read in DIO mode on this board: an image that leaves
|
||||
DIO enabled does not come up at all, both at the default read clock divider of 4
|
||||
and at 8 (two boards tested), while the same image with single-IO boots and runs
|
||||
normally. The board definition therefore sets `flash_sio`, which makes
|
||||
`flash_init()` use `CMD_FREAD` at divider 8. Only the management plane is
|
||||
slower, the ASIC keeps forwarding in hardware.
|
||||
@@ -0,0 +1,40 @@
|
||||
### 2M-PCB23-V3.2
|
||||
|
||||
## Brands
|
||||
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|
|
||||
| keepLINK | KP-9000-9XHML-X | Yes| 2M-PCB23-V3.2 | 2M (Winbond 25Q) | |
|
||||
|
||||
The original web interface reports this board as hardware version V3.2
|
||||
(original firmware V100.9.25, January 2026).
|
||||
|
||||
## PCB
|
||||
|
||||
<img src="photos/2M-PCB23-V3.2-managed/2M-PCB23-V3.2-top.jpeg" width="300" />
|
||||
|
||||
## Compared to V3.1
|
||||
|
||||
The component placement matches [2M-PCB23-V3.1](2M-PCB23-V3_1.md): same
|
||||
positions for the flash (U8), the T7/T8/T9/T10 headers, the SFP cage and its
|
||||
LED, and the unpopulated U7/U9 footprints. Build with
|
||||
`make MACHINE=KP_9000_9XHML_X_V3_2`, whose board file is a symlink to the V3.1
|
||||
definition and only differs in the reported name.
|
||||
|
||||
## Tested
|
||||
|
||||
Installed from the original firmware through its web interface with
|
||||
`installer/output/rtlplayground_oem_upgrade.bin`, then:
|
||||
|
||||
- RJ45 ports link at 2.5G; LEDs: orange at 2.5G, green below
|
||||
- SFP port: module detected with vendor/model/serial and DOM readings
|
||||
(temperature, Vcc, TX bias, TX/RX power), link up at 10G
|
||||
- factory MAC read from flash (0x1FC000)
|
||||
- reset button (GPIO48): held for more than 10 s it restores the default config
|
||||
|
||||
## Flash access
|
||||
|
||||
Reading the flash in-circuit with a SOIC-8 clip did not work: the chip ID
|
||||
comes back as `EF FF FF` (only the manufacturer byte is right) and reads
|
||||
return 0xff, the same as on a V3.1 board. The switch chip is powered through
|
||||
the clip and keeps driving the SPI lines. Make sure a way back is acceptable
|
||||
before installing, or hold the switch chip in reset while reading.
|
||||
@@ -15,7 +15,7 @@ and sold by Mokerlink.
|
||||
The device is fully supported:
|
||||
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||
- The SFP+ port supports 1G, 2.5G and 10G modules
|
||||
- LEDs work with the same indiciations as the OEM firmware (use KP_9000_6XHML_X2_V1_1 in machine.h if building yourself or the corresponding pre-compiled binary)
|
||||
- LEDs work with the same indiciations as the OEM firmware (build with `make MACHINE=KP_9000_6XHML_X2_V1_1` if building yourself, or use the corresponding pre-compiled binary)
|
||||
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
|
||||
|
||||
### Hardware overview
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
# MokerLink POE-2G080110GS
|
||||
|
||||
The `POE-2G080110GS` is an unmanaged 8x2.5G RJ45 and 1xSFP+ PoE switch sold by Mokerlink. There is also a `POE-2G080110GSM` managed version of the switch which may be similar but this has not been verified on actual hardware.
|
||||
The`KP-9000-9XHP-X` is the KeepLink rebrand for same product.
|
||||
|
||||
## Brands
|
||||
| Brand | Type |Managed| PCB | Flash | Chip RTL |
|
||||
|--------|------------------|-------|------------------|-----------------|---------------|
|
||||
| Mokerlink | POE-2G080110GS | No | 2M-PCB51-ML-V1.1 | 4MB (W25Q32JV) | 8373N + 8224N |
|
||||
| KeepLink | KP-9000-9XHP-X | No | 2M-PCB51-ML-V1.1 | 4MB (W25Q32JV) | 8373N + 8224N |
|
||||
|
||||
## Hardware overview
|
||||
Front
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# F7008-2.5
|
||||
|
||||
Documentation for the unmanaged 8 + 1 switch sold as `7018-2.5G` by Guangnianwei
|
||||
(光年微), board marking `F7008-2.5`, PCB `F7008-2.5GPOE-V1.2`.
|
||||
|
||||
### Brands
|
||||
|
||||
| Brand | Type | Managed | PCB | Flash | Chip RTL |
|
||||
|-------|------|---------|-----|-------|----------|
|
||||
| Guangnianwei (光年微) | 7018-2.5G | No | F7008-2.5GPOE-V1.2 | W25Q64JVSSIQ | 8373N + 8224N |
|
||||
|
||||
### What works
|
||||
|
||||
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- SFP+ port with 1G/2.5G/10G modules
|
||||
- LEDs of the eight RJ45 ports
|
||||
|
||||
### Not verified
|
||||
|
||||
- The LED pads for the SFP+ cage are not mapped yet. The SFP+ lamps are left
|
||||
undriven, so an inserted module lights nothing.
|
||||
- The UART header footprint is present but unpopulated, and no boot log could be
|
||||
captured from it, so the baud rate is unknown. There are most likely
|
||||
unpopulated 0-Ohm resistors next to the header; bridging those should bring
|
||||
the console to life.
|
||||
|
||||
### Build target
|
||||
|
||||
```
|
||||
make MACHINE=F7008_2_5
|
||||
```
|
||||
|
||||
### LED wiring
|
||||
|
||||
Measured pad to lamp map (`led_mux` index -> lamp):
|
||||
|
||||
| Port | green lamp | yellow lamp |
|
||||
|------|-----------|-------------|
|
||||
| 1 | pad 0 | pad 1 |
|
||||
| 2 | pad 2 | pad 3 |
|
||||
| 3 | pad 4 | pad 5 |
|
||||
| 4 | pad 6 | pad 8 |
|
||||
| 5 | pad 9 | pad 10 |
|
||||
| 6 | pad 12 | pad 15 |
|
||||
| 7 | pad 18 | pad 21 |
|
||||
| 8 | pad 24 | pad 25 |
|
||||
|
||||
Pads 7, 11, 13, 14, 16, 17, 19, 20, 22, 23, 26 and 27 do not drive an RJ45 lamp.
|
||||
|
||||
The front panel is silkscreened `2.5G: Green / 10/100M: Yellow`, and the target
|
||||
follows it: the green lamp is on while the port is linked at 2.5G, the yellow
|
||||
lamp blinks while data is flowing.
|
||||
|
||||
### PCB overview
|
||||
|
||||
The board is marked `F7008-2.5GPOE-V1.2`.
|
||||
|
||||
Top side:
|
||||
|
||||
<img src="photos/F7008-2.5/PCB-top.jpg" width="600" />
|
||||
|
||||
Bottom side:
|
||||
|
||||
<img src="photos/F7008-2.5/PCB-bottom.jpg" width="600" />
|
||||
|
||||
### Hardware notes
|
||||
|
||||
- 4 x `RT4802SNE` magnetics
|
||||
- Unpopulated UART header footprint, next to the magnetics
|
||||
- Power input 12V 1A, 180 x 84 x 29 mm metal case
|
||||
@@ -0,0 +1,75 @@
|
||||
# Hasivo S1100WP-8GT-1SX-SE
|
||||
|
||||
RTL8373-based 8×2.5G PoE + 1×SFP switch.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Manufacturer**: Hasivo
|
||||
- **Model**: S1100WP-8GT-1SX-SE
|
||||
- **Ports**:
|
||||
- 8 × RJ45: 10/100/1000/2500 Mbps with PoE
|
||||
- 1 × SFP: 1G / 2.5G / 10G
|
||||
- **Power input**: DC 52V 2.5A
|
||||
- **Stock firmware defaults**: IP 192.168.0.1, user/password `admin`/`admin`
|
||||
|
||||
### What works
|
||||
|
||||
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps (PoE is not configurable via RTLPlayground)
|
||||
- SFP port supporting 1G, 2.5G and 10G modules
|
||||
- LEDs: green (2.5G) and amber (1G/100M/10M) per copper port; combined link/act on the SFP port
|
||||
|
||||
### Photos
|
||||
|
||||
Front panel:
|
||||
|
||||
<img src="photos/HASIVO_S1100WP-8GT-1SX-SE/front.jpg" width="600" />
|
||||
|
||||
Label:
|
||||
|
||||
<img src="photos/HASIVO_S1100WP-8GT-1SX-SE/label.jpg" width="600" />
|
||||
|
||||
### PCB overview
|
||||
|
||||
Top side:
|
||||
|
||||
<img src="photos/HASIVO_S1100WP-8GT-1SX-SE/pcb_top.jpg" width="600" />
|
||||
|
||||
Bottom side:
|
||||
|
||||
<img src="photos/HASIVO_S1100WP-8GT-1SX-SE/pcb_bottom.jpg" width="600" />
|
||||
|
||||
### Port layout
|
||||
|
||||
| Logical port | Physical port | Type |
|
||||
|--------------|---------------|--------|
|
||||
| 1-8 | 1-8 | Copper |
|
||||
| 9 | 9 | SFP |
|
||||
|
||||
### LED configuration
|
||||
|
||||
Copper ports use LED SET0, the SFP port uses LED SET1.
|
||||
|
||||
| SET | LED0 | LED2 |
|
||||
|------|-----------------------------------------------|------------------------------------------------------|
|
||||
| SET0 | Green — lights on 2.5G link with activity | Amber — lights on 1G / 100M / 10M link with activity |
|
||||
| SET1 | All speeds — lights on any link with activity | — |
|
||||
|
||||
### SFP GPIO assignments
|
||||
|
||||
| SFP (logical 9) | pin_detect (ModAbs) | pin_los | pin_tx_disable | SerDes | I2C SDA | I2C SCL |
|
||||
|-----------------|---------------------|---------|----------------|--------|-----------------|---------------------|
|
||||
| SFP | GPIO30_ACL_BIT3_EN | GPIO37 | GPIO_NA | SDS1 | GPIO39_I2C_SDA4 | GPIO40_I2C_SCL3_MDC1 |
|
||||
|
||||
### Machine configuration
|
||||
|
||||
- `reset_pin`: GPIO54_ACL_BIT2_EN
|
||||
- High LEDs (pads 27-29): mux = `LED_27 | LED_28_SYS | LED_29`, enable = `LED_28_SYS | LED_29`
|
||||
|
||||
### PoE
|
||||
|
||||
The 8 copper ports support PoE powered by a DC 52V 2.5A input. Power management is handled by two HS104PTI chipsets over I2C (GPIO47_I2C_SDA0, GPIO46_I2C_SCL0):
|
||||
|
||||
* Chip 1 (I2C address 0x1A): 2.5G Ports 1–4
|
||||
* Chip 2 (I2C address 0x2A): 2.5G Ports 5–8
|
||||
|
||||
Note: The current implementation does not yet support PoE management. Consequently, PoE currently operates in standalone mode without software control.
|
||||
@@ -0,0 +1,64 @@
|
||||
# Lianguo HYWS-SGT0108S
|
||||
|
||||
Following is documentation for unmanaged switch marked as `HYWS-SGT0108S`.
|
||||
|
||||
Original software is running UART on 9600 baud rate. Output is very minimal.
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation and update.
|
||||
|
||||
Stock flash chip is 512KB in size. Consider replacing for update through Web UI.
|
||||
|
||||
- Header for uart is clearly identified.
|
||||
- The red LED act as a powered-on LED.
|
||||
- There is no SYS LED.
|
||||
- There is a footprint for a Reset button. Unpopulated. Unclear if routed back to RTL8373.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**: 2.5G Ethernet Switch 8+1
|
||||
- **Model**: HYWS-SGT0108S
|
||||
- **Ports**:
|
||||
- 8 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 1 × SFP: 1000 / 2500 / 10000 Mbps
|
||||
|
||||
### What works
|
||||
|
||||
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- SFP port supporting 1G, 2.5G and 10G modules
|
||||
- RJ45 LEDs (Blue+White)
|
||||
- SFP Single LED (Blue)
|
||||
|
||||
### Assembled unit
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/HYWS-SGT0108S-unmanaged\Assembled-top.jpg" width="300" />
|
||||
|
||||
Front
|
||||
|
||||
<img src="photos/HYWS-SGT0108S-unmanaged\Assembled-front.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/HYWS-SGT0108S-unmanaged\Assembled-bottom.jpg" width="300" />
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: 2G5F_20G_V1.01 / 2023-09-28
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/HYWS-SGT0108S-unmanaged\PCB-top.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/HYWS-SGT0108S-unmanaged\PCB-bot.jpg" width="300" />
|
||||
|
||||
Original SPI Flash Chip
|
||||
|
||||
<img src="photos/HYWS-SGT0108S-unmanaged\og_spi_flash.jpg" width="300" />
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
@@ -0,0 +1,41 @@
|
||||
# Hasivo S1100P-8GT-1SX-S
|
||||
|
||||
RTL8373N switch with 8 × 2.5G RJ45 ports and 1 × SFP port. GD25Q16 2 MiB flash.
|
||||
|
||||
## Port mapping
|
||||
|
||||
| Front port | ASIC MAC | Interface |
|
||||
| --- | --- | --- |
|
||||
| 1–8 | 0–7 | RJ45 |
|
||||
| 9 | 8 | SFP (SDS1) |
|
||||
|
||||
## Board signals
|
||||
|
||||
| Function | GPIO |
|
||||
| --- | --- |
|
||||
| SFP detect | 38 |
|
||||
| SFP LOS | 37 |
|
||||
| SFP TX disable | Not connected (`GPIO_NA`) |
|
||||
| SFP I2C SDA / SCL | 39 / 40 |
|
||||
| Reset | 54 |
|
||||
|
||||
PoE is managed by an RTL8238B and a separate STC8H8K64U controller, not directly by the RTL8373N. RTLPlayground does not control PoE on this board.
|
||||
|
||||
## Build
|
||||
|
||||
`make MACHINE=HASIVO_S1100P_8GT_1SX_S CI=1`
|
||||
|
||||
## Photos
|
||||
|
||||
Front panel:
|
||||
|
||||

|
||||
|
||||
PCB top:
|
||||
|
||||

|
||||
|
||||
PCB bottom:
|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
# ONT-S207CW-62TS-SE / Binardat 2G06-04210GSM / Binardat 2G06-04210GS
|
||||
|
||||
## Overview
|
||||
|
||||
ONT-S207CW-62TS-SE, Binardat 2G06-04210GSM (managed), and Binardat 2G06-04210GS (unmanaged) are **switches with identical hardware**:
|
||||
- **CPU:** RTL8372N (confirmed via serial: "Detecting CPU: RTL8372N")
|
||||
- **Flash:** GD25Q128E (16MB)
|
||||
- **Ports:** 4x 2.5G RJ45 + 2x 10G SFP+
|
||||
- **Console:** 115200 baud (RTLPlayground firmware) / 9600 baud (stock firmware)
|
||||
|
||||
**Note:** These devices are **RTL8372N-based** with **LAN ports mounted upside-down on the PCB**, requiring a custom configuration. The `MACHINE_ONT_S207CW_62TS_SE` definition uses a **custom configuration** with:
|
||||
- Corrected port mapping (physical ports 1-4 = RJ45, 5-6 = SFP)
|
||||
- Optimized LED sets for different port wiring (RJ45 Ports 1-2 have reversed LED wiring)
|
||||
- Custom LED mux configuration
|
||||
|
||||
## Device Photos
|
||||
|
||||
### Binardat 2G06-04210GSM
|
||||
|
||||
**Front View:**
|
||||
<img src="photos/ONT-S207CW-Binardat-2G06-04210GSM/binardat-2g06-04210gsm-front.jpg" width="400" />
|
||||
|
||||
**Back View:**
|
||||
<img src="photos/ONT-S207CW-Binardat-2G06-04210GSM/binardat-2g06-04210gsm-back.jpg" width="400" />
|
||||
|
||||
**PCB View:**
|
||||
<img src="photos/ONT-S207CW-Binardat-2G06-04210GSM/binardat-2g06-04210gsm-pcb.jpg" width="400" />
|
||||
|
||||
*Photos courtesy of [andreas5232](https://github.com/andreas5232) from [emesix/ONT-S207CW-62TS-SE#1](https://github.com/emesix/ONT-S207CW-62TS-SE/issues/1)*
|
||||
|
||||
## Hardware Specification
|
||||
|
||||
| Feature | Value |
|
||||
|---|---|
|
||||
| **CPU** | RTL8372N |
|
||||
| **Flash** | GD25Q128E (16MB) |
|
||||
| **RAM** | Integrated in RTL8372N |
|
||||
| **RJ45 Ports** | 4x 2.5GBase-T (Ports 1-4) |
|
||||
| **SFP+ Ports** | 2x 10G (Ports 5-6) |
|
||||
| **Console** | UART (115200 baud for RTLPlayground, 9600 baud for stock) |
|
||||
| **Stock Web UI IP** | 192.168.2.1 |
|
||||
| **Loader Mode IP** | 192.168.10.247 |
|
||||
|
||||
## Port Layout
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
|
||||
│ │RJ45 │ │RJ45 │ │RJ45 │ │RJ45 │ │SFP+ │ │SFP+ │ │
|
||||
│ │ 1 │ │ 2 │ │ 3 │ │ 4 │ │ 5 │ │ 6 │ │
|
||||
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
|
||||
│ │
|
||||
│ [System LEDs] │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## LED Behavior
|
||||
|
||||
### RJ45 Ports (Physical 1-4)
|
||||
|
||||
| LED Color | Speed |
|
||||
|---|---|
|
||||
| **Green** | 2.5G |
|
||||
| **Orange** | 1G / 100M / 10M |
|
||||
| **Off** | No link |
|
||||
|
||||
### SFP+ Ports (Physical 5-6)
|
||||
|
||||
| LED Color | Speed |
|
||||
|---|---|
|
||||
| **Green** | 10G |
|
||||
| **Orange** | 2.5G / 1G |
|
||||
| **Off** | No link / No SFP module |
|
||||
|
||||
## Port to Logical Mapping
|
||||
|
||||
Custom mapping for ONT-S207CW-62TS-SE:
|
||||
|
||||
| Physical Port | Logical Port | Type | LED Set |
|
||||
|---|---|---|---|
|
||||
| 1 | 7 | RJ45 | 2 |
|
||||
| 2 | 6 | RJ45 | 2 |
|
||||
| 3 | 5 | RJ45 | 0 |
|
||||
| 4 | 4 | RJ45 | 0 |
|
||||
| 5 | 3 | SFP+ (SDS0) | 3 |
|
||||
| 6 | 8 | SFP+ (SDS1) | 3 |
|
||||
|
||||
**Note:** Ports 1-2 (RJ45) have reversed LED wiring and use LED-Set 2. SFP Ports 5-6 use LED-Set 3 to account for wiring differences.
|
||||
|
||||
## Flashing Instructions
|
||||
|
||||
See the [README.md](../../README.md) for general flashing instructions.
|
||||
For compilation, use command `make MACHINE=ONT_S207CW_62TS_SE` to specify the machine.
|
||||
If you are using managed version of the switch, you can then also compile the installer and flash using GUI - run command `cd installer` and finally `make`.
|
||||
|
||||
## Stock Firmware Information
|
||||
|
||||
| Property | Value |
|
||||
|---|---|
|
||||
| **Default IP** | 192.168.2.1 (ONT) / 192.168.10.247 (Loader Mode) |
|
||||
| **Default Login** | admin/admin (may vary by OEM) |
|
||||
| **Console Baud** | 9600 (stock) / 115200 (RTLPlayground) |
|
||||
| **CPU String** | "RTL8372N" |
|
||||
| **Loader Mode IP** | 192.168.10.247 |
|
||||
|
||||
## Configuration Details
|
||||
|
||||
- **CPU:** RTL8372N
|
||||
- **SFP:** SDS0 on logical port 3 (GPIO37), SDS1 on logical port 8 (GPIO38)
|
||||
- **Port Mapping:** Physical 1-4 → Logical 7-4, Physical 5-6 → Logical 3,8
|
||||
- **LED Wiring:** RJ45 Ports 1-2 and SFP Port 6 have reversed LED pins (orange/green swapped)
|
||||
- **LED Sets:** Set 0 for RJ45 Ports 3-4, Set 1 unused, Set 2 for RJ45 Ports 1-2, Set 3 for SFP Ports 5-6
|
||||
|
||||
## Notes
|
||||
|
||||
- ONT-S207CW-62TS-SE, Binardat 2G06-04210GSM (managed), and Binardat 2G06-04210GS (unmanaged) are **RTL8372N-based** with **LAN ports mounted upside-down on the PCB**
|
||||
- Web UI shows correct physical port order (1-2-3-4 for RJ45, 5-6 for SFP)
|
||||
- Loader Mode always remains accessible at `192.168.10.247` for recovery
|
||||
- Serial console: 9600 baud (stock) → 115200 baud (RTLPlayground)
|
||||
|
||||
## References
|
||||
|
||||
- [GitHub Issue: emesix/ONT-S207CW-62TS-SE#1](https://github.com/emesix/ONT-S207CW-62TS-SE/issues/1) - Original photos and discussion
|
||||
- [PR: logicog/RTLPlayground#465](https://github.com/logicog/RTLPlayground/pull/465) - Feedback and improvements
|
||||
@@ -0,0 +1,53 @@
|
||||
# IG108
|
||||
|
||||
Following is documentation for unmanaged switch marked as `IG108`.
|
||||
|
||||
Original software is running UART on 9600 baud rate.
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
|
||||
### Brands
|
||||
|
||||
| Brand | Type | Managed | PCB | Flash | Chip RTL |
|
||||
|---------|------------|---------|------------|-------------|---------------|
|
||||
| Goalake | IG108 | No | PB-2132 | cFeon Q32A | 8373N + 8224N |
|
||||
| Netcore | GS9 | No | PB-2132 | cFeon Q32A | 8373N + 8224N |
|
||||
|
||||
### What works
|
||||
|
||||
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- SFP port with 1G/2.5G/10G modules
|
||||
- LEDs
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
|
||||
- Top silkscreen: PB-2132
|
||||
|
||||
Front Goalake:
|
||||
|
||||
<img src="photos/PB-2132/case.jpg" width="600" />
|
||||
|
||||
Label Goalake:
|
||||
|
||||
<img src="photos/PB-2132/label.jpg" width="600" />
|
||||
|
||||
Top side:
|
||||
|
||||
<img src="photos/PB-2132/PCB-top.jpg" width="600" />
|
||||
|
||||
Bottom:
|
||||
|
||||
<img src="photos/PB-2132/PCB-bottom.jpg" width="600" />
|
||||
|
||||
### Serial console
|
||||
|
||||
The PCB has unpopulated through-holes near the SFP Port, with description of each pin, works out of the box.
|
||||
|
||||
- **Settings**: 115200 baud / 8N1 / 3.3V TTL
|
||||
|
||||
### Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# PCB-AFGW SWTG218ANS V2.0.2
|
||||
|
||||
RTL8373-based 8×2.5G PoE + 1×10G SFP+ web-managed switch, sold as the
|
||||
**RealHD PSW8-25MG**.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Manufacturer**: RealHD
|
||||
- **Model**: PSW8-25MG
|
||||
- **PCB marking**: `PCB-AFGW SWTG218ANS_V2.0.2` (silkscreened as `PCB-AFGW SWTG218ANS_V2.0.2_23308`)
|
||||
- **Ports**:
|
||||
- 8 × RJ45: 10/100/1000/2500 Mbps with PoE
|
||||
- 1 × SFP+: 1G / 2.5G / 10G (front panel marking `9(10G)`)
|
||||
- **Power input**: internal AC PSU, `100-240V~ 50/60Hz 2A MAX`, DC output `53.5V 2.8A 150W`
|
||||
- **Front panel LEDs**: `PWR`, `SYS`, per RJ45 port `Link/Act` and `PoE`, per SFP port 2.5G (green) and 10G (blue)
|
||||
- **Stock firmware defaults**: web-managed PoE switch
|
||||
|
||||
### What works
|
||||
|
||||
- All eight 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps (PoE is not configurable via RTLPlayground)
|
||||
- SFP+ port supporting 1G, 2.5G and 10G modules
|
||||
- LEDs: green (2.5G) and amber (1G/100M/10M) per RJ45 port with activity, green (1G/2.5G) and blue (10G) on the SFP port, plus the `SYS` LED
|
||||
|
||||
### Photos
|
||||
|
||||
Front panel:
|
||||
|
||||
<img src="photos/PCB-AFGW_SWTG218ANS_V2.0.2/device_front.jpg" width="800" />
|
||||
|
||||
Board mounted in the case, with the internal PSU above it:
|
||||
|
||||
<img src="photos/PCB-AFGW_SWTG218ANS_V2.0.2/dev_top_w_pcb.jpg" width="800" />
|
||||
|
||||
### PCB overview
|
||||
|
||||
Top side:
|
||||
|
||||
<img src="photos/PCB-AFGW_SWTG218ANS_V2.0.2/pcb_front.jpg" width="800" />
|
||||
|
||||
Bottom side:
|
||||
|
||||
<img src="photos/PCB-AFGW_SWTG218ANS_V2.0.2/pcb_back.jpg" width="800" />
|
||||
|
||||
A 4-pad UART header with `RXD` / `TXD` silkscreened sits next to the right heatsink.
|
||||
|
||||
### Port layout
|
||||
|
||||
| Logical port | Physical port | Type |
|
||||
|--------------|---------------|--------|
|
||||
| 1-8 | 1-8 | RJ45 |
|
||||
| 9 | 9 | SFP+ |
|
||||
|
||||
### LED configuration
|
||||
|
||||
RJ45 ports use LED SET0, the SFP+ port uses LED SET1. The board needs the custom
|
||||
LED mux (`led_mux_custom = 1`), and `RTL837X_REG_LED_GLB_IO_EN` is written to
|
||||
`0x7f24977f` in `machine_custom_init()` so the LED pins are enabled as wired here.
|
||||
|
||||
| SET | LED pin 0 | LED pin 1 |
|
||||
|------|-----------------------------------------------|-------------------------------------------------------|
|
||||
| SET0 | Green — lights on 2.5G link with activity | Amber — lights on 1G / 100M / 10M link with activity |
|
||||
| SET1 | All speeds — lights on any link with activity | 10G — lights on 10G link with activity |
|
||||
|
||||
On the front panel this gives one bi-color `Link/Act` LED per RJ45 port (green at
|
||||
2.5G, amber at 10/100/1000M, blinking with activity) and one `PoE` LED per RJ45
|
||||
port, which is driven by the PoE hardware and not by the switch. The SFP+ port has
|
||||
a green 2.5G LED and a blue 10G LED.
|
||||
|
||||
### SFP GPIO assignments
|
||||
|
||||
| SFP (logical 9) | pin_detect (ModAbs) | pin_los | pin_tx_disable | SerDes | I2C SDA | I2C SCL |
|
||||
|-----------------|---------------------|---------|----------------|--------|------------------|----------------------|
|
||||
| SFP | GPIO38 | GPIO_NA | GPIO_NA | SDS1 | GPIO39_I2C_SDA4 | GPIO40_I2C_SCL3_MDC1 |
|
||||
|
||||
### Machine configuration
|
||||
|
||||
```
|
||||
make MACHINE=REALHD_PSW8_25MG
|
||||
```
|
||||
|
||||
### Programming
|
||||
|
||||
The serial console runs at 8N1 on 115200 baud with the RTLPlayground firmware
|
||||
(see the UART header note under *PCB overview*). The stock firmware baud rate 57600. The flash chip was 2MB.
|
||||
|
||||
### PoE
|
||||
|
||||
The 8 RJ45 ports support PoE, powered by the internal 150W AC PSU (DC output
|
||||
53.5V 2.8A) mounted above the main board.
|
||||
|
||||
Note: RTLPlayground does not provide PoE management for this board. The PoE
|
||||
hardware runs with its own configuration, the same as on the other PoE boards in
|
||||
this project.
|
||||
@@ -0,0 +1,72 @@
|
||||
# PCB-K0402WS-V1.0
|
||||
|
||||
This is the first revision of the PCB-K0402WS series of boards; it's very similar to 2.0 in terms of layout/wiring.
|
||||
|
||||
The board does have footprints for a VLAN modeswitch at the front and a second flash chip on the bottom of the PCB, but these have been seen to ship unpopulated.
|
||||
|
||||
### Brands
|
||||
|
||||
* YuanLey YS25-0402 <sup><sub>Note: there are [multiple revisions](PCB-K0402WS-V3.0.md) of the YS25-0402. This first revision lacks the "Vlan" switch cutout on the front of the enclosure.</sub></sup>
|
||||
|
||||
### Programming
|
||||
|
||||
Use a SOIC-8 clamp to the flash chip (U1 on silkscreen) at the top of the board, leaving it otherwise unpowered.
|
||||
|
||||
The board has been seen to ship with a single [BoyaMicro BY25Q16BSSIG](https://www.lcsc.com/datasheet/C382744.pdf) 16Mbit (2MiB) chip, though exact BOM may vary.
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/flash.jpg"><img src="photos/PCB-K0402WS-V1.0/flash.jpg" width="300" /></a>
|
||||
|
||||
### What works
|
||||
|
||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- Both SFP ports supporting 1G, 2.5G and 10G modules
|
||||
- LEDs (Power LED is always on)
|
||||
|
||||
### PCB overview
|
||||
|
||||
#### Board markings
|
||||
- Top silkscreen: PCB-K0402W-V1.0 / DIP-K0402WS-V1.0
|
||||
|
||||
#### Key components
|
||||
- U1: SPI NOR flash, 2 MiB
|
||||
- S1: unpopulated slide switch footprint (three through-holes used as serial console)
|
||||
|
||||
Front panel
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/ports.jpg"><img src="photos/PCB-K0402WS-V1.0/ports.jpg" width="300" /></a>
|
||||
|
||||
PCB top
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/pcb-top.jpg"><img src="photos/PCB-K0402WS-V1.0/pcb-top.jpg" width="300" /></a>
|
||||
|
||||
PCB bottom
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/pcb-bottom.jpg"><img src="photos/PCB-K0402WS-V1.0/pcb-bottom.jpg" width="300" /></a>
|
||||
|
||||
Bottom and rear
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/bottom.jpg"><img src="photos/PCB-K0402WS-V1.0/bottom.jpg" width="300" /></a>
|
||||
|
||||
### Power supply
|
||||
|
||||
Input power is delivered via a standard DC barrel jack (5.5x2.1mm) with an included 12V 1A adapter.
|
||||
|
||||
There is an optional grounding screw next to the DC input.
|
||||
|
||||
### Serial console
|
||||
|
||||
The PCB has a slide switch footprint (unpopulated) at the front right that is connected to the UART. It is labeled as "S1" on the silkscreen.
|
||||
|
||||
Facing the top front (port) side of the board, the pinout from left to right is:
|
||||
|
||||
| Position | Signal | GPIO |
|
||||
|----------|--------|-------------------|
|
||||
| 1 | RX | GPIO32\_UART0\_RX |
|
||||
| 2 | GND | N/A |
|
||||
| 3 | TX | GPIO31\_UART0\_TX |
|
||||
|
||||
Standard 0.1" / 2.54mm pin headers will not fit, so wires or clips may be used instead.
|
||||
|
||||
The image below shows some oversized clips clumsily attached.
|
||||
|
||||
<a href="photos/PCB-K0402WS-V1.0/uart.jpg"><img src="photos/PCB-K0402WS-V1.0/uart.jpg" width="300" /></a>
|
||||
@@ -19,9 +19,14 @@ of the device just above the big label, might be covered by a QC sticker.
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/Ztyuav_Z-QWYT0402_label.jpg" width="300" />
|
||||
|
||||
* Siscolink SL-G0402F
|
||||
* SICSOLINK SL-G0402F
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/SICSOLINK SL-G0402F.jpg" width="300"/>
|
||||
|
||||
* YuanLey YS25-0402 <sup><sub>Note: there are [multiple revisions](PCB-K0402WS-V1.0.md) of the YS25-0402. This is the newer revision that has a "Vlan" switch on the front.</sub></sup>
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/YuanLey_YS25-0402.jpg" width="300"/>
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/Siscolink SL-G0402F.jpg" width="300"/>
|
||||
### Programming
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
@@ -43,7 +48,7 @@ For the initial flash (at least with flashrom), the bin file produced by the bui
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-KO4022W-V3.0 / DIP-KO4022WS-V3.0
|
||||
- Top silkscreen: PCB-K0402W-V3.0 / DIP-K0402WS-V3.0
|
||||
|
||||
Top side
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
# Sirivision SR-S25G2109F (S25G1109FP V1.3)
|
||||
|
||||
RTL8373 (non-N) with an RTL8224 quad 2.5G PHY: 8 × 2.5G RJ45 + 1 × SFP+,
|
||||
2 MB flash, no PoE.
|
||||
|
||||
## Label specifications
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Manufacturer | Sirivision |
|
||||
| Model | SR-S25G2109F |
|
||||
| Ports | 8 × RJ45 10/100/1000/2500 Mbps, 1 × SFP+ 1G/2.5G/10G |
|
||||
| Power input | 12 V DC, 1.5 A |
|
||||
| Stock firmware | version 1.0.8.0 |
|
||||
| Stock defaults | IP 192.168.1.199, user `admin`, password `admin` |
|
||||
| Serial number | 001008130002003A000005 (also on the PCB barcode sticker) |
|
||||
|
||||
The label does not carry a MAC address. After a factory initialisation the
|
||||
stock firmware uses exactly the values printed on the label.
|
||||
|
||||
## PCB silkscreen and naming
|
||||
|
||||
Top side: `S25G1109FP V1.3 SIRIVISION`. That model name belongs to an unmanaged
|
||||
PoE switch; this board omits the PoE section entirely. What is actually shipped
|
||||
is the label model `SR-S25G2109F`: a simply managed, non-PoE switch. Its stock
|
||||
firmware provides a web interface, but it responds very slowly.
|
||||
|
||||
## CPU, PHY and flash
|
||||
|
||||
| Part | Identification |
|
||||
|------|----------------|
|
||||
| SoC | RTL8373, non-N: `regget 4` returns `0x83730000` and the boot console prints `Detecting CPU: RTL8373` |
|
||||
| PHY | RTL8224, reported as `RTL8224 ID: 0x82240000` |
|
||||
| Flash | GigaDevice 25Q16ESIG (U7), 2 MB, JEDEC id `c8 40 15` |
|
||||
|
||||
The two large ICs sit under soldered heatsinks, their markings are not readable.
|
||||
|
||||
## Build
|
||||
|
||||
```
|
||||
make MACHINE=S25G1109FP_V1_3 CI=1
|
||||
```
|
||||
|
||||
The resulting image can be uploaded through the web interface (`System` page)
|
||||
or the stock web UI.
|
||||
|
||||
## Port mapping
|
||||
|
||||
| Front port | ASIC MAC | Interface |
|
||||
|------------|----------|-----------|
|
||||
| 1–8 | 0–7 | RJ45 2.5G |
|
||||
| 9 | 8 | SFP+ (SDS1) |
|
||||
|
||||
## Board signals
|
||||
|
||||
| Function | GPIO |
|
||||
|----------|------|
|
||||
| SFP detect (ModAbs) | 30, low with a module inserted |
|
||||
| SFP LOS | 37, high without light |
|
||||
| SFP TX disable | not connected, `GPIO_NA` |
|
||||
| SFP I2C | SDA 39 / SCL 40, `I2CBUS(GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1)` |
|
||||
| Reset button | 54 |
|
||||
|
||||
ModAbs and LOS are separate signals here: GPIO30 tells whether a module is
|
||||
inserted, GPIO37 whether it receives light, so a module is identified even
|
||||
before the link comes up and loss of signal is reported. GPIO38 and GPIO48,
|
||||
which the 8+1 reference boards use for ModAbs and for the reset button, never
|
||||
change on this board; with GPIO38 as ModAbs the firmware believed a module was
|
||||
permanently present and retried the I2C read forever.
|
||||
|
||||
Serial console: the stock firmware runs the loader at 57600 baud and the runtime
|
||||
at 9600 baud, RTLPlayground uses 115200.
|
||||
|
||||
## Front panel
|
||||
|
||||
Each copper port has two LEDs, labelled `Link/Act` (left, yellow) and `2.5G`
|
||||
(right, green). The SFP cage has a single green `Link/Act` LED; next to it are
|
||||
a `Power` LED and the `Reset` button.
|
||||
|
||||
## LED configuration
|
||||
|
||||
Copper ports use LED set 0, the SFP port uses LED set 1:
|
||||
|
||||
| Set | Function 0 (left / SFP) | Function 1 (right) |
|
||||
|-----|-------------------------|--------------------|
|
||||
| SET0 | all speeds, link with activity | 2.5G link |
|
||||
| SET1 | all speeds, link with activity | not populated |
|
||||
|
||||
The board is wired in the stock port order — LED pin `3n+m` belongs to port
|
||||
`n+1`, LED function `m` — so the mux table is the chip default with a single
|
||||
change: the SFP LED sits on pin 25 and is driven by LED function 0, while the
|
||||
default table maps pin 25 to function 1, which is unpopulated in SET1. Without
|
||||
that change the SFP LED stays dark.
|
||||
|
||||
A speed condition alone leaves an LED dark, `LEDS_LINK` has to be set as well.
|
||||
|
||||
## Reset button
|
||||
|
||||
| Hold time while running | Effect |
|
||||
|-------------------------|--------|
|
||||
| less than 3 s | no action |
|
||||
| 3–10 s | reset the switch chip, the firmware reboots (~20 s of downtime) |
|
||||
| more than 10 s | additionally restore the default configuration |
|
||||
|
||||
The system LED blinks slowly while the button is held. Holding the button
|
||||
during power-up instead waits for the release and restores the default
|
||||
configuration when it is released after 10–30 s.
|
||||
|
||||
## MAC address
|
||||
|
||||
The factory MAC sits at `0x1FC000`, six bytes followed by `0xFF` padding. The
|
||||
stock value is a locally administered address (`1A:5D:23:47:4D:EB`), which the
|
||||
firmware rejects, so the device runs with a UUID-derived MAC (`06:…`). A valid
|
||||
globally administered address stored there is used instead.
|
||||
|
||||
## What works
|
||||
|
||||
- all eight 2.5GBASE-T ports at 10/100/1000/2500 Mbps
|
||||
- SFP+ with 10G and 1G modules, including DDM data where the module provides it
|
||||
- 10G: Finisar FCBG110SD1C05 AOC (no DDM), rate `0x67`, SerDes mode `1a`
|
||||
- 1G: ETU ESB5312-3SCD20 (DDM), rate `0x0d`, SerDes mode `04`
|
||||
- LEDs, module insert/remove detection, loss of signal reporting, reset button
|
||||
|
||||
## Unverified
|
||||
|
||||
- 2.5G SFP modules, none was available for testing
|
||||
|
||||
## Photos
|
||||
|
||||
Front panel:
|
||||
|
||||

|
||||
|
||||
Label:
|
||||
|
||||

|
||||
|
||||
PCB top side:
|
||||
|
||||

|
||||
|
||||
PCB bottom side:
|
||||
|
||||

|
||||
|
||||
Flash chip, GigaDevice 25Q16ESIG:
|
||||
|
||||

|
||||
@@ -0,0 +1,32 @@
|
||||
### SIRIVISION_S25G2206FP_V1_1
|
||||
|
||||
## Brands
|
||||
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|
|
||||
| YuanLey | YS25-0402M | Yes | SIRIVISION_S25G2206FP_V1_1 | 2M | 8372 |
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**:
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||
- **Power**: 12V DC, 1A 5525 connector
|
||||
|
||||
### What works
|
||||
The device is fully supported:
|
||||
- ALL 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||
- ALL SFP+ ports support 1G, 2.5G and 10G modules
|
||||
- LEDs work with the same indiciations as the OEM firmware
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: SIRIVISION S25G2206FP V1.1
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/SIRIVISION_S25G2206FP_V1_1/dev_pcb_top.jpg" width="300" />
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
@@ -1,9 +1,11 @@
|
||||
# SWTG018AS-A V2.0
|
||||
## Brands
|
||||
| Brand | Type |Managed| PCB | Flash | Chip RTL |
|
||||
|--------|------------------|-------|------------------|-----------------|---------------|
|
||||
| Ampcom | SWTG018AS-A V2.0 | No | SWTG018AS-A V2.0 | 2MB | 8273N + 8224N |
|
||||
| Horaco | HC-SWTGW218AS-A | Yes | SWTG018AS-A V2.0 | 2MB(25Q16JVSIQ) | 8273N + 8224N |
|
||||
| Brand | Type |Managed| PCB | Flash | Chip RTL |
|
||||
|---------|------------------|-------|------------------|-----------------|---------------|
|
||||
| Ampcom | SWTG018AS-A V2.0 | No | SWTG018AS-A V2.0 | 2MB | 8273N + 8224N |
|
||||
| Horaco | HC-SWTGW218AS-A | Yes | SWTG018AS-A V2.0 | 2MB(25Q16JVSIQ) | 8273N + 8224N |
|
||||
| GoodTop | GT-ST018M | Yes | SWTG018AS-A V2.0 | 2MB | 8273N + 8224N |
|
||||
| MokerLink | 2G08110GSN | No | SWTG018AS-A V2.0 | 512KB(25Q40) | 8273N + 8224N |
|
||||
|
||||
|
||||
The following is a documentation for the unmanaged switch marked as `SWTG018AS-A V2.0`.
|
||||
@@ -13,7 +15,7 @@ The original software is running UART on 9600 baud rate.
|
||||
|
||||
Using a SOIC clamp in-board is the only method for initial installation.
|
||||
|
||||
The board has a single flash chips `BS` with 4M-bit size. The front switch, switches between the two flash chips.
|
||||
The board has a single flash chips `BS` with 2M-byte 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
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
It is highly similar to SWTG024AS-V2.0, with the only difference being the GPIO configuration for the SFP port.
|
||||
|
||||
## Brands
|
||||
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|
|
||||
| Horaco | ZX-SG4T2 | | PCB-SWTG024AS-A-V2.0.1_19650 | P25D40SH | ??? |
|
||||
|Brand |Type |Managed|PCB |Flash |Chip RTL|
|
||||
|---------|--------------|-------|------------------------------|----------------|--------|
|
||||
| Horaco | ZX-SG4T2 | No | PCB-SWTG024AS-A-V2.0.1_19650 | 512K (P25D40SH)| 8372N |
|
||||
| Horaco | HC-SWTG124AS | Yes | PCB-SWTG024AS-A-V2.0.1_19650 | 2M (W25Q16JV)| 8372N |
|
||||
| GoodTop | GT-ST024M | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M | 8372N |
|
||||
|
||||
### Label specifications
|
||||
|
||||
@@ -33,6 +35,8 @@ Bottom
|
||||
|
||||
<img src="photos/SWTG024AS-A-V2_0_1_19650/horaco-zx-sg4t2-pcb-bottom.jpg" width="300" />
|
||||
|
||||
On Horaco HC-SWTG124AS with board PCB-SWTG024AS-A-V2.0.1_19650 the reset button is soldered at `SW1` (on the top left, GPIO48).
|
||||
|
||||
### J1, serial console
|
||||
|
||||
| `J1` pin | Signal |
|
||||
|
||||
@@ -46,4 +46,4 @@ Note,`R52`、`R53`may not be installed.You need to bridge them using either sold
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
@@ -0,0 +1,48 @@
|
||||
### SWTG024AS-V2.1
|
||||
|
||||
## Brands
|
||||
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|
|
||||
| Xikestor | SKS3200-4E2X | Yes | PCB-SWTG024AS-V2.1.0_19023 | 25Q16A | 8372N |
|
||||
| Solola | SL902-SWTG024AS | Yes | PCB-SWTG024AS-V2.1.0_19023 | | 8372N |
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1000/2500/10000 Mbps
|
||||
- **Power**: 1A @ 12V DC
|
||||
|
||||
#### Xikestore SKS-3200-4E2X label
|
||||
<img src="photos/SWTG024AS-V2.1.0/label.jpg" width="300" />
|
||||
|
||||
### What works
|
||||
- ALL 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||
- The SFP+ ports supports 1G, 2.5G and 10G modules.
|
||||
- LEDs work with the same indiciations as the OEM firmware.
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-SWTG024AS-V2.1.0
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/SWTG024AS-V2.1.0/pcb-top.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/SWTG024AS-V2.1.0/pcb-bottom.jpg" width="300" />
|
||||
|
||||
### Serial console
|
||||
|
||||
The four-pin through-hole serial header can be seen to the right of the CPU heatsink in the photo above. It is labelled J1, with pin 1 (Indicated by a triangle on the silkscren) at the bottom. the pinout is also on the silkscreen:
|
||||
|
||||
| Pin | Label |
|
||||
|-----|--------|
|
||||
| 1 | TX |
|
||||
| 2 | RX |
|
||||
| 3 | GND |
|
||||
| 4 | 3V3 |
|
||||
|
||||
Adding a header is a few moments work with a soldering iron. Only pins 1-3 are required for serial port use, and the stock firmware outputs at 57600bps at boot.
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
## RTLPlayground target
|
||||
|
||||
Use machine target `MACHINE_LIANGUO_ZX_SWTGW215AS` for this device.
|
||||
Build for this device with `make MACHINE=LIANGUO_ZX_SWTGW215AS`, which selects the `machine/LIANGUO_ZX_SWTGW215AS.c` board definition.
|
||||
|
||||
Physical hardware verification: 5x RJ45 ports + 1x SFP port.
|
||||
Port 5 RJ45 is interfaced through a RTL8221B IC.
|
||||
|
||||
@@ -5,9 +5,15 @@
|
||||
|---|---|---|---|---|---|
|
||||
| Mokerlink | ZX-SWTGW218AS | Yes| SWTG118AS-V2.0-16029 | 2MB (FM25Q16A)| 8273N + 8224N |
|
||||
| Sodola | | | | | |
|
||||
| Horaco | | | | | |
|
||||
| Horaco | HC-SWTGW218AS | Yes | SWTG118AS-V2.1 | 2MB | 8373 (non-N) |
|
||||
| XikeStor | SKS3200-8E1X | Yes | SWTG118AS-V2.1-17462 | 2MB (25Q16JVSIQ) | |
|
||||
|
||||
All boards in this table use `MACHINE=SWTGW218AS`. The Horaco HC-SWTGW218AS is also sold with the
|
||||
[SWTG018AS-A V2.0](SWTG018AS_A_V2_0.md) board, which needs a different firmware. Check the marking
|
||||
on the PCB before flashing.
|
||||
|
||||
The PHY and flash-chip models for the tested Horaco units remain unverified.
|
||||
|
||||
|
||||
## Photos
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
### HG0402XG V1.1
|
||||
|
||||
## Brands
|
||||
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|
|
||||
| ZoeRax | HG0402XG | No| HG0402XG V1.1 | 1M (Winbond 25Q) | |
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**: ZOERAX 2.5G 2SFP 4-Port Gigabit Switch
|
||||
- **Model**: HG0402XG-EU
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||
<img src="photos/HG0402XG_V1_1/HG0402XG_V1_1_bottom.jpg" width="300" />
|
||||
|
||||
## PCB
|
||||
|
||||
<img src="photos/HG0402XG_V1_1/HG0402XG_V1_1_top.jpg" width="300" />
|
||||
<img src="photos/HG0402XG_V1_1/HG0402XG_V1_1_bottom.jpg" width="300" />
|
||||
|
||||
Be aware that the UART header is metric, the pitch is 2mm. The JST PH2.0mm header shown was addeded after purchase
|
||||
|
||||
The slider switch controls microcontroller U4 in order to configure the VLAN on/off settings. U4 can reset the SoC
|
||||
and also write into its registers to configure VLAN. With RTLPlayground the slider cannot be used for anything else
|
||||
than triggering reset. Any change in the position will trigger this reset.
|
||||
|
||||
### Installation
|
||||
|
||||
Using SPI clamp on-board is the only method for initial installation.
|
||||
|
||||
### What works
|
||||
|
||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- SFP ports with various 1G/10G Fiber and Ethernet modules
|
||||
- LEDs
|
||||
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 234 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 434 KiB |
|
After Width: | Height: | Size: 565 KiB |
|
After Width: | Height: | Size: 480 KiB |
|
After Width: | Height: | Size: 519 KiB |
|
After Width: | Height: | Size: 529 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 273 KiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 3.6 MiB |
|
After Width: | Height: | Size: 2.8 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 791 KiB |
|
After Width: | Height: | Size: 760 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 262 KiB |
|
After Width: | Height: | Size: 546 KiB |
|
After Width: | Height: | Size: 478 KiB |
|
After Width: | Height: | Size: 639 KiB |
|
After Width: | Height: | Size: 907 KiB |
|
After Width: | Height: | Size: 923 KiB |
|
After Width: | Height: | Size: 290 KiB |
|
After Width: | Height: | Size: 360 KiB |
|
After Width: | Height: | Size: 4.0 MiB |
|
After Width: | Height: | Size: 469 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 944 KiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 229 KiB |
|
After Width: | Height: | Size: 804 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 253 KiB |
|
After Width: | Height: | Size: 270 KiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 398 KiB |
|
After Width: | Height: | Size: 283 KiB |
@@ -0,0 +1,23 @@
|
||||
# DNS
|
||||
|
||||
The switch can resolve host names to IPv4 addresses, for the NTP client and
|
||||
for anything else that is given a name instead of an address.
|
||||
|
||||
```
|
||||
dns server <ip> [<ip>] # one or two servers, 0.0.0.0 removes them
|
||||
dns lookup <name> # resolve a name and print the address
|
||||
dns # show the servers and the last lookup
|
||||
```
|
||||
|
||||
The answer to a lookup arrives after the command has returned, so it is
|
||||
printed on the serial console and in the syslog. In the console of the web
|
||||
interface, run `dns` afterwards to see it.
|
||||
|
||||
Without a configured server the resolver uses the one handed out by DHCP.
|
||||
Only address records are looked up; a query goes to the servers in turn,
|
||||
every two seconds, and gives up after six tries. A name that already is a
|
||||
dotted address is taken as it is, without a query.
|
||||
|
||||
The DNS servers are set in the Network card of the System page as well.
|
||||
Settings made there or on the console are kept only once the configuration is
|
||||
saved.
|
||||
@@ -0,0 +1,80 @@
|
||||
# The health command
|
||||
|
||||
`health` prints a one-page snapshot of the firmware's vital signs on the
|
||||
serial console. It exists for the situations where the switch misbehaves and
|
||||
every probe from the network measures the network instead of the device: the
|
||||
dump is taken from inside, costs one command, and works while HTTP does not.
|
||||
|
||||
```
|
||||
> health
|
||||
up 0000001f ticks 0x00001f4c loops 0x000016da rx 0x024e
|
||||
link max 01 slow 0x0000
|
||||
sfp max 74 slow 0x0001
|
||||
rx max 00 slow 0x0000
|
||||
tx max 00 slow 0x0000
|
||||
stp max 04 slow 0x0001
|
||||
cmd max 02 slow 0x0001
|
||||
lldp max 00 slow 0x0000
|
||||
sp 80 untouched 62
|
||||
tcp st 00 tmr 00 rtx 00 rto 00 len 0x0000 mss 0x05b4
|
||||
lport 0x0000 rport 0x0000 rip 0x0000 0x0000
|
||||
httpd left 0x0000 entry 00 stp 01 mvlan 0x0002
|
||||
```
|
||||
|
||||
The instrumentation is not part of a default build. It costs about 1.1 kB
|
||||
of bank 2, a few bytes of xdata and seven banked calls per main-loop pass,
|
||||
which is nothing a user needs unless they are chasing a problem, so it is
|
||||
switched on at build time:
|
||||
|
||||
```
|
||||
make MACHINE=SWTGW218AS HEALTH=1
|
||||
```
|
||||
|
||||
Without it the hooks compile to nothing and `health` is not a command.
|
||||
|
||||
All figures are raw hex. The counters are cumulative: take two dumps a known
|
||||
time apart and the differences give the rates.
|
||||
|
||||
## The first line
|
||||
|
||||
`up` is the seconds counter, `ticks` the system tick (200 per second),
|
||||
`loops` the number of main-loop passes and `rx` the frames handle_rx has
|
||||
taken off the NIC. A healthy loop completes one pass per tick, so the
|
||||
difference in `loops` tracks the difference in `ticks`; a loop that falls
|
||||
behind is being held up by one of the phases below. The `rx` rate separates
|
||||
a flooded CPU port from a stalled loop, which look identical from outside.
|
||||
|
||||
## Phases
|
||||
|
||||
Each line is one section of the main loop: the link poll, SFP handling,
|
||||
frame reception, TCP transmission, the STP timers, the LLDP timer and the command dispatch.
|
||||
`max` is the worst time that section has taken, in ticks of 5 ms; `slow`
|
||||
counts the passes that took two ticks or more. A misbehaving subsystem
|
||||
names itself here, which is the difference between knowing that the loop is
|
||||
slow and knowing why.
|
||||
|
||||
A dump of its own output takes the console some milliseconds, so running
|
||||
`health` repeatedly increments the `cmd` counters by itself. That is the
|
||||
instrument observing itself, not a fault.
|
||||
|
||||
## Stack
|
||||
|
||||
At boot the free stack area is painted with a pattern. `sp` is the live
|
||||
stack pointer; `untouched` counts the painted bytes still intact at the top,
|
||||
which is the closest thing to a high-water mark this hardware offers. A
|
||||
shrinking `untouched` across dumps means something is reaching deeper than
|
||||
anything before it.
|
||||
|
||||
## The TCP slot
|
||||
|
||||
The connection table is printed whole, one slot per pair of lines: TCP
|
||||
state (3 is ESTABLISHED, 0 closed), retransmission timer and counter, bytes
|
||||
in flight, negotiated MSS, then the ports and the peer address. With a
|
||||
single slot serving the entire web interface, one glance answers the
|
||||
question every management outage starts with: who is holding it. A slot
|
||||
showing state 3 with nothing in flight and a peer that no longer answers is
|
||||
a connection whose owner went away.
|
||||
|
||||
`httpd left` and `entry` describe the file transfer the web server believes
|
||||
it is in the middle of, and the trailing flags show whether STP is running
|
||||
and which VLAN carries management.
|
||||
@@ -0,0 +1,572 @@
|
||||
# LEDs HOWTO using firmware function tracing
|
||||
|
||||
This is a tutorial to show how to figure out the LED configuration for
|
||||
unmanaged switches (on managed ones one can just print out the registers
|
||||
from the command line) without using an I2C port on the device together
|
||||
an I2C-capable microcontroller. You will only need to have a SOIC clamp
|
||||
and will have to run ghidra to do a bit of reversing.
|
||||
|
||||
The additional advantage of this method is that it not only gives the LED
|
||||
configuration but also the full PHY configuration and SDS configuration e.g.
|
||||
in case of additional PHYs being used on the device.
|
||||
|
||||
We will use the ZoeRax HG0402XG V1.1 as an example device.
|
||||
|
||||
The first step is to read out the flash with a SOIC clamp.
|
||||
Save the image as
|
||||
`zoerax_hg0402xg.bin`
|
||||
|
||||
The next step is to use a decompiler such as ghidra to identify the
|
||||
functions used to write or read registers, SDS or to the PHY.
|
||||
|
||||
<img src="images/ghidra_open.png" width="300" />
|
||||
|
||||
First, load the code in BANK0 into ghidra. The type of code is
|
||||
8051 default big-endian. The code starts at offset 0x0002 in the file
|
||||
and has length 0x3ffd
|
||||
|
||||
<img src="images/ghidra_add_block.png" width="300" />
|
||||
Add BANK1 into ghidra by using File->Add to program...
|
||||
and add the code starting at 0x4000 in `zoerax_hg0402xg.bin` with length
|
||||
0xc000. Repeat for BANK2 (starts at 0x10000) and BANK3 (starts at 0x1c0000).
|
||||
They both have length 0xc000.
|
||||
|
||||
<img src="images/ghidra_search_read_reg.png" width="300" />
|
||||
|
||||
Now, find the read_reg function. An example of the read-register function
|
||||
is given below. Note the critical bit, namely the execution of the
|
||||
read-function of an ASIC register via an SFR:
|
||||
```
|
||||
CODE1::4dc9 75 a0 01 MOV SFR_EXEC_GO,#0x1
|
||||
```
|
||||
|
||||
This sequence of bytes is very specific. Replace 0x01 with 0x03 and you have
|
||||
the regster write SFR, 0x05 reads the SerDes, 0x07 writes it. 0x09 reads
|
||||
from the PHY and 0x0b writes to it.
|
||||
|
||||
|
||||
```
|
||||
**************************************************************
|
||||
* FUNCTION *
|
||||
**************************************************************
|
||||
undefined reg_read()
|
||||
undefined <UNASSIGNED> <RETURN>
|
||||
reg_read
|
||||
CODE1::4da9 ab 07 MOV R3,BANK0_R7 = ??
|
||||
CODE1::4dab aa 06 MOV R2,BANK0_R6 = ??
|
||||
CODE1::4dad e4 CLR A
|
||||
CODE1::4dae ff MOV R7,A
|
||||
CODE1::4daf fe MOV R6,A
|
||||
CODE1::4db0 fd MOV R5,A
|
||||
CODE1::4db1 fc MOV R4,A
|
||||
CODE1::4db2 90 00 c9 MOV DPTR,#0xc9
|
||||
CODE1::4db5 12 06 15 LCALL FUN_CODE_0615 undefined FUN_CODE_0615()
|
||||
CODE1::4db8 e4 CLR A
|
||||
CODE1::4db9 ff MOV R7,A
|
||||
CODE1::4dba fe MOV R6,A
|
||||
CODE1::4dbb fd MOV R5,A
|
||||
CODE1::4dbc fc MOV R4,A
|
||||
CODE1::4dbd 90 00 c5 MOV DPTR,#0xc5
|
||||
CODE1::4dc0 12 06 15 LCALL FUN_CODE_0615 undefined FUN_CODE_0615()
|
||||
CODE1::4dc3 ea MOV A,R2
|
||||
CODE1::4dc4 f5 a2 MOV SFR_A_ADDRH,A = ??
|
||||
CODE1::4dc6 eb MOV A,R3
|
||||
CODE1::4dc7 f5 a3 MOV SFR_A_ADDRL,A = ??
|
||||
CODE1::4dc9 75 a0 01 MOV SFR_EXEC_GO,#0x1 <<<<<<<< Executes READ REG
|
||||
LAB_CODE1__4dcc XREF[1]: CODE1::4dcf(j)
|
||||
CODE1::4dcc af a1 MOV R7,SFR_EXEC_STATUS = ??
|
||||
CODE1::4dce ef MOV A,R7
|
||||
CODE1::4dcf 70 fb JNZ LAB_CODE1__4dcc
|
||||
CODE1::4dd1 af a4 MOV R7,DAT_SFR_a4 = ??
|
||||
CODE1::4dd3 fc MOV R4,A
|
||||
CODE1::4dd4 fd MOV R5,A
|
||||
CODE1::4dd5 fe MOV R6,A
|
||||
CODE1::4dd6 90 00 c9 MOV DPTR,#0xc9
|
||||
CODE1::4dd9 12 06 15 LCALL FUN_CODE_0615 undefined FUN_CODE_0615()
|
||||
CODE1::4ddc 90 00 c5 MOV DPTR,#0xc5
|
||||
CODE1::4ddf 12 05 f9 LCALL FUN_CODE_05f9 undefined FUN_CODE_05f9()
|
||||
CODE1::4de2 c0 00 PUSH BANK0_R0
|
||||
CODE1::4de4 90 00 c9 MOV DPTR,#0xc9
|
||||
CODE1::4de7 12 05 dd LCALL read_xmem_32_b undefined read_xmem_32_b()
|
||||
CODE1::4dea 78 18 MOV R0,#0x18
|
||||
CODE1::4dec 12 05 86 LCALL FUN_CODE_0586 undefined FUN_CODE_0586()
|
||||
CODE1::4def d0 00 POP BANK0_R0
|
||||
CODE1::4df1 12 05 48 LCALL FUN_CODE_0548 undefined FUN_CODE_0548()
|
||||
CODE1::4df4 90 00 c5 MOV DPTR,#0xc5
|
||||
CODE1::4df7 12 06 15 LCALL FUN_CODE_0615 undefined FUN_CODE_0615()
|
||||
CODE1::4dfa af a5 MOV R7,DAT_SFR_a5 = ??
|
||||
CODE1::4dfc e4 CLR A
|
||||
CODE1::4dfd fc MOV R4,A
|
||||
CODE1::4dfe fd MOV R5,A
|
||||
CODE1::4dff fe MOV R6,A
|
||||
CODE1::4e00 90 00 c9 MOV DPTR,#0xc9
|
||||
CODE1::4e03 12 06 15 LCALL FUN_CODE_0615 undefined FUN_CODE_0615()
|
||||
CODE1::4e06 90 00 c5 MOV DPTR,#0xc5
|
||||
CODE1::4e09 12 05 f9 LCALL FUN_CODE_05f9 undefined FUN_CODE_05f9()
|
||||
CODE1::4e0c c0 00 PUSH BANK0_R0
|
||||
CODE1::4e0e 90 00 c9 MOV DPTR,#0xc9
|
||||
CODE1::4e11 12 05 dd LCALL read_xmem_32_b undefined read_xmem_32_b()
|
||||
CODE1::4e14 78 10 MOV R0,#0x10
|
||||
CODE1::4e16 12 05 86 LCALL FUN_CODE_0586 undefined FUN_CODE_0586()
|
||||
CODE1::4e19 d0 00 POP BANK0_R0
|
||||
CODE1::4e1b 12 05 48 LCALL FUN_CODE_0548 undefined FUN_CODE_0548()
|
||||
CODE1::4e1e 90 00 c5 MOV DPTR,#0xc5
|
||||
CODE1::4e21 12 06 15 LCALL FUN_CODE_0615 undefined FUN_CODE_0615()
|
||||
CODE1::4e24 af a6 MOV R7,DAT_SFR_a6 = ??
|
||||
CODE1::4e26 e4 CLR A
|
||||
CODE1::4e27 fc MOV R4,A
|
||||
CODE1::4e28 fd MOV R5,A
|
||||
CODE1::4e29 fe MOV R6,A
|
||||
CODE1::4e2a 90 00 c9 MOV DPTR,#0xc9
|
||||
CODE1::4e2d 12 06 15 LCALL FUN_CODE_0615 undefined FUN_CODE_0615()
|
||||
CODE1::4e30 90 00 c5 MOV DPTR,#0xc5
|
||||
CODE1::4e33 12 05 f9 LCALL FUN_CODE_05f9 undefined FUN_CODE_05f9()
|
||||
CODE1::4e36 c0 00 PUSH BANK0_R0
|
||||
CODE1::4e38 90 00 c9 MOV DPTR,#0xc9
|
||||
CODE1::4e3b 12 05 dd LCALL read_xmem_32_b undefined read_xmem_32_b()
|
||||
CODE1::4e3e 78 08 MOV R0,#0x8
|
||||
CODE1::4e40 12 05 86 LCALL FUN_CODE_0586 undefined FUN_CODE_0586()
|
||||
CODE1::4e43 d0 00 POP BANK0_R0
|
||||
CODE1::4e45 12 05 48 LCALL FUN_CODE_0548 undefined FUN_CODE_0548()
|
||||
CODE1::4e48 90 00 c5 MOV DPTR,#0xc5
|
||||
CODE1::4e4b 12 06 15 LCALL FUN_CODE_0615 undefined FUN_CODE_0615()
|
||||
CODE1::4e4e af a7 MOV R7,DAT_SFR_a7 = ??
|
||||
CODE1::4e50 e4 CLR A
|
||||
CODE1::4e51 fc MOV R4,A
|
||||
CODE1::4e52 fd MOV R5,A
|
||||
CODE1::4e53 fe MOV R6,A
|
||||
CODE1::4e54 90 00 c9 MOV DPTR,#0xc9
|
||||
CODE1::4e57 12 06 15 LCALL FUN_CODE_0615 undefined FUN_CODE_0615()
|
||||
CODE1::4e5a 90 00 c5 MOV DPTR,#0xc5
|
||||
CODE1::4e5d 12 05 dd LCALL read_xmem_32_b undefined read_xmem_32_b()
|
||||
CODE1::4e60 90 00 c9 MOV DPTR,#0xc9
|
||||
CODE1::4e63 12 05 f9 LCALL FUN_CODE_05f9 undefined FUN_CODE_05f9()
|
||||
CODE1::4e66 12 05 48 LCALL FUN_CODE_0548 undefined FUN_CODE_0548()
|
||||
CODE1::4e69 90 00 c5 MOV DPTR,#0xc5
|
||||
CODE1::4e6c 12 06 15 LCALL FUN_CODE_0615 undefined FUN_CODE_0615()
|
||||
CODE1::4e6f 90 00 c5 MOV DPTR,#0xc5
|
||||
CODE1::4e72 02 05 dd LJMP read_xmem_32_b undefined read_xmem_32_b()
|
||||
-- Flow Override: CALL_RETURN (CALL_TERMINATOR)
|
||||
|
||||
```
|
||||
|
||||
INSERT ghidra_search_read_reg.png
|
||||
|
||||
Identify all the read and write function to the HW of the SoC using the find
|
||||
in memory function.
|
||||
|
||||
The next task is to adapt the intercept routines in a special assembler
|
||||
file. Don't worry, you do not need to understand assembler to do this.
|
||||
|
||||
```
|
||||
; Assembler file to intercept register writes/reads and PHY writes/reads
|
||||
; assemble with as31
|
||||
; Compile with
|
||||
; as31 -Fbyte -Orwintercept_zoerax_hg0402xg.hex rwintercept_zoerax_hg0402xg.asm
|
||||
; ./injector zoerax_hg0402xg.bin RTLPlayground/rwintercept_zoerax_hg0402xg.hex zoerax_hg0402xg_patched.bin
|
||||
; Start at 0x3b00, where there is always some space in BANK 0
|
||||
.equ valptr, 0x199
|
||||
|
||||
|
||||
.equ SFR_DATA_0, 0xa7
|
||||
.equ SFR_DATA_8, 0xa6
|
||||
.equ SFR_DATA_16, 0xa5
|
||||
.equ SFR_DATA_24, 0xa4
|
||||
|
||||
; Intercept Register Write
|
||||
.org 0x4d62
|
||||
lcall reg_write
|
||||
nop
|
||||
|
||||
; Intercept Register Read
|
||||
.org 0x4dad
|
||||
lcall reg_read_head
|
||||
.org 0x4e6f
|
||||
lcall reg_read_tail
|
||||
|
||||
; Intercept PHY write
|
||||
.org 0x522c
|
||||
lcall phy_write
|
||||
|
||||
; Intercept PHY read
|
||||
.org 0x526f
|
||||
lcall phy_read_head
|
||||
.org 0x5295
|
||||
ljmp phy_read_tail
|
||||
|
||||
; Intercept SDS write
|
||||
.org 0x503c
|
||||
lcall sds_write
|
||||
nop
|
||||
|
||||
; Intercept SDS read
|
||||
.org 0x5061
|
||||
lcall sds_read_head
|
||||
nop
|
||||
.org 0x507b
|
||||
ljmp sds_read_tail
|
||||
|
||||
;
|
||||
; BEGIN actual code at unused end of BANK0
|
||||
;
|
||||
.org 0x3b00
|
||||
|
||||
;
|
||||
; print the address of a register write. The address is in R6/R7. A and r4 can be scratched
|
||||
;
|
||||
reg_write:
|
||||
mov a, #'R'
|
||||
acall putc
|
||||
|
||||
mov a, r6
|
||||
acall wbyte
|
||||
|
||||
mov a, r7
|
||||
acall wbyte
|
||||
|
||||
mov a, #'-'
|
||||
acall putc
|
||||
|
||||
mov dptr, #valptr
|
||||
movx a, @dptr
|
||||
acall wbyte
|
||||
mov dptr, #valptr + 1
|
||||
movx a, @dptr
|
||||
acall wbyte
|
||||
mov dptr, #valptr + 2
|
||||
movx a, @dptr
|
||||
acall wbyte
|
||||
mov dptr, #valptr + 3
|
||||
movx a, @dptr
|
||||
acall wbyte
|
||||
|
||||
mov a, #' '
|
||||
acall putc
|
||||
|
||||
mov a, r7
|
||||
mov r5, a
|
||||
mov a, r6
|
||||
mov r4, a
|
||||
ret
|
||||
[...]
|
||||
```
|
||||
|
||||
The full assembler file can be found here: XXXXXXXXXX
|
||||
|
||||
|
||||
Once you have assembled the code, inject the bytes into the existing image,
|
||||
creating a patched version:
|
||||
```
|
||||
$ as31 -Fbyte -Orwintercept_zoerax_hg0402xg.hex rwintercept_zoerax_hg0402xg.asm
|
||||
Begin Pass #1
|
||||
Begin Pass #2
|
||||
./injector zoerax_hg0402xg.bin rwintercept_zoerax_hg0402xg.hex zoerax_hg0402xg_patched.bin
|
||||
Input file size: 1048576
|
||||
Bytes read:: 1048576
|
||||
Patched 417 bytes.
|
||||
```
|
||||
|
||||
Now flash `zoerax_hg0402xg_patched.bin` onto device.
|
||||
|
||||
Connect a serial adapter and plug in power. You will see:
|
||||
|
||||
```
|
||||
$ picocom -b 9600 /dev/ttyUSB0
|
||||
picocom v3.1
|
||||
|
||||
port is : /dev/ttyUSB0
|
||||
flowcontrol : none
|
||||
baudrate is : 9600
|
||||
parity is : none
|
||||
databits are : 8
|
||||
stopbits are : 1
|
||||
escape is : C-a
|
||||
local echo is : no
|
||||
noinit is : no
|
||||
noreset is : no
|
||||
hangup is : no
|
||||
nolock is : no
|
||||
send_cmd is : sz -vv
|
||||
receive_cmd is : rz -vv -E
|
||||
imap is :
|
||||
omap is :
|
||||
emap is : crcrlf,delbs,
|
||||
logfile is : none
|
||||
initstring : none
|
||||
exit_after is : not set
|
||||
exit is : no
|
||||
|
||||
Type [C-a] [C-h] to see available commands
|
||||
Terminal ready
|
||||
[The printout only starts once the serial peripherial has been set up. Initially its timing is off:]
|
||||
�.Ӛ�҂���������30-00005555 r6330:00005555 R6330-00005515 [RTL837X_REG_SMI_MAC_TYPE]
|
||||
[RTL837X_REG_SMI_PORT_POLLING: ]
|
||||
r6334:00000000 R6334-000000f0
|
||||
r6454:00000000 R6454-00007000
|
||||
|
||||
[Read SoC-Revision]
|
||||
r000c:00200000 R000c-002a0000 r000c:202a6818 r000c:202a6818 R000c-20206818
|
||||
p001e.000d:ffff R02f8-0000ffff R02f4-0000fffa P000001.1e00000d:fffa p001e.000d:ffff p001e.000d:ffff
|
||||
R02f8-0000ffff R02f4-0000fff0 P000001.1e00000d:fff0
|
||||
|
||||
[RTL837X_REG_LED_MODE being configured:]
|
||||
r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0
|
||||
|
||||
[RLDP Leds configured via RTL837X_REG_LED_RLDP_X:]
|
||||
r65f8:00000018 R65f8-0000001b R65fc-fffff000 r6600:00000000 R6600-0000000f
|
||||
|
||||
[RTL837X_REG_LED_GLB_IO_EN: ]
|
||||
r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00
|
||||
|
||||
[RTL837X_PIN_MUX_0, makes serial go out of sync:]
|
||||
r7f8c:30000000 R7f8c-30000000 r7f8c:300��.Ӛ�҂���������30-00005555
|
||||
|
||||
r6330:00005555 R6330-00005515 r6334:00000000 R6334-000000f0
|
||||
|
||||
r6454:00000000 R6454-00007000
|
||||
|
||||
[Read SoC-Revision (again)]
|
||||
r000c:00200000 R000c-002a0000 r000c:202a6818 r000c:202a6818 R000c-20206818
|
||||
p001e.000d:ffff R02f8-0000ffff R02f4-0000fffa P000001.1e00000d:fffa p001e.000d:ffff p001e.000d:ffff
|
||||
R02f8-0000ffff R02f4-0000fff0
|
||||
P000001.1e00000d:fff0
|
||||
|
||||
#### LED configuration ########
|
||||
[RTL837X_REG_LED_MODE being configured (final):]
|
||||
r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0
|
||||
|
||||
[More RTL837X_REG_LED_RLDP]
|
||||
r65f8:00000018 R65f8-0000001b R65fc-fffff000 r6600:00000000 R6600-0000000f
|
||||
|
||||
[RTL837X_REG_LED_GLB_IO_EN]
|
||||
r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00
|
||||
|
||||
[RTL837X_PIN_MUX_0
|
||||
r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000
|
||||
|
||||
[RTL837X_LED_PORT_SET_SEL]
|
||||
r654c:00000000 R654c-00010000
|
||||
|
||||
[RTL837X_REG_LED1_0_SET0]
|
||||
R6548-00000141
|
||||
|
||||
[RTL837X_REG_LED3_2_SET0]
|
||||
r6544:01411000 R6544-01410174
|
||||
|
||||
[RTL837X_REG_LED1_0_SET1]
|
||||
r6540:00440070 R6540-0044017f
|
||||
|
||||
[RTL837X_REG_LED3_0_SET1]
|
||||
r6528:00000000 R6528-000f0000
|
||||
|
||||
[SDS 0 being configure:]
|
||||
r7b20:00000bff R7b20-000003ff r7b20:000003ff R7b20-000003fa r7b20:000003fa R7b20-000003fa
|
||||
Q002110:4480 Q002113:0400 Q002118:6d02 Q00211b:424e Q00211d:0002 Q00361c:1390
|
||||
Q003614:003f Q003610:0200 Q002e04:0080 Q002e06:0408 Q002e07:020d Q002e09:0601
|
||||
Q002e0b:222c Q002e0c:a217 Q002e0d:fe40 Q002e15:f5c1 Q002e16:0443 Q002e1d:abb0
|
||||
Q000612:5078 Q000706:9401 Q000708:9401 Q00070a:9401 Q00070c:9401 Q001f0b:0003
|
||||
Q000603:c45c Q00061f:2100 q001f0b:0003 Q001f0b:000f q002000:0000 Q002000:0030
|
||||
q002000:0030 Q002000:0010 q002000:0010 Q002000:0050 q002000:0050 Q002000:00d0
|
||||
q002000:00d0 Q002000:0cd0 q002000:0cd0 Q002000:04d0 q002000:04d0 Q002000:04d0
|
||||
q002000:04d0 Q002000:0cd0 q002000:0cd0 Q002000:00d0 q002000:00d0 Q002000:00d0
|
||||
q002000:00d0 Q002000:0050 q002000:0050 Q002000:0010 q002000:0010 Q002000:0010
|
||||
q002000:0010 Q002000:0030 q002000:0030 Q002000:0000 q001f00:0000 Q001f00:000b
|
||||
q001f00:000b Q001f00:0000
|
||||
|
||||
[SDS 1 being configured]
|
||||
r7b20:000003fa R7b20-000003fa r7b20:000003fa R7b20-0000035a r7b20:0000035a R7b20-0000035a
|
||||
Q012110:4480 Q012113:0400 Q012118:6d02 Q01211b:424e Q01211d:0002 Q01361c:1390
|
||||
Q013614:003f Q013610:0200 Q012e04:0080 Q012e06:0408 Q012e07:020d Q012e09:0601
|
||||
Q012e0b:222c Q012e0c:a217 Q012e0d:fe40 Q012e15:f5c1 Q012e16:0443 Q012e1d:abb0
|
||||
Q010612:5078 Q010706:9401 Q010708:9401 Q01070a:9401 Q01070c:9401 Q011f0b:0003
|
||||
Q010603:c45c Q01061f:2100 q011f0b:0003 Q011f0b:000f q012000:0000 Q012000:0030
|
||||
q012000:0030 Q012000:0010 q012000:0010 Q012000:0050 q012000:0050 Q012000:00d0
|
||||
q012000:00d0 Q012000:0cd0 q012000:0cd0 Q012000:04d0 q012000:04d0 Q012000:04d0
|
||||
q012000:04d0 Q012000:0cd0 q012000:0cd0 Q012000:00d0 q012000:00d0 Q012000:00d0
|
||||
q012000:00d0 Q012000:0050 q012000:0050 Q012000:0010 q012000:0010 Q012000:0010
|
||||
q012000:0010 Q012000:0030 q012000:0030 Q012000:0000 q011f00:0000 Q011f00:000b
|
||||
q011f00:000b Q011f00:0000 q012100:4902 Q012100:4906 q013605:0000 Q013605:4000
|
||||
Q011f02:001f q011f15:0096 q002100:4902 Q002100:4906 q003605:0000 Q003605:4000
|
||||
Q001f02:001f q001f15:00a6
|
||||
|
||||
r0a90:000000f3 R0a90-000000fc P0000f0.1f00a610:2858 r5fd4:0002914a
|
||||
R5fd4-001a914a r1538:00000e33 R1538-00000e37 r1538:00000e37 R1538-00000e37
|
||||
r1538:00000e37 R1538-00000f37 r1638:00000e33 R1638-00000e37 r1638:00000e37
|
||||
R1638-00000e37 r1638:00000e37 R1638-00000f37 r1738:00000e33 R1738-00000e37
|
||||
r1738:00000e37 R1738-00000e37 r1738:00000e37 R1738-00000f37 r1838:00000e33
|
||||
R1838-00000e37 r1838:00000e37 R1838-00000e37 r1838:00000e37 R1838-00000f37
|
||||
r1938:00000e33 R1938-00000e37 r1938:00000e37 R1938-00000e37 r1938:00000e37
|
||||
R1938-00000f37 r1a38:00000e33 R1a38-00000e37 r1a38:00000e37 R1a38-00000e37
|
||||
r1a38:00000e37 R1a38-00000f37 r0b7c:000000d8 R0b7c-000000f8 R7124-00001050
|
||||
R7128-00001050 R712c-00001050 R7130-00001050 R7134-00001050 R7138-00001050
|
||||
R713c-00001050 R7140-00001050 R7144-00001050 R7148-00001050 r6040:00000030
|
||||
R6040-00000031 p041f.a436:8195 P000010.1f00a436:0005 p041f.a438:02d4
|
||||
P000010.1f00a436:801e p041f.a438:0000 p041f.b820:0000 P000010.1f00b820:0010
|
||||
p041f.b800:00c0 p041f.a436:801e P000010.1f00a436:8023 p041f.a438:0000
|
||||
P000010.1f00a438:1802 p041f.a436:8025
|
||||
|
||||
[PHY with ID 5 being patched] P000010.1f00a436:b82e p041f.a438:0000
|
||||
P000010.1f00a438:0001 p041f.b820:0010 P000010.1f00b820:0090
|
||||
P000010.1f00a436:a016 P000010.1f00a438:0000 P000010.1f00a436:a012
|
||||
P000010.1f00a438:0000 P000010.1f00a436:a014 P000010.1f00a438:1800
|
||||
P000010.1f00a438:8010 P000010.1f00a438:1800 P000010.1f00a438:8013
|
||||
P000010.1f00a438:1800 P000010.1f00a438:8026 P000010.1f00a438:1800
|
||||
P000010.1f00a438:802a P000010.1f00a438:1800 P000010.1f00a438:802e
|
||||
P000010.1f00a438:1800 P000010.1f00a438:802e P000010.1f00a438:1800
|
||||
P000010.1f00a438:802e P000010.1f00a438:1800 P000010.1f00a438:802e
|
||||
...
|
||||
```
|
||||
Where:
|
||||
```
|
||||
r: read-reg
|
||||
R: write-reg
|
||||
q: read SDS
|
||||
Q: write SDS
|
||||
p: read PHY
|
||||
P: write SDS
|
||||
```
|
||||
|
||||
The LED configuration has been marked above. We now write exactly those registers
|
||||
into the registers of `rtlplayground.c` on startup:
|
||||
|
||||
```
|
||||
[...]
|
||||
set_sys_led_state(SYS_LED_ON);
|
||||
|
||||
// [RTL837X_REG_LED_MODE being configured (final):]
|
||||
// r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0
|
||||
REG_SET(RTL837X_REG_LED_MODE, 0x0021e6b0);
|
||||
|
||||
// [More RTL837X_REG_LED_RLDP]
|
||||
// r65f8:00000018 R65f8-0000001b R65fc-fffff000 r6600:00000000 R6600-0000000f
|
||||
REG_SET(0x65f8, 0x0000001b);
|
||||
REG_SET(0x65fc, 0xfffff000);
|
||||
REG_SET(0x6600, 0x0000000f);
|
||||
|
||||
// [RTL837X_REG_LED_GLB_IO_EN]
|
||||
// r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00
|
||||
REG_SET(0x65dc, 0x77ffff00);
|
||||
|
||||
// [RTL837X_PIN_MUX_0
|
||||
// r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000
|
||||
REG_SET(0x7f8c, 0x38000000);
|
||||
|
||||
// [RTL837X_LED_PORT_SET_SEL]
|
||||
// r654c:00000000 R654c-00010000
|
||||
REG_SET(0x654c, 0x00010040);
|
||||
|
||||
// [RTL837X_REG_LED1_0_SET0]
|
||||
// R6548-00000141
|
||||
REG_SET(0x6548, 0x00000141);
|
||||
|
||||
// [RTL837X_REG_LED3_2_SET0]
|
||||
// r6544:01411000 R6544-01410174
|
||||
REG_SET(0x6544, 0x01410174);
|
||||
|
||||
// [RTL837X_REG_LED1_0_SET1]
|
||||
// r6540:00440070 R6540-0044017f
|
||||
REG_SET(0x6540, 0x0044017f);
|
||||
|
||||
// [RTL837X_REG_LED3_0_SET1]
|
||||
// r6528:00000000 R6528-000f0000
|
||||
REG_SET(0x6528, 0x000f0000);
|
||||
|
||||
cmd_editor_init();
|
||||
[...]
|
||||
```
|
||||
|
||||
Create an initial configuraiton for your device by copying over an existing one
|
||||
for the same device type, i.e. same port-configuraiton and same SoC,
|
||||
give it a new name. Make sure that the led_mux_custom and led_mux fields are not
|
||||
used, because our device does not customize the LED muxes.
|
||||
|
||||
Compile and flash onto your device.
|
||||
|
||||
Now, boot the switch and issue the `leds`command, which will print out:
|
||||
```
|
||||
RTL837X_PIN_MUX_0: 0x38000000
|
||||
RTL837X_REG_LED_GLB_IO_EN: 0x77ffff00
|
||||
RTL837X_REG_LED1_0_SET0: 0x00000141
|
||||
RTL837X_REG_LED3_2_SET0: 0x01410174
|
||||
RTL837X_REG_LED1_0_SET1: 0x0044017f
|
||||
RTL837X_REG_LED3_2_SET1: 0x18000040
|
||||
RTL837X_REG_LED1_0_SET2: 0x00000000
|
||||
RTL837X_REG_LED3_2_SET2: 0x00000000
|
||||
RTL837X_REG_LED1_0_SET3: 0x00000000
|
||||
RTL837X_REG_LED3_2_SET3: 0x00000000
|
||||
RTL837X_REG_LED3_0_SET1: 0x000f0000
|
||||
RTL837X_REG_LED3_0_SET3: 0x00000000
|
||||
RTL837X_LED_PORT_SET_SEL: 0x00010040
|
||||
RTL837X_REG_LED_GLB_MUX_1: 0x3fffffff
|
||||
RTL837X_REG_LED_GLB_MUX_2: 0x0c3fffff
|
||||
RTL837X_REG_LED_GLB_MUX_3: 0x1245038d
|
||||
RTL837X_REG_LED_GLB_MUX_4: 0x19616554
|
||||
RTL837X_REG_LED_GLB_MUX_5: 0x2079d71a
|
||||
RTL837X_REG_LED_GLB_MUX_6: 0x000238a1
|
||||
RTL837X_REG_LED_GLB_ACTIVE: 0x3ffbedff
|
||||
RTL837X_REG_LED_MODE: 0x0021e6b0
|
||||
LED pad Configuration:
|
||||
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b
|
||||
3f 3f 3f 3f 3f 3f 3f 3f 0f 0c 0d 0e 10 11 12 14 15 16 18 19 1a 1c 1d 1e 20 21 22 23
|
||||
LED-set Configuration:
|
||||
LED-ID 0 1 2 3
|
||||
SET 0: 000141 000000 000174 000141
|
||||
SET 1: 0f017f 000044 000040 001800
|
||||
SET 2: 000000 000000 000000 000000
|
||||
SET 3: 000000 000000 000000 000000
|
||||
Port 3: SET 1: ( 2G5 TWO_1G 1G 500M 100M 10M LINK ACT 10G TWO_5G 5G TWO_2G5), ( 1G LINK), ( LINK), ( COL DUPLEX),
|
||||
Port 4: SET 0: ( 2G5 LINK ACT), (), ( 1G 100M 10M LINK ACT), ( 2G5 LINK ACT),
|
||||
Port 5: SET 0: ( 2G5 LINK ACT), (), ( 1G 100M 10M LINK ACT), ( 2G5 LINK ACT),
|
||||
Port 6: SET 0: ( 2G5 LINK ACT), (), ( 1G 100M 10M LINK ACT), ( 2G5 LINK ACT),
|
||||
Port 7: SET 0: ( 2G5 LINK ACT), (), ( 1G 100M 10M LINK ACT), ( 2G5 LINK ACT),
|
||||
Port 8: SET 1: ( 2G5 TWO_1G 1G 500M 100M 10M LINK ACT 10G TWO_5G 5G TWO_2G5), ( 1G LINK), ( LINK), ( COL DUPLEX),
|
||||
|
||||
```
|
||||
Together with the GPIO information, this will give you the following machine configuration:
|
||||
```
|
||||
_code const struct machine machine = {
|
||||
.machine_name = "ZOERAX HG0402XG",
|
||||
.isRTL8373 = 0,
|
||||
.min_port = 3,
|
||||
.max_port = 8,
|
||||
.n_sfp = 2,
|
||||
.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},
|
||||
.is_sfp = {0, 0, 0, 1, 0, 0, 0, 0, 2},
|
||||
// Left SFP port (5)
|
||||
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
|
||||
.sfp_port[0].pin_los = GPIO_NA,
|
||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||
.sfp_port[0].sds = 1,
|
||||
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
|
||||
// Right SFP port (6)
|
||||
.sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX,
|
||||
.sfp_port[1].pin_los = GPIO_NA,
|
||||
.sfp_port[1].pin_tx_disable = GPIO_NA,
|
||||
.sfp_port[1].sds = 0,
|
||||
.sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ),
|
||||
.reset_pin = GPIO_NA,
|
||||
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
|
||||
.port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1},
|
||||
/* On Ethernet: Left led is orange, right green
|
||||
* 100M and 1G give right led green with activity
|
||||
* 2.5GBit adds solid left orange LED
|
||||
* LEDs for the SFP-ports are the same as for the Ethernet ports
|
||||
*/
|
||||
.led_sets = { { LEDS_2G5 | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
LEDS_2G5 | LEDS_LINK | LEDS_ACT
|
||||
},
|
||||
{ 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_LINK,
|
||||
LEDS_COL | LEDS_DUPLEX
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
@@ -69,18 +69,26 @@ The code currently provides the following functions:
|
||||
void igmp_setup(void) __banked;
|
||||
void igmp_enable(void) __banked;
|
||||
void igmp_router_port_set(uint16_t pmask) __banked;
|
||||
void igmp_packet_handler(void) __banked;
|
||||
uint8_t igmp_packet_handler(void) __banked;
|
||||
void igmp_show(void) __banked;
|
||||
```c
|
||||
`igmp_setup()` is called at boot-time and configures flooding of all IP-MC packets by
|
||||
default, as otherwise no IP-MC would be possible in the network.
|
||||
default, as otherwise no IP-MC would be possible in the network. `igmp off` calls it as
|
||||
well; groups learned while IGMP was on stay in the table, but are no longer looked up.
|
||||
|
||||
`igmp_enable()`starts IGMP which cause IGMP packets to be handled by the CPU and forwarding
|
||||
of IP-MC packets to be limited to only subscribed ports.
|
||||
|
||||
`igmp_router_port_set()`configures forwarding ports for IGMP messages.
|
||||
|
||||
`igmp_packet_handler()` implements handling of trapped IGMP packets by the CPU.
|
||||
`igmp_packet_handler()` implements handling of trapped IGMP packets by the CPU. It is called
|
||||
for frames to 01:00:5e:xx:xx:xx and returns 0 when the frame is not a trapped IGMP packet,
|
||||
so that it is passed on to the IP stack. IGMPv1/v2 reports (0x12, 0x16) join the group given
|
||||
in the IGMP header, IGMPv2 leaves (0x17) leave it, IGMPv3 reports use the first group record
|
||||
(type 4 joins, type 3 leaves). Trapped IGMP frames arrive without a VLAN tag.
|
||||
Reports for groups in 224.0.0.0/24 are ignored: the switch floods that block
|
||||
even with IGMP on, and an entry for a group such as 224.0.0.251 (mDNS) would
|
||||
otherwise limit it to the ports that reported it, as RFC 4541 warns against.
|
||||
|
||||
`igmp_show()` prints out the IGMP configuration on the CLI.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 100 KiB |