Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a202842107 | ||
|
|
6fad2836ae | ||
|
|
2415015a87 | ||
|
|
d9fc20addf | ||
|
|
c15b2d48da | ||
|
|
f17ca1c9fc | ||
|
|
be5dee04e3 | ||
|
|
496ac8b757 | ||
|
|
bf670aed0b | ||
|
|
6af5580433 | ||
|
|
6194356f66 | ||
|
|
bd56c1a8c5 | ||
|
|
d562fd661e | ||
|
|
0b6b613c03 | ||
|
|
f325bdbd11 | ||
|
|
adecc26ae2 | ||
|
|
44ae7a8d3b | ||
|
|
c3fc541339 | ||
|
|
28ea2184c2 | ||
|
|
d5f84cc2fb | ||
|
|
682ac462c4 | ||
|
|
ecc8356f4d | ||
|
|
3a8d1d323f | ||
|
|
e125ebd097 | ||
|
|
4050555667 | ||
|
|
8224b06f9e | ||
|
|
69151362a0 | ||
|
|
24e83d5b74 | ||
|
|
e890e429a5 | ||
|
|
813a62ca7d | ||
|
|
3d81df0cad | ||
|
|
2481810906 | ||
|
|
03311debe6 | ||
|
|
e4adec9c11 | ||
|
|
8a7c847ad9 | ||
|
|
b94d2aeabc | ||
|
|
d525229b42 | ||
|
|
73b23808cf | ||
|
|
4a14f50932 | ||
|
|
1bfe632174 | ||
|
|
265a80bb25 | ||
|
|
64efd3fb9f | ||
|
|
2e6425f5e6 | ||
|
|
1856aeba28 | ||
|
|
4e4a2ea4db | ||
|
|
4ccbf51976 | ||
|
|
0df48fbb1c | ||
|
|
25040070e5 | ||
|
|
edf6351d85 | ||
|
|
c3b4cc893b | ||
|
|
b83b67d234 | ||
|
|
efd61be64e | ||
|
|
0e85137e7a | ||
|
|
da7909f422 | ||
|
|
14b2ce1c49 | ||
|
|
84d9408151 | ||
|
|
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 | ||
|
|
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 | ||
|
|
434acbcc13 | ||
|
|
1aae2fac30 | ||
|
|
1f9b3df3e6 | ||
|
|
eb4bae278b | ||
|
|
7908044a44 | ||
|
|
0ec1a5e63f | ||
|
|
114af559c7 | ||
|
|
5a2c4ca029 | ||
|
|
63e367d298 | ||
|
|
5e513daf17 | ||
|
|
3ec9319d77 | ||
|
|
b42eace21d | ||
|
|
3dfd6a88c7 | ||
|
|
7fa26e0ae3 | ||
|
|
1c8cdab4bf | ||
|
|
f49ca0d6fe | ||
|
|
12fb6fd809 | ||
|
|
dad65fd550 | ||
|
|
dc82e044bc | ||
|
|
7daa9effe0 | ||
|
|
950586135a | ||
|
|
c1ad800fc5 | ||
|
|
dc4fb5becc | ||
|
|
78ecef15e9 | ||
|
|
eab927f52a | ||
|
|
02c816647c | ||
|
|
d3f1069285 | ||
|
|
98bda62181 | ||
|
|
3f65db9984 | ||
|
|
df95c544d4 | ||
|
|
7df3c87892 | ||
|
|
53f12a42c5 | ||
|
|
1b514b5ea8 | ||
|
|
dd09be9dd0 | ||
|
|
b2b7f8a0c6 | ||
|
|
5b28ddf80a | ||
|
|
624f93a28a | ||
|
|
fe3da0c7a5 | ||
|
|
412098d0ed | ||
|
|
5ecce86ef1 | ||
|
|
247b230212 | ||
|
|
c012dda029 | ||
|
|
6616a0c9ce | ||
|
|
eab8c901cf | ||
|
|
21a9fdf45a | ||
|
|
1ed12d1101 | ||
|
|
8d7faf5312 | ||
|
|
af4101f060 | ||
|
|
d6d9c368e9 | ||
|
|
36de9791be | ||
|
|
eab17f8a3f | ||
|
|
552bd1cb18 | ||
|
|
4bcbada764 | ||
|
|
9fae0f9249 | ||
|
|
774e04816e | ||
|
|
ead1c40aac | ||
|
|
6488433584 | ||
|
|
59088b4787 | ||
|
|
30547cc453 | ||
|
|
58aead38cf | ||
|
|
9c3433cf6b | ||
|
|
97d44fbf4b | ||
|
|
00ee3d1325 | ||
|
|
078a446cee | ||
|
|
efdf93a97a | ||
|
|
025e1a186b | ||
|
|
dc5cbcda16 | ||
|
|
12c15603ed | ||
|
|
3a7da77a99 | ||
|
|
13509d56e5 | ||
|
|
54b5e90976 | ||
|
|
38b8e38c04 | ||
|
|
d245249385 | ||
|
|
8b7306f995 | ||
|
|
ecac6d1934 | ||
|
|
f2966ad248 | ||
|
|
8a7b146892 | ||
|
|
0998a9dfaa | ||
|
|
aded07730e | ||
|
|
58d059384d | ||
|
|
a7692022f1 | ||
|
|
e26693826e | ||
|
|
be6bd2a5b3 | ||
|
|
6c43091b7a | ||
|
|
b57b7d1a3d | ||
|
|
fc86ea8be5 | ||
|
|
91780110f2 | ||
|
|
f0e9953081 | ||
|
|
1c9bf10b87 | ||
|
|
2e2529be27 | ||
|
|
f6348765b4 | ||
|
|
6411c5157c | ||
|
|
d06dc3e5f8 | ||
|
|
dd7f9f7c7b | ||
|
|
3b8dba6e87 | ||
|
|
a259587bf9 | ||
|
|
f23d840cee | ||
|
|
f46ef3a43c | ||
|
|
81af3a29a2 | ||
|
|
5a55524115 | ||
|
|
6b39bcc448 | ||
|
|
4c8e0ce975 | ||
|
|
71344825c7 | ||
|
|
40ce742d04 | ||
|
|
f5e4fa5134 | ||
|
|
28020e8186 | ||
|
|
cbcf67a693 | ||
|
|
d6bf46595a | ||
|
|
2499d116a3 | ||
|
|
74a1c6831a | ||
|
|
a79c483f94 | ||
|
|
75aa23468c | ||
|
|
373a21f4a1 | ||
|
|
89b4cf83ce | ||
|
|
005209f97a | ||
|
|
f0f142fbe0 | ||
|
|
daf9d8965a | ||
|
|
58b12c4aa6 | ||
|
|
4ce3e33447 | ||
|
|
ebd27e4763 | ||
|
|
e60a09fb7e | ||
|
|
828963b586 | ||
|
|
944f4ce6f0 | ||
|
|
73d9a8ccb1 | ||
|
|
3a3967960f | ||
|
|
e38abf27c9 | ||
|
|
05ded88f85 | ||
|
|
dc22c4908b | ||
|
|
c0d9bf7f0d | ||
|
|
1947356ec5 | ||
|
|
2fa4686b33 | ||
|
|
bd06f7f5e5 | ||
|
|
b6d2d7c072 | ||
|
|
3c72f0e1b6 | ||
|
|
6be5693385 | ||
|
|
8e9bb56a29 | ||
|
|
e50d3c6950 | ||
|
|
4db1ccbbd9 | ||
|
|
ccafa01c74 | ||
|
|
cb43b3cbd6 | ||
|
|
9d4e531306 | ||
|
|
7f0e7fdc82 | ||
|
|
f187261085 | ||
|
|
aba69cd640 | ||
|
|
b6dcb75130 | ||
|
|
4e04735a5f | ||
|
|
fc3c686564 | ||
|
|
e826180d06 | ||
|
|
b63117ba6c | ||
|
|
be7796a22c | ||
|
|
1bd4a8d3cc | ||
|
|
1db30f22de | ||
|
|
4c70e654d1 | ||
|
|
3c24f2bdea | ||
|
|
3e610392a9 | ||
|
|
f00dbab0c4 | ||
|
|
bc46646398 | ||
|
|
5fa6c36b73 | ||
|
|
146771f5ca | ||
|
|
bf0bea1edd | ||
|
|
907ad08830 | ||
|
|
7cf0115182 | ||
|
|
adfbead438 | ||
|
|
301774040b | ||
|
|
683037f410 | ||
|
|
57b820c4e8 | ||
|
|
75b223223c | ||
|
|
9a6e2b3e01 | ||
|
|
6e394300c8 | ||
|
|
801150431b | ||
|
|
45d0aac118 | ||
|
|
ee05cd4000 | ||
|
|
74013bb14f | ||
|
|
beb14deba5 | ||
|
|
1212def799 | ||
|
|
95b3bde822 | ||
|
|
f511453f79 | ||
|
|
8653216047 | ||
|
|
e62e0fc8bd | ||
|
|
2ff418f80f | ||
|
|
5d42e8843e | ||
|
|
3c183f73f8 | ||
|
|
3776f12f5c | ||
|
|
5ddec9710a | ||
|
|
f627559005 | ||
|
|
dca92d7f45 | ||
|
|
149dc8537f | ||
|
|
42f7b4fba1 | ||
|
|
17642699d4 | ||
|
|
724fd1e061 | ||
|
|
3eb2dfe0c9 | ||
|
|
73df006d39 | ||
|
|
175f3bb185 | ||
|
|
57061161b6 | ||
|
|
80f97a50e0 | ||
|
|
c265a20d83 | ||
|
|
4937618684 | ||
|
|
1a743b3889 | ||
|
|
425283b774 | ||
|
|
f582576b10 | ||
|
|
16b0f207ed | ||
|
|
fe2bcc7f2d | ||
|
|
a0628c7df5 | ||
|
|
cefe48fe51 | ||
|
|
e8e7fcbe7f | ||
|
|
8a28b4fc88 | ||
|
|
9a96c80af2 | ||
|
|
772e9dc526 | ||
|
|
025f72c876 | ||
|
|
62f80f0ad2 | ||
|
|
803d9c1242 | ||
|
|
ec069a5bcc | ||
|
|
81d11c246c | ||
|
|
85d1d7520a | ||
|
|
810db48a00 | ||
|
|
f9d3dec50f | ||
|
|
236eac610d | ||
|
|
9df9eece3f | ||
|
|
3cd9131795 | ||
|
|
50b68f908e | ||
|
|
f1f3d521b5 | ||
|
|
addca1cb26 | ||
|
|
cbd2a8c080 | ||
|
|
78b3971782 | ||
|
|
201c7e333d | ||
|
|
2c26a4f389 | ||
|
|
266c95e4d7 | ||
|
|
38b19820e4 | ||
|
|
988bddacf7 | ||
|
|
4264856109 | ||
|
|
35d26cb08f | ||
|
|
a9af466702 | ||
|
|
024c8cef49 | ||
|
|
64906ad135 | ||
|
|
4d7a2e28c7 | ||
|
|
a6c5f558bf | ||
|
|
5a6b854c5d | ||
|
|
d31980eb9e | ||
|
|
eb4a6ac275 | ||
|
|
1ba1224644 | ||
|
|
4a78b2dc8c | ||
|
|
0160b430f4 | ||
|
|
c72d36af36 | ||
|
|
7ebb420e7d | ||
|
|
2cf60e177b | ||
|
|
0ce5fb4af3 | ||
|
|
4b5bf09c83 | ||
|
|
be520d6716 | ||
|
|
f3c1b7f3ac | ||
|
|
7a790b32b1 | ||
|
|
293a196c91 | ||
|
|
6b4d2b9cfa | ||
|
|
3c4fb679bd | ||
|
|
f1f69e26fd | ||
|
|
b51ed71bb1 | ||
|
|
65a41eaddd | ||
|
|
5361c85d30 | ||
|
|
a31be093e7 | ||
|
|
f39eefa90c | ||
|
|
eaff9537ef | ||
|
|
2110cf128a | ||
|
|
267e371d3c | ||
|
|
9702f8e4c4 | ||
|
|
524c37d7c7 | ||
|
|
b5387016fa | ||
|
|
5c881da4fe | ||
|
|
0df699659a | ||
|
|
032305ad3a | ||
|
|
b16c7d9723 | ||
|
|
6e1f199571 | ||
|
|
5329193987 | ||
|
|
52cf759bec | ||
|
|
cbbc6160f4 | ||
|
|
a8d3b7d39a | ||
|
|
80095ba617 | ||
|
|
a3d1a35e2f | ||
|
|
8c3df643d0 | ||
|
|
37eefb4b35 | ||
|
|
3f5093f180 | ||
|
|
47b3ee60b6 | ||
|
|
59d20ed9b6 | ||
|
|
f41ed2b943 | ||
|
|
56fa96c494 | ||
|
|
6bfcbd2f9a | ||
|
|
fa7895ad62 | ||
|
|
d405dd7776 | ||
|
|
1ed8b131bc | ||
|
|
9ada6adad7 | ||
|
|
719c6db228 | ||
|
|
a96fdfe10c | ||
|
|
1d1e33f4d5 | ||
|
|
3fda9ccd86 | ||
|
|
3be6667789 | ||
|
|
5103d1c168 | ||
|
|
ce85576882 | ||
|
|
59c60504e7 | ||
|
|
a3c586ef38 | ||
|
|
8bc530d3d0 | ||
|
|
f2c6ac01d9 | ||
|
|
94d9f2c8e8 | ||
|
|
0503e7952d | ||
|
|
787d593996 | ||
|
|
db2a541e5f | ||
|
|
11be13fe53 | ||
|
|
65f8afb908 | ||
|
|
0126b159bf | ||
|
|
31024388ba | ||
|
|
9f2d6b72b7 | ||
|
|
5c5dcb5209 | ||
|
|
be6d47a3ab | ||
|
|
4ff009dbfc | ||
|
|
0998b7381f | ||
|
|
0c339e9123 | ||
|
|
75151e0b00 | ||
|
|
4c4232cc07 | ||
|
|
43845b911b | ||
|
|
0ed45e0710 | ||
|
|
5e30f8e6c0 | ||
|
|
7f3c91ac0c | ||
|
|
3853a2701d | ||
|
|
00a5f81871 | ||
|
|
53d865059d | ||
|
|
b90aedd8f2 | ||
|
|
c4928e5546 | ||
|
|
67ae4598d9 | ||
|
|
6b190eb9f3 | ||
|
|
fae16dabf5 | ||
|
|
b651890a3a | ||
|
|
caa7874bb3 | ||
|
|
53f33bd606 | ||
|
|
57e3fce95e | ||
|
|
52692d05b1 | ||
|
|
d364bd69e4 | ||
|
|
70ab7ff769 | ||
|
|
e30976be76 | ||
|
|
1a55a134c7 | ||
|
|
23f0ba995c | ||
|
|
22a09bd06a | ||
|
|
930a08ec52 | ||
|
|
1701d4dc53 | ||
|
|
1e19a9abe2 | ||
|
|
1098e73337 | ||
|
|
99b0fc4b32 | ||
|
|
10d472d8a6 | ||
|
|
6254f44001 | ||
|
|
c435838376 | ||
|
|
3f7db7e430 | ||
|
|
f98fe32d0c | ||
|
|
d2e8ee0e41 | ||
|
|
a9a455e447 | ||
|
|
3f26bf7348 | ||
|
|
ac302d4a67 | ||
|
|
409bc58e17 | ||
|
|
fbcec2cb5a | ||
|
|
ccb90ed16f | ||
|
|
4389cfcd8b | ||
|
|
5e901fb5c2 | ||
|
|
2974e4b66a | ||
|
|
108ac9b8fc | ||
|
|
de3eca26c3 | ||
|
|
8164166465 | ||
|
|
87fe1e77ae | ||
|
|
a753f6f02e | ||
|
|
c86d4b31f2 | ||
|
|
3c89b22207 | ||
|
|
bebe79c4c9 | ||
|
|
adb0b54691 | ||
|
|
b99436543a | ||
|
|
1194823cd5 | ||
|
|
94716ceb5d | ||
|
|
13120127df | ||
|
|
46037cd54d | ||
|
|
e6cd362a1e | ||
|
|
f21b3a32bd | ||
|
|
35941dd19f | ||
|
|
0f257d38df | ||
|
|
912e68d6eb | ||
|
|
c473646389 | ||
|
|
51cf40d040 | ||
|
|
3fd9cdfa7e | ||
|
|
3189820ba0 | ||
|
|
ed74ec1e97 | ||
|
|
dd95a05487 | ||
|
|
481c02c740 | ||
|
|
0a31a65477 | ||
|
|
2d176b7ccc | ||
|
|
a1fac63710 | ||
|
|
5c7f82e2fe | ||
|
|
e765d17c2b | ||
|
|
8fb9afb955 | ||
|
|
e96780fadb | ||
|
|
2221f0fa32 | ||
|
|
f86b8f32de | ||
|
|
9389db9e9b | ||
|
|
519c3a8df3 | ||
|
|
64422367d5 | ||
|
|
dc2b03e331 | ||
|
|
fcf1b3c310 | ||
|
|
1dd6156a1f | ||
|
|
e75a4c2a95 | ||
|
|
05d8c36afe | ||
|
|
b6c9eaf00f | ||
|
|
ecf5f47960 | ||
|
|
457f117216 | ||
|
|
ebf6ed7526 | ||
|
|
96f2c860fc | ||
|
|
dd52e8e85e | ||
|
|
ecf8c999b1 | ||
|
|
64a1d252cd | ||
|
|
b80d46955c | ||
|
|
0a18c64dcc | ||
|
|
b53c56e7f6 | ||
|
|
17d41b53b7 | ||
|
|
bd98cb0312 | ||
|
|
5566d71522 | ||
|
|
5e1396cc42 | ||
|
|
7fe0678c92 | ||
|
|
7ec25a39a2 | ||
|
|
98e3cde2f5 | ||
|
|
d90c02f951 | ||
|
|
bbb92c86db | ||
|
|
1635236a05 | ||
|
|
5e3a280b5c | ||
|
|
a56e2a419b | ||
|
|
9c01227572 | ||
|
|
6d37a47481 | ||
|
|
87b9e59cdb | ||
|
|
0e86b84efa | ||
|
|
bd595b7f94 | ||
|
|
06d4a3504a | ||
|
|
d68534e833 | ||
|
|
e0356bd751 | ||
|
|
4b770a8abc | ||
|
|
709436ca13 | ||
|
|
28856ef495 | ||
|
|
113bb654aa | ||
|
|
efc1883685 | ||
|
|
72921ba3be | ||
|
|
70be673fca | ||
|
|
bf5205258e | ||
|
|
98ddb0bb29 | ||
|
|
d152f89549 | ||
|
|
c61e94527e | ||
|
|
f76ccaf3d8 | ||
|
|
ebc6cd06ad | ||
|
|
017aaf71d6 | ||
|
|
4eaf16f96d | ||
|
|
718745e7b5 | ||
|
|
06ee1ce38e | ||
|
|
d3e8698e40 | ||
|
|
f122402bdd | ||
|
|
842d68af97 | ||
|
|
bfd1ce9183 | ||
|
|
4ed6575a87 | ||
|
|
1b1c656404 | ||
|
|
018eab9810 | ||
|
|
ec36658ab9 | ||
|
|
eeded0f788 | ||
|
|
7a7ffd3bf8 | ||
|
|
8f3b738e59 | ||
|
|
e7f70a724b | ||
|
|
d7a7bdac7e | ||
|
|
592b903305 |
No files matched your search
@@ -0,0 +1,19 @@
|
||||
.git/
|
||||
.gitignore
|
||||
.gitattributes
|
||||
.github/
|
||||
output/
|
||||
installer/output/
|
||||
*.bin
|
||||
html_data.c
|
||||
html_data.h
|
||||
*.o
|
||||
*.rel
|
||||
*.lst
|
||||
*.sym
|
||||
*.asm
|
||||
*.ihx
|
||||
*.img
|
||||
*.map
|
||||
*.mem
|
||||
*.lk
|
||||
@@ -3,6 +3,7 @@ name: Build firmware
|
||||
on:
|
||||
push:
|
||||
branches: ['**']
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -16,8 +17,14 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt update
|
||||
apt install make gcc sdcc xxd python-is-python3 libjson-c-dev -y
|
||||
- name: Check if machine.c can be compiled for all machines
|
||||
apt install make gcc sdcc xxd python-is-python3 libjson-c-dev zlib1g-dev -y
|
||||
- name: Run the host-side unit tests
|
||||
run: make -C test
|
||||
- name: Check that every machine definition can be compiled
|
||||
run: make machine_check
|
||||
- name: Make project
|
||||
run: make MACHINE="KP_9000_6XHML_X2"
|
||||
- name: Make project (4x2/RTL8372)
|
||||
run: make CI=1 MACHINE="KP_9000_6XHML_X2"
|
||||
- name: Make project (8x1/RTL8373)
|
||||
run: make CI=1 MACHINE="KP_9000_9XHML_X_V3_1"
|
||||
- name: Make project with the health instrumentation
|
||||
run: make clean && make CI=1 MACHINE="KP_9000_6XHML_X2" HEALTH=1
|
||||
@@ -7,3 +7,7 @@ version.h
|
||||
tools/httpd_sim
|
||||
tools/injector
|
||||
tools/fileadder
|
||||
|
||||
# host-test stand-ins for the two generated headers
|
||||
!test/stub/html_data.h
|
||||
!test/stub/version.h
|
||||
@@ -0,0 +1,37 @@
|
||||
# Change Log
|
||||
|
||||
## [0.x] - 2026-xx-XX
|
||||
|
||||
## Added
|
||||
|
||||
- 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
|
||||
|
||||
- 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.
|
||||
|
||||
## Breaking changes
|
||||
|
||||
- Config
|
||||
- VLAN don't accept port `u`-suffix anymore.
|
||||
So `vlan 1 4u` is not valid anymore.
|
||||
Replace it with `vlan 1 4`.
|
||||
- Commands
|
||||
- port zero/`0` is treated as the `CPU_PORT`. #326
|
||||
- Many commands don't accept the CPU_PORT anymore. See #334.
|
||||
When the CPU_PORT is needed, the command/service will add the CPU_PORT automaticly.
|
||||
Only `isolate` accept the CPU_PORT as destination port.
|
||||
|
||||
## [v0.1_aplha] - 2025-11-03
|
||||
|
||||
First release.
|
||||
@@ -0,0 +1,19 @@
|
||||
FROM debian:13-slim
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
make \
|
||||
gcc \
|
||||
sdcc \
|
||||
xxd \
|
||||
python3 \
|
||||
libjson-c-dev \
|
||||
git \
|
||||
zlib1g-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# git safe.directory for mounted repos (Makefile uses git describe)
|
||||
RUN git config --global --add safe.directory /workspace
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
CMD ["bash"]
|
||||
@@ -4,19 +4,35 @@ DEFAULT_CONFIG_LOCATION = 454656
|
||||
CONFIG_LOCATION = 458752
|
||||
HTML_LOCATION = 262144
|
||||
|
||||
ifeq ($(origin CC),default)
|
||||
CC = sdcc
|
||||
CC_FLAGS = -mmcs51 -I. -Ihttpd -Iuip
|
||||
ASM = sdas8051
|
||||
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
|
||||
# $MACHINE selects machine/$(MACHINE).c as the board definition and is passed
|
||||
# on as -DMACHINE_$(MACHINE), which the rest of the firmware tests with
|
||||
# #if defined(MACHINE_...), and as -DMACHINE_NAME, which machine.h uses to
|
||||
# include machine/$(MACHINE).h. Both take the same value, so they cannot drift.
|
||||
ifneq ($(MACHINE),)
|
||||
CC_FLAGS += -DMACHINE_$(MACHINE)
|
||||
CC_FLAGS += -DMACHINE_NAME=$(MACHINE)
|
||||
endif
|
||||
# Health instrumentation and the "health" console command: HEALTH=1 gmake ...
|
||||
ifneq ($(HEALTH),)
|
||||
CC_FLAGS += -DHEALTH
|
||||
endif
|
||||
|
||||
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
|
||||
|
||||
BUILDDIR = output/$(MACHINE)
|
||||
VERSION_HEADER := version.h
|
||||
@@ -30,76 +46,177 @@ endif
|
||||
VERSION_EXTENSION = v$(VERSION)-$(GIT_VERSION)
|
||||
FILENAME_EXTENSION = $(VERSION_EXTENSION)-$(MACHINE)
|
||||
|
||||
all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
|
||||
# Deterministic build date: honor SOURCE_DATE_EPOCH, else the HEAD commit date,
|
||||
# else wall-clock (no-git fallback). Keeps same-commit builds byte-identical
|
||||
# (BUILD_DATE is baked into the image and covered by the trailing CRC).
|
||||
SOURCE_DATE_EPOCH ?= $(shell git show -s --format=%ct HEAD 2>/dev/null)
|
||||
ifeq ($(SOURCE_DATE_EPOCH),)
|
||||
BUILD_DATE := $(shell date +"%Y-%m-%d %H:%M:%S")
|
||||
else
|
||||
BUILD_DATE := $(shell date -u -d @$(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S" 2>/dev/null \
|
||||
|| date -u -r $(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S")
|
||||
endif
|
||||
|
||||
# $(MACHINE_SRC) is listed here so an unknown $MACHINE fails before anything else
|
||||
# is built, including the tools/ subdirectory.
|
||||
all: create_build_dir $(VERSION_HEADER) $(MACHINE_SRC) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
|
||||
|
||||
create_build_dir:
|
||||
mkdir -p $(BUILDDIR)
|
||||
mkdir -p $(BUILDDIR)/uip
|
||||
mkdir -p $(BUILDDIR)/httpd
|
||||
mkdir -p "$(BUILDDIR)"
|
||||
mkdir -p "$(BUILDDIR)/uip"
|
||||
mkdir -p "$(BUILDDIR)/httpd"
|
||||
mkdir -p "$(BUILDDIR)/machine"
|
||||
|
||||
# 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
|
||||
|
||||
# Keep the per-machine definition in first position to fail immediately on an
|
||||
# invalid $MACHINE value
|
||||
SRCS = \
|
||||
$(MACHINE_SRC) \
|
||||
machine_init.c \
|
||||
cmd_editor.c \
|
||||
cmd_parser.c \
|
||||
dhcp.c \
|
||||
html_data.c \
|
||||
rtlplayground.c \
|
||||
boot.c \
|
||||
sfp.c \
|
||||
dns.c \
|
||||
dns_cli.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_leds.c \
|
||||
rtl837x_leds_dump.c \
|
||||
rtl837x_phy.c \
|
||||
rtl837x_pins.c\
|
||||
rtl837x_port.c \
|
||||
rtl837x_stp.c \
|
||||
rtl837x_lldp.c \
|
||||
rtl837x_storm.c \
|
||||
rtl837x_lacp.c \
|
||||
rtl837x_trap.c
|
||||
SRCS += \
|
||||
httpd/httpd.c \
|
||||
httpd/page_impl.c
|
||||
SRCS += \
|
||||
uip/timer.c \
|
||||
uip/uip.c \
|
||||
uip/uiplib.c \
|
||||
uip/uip_arp.c \
|
||||
uip/uip-fw.c \
|
||||
uip/uip-neighbor.c \
|
||||
uip/uip-split.c
|
||||
|
||||
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_leds.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c
|
||||
SRCS += rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c cmd_editor.c rtl837x_bandwidth.c rtl837x_init.c syslog.c
|
||||
SRCS += uip/timer.c uip/uip.c uip/uip_arp.c uip/uiplib.c uip/uip-fw.c uip/uip-neighbor.c uip/uip-split.c udp_apps.c
|
||||
SRCS += httpd/httpd.c httpd/page_impl.c
|
||||
OBJS = ${SRCS:%.c=$(BUILDDIR)/%.rel}
|
||||
DEPS := ${SRCS:%.c=$(BUILDDIR)/%.d}
|
||||
HTML := $(shell find $(html) -name '*.js' -or -name '*.html' -or -name '*.svg')
|
||||
HTML := $(shell find html -name '*.js' -or -name '*.html' -or -name '*.svg' -or -name '*.css' -or -name '*.ico')
|
||||
|
||||
html_data.c html_data.h: $(HTML) tools/output/fileadder
|
||||
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -d html -p html_data
|
||||
# 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
|
||||
.PHONY: html_min
|
||||
html_min: $(HTML)
|
||||
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
|
||||
|
||||
$(VERSION_HEADER):
|
||||
@echo "#ifndef VERSION_H" > $(VERSION_HEADER)
|
||||
@echo "#define VERSION_H" >> $(VERSION_HEADER)
|
||||
@echo "#define VERSION_SW \"$(VERSION_EXTENSION)\"" >> $(VERSION_HEADER)
|
||||
@echo "#define BUILD_DATE \"$(shell date +"%Y-%m-%d %H:%M:%S")\"" >> $(VERSION_HEADER)
|
||||
@echo "#endif" >> $(VERSION_HEADER)
|
||||
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
|
||||
|
||||
$(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).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 $@
|
||||
|
||||
clean:
|
||||
clean: $(SUBDIRSCLEAN)
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER)
|
||||
-if [ -d $(BUILDDIR) ]; then find $(BUILDDIR) -type f ! -name "*.bin" -delete; fi
|
||||
|
||||
distclean:
|
||||
distclean: $(SUBDIRSCLEAN)
|
||||
-rm -f html_data.c html_data.h $(VERSION_HEADER)
|
||||
-rm -rf $(BUILDDIR)
|
||||
|
||||
$(BUILDDIR)/%.rel: %.c
|
||||
$(SUBDIRSCLEAN):
|
||||
$(MAKE) -C $(@:clean=) clean
|
||||
|
||||
# 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)' > $@
|
||||
|
||||
$(BUILDDIR)/%.rel: %.c $(CCFLAGS_STAMP) | create_build_dir html_data.h
|
||||
$(CC) -MMD $(CC_FLAGS) -o $@ -c $<
|
||||
|
||||
$(BUILDDIR)/%.rel: %.asm
|
||||
$(BUILDDIR)/%.rel: %.asm $(CCFLAGS_STAMP) | create_build_dir
|
||||
${ASM} ${AFLAGS} -o $@ $<
|
||||
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
|
||||
|
||||
$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtstart.rel $(BUILDDIR)/crc16.rel
|
||||
$(CC) $(CC_FLAGS) -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-r -o $@ $^
|
||||
$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtbank.rel $(BUILDDIR)/crc16.rel
|
||||
$(CC) $(CC_FLAGS) --xram-size 49151 -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-bBANK3=0x34000 -Wl-r -o $@ $^
|
||||
|
||||
$(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx
|
||||
objcopy --input-target=ihex -O binary $< $@
|
||||
|
||||
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img
|
||||
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img | 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) -d html -p html_data -b BANK1 $@
|
||||
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -z -d $(HTML_MIN) -b BANK1 $@
|
||||
tools/output/crc_calculator -u $@
|
||||
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin output/rtlplayground.bin
|
||||
|
||||
.PHONY: clean all $(SUBDIRS) $(VERSION_HEADER)
|
||||
.PHONY: clean distclean all $(SUBDIRS) $(SUBDIRSCLEAN) create_build_dir
|
||||
|
||||
# Every machine/ definition is compiled, so a machine added to machine/ is
|
||||
# covered without registering it anywhere. 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 $(patsubst machine/%.c,%,$(wildcard machine/*.c)))
|
||||
MACHINE_LESS_CC_FLAGS = $(filter-out -DMACHINE_%,$(CC_FLAGS))
|
||||
|
||||
.PHONY:
|
||||
machine_check:
|
||||
@mkdir -p $(BUILDDIR)/tmp
|
||||
@set -eo pipefail; \
|
||||
for MACHINE in `grep -e ' MACHINE_' machine.c | sed -e 's%^.* MACHINE_%%' -e 's%[ ]*//.*$$%%' | 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) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_$${MACHINE} -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine/$${MACHINE}.c; \
|
||||
$(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_$${MACHINE} -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine_init.c; \
|
||||
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,17 +25,19 @@ 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 STP and the proprietary loop prevention
|
||||
protocols as well as DHCP. If you need these features, do not install the playground on your managed
|
||||
the firmware still lacks support for the proprietary loop prevention
|
||||
protocols as well as DHCP. Spanning Tree is available (see doc/stp.md), but is
|
||||
a simplified implementation - read that document before enabling it on a
|
||||
switch you administer over the network. If you need these features, do not install the playground on your managed
|
||||
devices. In any case, installation is strongly discouraged unless you can at least make
|
||||
a backup of the original flash content via a SOIC clamp such as also used for BIOS
|
||||
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
|
||||
@@ -57,21 +59,73 @@ device simulator is provided, which runs entirely under Linux as a local webserv
|
||||
Install the following particular build requisites (Debian 12/13), note that Ubuntu 24.04
|
||||
still has an older version of sdcc, but you will need sdcc version 4.5 for the code to compile:
|
||||
```
|
||||
sudo apt install make gcc sdcc xxd python-is-python3 libjson-c-dev
|
||||
sudo apt install make gcc sdcc xxd python-is-python3 libjson-c-dev zlib1g-dev
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>If using Docker (click to expand)</summary>
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Install Docker for your platform:
|
||||
|
||||
- **Linux (Debian/Ubuntu)**: `sudo apt install docker.io` then `sudo usermod -aG docker $USER` (log out and back in)
|
||||
- **Linux (other distros)**: Follow the [Docker Engine install guide](https://docs.docker.com/engine/install/)
|
||||
- **Windows**: Install [Docker Desktop for Windows](https://docs.docker.com/desktop/setup/install/windows-install/)
|
||||
- **macOS**: Install [Docker Desktop for Mac](https://docs.docker.com/desktop/setup/install/mac-install/)
|
||||
|
||||
### Usage
|
||||
|
||||
A Dockerfile is provided for a reproducible build environment:
|
||||
|
||||
```
|
||||
docker build -t rtlplayground-dev .
|
||||
```
|
||||
|
||||
Build the firmware (replace MACHINE with your target, e.g. `DEFAULT_8C_1SFP`):
|
||||
|
||||
```
|
||||
docker run --rm -v $(pwd):/workspace rtlplayground-dev make MACHINE=DEFAULT_8C_1SFP
|
||||
```
|
||||
|
||||
The resulting `.bin` file appears in `output/` on your host.
|
||||
|
||||
Build host tools only:
|
||||
|
||||
```
|
||||
docker run --rm -v $(pwd):/workspace rtlplayground-dev make -C tools
|
||||
```
|
||||
|
||||
Run the web-interface simulator locally:
|
||||
|
||||
```
|
||||
docker run --rm -p 8080:8080 -v $(pwd):/workspace rtlplayground-dev \
|
||||
tools/output/httpd_sim /workspace/html
|
||||
```
|
||||
|
||||
Edit `config.txt` on your host, then re-run `make` — the
|
||||
source directory is mounted into the container, so changes take effect
|
||||
immediately. To build for a different machine, pass `MACHINE=<name>`, which
|
||||
selects `machine/<name>.c` (see [Adding a new device](doc/adding-a-device.md)).
|
||||
|
||||
</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).
|
||||
|
||||
> [!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`
|
||||
@@ -82,7 +136,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)
|
||||
|
||||
@@ -126,11 +180,11 @@ Header checksum is: 0x5a1
|
||||
## (3) Sandbox Usage with Ghidra (optional)
|
||||
|
||||
You can play with the image using ghidra or flash real Switch Hardware. For
|
||||
ghidra see this information about [Ghidra images](ghidra.md).
|
||||
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.
|
||||
@@ -141,7 +195,7 @@ Go to "Firmware update" tab, select the correct file.
|
||||
|
||||
> [!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 !
|
||||
|
||||
@@ -149,7 +203,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.
|
||||
@@ -169,7 +223,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)
|
||||
@@ -184,7 +238,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`.
|
||||
@@ -284,17 +338,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]
|
||||
|
||||
@@ -303,11 +358,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)
|
||||
- [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)
|
||||
@@ -0,0 +1,479 @@
|
||||
#pragma codeseg BANK3
|
||||
#pragma constseg BANK3
|
||||
|
||||
#include <8051.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "rtl837x_sfr.h"
|
||||
#include "rtl837x_regs.h"
|
||||
#include "rtl837x_common.h"
|
||||
#include "rtl837x_flash.h"
|
||||
#include "rtl837x_pins.h"
|
||||
#include "rtl837x_phy.h"
|
||||
#include "rtl837x_port.h"
|
||||
#include "rtl837x_init.h"
|
||||
#include "machine.h"
|
||||
#include "phy.h"
|
||||
#include "boot.h"
|
||||
|
||||
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 const uint8_t * __code const hex;
|
||||
|
||||
|
||||
|
||||
void sds_config_mac(uint8_t sds, uint8_t mode) __banked
|
||||
{
|
||||
reg_read_m(RTL837X_REG_SDS_MODES);
|
||||
sfr_data[0] = 0;
|
||||
sfr_data[1] = 0;
|
||||
switch (sds) {
|
||||
case 0:
|
||||
sfr_mask_data(0, 0x1f, mode);
|
||||
break;
|
||||
case 1:
|
||||
sfr_mask_data(0, 0xe0, mode << 5);
|
||||
sfr_mask_data(1, 0x03, mode >> 3);
|
||||
break;
|
||||
case 2:
|
||||
sfr_mask_data(1, 0xfc, 0x02 << 2);
|
||||
}
|
||||
if (machine_detected.isRTL8373) // Set 3rd SERDES Mode to 0x2 for RTL8224
|
||||
sfr_mask_data(1, 0xfc, 0x02 << 2);
|
||||
else
|
||||
sfr_data[2] &= 0x03;
|
||||
reg_write_m(RTL837X_REG_SDS_MODES);
|
||||
print_string("\nRTL837X_REG_SDS_MODES: ");
|
||||
print_reg(RTL837X_REG_SDS_MODES);
|
||||
print_string("\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void early_boot_handle_button(void) __banked
|
||||
{
|
||||
if (machine.reset_pin == GPIO_NA)
|
||||
return;
|
||||
|
||||
gpio_input_setup(machine.reset_pin);
|
||||
|
||||
// Debounce after init
|
||||
delay(100);
|
||||
// If the button is not already held at boot, continue normally.
|
||||
if (gpio_pin_test(machine.reset_pin))
|
||||
return;
|
||||
|
||||
set_sys_led_state(SYS_LED_FAST);
|
||||
print_string("\n[Reset button held at boot]\n");
|
||||
|
||||
if (gpio_pin_test(machine.reset_pin))
|
||||
return;
|
||||
|
||||
const __xdata uint32_t min_hold_ticks = 10UL * SYS_TICK_HZ;
|
||||
const __xdata uint32_t max_hold_ticks = 30UL * SYS_TICK_HZ;
|
||||
const __xdata uint32_t blink_ticks = SYS_TICK_HZ / 10; // 100 ms
|
||||
const __xdata uint32_t pause_ticks = SYS_TICK_HZ / 2; // 500 ms
|
||||
__xdata uint32_t start_ticks = ticks;
|
||||
__xdata uint32_t last_blink_step = start_ticks;
|
||||
__xdata uint8_t blink_step = 0;
|
||||
|
||||
set_sys_led_state(SYS_LED_ON);
|
||||
|
||||
while (!gpio_pin_test(machine.reset_pin)) {
|
||||
__xdata uint32_t held_ticks = ticks - start_ticks;
|
||||
|
||||
if (held_ticks > max_hold_ticks) {
|
||||
print_string("[Button held >30s at boot; continuing normal boot]\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Double blink pattern while button is held:
|
||||
// ON (100ms), OFF (100ms), ON (100ms), OFF (500ms)
|
||||
__xdata uint32_t step_ticks = (blink_step == 3) ? pause_ticks : blink_ticks;
|
||||
if ((ticks - last_blink_step) >= step_ticks) {
|
||||
blink_step = (blink_step + 1) & 0x3;
|
||||
set_sys_led_state((blink_step == 0 || blink_step == 2) ? SYS_LED_ON : SYS_LED_OFF);
|
||||
last_blink_step = ticks;
|
||||
}
|
||||
|
||||
PCON |= 1;
|
||||
}
|
||||
|
||||
set_sys_led_state(SYS_LED_ON);
|
||||
|
||||
if ((ticks - start_ticks) >= min_hold_ticks) {
|
||||
print_string("[Button held 10s-30s at boot; restoring default config]\n");
|
||||
set_sys_led_state(SYS_LED_FAST);
|
||||
flash_default_config();
|
||||
delay(3UL * SYS_TICK_HZ);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Configure the SerDes of the SoC for a particular mode
|
||||
* to connect to an SFP module or a PHY
|
||||
* Valid modes are SDS_10GR, SDS_QXGMII, SDS_HISGMII, SDS_HSG, SDS_SGMII and SDS_1000BX_FIBER
|
||||
* The SerDes ID may be 0 or 1 for RTL8272 and 0-2 for RTL8373
|
||||
* SDS_QXGMII is used for 10G Fiber, RTL8224 and RTL8261BE
|
||||
*/
|
||||
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;
|
||||
|
||||
switch (mode) {
|
||||
case SDS_SGMII:
|
||||
case SDS_1000BX_FIBER:
|
||||
v = 0x0300;
|
||||
page = 0x24;
|
||||
break;
|
||||
case SDS_HISGMII:
|
||||
case SDS_HSG:
|
||||
v = 0x0200;
|
||||
page = 0x28;
|
||||
break;
|
||||
case SDS_10GR:
|
||||
case SDS_QXGMII:
|
||||
v = 0x0200;
|
||||
page = 0x2e;
|
||||
break;
|
||||
case SDS_100FX:
|
||||
v = 0x0200;
|
||||
page = 0x26;
|
||||
break;
|
||||
default:
|
||||
print_string("Error in SDS Mode\n");
|
||||
return;
|
||||
}
|
||||
sds_write_v(sds, 0x36, 0x10, v); // Q003610:0200
|
||||
|
||||
if (page == 0x2e) { // 10G Fiber / SDS_QXGMII
|
||||
sds_write_v(sds, page, 0x04, 0x0080); // Q012e04:0080
|
||||
sds_write_v(sds, page, 0x06, 0x0408); // Q012e06:0408
|
||||
sds_write_v(sds, page, 0x07, 0x020d); // Q012e07:020d
|
||||
sds_write_v(sds, page, 0x09, 0x0601); // Q012e09:0601
|
||||
sds_write_v(sds, page, 0x0b, 0x222c); // Q012e0b:222c
|
||||
sds_write_v(sds, page, 0x0c, 0xa217); // Q012e0c:a217
|
||||
sds_write_v(sds, page, 0x0d, 0xfe40); // Q012e0d:fe40
|
||||
sds_write_v(sds, page, 0x15, 0xf5c1); // Q012e15:f5c1
|
||||
} else {
|
||||
sds_write_v(sds, page, 0x04, 0x0080); // Q002804:0080
|
||||
sds_write_v(sds, page, 0x07, 0x1201); // Q002807:1201
|
||||
sds_write_v(sds, page, 0x09, 0x0601); // Q002809:0601
|
||||
sds_write_v(sds, page, 0x0b, 0x232c); // Q00280b:232c
|
||||
sds_write_v(sds, page, 0x0c, 0x9217); // Q00280c:9217
|
||||
sds_write_v(sds, page, 0x0f, 0x5b50); // Q00280f:5b50
|
||||
sds_write_v(sds, page, 0x15, 0xe7c1); // Q002815:e7f1 BUG !
|
||||
}
|
||||
|
||||
sds_write_v(sds, page, 0x16, 0x0443); // Q002816:0443 / Q012e16:0443
|
||||
sds_write_v(sds, page, 0x1d, 0xabb0); // Q00281d:abb0 / Q012e1d:abb0
|
||||
|
||||
sds_write_v(sds, 0x06, 0x12, 0x5078); // Q000612:5078
|
||||
sds_write_v(sds, 0x07, 0x06, 0x9401); // Q000706:9401
|
||||
sds_write_v(sds, 0x07, 0x08, 0x9401); // Q000708:9401
|
||||
sds_write_v(sds, 0x07, 0x0a, 0x9401); // Q00070a:9401
|
||||
sds_write_v(sds, 0x07, 0x0c, 0x9401); // Q00070c:9401
|
||||
sds_write_v(sds, 0x1f, 0x0b, 0x0003); // Q001f0b:0003
|
||||
sds_write_v(sds, 0x06, 0x03, 0xc45c); // Q000603:c45c
|
||||
|
||||
// RTL8261BE
|
||||
if (machine.n_10g && mode == SDS_QXGMII) {
|
||||
sds_write_v(sds, 0x06, 0x1f, 0x2100); // Q00061f:2100
|
||||
sds_write_v(sds, 0x07, 0x11, 0x054f); // Q000711:054f
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0030); // Q002000:0030
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0050); // Q002000:0050
|
||||
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0cd0); // Q002000:0cd0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x04d0); // Q002000:04d0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x04d0); // Q002000:04d0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0cd0); // Q002000:0cd0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0050); // Q002000:0050
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0030); // Q002000:0030
|
||||
sds_write_v(sds, 0x20, 0x00, 0x0000); // Q002000:0000
|
||||
sds_write_v(sds, 0x1f, 0x00, 0x000b); // Q001f00:000b
|
||||
sds_write_v(sds, 0x1f, 0x00, 0x0000); // Q001f00:0000
|
||||
return;
|
||||
}
|
||||
if (mode != SDS_QXGMII)
|
||||
sds_write_v(sds, 0x06, 0x1f, 0x2100); // Q00061f:2100
|
||||
|
||||
if (mode == SDS_1000BX_FIBER) {
|
||||
sds_write_v(sds, 0x02, 0x04, 0x0020); // Q000204:0020
|
||||
sds_write_v(sds, 0x00, 0x02, 0x73d0); // Q000002:73d0
|
||||
sds_write_v(sds, 0x00, 0x04, 0x074d); // Q000004:074d
|
||||
sds_write_v(sds, 0x20, 0x04, 0x0000); // Q002000:0000
|
||||
sds_write_v(sds, 0x1f, 0x00, 0x0000); // Q001f00:0000
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void rtl8224_enable(void) __banked
|
||||
{
|
||||
// Set Pin 4 low
|
||||
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(4);
|
||||
// Set pin 4 high
|
||||
reg_bit_set(RTL837X_REG_GPIO_32_63_OUTPUT, 4);
|
||||
rtl8224_release_tick = ticks;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void nic_setup(void) __banked
|
||||
{
|
||||
// Enable NIC
|
||||
// r6040:00000100 R6040-00001100
|
||||
reg_bit_set(RTL837X_REG_HW_CONF, 0xc);
|
||||
|
||||
// This sets the size of the RX buffer, the filling level is in 0x7874
|
||||
// R7848-000004ff
|
||||
REG_SET(RTL837X_REG_NIC_RXBUFF_RX, 0x4ff);
|
||||
|
||||
// R7844-000007fe
|
||||
REG_SET(RTL837X_REG_NIC_BUFFSIZE_TX, 0x7fe);
|
||||
|
||||
// Configure NIC RX to receive various types of packets
|
||||
// RTL837X_REG_RX_CTRL: Set bits 24-31 to 0x4, clear bits 16/17
|
||||
reg_read_m(RTL837X_REG_RX_CTRL);
|
||||
sfr_mask_data(3, 0xff, 0x04);
|
||||
sfr_mask_data(2, 0x03, 0);
|
||||
reg_write_m(RTL837X_REG_RX_CTRL);
|
||||
|
||||
// Enable NIC TX (set bit 0)
|
||||
reg_bit_set(RTL837X_REG_TX_CTRL, 0);
|
||||
|
||||
// Enable NIC RX (set bit 0)
|
||||
reg_bit_set(RTL837X_REG_RX_CTRL, 0);
|
||||
|
||||
// Drop packets with invalid CRC
|
||||
reg_bit_clear(RTL837X_REG_RX_CTRL, 2);
|
||||
|
||||
// R603c-00000200
|
||||
// CPU-port is CPU-Tag aware (bit 9)
|
||||
REG_SET(RTL837X_REG_CPU_TAG_AWARE_PMASK, 0x200);
|
||||
|
||||
// Insert CPU-tag for internally received packets (bit 0), MODE is 0, i.e. ALL packets (bits 8-9)
|
||||
reg_read_m(RTL837X_REG_CPU_TAG);
|
||||
sfr_mask_data(0, 1, 1);
|
||||
sfr_mask_data(1, 3, 0);
|
||||
reg_write_m(RTL837X_REG_CPU_TAG);
|
||||
|
||||
// Force MAC mode of the CPU port (port 9)
|
||||
// r6368:00000194 R6368-00000197
|
||||
reg_read_m(RTL837X_REG_MAC_FORCE_MODE + 9 * 4);
|
||||
sfr_mask_data(0, 0, 3); // Set bits 0, 1: Force link
|
||||
reg_write_m(RTL837X_REG_MAC_FORCE_MODE+ 9 * 4);
|
||||
|
||||
// Sequence number of TX packets
|
||||
tx_seq = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void rtl8373_revision(void) __banked
|
||||
{
|
||||
reg_read_m(RTL837X_REG_CHIP_INFO);
|
||||
sfr_mask_data(2, 0x0a, 0x0a); // Enable reading version
|
||||
reg_write_m(RTL837X_REG_CHIP_INFO);
|
||||
delay(50);
|
||||
|
||||
reg_read_m(RTL837X_REG_CHIP_INFO);
|
||||
print_string("CPU revision: "); print_byte(sfr_data[2]); print_byte(sfr_data[2]); write_char('\n');
|
||||
sfr_mask_data(2, 0x0a, 0x00); // Enable reading version
|
||||
reg_write_m(RTL837X_REG_CHIP_INFO);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The SoC manages Link-State for steering the LEDs and can set PHY-settings
|
||||
* automatically through Realtek's SMI (Simple Managagement) Interface, a
|
||||
* proprietary version of MDIO which for example allows for more PHYs on the same
|
||||
* bus.
|
||||
* Configure polling via SMI and the interface setup during boot.
|
||||
*/
|
||||
void init_smi(void) __banked
|
||||
{
|
||||
print_string("\ninit_switch called\n");
|
||||
|
||||
/* Set the SMI(i.e.I2C) type for PHY polling, 0b01 is 2.5/10G PHY. Disable (0b00) for the SFP-ports
|
||||
* which are at port 8 and additionally at port 3 for a dual SFP device
|
||||
*/
|
||||
|
||||
// Default: 0x00005555
|
||||
// Workaround for SDCC BUG 4070: SFR_DATA_U32 = 0x00005555;
|
||||
SFR_DATA_U16_UPPER = 0x0000;
|
||||
SFR_DATA_U16 = 0x5555;
|
||||
if (machine.n_10g == 2) {
|
||||
// 0x00015555, only change the bytes that differs from the default.
|
||||
SFR_DATA_16 = 0x01;
|
||||
} else if (machine.n_sfp == 2)
|
||||
// 0x00005515
|
||||
SFR_DATA_0 = 0x15;
|
||||
reg_write(RTL837X_REG_SMI_MAC_TYPE);
|
||||
|
||||
// Configure polling of all PHYs by the MAC to detect link-state changes
|
||||
// Default: 0x000000ff
|
||||
// Workaround for SDCC BUG 4070: SFR_DATA_U32 = 0x000000ff;
|
||||
SFR_DATA_U16_UPPER = 0x0000;
|
||||
SFR_DATA_U16 = 0x00ff;
|
||||
if (!machine_detected.isRTL8373) {
|
||||
if (machine.n_sfp == 2) {
|
||||
// 0x000000f0, only change the bytes that differs from the default.
|
||||
SFR_DATA_0 = 0xf0;
|
||||
} else {
|
||||
// 0x000001f8, only change the bytes that differs from the default.
|
||||
SFR_DATA_8 = 0x01;
|
||||
SFR_DATA_0 = 0xf8;
|
||||
}
|
||||
}
|
||||
reg_write(RTL837X_REG_SMI_PORT_POLLING);
|
||||
// Enable MDC
|
||||
reg_read_m(RTL837X_REG_SMI_CTRL);
|
||||
sfr_mask_data(1, 0, 0x70); // Set bits 12-14 to enable MDC for SMI0-SMI2
|
||||
reg_write_m(RTL837X_REG_SMI_CTRL);
|
||||
delay(50);
|
||||
|
||||
if (!machine_detected.isRTL8373) {
|
||||
// Change I2C addresses for SMI of the non-existent PHYs
|
||||
// r6450:000020e6 R6450-000000e6
|
||||
reg_read_m(RTL837X_REG_SMI_PORT6_9_ADDR);
|
||||
sfr_mask_data(1, 0x7c, 0);
|
||||
reg_write_m(RTL837X_REG_SMI_PORT6_9_ADDR);
|
||||
|
||||
// r644c:0a418820 R644c-0a400820
|
||||
reg_read_m(RTL837X_REG_SMI_PORT0_5_ADDR);
|
||||
sfr_mask_data(2, 0x0f, 0);
|
||||
sfr_mask_data(1, 0x80, 0);
|
||||
reg_write_m(RTL837X_REG_SMI_PORT0_5_ADDR);
|
||||
}
|
||||
|
||||
if (machine.n_10g == 2) {
|
||||
// Set address of second external PHY on port 8
|
||||
REG_SET(RTL837X_REG_SMI_PORT6_9_ADDR, 0x000040e6);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setup_i2c(void) __banked
|
||||
{
|
||||
REG_SET(RTL837X_REG_I2C_MST_IF_CTRL, 0);
|
||||
// Configure SFP EEPROM address (0x50) as I2C device address
|
||||
// Configure SFP readings address (0x51) as I2C device address
|
||||
REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16), 0x50 >> 5, (0x50 << 3) & 0xff);
|
||||
|
||||
REG_SET(RTL837X_REG_I2C_CTRL2, 0);
|
||||
|
||||
// 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++) {
|
||||
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');
|
||||
// `& 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);
|
||||
break;
|
||||
case 2:
|
||||
// Bit 15-16 0b01 -> SCL
|
||||
sfr_mask_data(1, 0x80, 0x80);
|
||||
sfr_mask_data(2, 0x01, 0x00);
|
||||
break;
|
||||
case 1:
|
||||
// Bit 11-12 0b01 -> SCL
|
||||
sfr_mask_data(1, 0x18, 0x08);
|
||||
break;
|
||||
case 0:
|
||||
// Bit 7-8 0b01 -> SCL
|
||||
sfr_mask_data(0, 0x80, 0x80);
|
||||
sfr_mask_data(1, 0x01, 0x00);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (sda_bus) {
|
||||
case 4:
|
||||
// Bit 29 0b0 -> SDA
|
||||
sfr_mask_data(3, 0x20, 0x00);
|
||||
break;
|
||||
case 3:
|
||||
// Bit 5-6 0b10 -> SDA (implies enabled SCL on bus 3)
|
||||
sfr_mask_data(0, 0x60, 0x40);
|
||||
break;
|
||||
case 2:
|
||||
// Bit 17-18 0b01 -> SDA
|
||||
sfr_mask_data(2, 0x06, 0x02);
|
||||
break;
|
||||
case 1:
|
||||
// Bit 13-14 0b01 -> SDA
|
||||
sfr_mask_data(1, 0x60, 0x20);
|
||||
break;
|
||||
case 0:
|
||||
// Bit 9-10 0b01 -> SDA
|
||||
sfr_mask_data(1, 0x06, 0x02);
|
||||
break;
|
||||
}
|
||||
}
|
||||
reg_write_m(RTL837X_PIN_MUX_1);
|
||||
}
|
||||
|
||||
|
||||
/* Give the switch a name carrying the tail of its MAC, so several of them on
|
||||
* one network are distinguishable out of the box. Called after the startup
|
||||
* config has been replayed and returns at once if that config already set a
|
||||
* name, so a configured switch does no work for it (suggested in review).
|
||||
*
|
||||
* Written without a loop on purpose. Locals - counters and pointers alike -
|
||||
* land in the 8051's internal-RAM overlay, and on an image with LACP and STP
|
||||
* both enabled that overlay is exhausted: a loop here makes the linker fail
|
||||
* with "Could not get 8 consecutive bytes in internal RAM for area OSEG".
|
||||
* Moving the code into its own function does not help; the overlay is shared
|
||||
* across the whole image. Hoisting the locals to xdata does not help either,
|
||||
* because itohex() is inline and brings its own frame. */
|
||||
void set_hostname_default(void) __banked
|
||||
{
|
||||
if (hostname[0] != NUL)
|
||||
return;
|
||||
|
||||
strcpy((__xdata uint8_t *)hostname, "RTLPlayground-");
|
||||
hostname[14] = hex[uip_ethaddr.addr[3] >> 4];
|
||||
hostname[15] = hex[uip_ethaddr.addr[3] & 0xf];
|
||||
hostname[16] = hex[uip_ethaddr.addr[4] >> 4];
|
||||
hostname[17] = hex[uip_ethaddr.addr[4] & 0xf];
|
||||
hostname[18] = hex[uip_ethaddr.addr[5] >> 4];
|
||||
hostname[19] = hex[uip_ethaddr.addr[5] & 0xf];
|
||||
hostname[20] = NUL;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef BOOT_H
|
||||
#define BOOT_H
|
||||
|
||||
void sds_config_mac(uint8_t sds, uint8_t mode) __banked;
|
||||
void sds_config(uint8_t sds, uint8_t mode) __banked;
|
||||
void early_boot_handle_button(void) __banked;
|
||||
void rtl8224_enable(void) __banked;
|
||||
void nic_setup(void) __banked;
|
||||
void rtl8373_revision(void) __banked;
|
||||
void init_smi(void) __banked;
|
||||
void setup_i2c(void) __banked;
|
||||
void set_hostname_default(void) __banked;
|
||||
|
||||
#endif
|
||||
@@ -40,21 +40,24 @@ void cmd_edit(void) __banked
|
||||
{
|
||||
while (l != sbuf_ptr) {
|
||||
if (sbuf[l] >= ' ' && sbuf[l] < 127) { // A printable character, copy to command line
|
||||
if (cmd_line_len >= CMD_BUF_SIZE)
|
||||
continue;
|
||||
write_char(sbuf[l]);
|
||||
// Shift buffer to right
|
||||
for (uint8_t i = cmd_line_len; i > cursor; i--)
|
||||
cmd_buffer[i] = cmd_buffer[i-1];
|
||||
// Insert char in comand buffer
|
||||
cmd_buffer[cursor++] = sbuf[l];
|
||||
cmd_line_len++;
|
||||
// Print rest of line
|
||||
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
||||
write_char(cmd_buffer[i]);
|
||||
// Move backwards
|
||||
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
||||
write_char('\010'); // BS works like cursor-left
|
||||
// Reserve one byte for the terminating NUL written on Enter. When the
|
||||
// line is full, drop the character but still fall through to advance the
|
||||
// serial-ring read pointer below; a 'continue' here would spin forever.
|
||||
if (cmd_line_len < CMD_BUF_SIZE - 1) {
|
||||
write_char(sbuf[l]);
|
||||
// Shift buffer to right
|
||||
for (uint8_t i = cmd_line_len; i > cursor; i--)
|
||||
cmd_buffer[i] = cmd_buffer[i-1];
|
||||
// Insert char in comand buffer
|
||||
cmd_buffer[cursor++] = sbuf[l];
|
||||
cmd_line_len++;
|
||||
// Print rest of line
|
||||
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
||||
write_char(cmd_buffer[i]);
|
||||
// Move backwards
|
||||
for (uint8_t i = cursor; i < cmd_line_len; i++)
|
||||
write_char('\010'); // BS works like cursor-left
|
||||
}
|
||||
} else if (sbuf[l] == '\033') { // ESC-Sequence
|
||||
// Wait until we have at least 3 characters including the ESC character in the serial buffer
|
||||
if (((sbuf_ptr + SBUF_SIZE - l) & SBUF_MASK) < 3)
|
||||
@@ -190,7 +193,7 @@ void cmd_edit(void) __banked
|
||||
// Check whether return was pressed:
|
||||
if (sbuf[l] == '\n' || sbuf[l] == '\r') {
|
||||
write_char('\n');
|
||||
cmd_buffer[cmd_line_len] = '\0';
|
||||
cmd_buffer[cmd_line_len] = NUL;
|
||||
// write_char('>'); print_string_x(cmd_buffer); write_char('<');
|
||||
// If there is a command we print the prompt after execution
|
||||
// otherwise immediately because there is nothing to execute
|
||||
|
||||
@@ -6,13 +6,42 @@
|
||||
#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_PHASES 6
|
||||
#define HEALTH_LLDP 7
|
||||
|
||||
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;
|
||||
void execute_commands(__xdata uint8_t *p) __banked;
|
||||
void print_ip(__xdata uint8_t *ptr) __banked;
|
||||
void print_mac(__xdata uint8_t *ptr) __banked;
|
||||
void print_sw_version(void) __banked;
|
||||
void clear_command_history(void) __banked;
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
;
|
||||
.globl _crc_value
|
||||
.globl _crc16
|
||||
.globl _crc16_bank1
|
||||
.globl __sdcc_banked_ret
|
||||
.equ BANK, 0x96
|
||||
; .equ DPS, 0x86
|
||||
; Variable in XMEM holding current CRC16 value, being updated
|
||||
@@ -18,7 +20,7 @@ _crc_value::
|
||||
.area HOME (CODE)
|
||||
.area CSEG (CODE)
|
||||
; .area BANK1 (CODE)
|
||||
_crc16:
|
||||
_crc16_bank1:
|
||||
mov BANK, #1
|
||||
push dph
|
||||
push dpl
|
||||
@@ -52,6 +54,10 @@ _crc16:
|
||||
|
||||
.area BANK1 (CODE)
|
||||
|
||||
_crc16:
|
||||
lcall _crc16_bank1
|
||||
ljmp __sdcc_banked_ret
|
||||
|
||||
crc16_table_l:
|
||||
.byte #0x00, #0xc1, #0x81, #0x40, #0x01, #0xc0, #0x80, #0x41
|
||||
.byte #0x01, #0xc0, #0x80, #0x41, #0x00, #0xc1, #0x81, #0x40
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
.area HOME (CODE)
|
||||
.area GSINIT0 (CODE)
|
||||
.area GSINIT1 (CODE)
|
||||
.area GSINIT2 (CODE)
|
||||
.area GSINIT3 (CODE)
|
||||
.area GSINIT4 (CODE)
|
||||
.area GSINIT5 (CODE)
|
||||
.area GSINIT (CODE)
|
||||
.area GSFINAL (CODE)
|
||||
.area CSEG (CODE)
|
||||
|
||||
|
||||
.area HOME (CODE)
|
||||
|
||||
__sdcc_banked_call::
|
||||
push _PSBANK
|
||||
xch a,r0
|
||||
push a
|
||||
mov a,r1
|
||||
push a
|
||||
mov a,r2
|
||||
anl a,#0x1f
|
||||
mov _PSBANK, a
|
||||
xch a, r0
|
||||
ret
|
||||
|
||||
__sdcc_banked_ret::
|
||||
pop _PSBANK
|
||||
ret
|
||||
@@ -1,17 +0,0 @@
|
||||
.area GSFINAL (CODE)
|
||||
|
||||
__sdcc_banked_call::
|
||||
push _PSBANK
|
||||
xch a,r0
|
||||
push a
|
||||
mov a,r1
|
||||
push a
|
||||
mov a,r2
|
||||
anl a,#0x1f
|
||||
mov _PSBANK, a
|
||||
xch a, r0
|
||||
ret
|
||||
|
||||
__sdcc_banked_ret::
|
||||
pop _PSBANK
|
||||
ret
|
||||
@@ -41,6 +41,7 @@ __xdata uip_ipaddr_t server;
|
||||
#define DHCP_REBIND_LEN 4
|
||||
#define DHCP_CLIENT_ID 61
|
||||
#define DHCP_CLIENT_ID_LEN 7
|
||||
#define DHCP_HOSTNAME 12
|
||||
#define DHCP_REQUEST_IP 50
|
||||
#define DHCP_REQUEST_IP_LEN 4
|
||||
#define DHCP_PARAMS 55
|
||||
@@ -49,7 +50,7 @@ __xdata uip_ipaddr_t server;
|
||||
#define DHCP_PARAM_DNS 6
|
||||
#define DHCP_END 255
|
||||
|
||||
#pragma codeseg BANK2
|
||||
#pragma codeseg BANK3
|
||||
#pragma constseg BANK2
|
||||
|
||||
struct dhcp_pkt {
|
||||
@@ -93,7 +94,7 @@ void dhcp_prepare_request(void)
|
||||
DHCP_P->hw_len = 6;
|
||||
DHCP_P->hops = 0;
|
||||
|
||||
DHCP_P->tid = HTONS(dhcp_state.transaction_id);
|
||||
DHCP_P->tid = dhcp_state.transaction_id;
|
||||
DHCP_P->delay = HTONS(0);
|
||||
DHCP_P->flags = 0;
|
||||
// Clear fields client_ip to bootp_file
|
||||
@@ -116,6 +117,20 @@ void dhcp_addopt_client_id(void)
|
||||
}
|
||||
|
||||
|
||||
void dhcp_addopt_hostname(void)
|
||||
{
|
||||
uint8_t len = 0;
|
||||
while (hostname[len])
|
||||
len++;
|
||||
if (!len)
|
||||
return;
|
||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_HOSTNAME;
|
||||
DHCP_OPT[dhcp_state.opt_ptr++] = len;
|
||||
memcpy(&DHCP_OPT[dhcp_state.opt_ptr], hostname, len);
|
||||
dhcp_state.opt_ptr += len;
|
||||
}
|
||||
|
||||
|
||||
void dhcp_addopt_request_ip(void)
|
||||
{
|
||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REQUEST_IP;
|
||||
@@ -124,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -136,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;
|
||||
@@ -152,6 +164,7 @@ void dhcp_send_discover(void)
|
||||
|
||||
dhcp_addopt_client_id();
|
||||
dhcp_addopt_request_ip();
|
||||
dhcp_addopt_hostname();
|
||||
|
||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
|
||||
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
|
||||
@@ -177,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;
|
||||
@@ -188,6 +200,7 @@ void dhcp_send_request(void)
|
||||
dhcp_addopt_client_id();
|
||||
dhcp_addopt_request_ip();
|
||||
dhcp_addopt_server_id();
|
||||
dhcp_addopt_hostname();
|
||||
|
||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
|
||||
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
|
||||
@@ -215,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++];
|
||||
@@ -235,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -258,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;
|
||||
@@ -283,7 +300,7 @@ void parse_opts(void)
|
||||
|
||||
void parse_dhcp(void)
|
||||
{
|
||||
if (!DHCP_P->tid == HTONS(dhcp_state.transaction_id))
|
||||
if (DHCP_P->tid != dhcp_state.transaction_id)
|
||||
return;
|
||||
if (DHCP_P->cookie[0] != 0x63 || DHCP_P->cookie[1] != 0x82 || DHCP_P->cookie[2] != 0x53 || DHCP_P->cookie[3] != 0x63)
|
||||
return;
|
||||
@@ -315,6 +332,18 @@ void parse_dhcp(void)
|
||||
uip_ipaddr(&uip_hostaddr, dhcp_state.current_ip[0], dhcp_state.current_ip[1], dhcp_state.current_ip[2], dhcp_state.current_ip[3]);
|
||||
uip_ipaddr(&uip_draddr, dhcp_state.router[0], dhcp_state.router[1], dhcp_state.router[2], dhcp_state.router[3]);
|
||||
uip_ipaddr(&uip_netmask, dhcp_state.subnet[0], dhcp_state.subnet[1], dhcp_state.subnet[2], dhcp_state.subnet[3]);
|
||||
/* T1 is optional. Without it the renewal time stays zero, which
|
||||
* makes dhcp_timer zero, and the callback then sends a REQUEST on
|
||||
* every pass through LEASING: client and server trade REQUEST and
|
||||
* ACK as fast as the round trip allows. RFC 2131 has the client
|
||||
* renew at half the lease when the server does not say, and if
|
||||
* there is no lease either, pick something rather than zero. Only
|
||||
* filled in when absent, so a server that asks for a short renewal
|
||||
* still gets it. */
|
||||
if (!dhcp_state.renewal)
|
||||
dhcp_state.renewal = dhcp_state.lease / 2;
|
||||
if (!dhcp_state.renewal)
|
||||
dhcp_state.renewal = 60;
|
||||
dhcp_state.state = DHCP_LEASING;
|
||||
dhcp_state.ticks = SYS_TICK_HZ;
|
||||
dhcp_state.dhcp_timer = dhcp_state.renewal > 0xffff ? 0xffff : dhcp_state.renewal;
|
||||
@@ -324,6 +353,12 @@ void parse_dhcp(void)
|
||||
|
||||
void dhcp_start(void) __banked
|
||||
{
|
||||
/* Starting twice would leave the first socket bound: uip_udp_new() takes
|
||||
* the next free slot while the old one keeps port 68, and dhcp_callback()
|
||||
* matches on that port rather than on the connection, so every leftover
|
||||
* runs the state machine too and the timers count down once per socket. */
|
||||
if (dhcp_state.state != DHCP_OFF)
|
||||
dhcp_stop();
|
||||
uip_ipaddr(server, 255,255,255,255);
|
||||
dhcp_state.conn = uip_udp_new(&server, HTONS(DHCPC_SERVER_PORT));
|
||||
dhcp_state.current_ip[0] = dhcp_state.current_ip[1] = dhcp_state.current_ip[2] = dhcp_state.current_ip[3] = 0;
|
||||
@@ -334,15 +369,18 @@ void dhcp_start(void) __banked
|
||||
return;
|
||||
}
|
||||
get_random_32();
|
||||
dhcp_state.transaction_id = SFR_DATA_U32;
|
||||
// Workaround SDCC bug 4070: dhcp_state.transaction_id = SFR_DATA_U32;
|
||||
__xdata uint8_t * tid = &dhcp_state.transaction_id;
|
||||
*tid++ = SFR_DATA_24;
|
||||
*tid++ = SFR_DATA_16;
|
||||
*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");
|
||||
}
|
||||
@@ -64,3 +64,33 @@ Writing 0x1 to register 0x7850 will transmit the frame. The Ethernet frame
|
||||
checksum and the TCP checksum are automatically calculated (offloaded) by the
|
||||
ASIC before transmitting on the wire.
|
||||
|
||||
|
||||
## The RTL tag words
|
||||
|
||||
The frame header uses the Realtek Remote Control Protocol (RRCP) format or
|
||||
the like.
|
||||
|
||||
The `flags` word:
|
||||
|
||||
```
|
||||
bit15 EFID_EN | 14:12 EFID | 11 PRI_EN | 10:8 PRI |
|
||||
bit7 KEEP | 6 VSEL | 5 LEARN_DIS | 4:0 VIDX
|
||||
```
|
||||
|
||||
All fields are in network byte order.
|
||||
|
||||
* `EFID_EN`, `EFID`: look the destination up under this filtering ID
|
||||
instead of the port's own
|
||||
* `PRI_EN`, `PRI`: force the given priority on the frame
|
||||
* `KEEP`: keep the 802.1Q tagging of the frame exactly as injected,
|
||||
bypassing the egress tagging rules of the port
|
||||
* `VSEL`, `VIDX`: classify the frame into the VLAN at this index of the
|
||||
VLAN table
|
||||
* `LEARN_DIS`: do not learn the source address from this frame
|
||||
|
||||
The `pmask` word: bit 15 is `ALLOW`, bits 14 to 0 are a port mask.
|
||||
|
||||
* `ALLOW` clear: the mask is the egress set, the frame goes to exactly
|
||||
the ports given
|
||||
* `ALLOW` set: the ASIC looks the destination up as usual and the mask
|
||||
only limits which ports the result may use
|
||||
@@ -0,0 +1,179 @@
|
||||
# Adding a new device
|
||||
|
||||
A device is supported by adding one board definition `.h` and board configuration `.c` file
|
||||
under `machine/`.
|
||||
the build selects the definition by name, and CI compiles every file it finds.
|
||||
|
||||
To compile for your added device, do:
|
||||
```
|
||||
make MACHINE=<NAME>
|
||||
```
|
||||
|
||||
## What a new device consists of
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `machine/<NAME>.c` | the `struct machine machine` board definition |
|
||||
| `machine/<NAME>.h` | `MACHINE_MODEL`, the model string shown in the UI and the CLI |
|
||||
| `doc/devices/<name>.md` + `doc/supported_devices.md` | (only if the board is verified and you want to support it publicly) user-facing documentation |
|
||||
|
||||
`<NAME>` is the machine symbol without its `MACHINE_` prefix, so `MACHINE` is
|
||||
passed exactly as spelled on the command line: `make MACHINE=MY_BOARD_1_0`
|
||||
needs `machine/MY_BOARD_1_0.c` and `machine/MY_BOARD_1_0.h`.
|
||||
|
||||
## Step 1: the model header
|
||||
|
||||
`machine/<NAME>.h` only carries the product string. Use the existing files as
|
||||
the template:
|
||||
|
||||
```c
|
||||
#ifndef _MACHINE_MY_BOARD_1_0_H_
|
||||
#define _MACHINE_MY_BOARD_1_0_H_
|
||||
|
||||
#define MACHINE_MODEL "Brand Model V1.0"
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
The device product string is what the CLI or the Web-Interface will print to identify the device; `machine.h` includes it by name.
|
||||
|
||||
> [!NOTE]
|
||||
> `machine_name` is a `char[30]` and `MACHINE_MODEL` is copied into it at
|
||||
> compile time. A longer model string still builds, but SDCC emits
|
||||
> `warning 147: excess elements in array of chars initializer` and the name is
|
||||
> truncated in the UI. Keep it to 29 characters or less.
|
||||
|
||||
## Step 2: the board definition
|
||||
|
||||
`machine/<NAME>.c` starts with the shared prelude and then defines the single
|
||||
`machine` object. Copy the closest existing board and adjust it — do not start
|
||||
from a blank file, the field meanings are easier to see in a real example.
|
||||
The best choice is usually a device that has the same number and type of Ethernet
|
||||
ports and the same number of SFP+ cages.
|
||||
|
||||
```c
|
||||
#include "machine_defs.h"
|
||||
|
||||
__code const struct machine machine = {
|
||||
.machine_name = MACHINE_MODEL,
|
||||
.isRTL8373 = 1,
|
||||
.min_port = 0,
|
||||
.max_port = 8,
|
||||
.n_sfp = 1,
|
||||
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
|
||||
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
|
||||
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
|
||||
.sfp_port[0].pin_los = GPIO37,
|
||||
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||
.sfp_port[0].sds = 1,
|
||||
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
|
||||
.reset_pin = GPIO_NA,
|
||||
|
||||
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
|
||||
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
||||
.led_sets = {
|
||||
{ /* RJ45 ports */
|
||||
LEDS_2G5 | LEDS_LINK,
|
||||
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
0
|
||||
}, { /* SFP port, single green LED */
|
||||
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | Meaning |
|
||||
|-------|---------|
|
||||
| `machine_name` | always `MACHINE_MODEL` |
|
||||
| `isRTL8373` | `1` for an RTL8373 SoC, `0` for RTL8372 |
|
||||
| `min_port` / `max_port` | range of logical port numbers the device has; `min_port` is `0` for RTL8373 boards and `3` for RTL8372 boards (logical ports 1–2 are the SoC's internal ports on the 8372), `max_port` is usually 8. |
|
||||
| `n_sfp` | number of SFP+ cages |
|
||||
| `n_10g` | SerDes 10G capability used by the RTL837xN init: `0` none, `1` one, `2` two 10G-capable SerDes |
|
||||
| `log_to_phys_port[9]` | logical port (0-based index) → physical front-panel port number |
|
||||
| `phys_to_log_port[9]` | the inverse, physical port 1 is index 0, unused slots are 0 |
|
||||
| `is_sfp[9]` | `0` for copper, `1` for left slot and `2` for right slot |
|
||||
| `sfp_port[2]` | per-cage wiring, `sfp_port[0]` is the leftmost cage |
|
||||
| `reset_pin` | GPIO of the reset button, `GPIO_NA` if unpopulated |
|
||||
| `high_leds` | mux/enable for the LED pins 27–29 (`LED_27`, `LED_28_SYS`, `LED_29`) |
|
||||
| `port_led_set[9]` | which LED set (0–3) each logical port uses |
|
||||
| `led_sets[4][4]` | Each port can have up to 4 GPIO output pins assigned. 4 sets of LEDs with 4 LED-conditions per set; the conditions define which GPIO pins become active for a port given a port link-state. Which LEDs are then enabled depends on the wiring of the pins to up to 3 LEDs for that port, which can make a logical combination of the 4 LED output-pins. |
|
||||
| `led_mux_custom` / `led_mux[28]` | `1` plus the 28 mux values when the stock LED muxing does not fit the board |
|
||||
| `mac_flash_offset` | flash offset of the factory MAC address, omit or `0` if the board does not store one |
|
||||
|
||||
Each `struct sfp_port` entry holds `pin_detect`, `pin_los`, `pin_tx_disable`,
|
||||
`sds` (which SerDes drives the cage) and `i2c` (built with `I2CBUS(sda, scl)`,
|
||||
or `GPIO_NA`-based values where a cage has no such pin).
|
||||
|
||||
`I2CBUS(...)` only accepts the pin pairs listed in `machine_defs.h`. A wrong
|
||||
pair is caught at compile time: SDCC reports
|
||||
`error 176: sizeof applied to an incomplete type` pointing at the offending
|
||||
`.i2c` line, because the macro deliberately turns an invalid bus number into an
|
||||
array of size 0.
|
||||
|
||||
### Reusing an existing definition
|
||||
|
||||
If the new board is electrically identical to one that already exists — same
|
||||
port mapping, same SFP wiring, same LEDs — do not copy the file. Make the new
|
||||
`.c` a symlink and keep only a distinct `.h`, so the two boards cannot drift
|
||||
apart:
|
||||
|
||||
```
|
||||
ln -s KP_9000_6XHML_X2.c machine/MY_BOARD_1_0.c
|
||||
```
|
||||
|
||||
The new board still needs `machine/MY_BOARD_1_0.h` (pick the version number on the PCB) with its own
|
||||
`MACHINE_MODEL`, because `MACHINE_MODEL` is what distinguishes the products.
|
||||
Existing examples: `machine/PCB_K0402WS_V3.c`, `machine/KP_9000_9XHML_X_V3_2.c`
|
||||
and the six `KP_9000_*` revision variants.
|
||||
|
||||
Two files that differ only in whitespace or comments are duplicates and should
|
||||
be collapsed this way.
|
||||
|
||||
## Step 3: build and verify
|
||||
|
||||
```
|
||||
make MACHINE=MY_BOARD_1_0
|
||||
```
|
||||
|
||||
The generated flash image appears as `output/rtlplayground-<version>-MY_BOARD_1_0.bin`. An
|
||||
unknown or empty `MACHINE` fails immediately with a message naming the expected
|
||||
file, before anything is compiled.
|
||||
|
||||
Then run the checks CI runs:
|
||||
|
||||
```
|
||||
make machine_check # compiles machine/<NAME>.c and machine_init.c for every machine
|
||||
make -C test # host-side unit tests
|
||||
```
|
||||
|
||||
`make machine_check` discovers the definitions with
|
||||
`$(wildcard machine/*.c)`, so a new file is covered without registering it
|
||||
anywhere. CI (`.github/workflows/build.yml`) runs it on every push and pull
|
||||
request, alongside full builds for a 4+2 and an 8+1 board.
|
||||
|
||||
A successful compile only proves the definition is syntactically valid. The
|
||||
actual behaviour — port numbering, SFP detection, LEDs — has to be confirmed on
|
||||
hardware, and the console commands (`port`, `stat`, `sfp`, `leds`) are the
|
||||
tools for that.
|
||||
|
||||
## Step 4: documentation
|
||||
|
||||
Once the board has been tested on hardware:
|
||||
|
||||
1. Add a row to the table in [Supported devices](supported_devices.md).
|
||||
2. Add `doc/devices/<name>.md` describing the board, the build target
|
||||
(`make MACHINE=MY_BOARD_1_0`), what works and what is unverified, plus
|
||||
photos and the PCB silkscreen marking.
|
||||
3. If the board shares a PCB with other revisions, follow
|
||||
`doc/devices/KP-9000-6XH-X2.md` and document which `MACHINE` to pick for
|
||||
which silkscreen.
|
||||
|
||||
@@ -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.
|
||||
@@ -0,0 +1,55 @@
|
||||
# 2G040210GSM
|
||||
|
||||
The following is a documentation for the managed switch marked as `2G040210GSM`
|
||||
and sold by Mokerlink.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**: 4-port 2.5G Web Managed Switch
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||
- **Power**: 12V DC, 1A barrel connector
|
||||
|
||||
### What works
|
||||
The device is fully supported:
|
||||
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||
- The SFP+ port supports 1G, 2.5G and 10G modules
|
||||
- LEDs work with the same indiciations as the OEM firmware (build with `make MACHINE=KP_9000_6XHML_X2_V1_1` if building yourself, or use the corresponding pre-compiled binary)
|
||||
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
|
||||
|
||||
### Hardware overview
|
||||
Front
|
||||
|
||||
<img src="photos/2M-PCB43-V1.1-managed/2M-PCB43-V1.1-front.jpeg" width="300" />
|
||||
|
||||
Label
|
||||
|
||||
<img src="photos/2M-PCB43-V1.1-managed/2M-PCB43-V1.1-label.jpeg" width="300" />
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: 2M-PCB43-V1.1
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/2M-PCB43-V1.1-managed/2M-PCB43-V1.1-top.jpeg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/2M-PCB43-V1.1-managed/2M-PCB43-V1.1-bottom.jpeg" width="300" />
|
||||
|
||||
### J1, serial console
|
||||
|
||||
| `J8` pin | Signal |
|
||||
| -------- | ----------- |
|
||||
| 1 | RX (Input) |
|
||||
| 2 | TX (Output) |
|
||||
| 3 | GND |
|
||||
| 4 | 3V3 |
|
||||
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
@@ -0,0 +1,32 @@
|
||||
# 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.
|
||||
|
||||
## Brands
|
||||
| Brand | Type |Managed| PCB | Flash | Chip RTL |
|
||||
|--------|------------------|-------|------------------|-----------------|---------------|
|
||||
| Mokerlink | POE-2G080110GS | No | 2M-PCB51-ML-V1.1 | 4MB (W25Q32JV) | 8373N + 8224N |
|
||||
|
||||
## Hardware overview
|
||||
Front
|
||||
|
||||
<img src="photos/POE-2G080110GS/POE-2G080110GS-front.jpg" width="300" />
|
||||
|
||||
Label
|
||||
|
||||
<img src="photos/POE-2G080110GS/POE-2G080110GS-label.jpg" width="300" />
|
||||
|
||||
The stock firmware from a POE-2G080110GS device had a sha256sum of `4c280853465eaad80e1772075c0f2d29c11fb8c561547f06353d3a5443c388e9`.
|
||||
|
||||
### PCB
|
||||
|
||||
Top silkscreen is marked `2M-PCB51-ML-V1.1`. PoE is provided by RTL8238C. Flash chip is 4 MB Winbond 25Q32JV (U8).
|
||||
|
||||
<img src="photos/POE-2G080110GS/POE-2G080110GS-pcb.jpg" width="300" />
|
||||
|
||||
> [!CAUTION]
|
||||
> This device operates on mains voltage, which can be a dangerous or potentially lethal hazard. Even after the device is unplugged, high-voltage capacitors can remain charged afterward and may still shock you. Do not attempt to open/disassemble a mains powered device unless you understand how to do so safely. Also, opening the device may void your warranty.
|
||||
|
||||
## Notes
|
||||
|
||||
The stock firmware blinks both the 2.5G and 1G LEDs on activity, despite the front of the device indicating that each LED should be independent. The `POE_2G080110GS` machine config behaves as the front of the device indicates (and what seems more logical) -- each port LED turns on and blinks independently.
|
||||
@@ -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,39 @@
|
||||
# FG-4GT-2SX_V2.0
|
||||
|
||||
Following is documentation for unmanaged switch marked as `FG-4GT-2SX_V2.0`.
|
||||
|
||||
Original software is running UART on 9600 baud rate.
|
||||
|
||||
## Brands
|
||||
|
||||
* Ruiying RY-4GT-2SX
|
||||
|
||||
<img src="photos/FG-4GT-2SX_V2.0/RY-4GT-2SX_label.jpg" width="300" />
|
||||
|
||||
## 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
|
||||
|
||||
## PCB overview
|
||||
|
||||
**Board markings**
|
||||
|
||||
- Top silkscreen: FG-4GT-2SX_V2.0
|
||||
|
||||
Front panel
|
||||
|
||||
<img src="photos/FG-4GT-2SX_V2.0/chassis-front.jpg" width="300" />
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/FG-4GT-2SX_V2.0/PCB-top.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/FG-4GT-2SX_V2.0/PCB-bottom.jpg" width="300" />
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
@@ -0,0 +1,79 @@
|
||||
# FG-8GT-1SX
|
||||
|
||||
Following is documentation for unmanaged switch marked as `FG-8GT-1SX`.
|
||||
|
||||
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 |
|
||||
|---------|------------|---------|------------|-------------|---------------|
|
||||
| Ruiying | RY-8GT-1SX | No | FG-8GT-1SX | GD25Q80ESIG | 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: FG-8GT-1SX
|
||||
|
||||
Top side:
|
||||
|
||||
<img src="photos/FG-8GT-1SX/PCB-top.jpg" width="600" />
|
||||
|
||||
Bottom:
|
||||
|
||||
<img src="photos/FG-8GT-1SX/PCB-bottom.jpg" width="600" />
|
||||
|
||||
### Serial console
|
||||
|
||||
The PCB has five unpopulated through-holes near the SoC, with a white rectangle surrouding them, labeled as `J18` and a triangle points to the square shaped first pin.
|
||||
|
||||
This is where the "expected" UART header should be soldered at, with redundant 3V3 VCC, but also with missing 0Ω resistors between TX/RX and SoC, so simply soldering a header would not work. One need also add the missing resistors or solder the pads together, while making sure not connecting unrelated pads.
|
||||
|
||||
Numbered from the triangle, the header pinout is:
|
||||
|
||||
| Position | Signal | GPIO | Status |
|
||||
|----------|--------|--------|-------------|
|
||||
| 1 | GND | GND | Internal |
|
||||
| 2 | TX | GPIO31 | Unconnected |
|
||||
| 3 | RX | GPIO32 | Unconnected |
|
||||
| 4 | 3V3 | - | Internal |
|
||||
| 5 | 3V3 | - | Internal |
|
||||
|
||||
There're four resistor pads near the header.
|
||||
|
||||
| Resistor ID | SoC Side | Header Side |
|
||||
|-------------|-------------|-------------|
|
||||
| R1240 | TX / GPIO31 | Pin 2 |
|
||||
| R1243 | 3V3 | - |
|
||||
| R1242 | 3V3 | Pin 3 |
|
||||
| R1241 | RX / GPIO32 | - |
|
||||
|
||||
To get TX working, solder a 0Ω resistor between the pads for R1240 or solder them together.
|
||||
|
||||
For RX However, the designer certainly made a mistake, as the SoC-side lines to the resistor expected for Rx (R1242) and 3V3 (R1241) are swapped. For RX to work, the R1241 SoC side and R1242 header side shall be connected, so either:
|
||||
|
||||
- Solder: R1241 SoC side -> R1241 header side -> R1242 header side
|
||||
- Jump wire: R1241 SoC side -> R1242 header side
|
||||
|
||||
Be sure not to bring R1242 SoC side to the connection as that would wire Rx to 3v3.
|
||||
|
||||
A complete working serial header should look like following on this PCB:
|
||||
|
||||
<img src="photos/FG-8GT-1SX/Serial.png" width="600" />
|
||||
|
||||
- **Settings**: 115200 baud / 8N1 / 3.3V TTL
|
||||
- Connect a USB-TTL adapter: adapter GND → pin 1, RX → pin 2, TX → pin 3
|
||||
|
||||
### Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
|
||||
@@ -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.
|
||||
@@ -1,17 +1,36 @@
|
||||
# Keeplink KP-9000-6XH-X2
|
||||
# Keeplink KP-9000-6XH-X2 / KP-9000-6XHML-X2
|
||||
|
||||
Following is documentation for unmanaged switch marked as `KP-9000-6XH-X2`.
|
||||
Following is documentation for switches marked as `KP-9000-6XH-X2` or
|
||||
`KP-9000-6XHML-X2`.
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**: 4X 2.5G RJ45 Port + 2 X 10G SFP+ Port
|
||||
- **Model**: KP-9000-6XH-X2
|
||||
- **Model**: KP-9000-6XH-X2 / KP-9000-6XHML-X2
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||
|
||||
### Machine target
|
||||
|
||||
These devices exist with different PCB revisions. Select the machine target by
|
||||
the PCB silkscreen, not by the label on the case. The `6XH` / `6XHML`
|
||||
distinction appears to be a stock firmware, SKU or label difference, not a
|
||||
reliable indicator of PCB wiring. The PCB revision defines the hardware layout.
|
||||
|
||||
| PCB silkscreen | Known labels / devices | Recommended machine target | Equivalent target | Legacy target |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `2M-PCB43-V1.1` | Mokerlink 2G040210GSM web-managed 4+2 switch | `MACHINE_KP_9000_6XHML_X2_V1_1` | `MACHINE_KP_9000_6XH_X2_V1_1` | `MACHINE_KP_9000_6XHML_X2` |
|
||||
| `2M-PCB43-V1.2` | `KP-9000-6XHML-X2` | `MACHINE_KP_9000_6XHML_X2_V1_2` | `MACHINE_KP_9000_6XH_X2_V1_2` | `MACHINE_KP_9000_6XHML_X2` |
|
||||
| `2M-PCB43-V2.1` | `KP-9000-6XH-X2`, `KP-9000-6XHML-X2` | `MACHINE_KP_9000_6XH_X2_V2_1` or `MACHINE_KP_9000_6XHML_X2_V2_1` | same V2.1 layout | `MACHINE_KP_9000_6XH_X2` |
|
||||
|
||||
The V1.1 and V1.2 boards currently use the same V1.x GPIO, SFP, port and LED
|
||||
layout. The V2.1 board uses a different V2.1 layout with custom LED muxing.
|
||||
Legacy targets are preserved for compatibility with already-tested devices, but
|
||||
new builds should prefer the explicit PCB-revision targets.
|
||||
|
||||
### What works
|
||||
|
||||
- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
@@ -19,7 +38,7 @@ Using SPI clamp in-board is the only method for initial installation.
|
||||
- LEDs
|
||||
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
|
||||
|
||||
### Hardware overview
|
||||
### Hardware overview: 2M-PCB43-V2.1
|
||||
|
||||
Front side:
|
||||
|
||||
@@ -44,6 +63,24 @@ Bottom
|
||||
|
||||
<img src="photos/2M-PCB43-V2.1-unmanaged/2M-PCB43-V2.1-bottom.jpg" width="600" />
|
||||
|
||||
### Hardware overview: 2M-PCB43-V1.1 / V1.2
|
||||
|
||||
The V1.1 board has been reported in the Mokerlink 2G040210GSM web-managed 4+2
|
||||
switch. The V1.2 board has been seen in managed `KP-9000-6XHML-X2` devices.
|
||||
Both use the same V1.x layout.
|
||||
|
||||
Label:
|
||||
|
||||
<img src="photos/KP-9000-6XHML-X2/label.jpg" width="600" />
|
||||
|
||||
Top side:
|
||||
|
||||
<img src="photos/KP-9000-6XHML-X2/pcb_top.jpg" width="600" />
|
||||
|
||||
Bottom:
|
||||
|
||||
<img src="photos/KP-9000-6XHML-X2/pcb_bottom.jpg" width="600" />
|
||||
|
||||
## Reset Button
|
||||
|
||||
There's an unpopulated Reset button on the front left side of the PCB.
|
||||
@@ -54,4 +91,3 @@ The front case has already the hole in the metal case, you just have to punch a
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
# 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.
|
||||
|
||||
## 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,97 @@
|
||||
Hisource Hi-K0402WS V2
|
||||
|
||||
RTL8372-based 4×2.5G + 2×SFP+ unmanaged switch.
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Manufacturer**: HISOURCE
|
||||
- **Model**: Hi-K0402WS V2
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1G / 2.5G / 10G
|
||||
|
||||
### 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: amber (2.5G) and green (1G/100M/10M) per copper port; combined link/act on SFP ports
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- PCB-K0402WS-V2.0
|
||||
- DIP-K0402WS-V2.0
|
||||
|
||||
**Key components**
|
||||
- U1: SPI NOR flash, 2 MiB
|
||||
- S1: unpopulated slide switch footprint (three through-holes used as serial console)
|
||||
|
||||
Front panel
|
||||
|
||||
<img src="photos/PCB-K0402WS-V2.0/chassis-front.jpg" width="400" />
|
||||
|
||||
Bottom label
|
||||
|
||||
<img src="photos/PCB-K0402WS-V2.0/chassis-bottom.jpg" width="400" />
|
||||
|
||||
Top side (PCB)
|
||||
|
||||
<img src="photos/PCB-K0402WS-V2.0/PCB-top.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+ |
|
||||
|
||||
### Serial console
|
||||
|
||||
The PCB has three unpopulated through-holes intended for a slide switch, directly connected to UART0.
|
||||
Numbered from the left (SFP port side), the pinout is:
|
||||
|
||||
| Position (left→right) | Signal | GPIO |
|
||||
|-----------------------|--------|--------------------------|
|
||||
| 1 (leftmost) | RX | GPIO32\_UART0\_RX (32) |
|
||||
| 2 (middle) | GND | GND |
|
||||
| 3 (rightmost) | TX | GPIO31\_UART0\_TX (31) |
|
||||
|
||||
- **Settings**: 115200 baud / 8N1 / 3.3V TTL
|
||||
- Connect a USB-TTL adapter: adapter TX → pin 1, GND → pin 2, adapter RX → pin 3
|
||||
|
||||
### LED configuration
|
||||
|
||||
Copper ports use LED SET0, SFP ports use LED SET1.
|
||||
|
||||
| SET | LED0 | LED2 |
|
||||
|------|--------------------------------------------------|---------------------------------------------------|
|
||||
| SET0 | Amber — lights on 2.5G link | Green — lights on 1G / 100M / 10M link |
|
||||
| SET1 | All speeds — lights on any link with activity | — |
|
||||
|
||||
LED pad to physical port mapping:
|
||||
|
||||
| GPIO pads | Port |
|
||||
|-----------|-------------------------|
|
||||
| GPIO8–11 | Physical port 5 (left SFP) |
|
||||
| GPIO12–14 | Physical port 1 (RJ45 1) |
|
||||
| GPIO15–17 | Physical port 2 (RJ45 2) |
|
||||
| GPIO18–20 | Physical port 3 (RJ45 3) |
|
||||
| GPIO21–23 | Physical port 4 (RJ45 4) |
|
||||
| GPIO24–27 | Physical port 6 (right SFP) |
|
||||
|
||||
### SFP GPIO assignments
|
||||
|
||||
| SFP | pin\_detect (ModAbs) | pin\_los | SerDes | I2C SDA | I2C SCL |
|
||||
|------------------|-----------------------------|------------------------|--------|----------------------|--------------------------|
|
||||
| Left (logical 8) | GPIO30\_ACL\_BIT3\_EN | GPIO37 | SDS1 | GPIO39\_I2C\_SDA4 | GPIO40\_I2C\_SCL3\_MDC1 |
|
||||
| Right (logical 3)| GPIO50\_I2C\_SCL2\_UART1\_TX | GPIO51\_I2C\_SDA2\_UART1\_RX | SDS0 | GPIO41\_I2C\_SDA3\_MDIO1 | GPIO40\_I2C\_SCL3\_MDC1 |
|
||||
|
||||
GPIO assignments were verified by observing GPIO state changes during SFP module insertion/removal
|
||||
and cross-checked against an original firmware register dump.
|
||||
`pin_tx_disable` is GPIO\_NA on both ports (original firmware keeps all GPIOs as inputs).
|
||||
@@ -19,6 +19,9 @@ of the device just above the big label, might be covered by a QC sticker.
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/Ztyuav_Z-QWYT0402_label.jpg" width="300" />
|
||||
|
||||
* Siscolink SL-G0402F
|
||||
|
||||
<img src="photos/PCB-K0402WS-V3.0/Siscolink SL-G0402F.jpg" width="300"/>
|
||||
### Programming
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
# Steamemo IG204-V1
|
||||
|
||||
Following is documentation for unmanaged switch marked as `IG204-V1`.
|
||||
|
||||
Using SPI clamp in-board is the only method for initial installation.
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**: 2.5G Ethernet Switch
|
||||
- **Model**: IG204 V1
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP: 1000 / 2500 / 10000 Mbps
|
||||
|
||||
### What works (expected from label + similar devices)
|
||||
|
||||
- Four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps
|
||||
- Two SFP ports supporting 1G, 2.5G and 10G modules
|
||||
- LEDs
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PB-2131
|
||||
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/STEAMEMO_IG204_V1/PCB-top.jpg" width="600" />
|
||||
|
||||
### Connectors
|
||||
### T7, serial console
|
||||
|
||||
| `T7` pin | Signal |
|
||||
| -------- | ----------- |
|
||||
| 1 | TX (Output) |
|
||||
| 2 | GND |
|
||||
| 3 | RX (Input) |
|
||||
| 4 | 3V3 |
|
||||
|
||||
### Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
@@ -1,4 +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 |
|
||||
| GoodTop | GT-ST018M | Yes | SWTG018AS-A V2.0 | ? | 8273N + 8224N |
|
||||
|
||||
|
||||
The following is a documentation for the unmanaged switch marked as `SWTG018AS-A V2.0`.
|
||||
It is e.g. sold under the Ampcom brand, but no branh-markings are found on the device.
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
### SWTG024AS-A-V2.0.1_4C_2SFP
|
||||
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 | ??? |
|
||||
| GoodTop | GT-ST024M | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M | ??? |
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**:
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||
|
||||
<img src="photos/SWTG024AS-A-V2_0_1_19650/horaco-zx-sg4t2-label.jpg" width="300" />
|
||||
|
||||
### What works
|
||||
The device is fully supported:
|
||||
- ALL 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||
- The SFP+ port supports 1G, 2.5G and 10G modules
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-SWTG024AS-A-V2.0.1_19650
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/SWTG024AS-A-V2_0_1_19650/horaco-zx-sg4t2-pcb-top.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/SWTG024AS-A-V2_0_1_19650/horaco-zx-sg4t2-pcb-bottom.jpg" width="300" />
|
||||
|
||||
### J1, serial console
|
||||
|
||||
| `J1` pin | Signal |
|
||||
| -------- | ----------- |
|
||||
| 1 | 3V3 |
|
||||
| 2 | GND |
|
||||
| 3 | RX (Input) |
|
||||
| 4 | TX (Output) |
|
||||
@@ -0,0 +1,44 @@
|
||||
### SWTG024AS-A-V2.0.1_5C_1SFP
|
||||
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 | HC-SWTGW215AS | | PCB-SWTG024AS-A-V2.0.1_19650 | W25Q16JV | 8272N |
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**:
|
||||
- **Ports**:
|
||||
- 5 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 1 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||
|
||||
<!-- <img src="" width="300" /> -->
|
||||
|
||||
### What works
|
||||
The device is fully supported:
|
||||
- ALL 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||
- The SFP+ port supports 1G, 2.5G and 10G modules
|
||||
- LEDs work with the same indiciations as the OEM firmware
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-SWTG024AS-A-V2.0.1_19650
|
||||
|
||||
Top side
|
||||
|
||||
<!-- <img src="" width="300" /> -->
|
||||
|
||||
Bottom
|
||||
|
||||
<!-- <img src="" width="300" /> -->
|
||||
|
||||
### J1, serial console
|
||||
|
||||
| `J1` pin | Signal |
|
||||
| -------- | ----------- |
|
||||
| 1 | 3V3 |
|
||||
| 2 | GND |
|
||||
| 3 | RX (Input) |
|
||||
| 4 | TX (Output) |
|
||||
@@ -0,0 +1,49 @@
|
||||
### SWTG024AS-V2.0
|
||||
|
||||
## Brands
|
||||
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|
|
||||
| hongyavision | LG-SG5T1 | No | PCB-SWTG024AS-V2.0_16895 | 25Q40 | 8272 |
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**:
|
||||
- **Ports**:
|
||||
- 5 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 1 × SFP+: 1000 / 2500 / 10000 Mbps
|
||||
- **Power**: 12V DC, 1A 5525 connector
|
||||
|
||||
<img src="photos/SWTG024AS-V2.0/label.jpg" width="300" />
|
||||
|
||||
### What works
|
||||
The device is fully supported:
|
||||
- ALL 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
|
||||
- Online update does not work with 512KiB flash.
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-SWTG024AS-V2.0
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/SWTG024AS-V2.0/pcb_top.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/SWTG024AS-V2.0/pcb_bottom.jpg" width="300" />
|
||||
|
||||
### J1, serial console
|
||||
|
||||
| `J1` pin | Signal |
|
||||
| -------- | ----------- |
|
||||
| 1 | GND |
|
||||
| 2 | RX (Input) |
|
||||
| 3 | TX (Output) |
|
||||
|
||||
Note,`R52`、`R53`may not be installed.You need to bridge them using either solder or resistors.
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 1A` adapter was provided.
|
||||
@@ -9,8 +9,8 @@ Also the RJ45 connectors can be all plastic/non-shielded or with metal shielding
|
||||
|Brand|Type|Managed|PCB|PCB Label|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|---|
|
||||
| LIANGUO |SWTG024AS |No| SWTG024AS-v2.0-17452 | CM-23-11-2336 023-17453| 512 KiB | 8272 |
|
||||
| Haraco |ZX-SWTG124AS | Yes | SWTG024AS-v2.0 | ??? | ??? | 8272 |
|
||||
| Xikestore |SKS3200M-4GPY2XF | Yes | SWTG024AS-v1.0 | CM-23-08-2043 023-16721 | ??? | 8272 |
|
||||
| Horaco |ZX-SWTG124AS | Yes | SWTG024AS-v2.0 | ??? | ??? | 8272 |
|
||||
| Xikestore |SKS3200M-4GPY2XF | Yes | SWTG024AS-v1.0 | CM-23-08-2043 023-16721 | 2048 KiB | 8272 |
|
||||
| Sodola | SL-SWTG124AS-D | Yes | SWTG024AS-v2.0-17452 | ??? | 2048 KiB | 8272 |
|
||||
|
||||
## PCB
|
||||
|
||||
@@ -1,24 +1,36 @@
|
||||
### ZX-SWTGW215AS
|
||||
# ZX-SWTGW215AS
|
||||
|
||||
## Brands
|
||||
|
||||
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||
|---|---|---|---|---|---|
|
||||
| Lianguo | ZX-SWTGW215AS | Yes | PCB-SWTG115AS-V2.0 | FM25Q16A | 8272 |
|
||||
| Lianguo | ZX-SWTGW215AS | Yes | PCB-SWTG115AS-V2.0 | FM25Q16A | 8372 |
|
||||
| sold as Lianguo, actual device unbranded | ZX-SWTGW215AS | Yes | PCB-SWTG115AS-V2.1 | W25Q16JVSIQ (2MiB) | 8372 |
|
||||
|
||||
## 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.
|
||||
|
||||
## PCB
|
||||
## Label (V2.0)
|
||||
|
||||
<img src="photos/ZX-SWTGW215AS/pcb_top.jpg" width="300" />
|
||||
<img src="photos/ZX-SWTGW215AS-V2.0/label.jpg" width="300" />
|
||||
|
||||
# Connectors
|
||||
## PCB (V2.0)
|
||||
|
||||
## Port overview
|
||||
<img src="photos/ZX-SWTGW215AS-V2.0/pcb_top.jpg" width="300" />
|
||||
<img src="photos/ZX-SWTGW215AS-V2.0/pcb_bottom.jpg" width="300" />
|
||||
|
||||
## PCB (V2.1)
|
||||
|
||||
<img src="photos/ZX-SWTGW215AS-V2.1/pcb-top.jpg" width="300" />
|
||||
<img src="photos/ZX-SWTGW215AS-V2.1/pcb-bottom.jpg" width="300" />
|
||||
|
||||
## Connectors
|
||||
|
||||
### Port overview
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────────────────────┐
|
||||
@@ -36,7 +48,7 @@ Port 5 RJ45 is interfaced through a RTL8221B IC.
|
||||
| RJ45 | 3, 4, 5, 6, 7 | 1-5 |
|
||||
| SFP | 8 | 6 |
|
||||
|
||||
## J4
|
||||
### J4
|
||||
|
||||
* Location: SFP connector `J4`.
|
||||
* Connected to: 10GMAC number 8, SerDes 1.
|
||||
@@ -48,10 +60,11 @@ Port 5 RJ45 is interfaced through a RTL8221B IC.
|
||||
|5| MODDEF1 – SCL | GPIO40 | I2C SCL |
|
||||
|6| MODDEF0 – PRESENT | GPIO30 | Detect |
|
||||
|8| LOS | GPIO37 | RX Loss of Signal |
|
||||
### Notes
|
||||
|
||||
#### Notes
|
||||
* Not all signals were mapped mechanically, hence they've been left out of documentation.
|
||||
|
||||
## T3, Slave Interface
|
||||
### T3, Slave Interface
|
||||
|
||||
This connector goes to U4 `I2C EEPROM` and U10 `SPI FLASH` (mappings identical to SWTG024AS).
|
||||
|
||||
@@ -65,11 +78,12 @@ For detailed Slave Interface functionality and protocol information, see [T3 doc
|
||||
|4| VCC |
|
||||
|5| 33R -> U10-P2 | SPI-DO/D1 |
|
||||
|6| U10-P1 | SPI-CS |
|
||||
### Notes
|
||||
|
||||
#### Notes
|
||||
* 1 pin is square shaped.
|
||||
|
||||
|
||||
## T5, Serial Console
|
||||
### T5, Serial Console
|
||||
|
||||
|`T5` pin|GPIO|Signal|
|
||||
|---|---|---|
|
||||
@@ -77,10 +91,11 @@ For detailed Slave Interface functionality and protocol information, see [T3 doc
|
||||
| 2 | GND | |
|
||||
| 3 | GPIO32 | U0RXD (Input) |
|
||||
| 4 | 3V3 | |
|
||||
### Notes
|
||||
|
||||
#### Notes
|
||||
* 1 pin is square shaped.
|
||||
|
||||
## T8
|
||||
### T8
|
||||
|
||||
|`T8` pin|GPIO|Signal|
|
||||
|---|---|---|
|
||||
@@ -91,18 +106,19 @@ For detailed Slave Interface functionality and protocol information, see [T3 doc
|
||||
| 5 | GPIO47 | |
|
||||
| 6 | GPIO49 | |
|
||||
|
||||
### Notes
|
||||
#### Notes
|
||||
* 1 pin is square shaped.
|
||||
* Mapping unverified but assumed the same as [LIANGUO SWTG024AS](SWTG024AS.md#t8).
|
||||
|
||||
# Reset Circuit
|
||||
## Reset Circuit
|
||||
| Function | GPIO |
|
||||
|---|---|
|
||||
| Reset button | GPIO54 |
|
||||
|
||||
### Notes
|
||||
* Circuit is active-low
|
||||
|
||||
# GPIO
|
||||
## GPIO
|
||||
|
||||
Note: T3/U4/U10-related signal annotations below are copied from [LIANGUO SWTG024AS T3 section](SWTG024AS.md#t3-slave-interface) as well as T8 port from [LIANGUO SWTG024AS T8 section](SWTG024AS.md#t8). They should be treated as assumed identical for ZX-SWTGW215AS as it has not been 100% confirmed true at the moment.
|
||||
|
||||
@@ -141,7 +157,7 @@ Note: T3/U4/U10-related signal annotations below are copied from [LIANGUO SWTG02
|
||||
| 40000000 | GPIO30 | J4-6 | SFP DETECT | | GPIO62 | | |
|
||||
| 80000000 | GPIO31 | T5-1 | U0TXD | | GPIO63 | | |
|
||||
|
||||
# LEDs
|
||||
## LEDs
|
||||
|
||||
| NAME | GPIO | Port(s) | Function | Notes |
|
||||
| ---- | ---- | ---- | ---- | ---- |
|
||||
@@ -162,3 +178,6 @@ Note: T3/U4/U10-related signal annotations below are copied from [LIANGUO SWTG02
|
||||
|
||||
While [SWTG024AS.md](SWTG024AS.md) can be used as a general reference for hardware concepts and interface specifications, this device should not be assumed to be identical beside the difference implicitely highlighted below. Not all information has been validated for compatibility with the SWTG215AS. Consult the SWTG024AS documentation with caution and verify any critical details against this device's.
|
||||
|
||||
## Flashing
|
||||
|
||||
For devices with Winbond 25Q16JVSIQ, flashing is possible for example using flashprog with device "W25Q16.V". Note that you should not overwrite the whole flash to keep device-specific data (like the MAC address at 0x1fc000). Also, creating a backup of the entire falsh before is of course a very good idea.
|
||||
@@ -6,6 +6,7 @@
|
||||
| Mokerlink | ZX-SWTGW218AS | Yes| SWTG118AS-V2.0-16029 | 2MB (FM25Q16A)| 8273N + 8224N |
|
||||
| Sodola | | | | | |
|
||||
| Horaco | | | | | |
|
||||
| XikeStor | SKS3200-8E1X | Yes | SWTG118AS-V2.1-17462 | 2MB (25Q16JVSIQ) | |
|
||||
|
||||
|
||||
## Photos
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# ZX310S-4T2XT
|
||||
|
||||
The following is a documentation for the managed switch marked as
|
||||
`ZX310S-4T2XT` and sold by Horaco.
|
||||
|
||||
The original software is running UART on 57600 baud rate 8N1.
|
||||
|
||||
CPU: RTL8372
|
||||
Flash: 2MByte Winbond W25Q16DV (U3)
|
||||
PHY 2x RTL8261BE
|
||||
|
||||
### Label specifications
|
||||
|
||||
- **Name**:
|
||||
- **Ports**:
|
||||
- 4 × RJ45: 10/100/1000/2500 Mbps
|
||||
- 2 x RJ45: 10/100/1000/2500/5000/10000 Mbps
|
||||
- **Power**: 12V DC, 2A barrel connector
|
||||
|
||||
<img src="photos/ZX310S-4T2XT/label.jpg" width="300" />
|
||||
|
||||
### What works
|
||||
The device is fully supported:
|
||||
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps, including EEE
|
||||
- The 10GBit ports works, including EEE.
|
||||
- LEDs work with the same indiciations as the OEM firmware
|
||||
|
||||
### PCB overview
|
||||
|
||||
**Board markings**
|
||||
- Top silkscreen: PCB-SL310S-4T2XT-V1.0.0-22273
|
||||
|
||||
Top side
|
||||
|
||||
<img src="photos/ZX310S-4T2XT/pcb_top.jpg" width="300" />
|
||||
|
||||
Bottom
|
||||
|
||||
<img src="photos/ZX310S-4T2XT/pcb_bottom.jpg" width="300" />
|
||||
|
||||
### J1, serial console
|
||||
|
||||
| `J1` pin | Signal |
|
||||
| -------- | ----------- |
|
||||
| 1 | TX (Output) |
|
||||
| 2 | RX (Input) |
|
||||
| 3 | GND |
|
||||
| 4 | 3V3 |
|
||||
|
||||
|
||||
## Power supply
|
||||
|
||||
Input power is delivered via barell plug, `12V 2A` adapter was provided.
|
||||
|
After Width: | Height: | Size: 480 KiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 715 KiB |
|
After Width: | Height: | Size: 615 KiB |
|
After Width: | Height: | Size: 2.1 MiB |
|
After Width: | Height: | Size: 519 KiB |
|
After Width: | Height: | Size: 529 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 207 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 203 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
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: 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: 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: 170 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 3.5 MiB |
|
After Width: | Height: | Size: 242 KiB |
|
After Width: | Height: | Size: 157 KiB |
|
After Width: | Height: | Size: 934 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 455 KiB |
|
After Width: | Height: | Size: 710 KiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 3.2 MiB |
|
After Width: | Height: | Size: 9.7 MiB |
|
After Width: | Height: | Size: 36 MiB |
|
After Width: | Height: | Size: 476 KiB |
|
After Width: | Height: | Size: 657 KiB |
|
After Width: | Height: | Size: 2.2 MiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 2.7 MiB |
@@ -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,79 @@
|
||||
# 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
|
||||
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 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.
|
||||
@@ -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 |