Merge pull request #39 from logicog/sfp_work

Put all the device information in one struct `machine`.
So all the device information is defined in one place.
Also easier to add new devices.
Show device name also on website.
Fix SFP status information, some devices have a different SFP layout.
Reworks GPIO handling
Able to set manual port speed, duplex for the RJ45 ports.
This commit is contained in:
René van Dorst
2025-12-14 11:53:23 +00:00
committed by GitHub
17 changed files with 732 additions and 475 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)rtlplayground.bin
create_build_dir: create_build_dir:
mkdir -p $(BUILDDIR) mkdir -p $(BUILDDIR)
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c machine.c
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel} OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
OBJS += uip/$(BUILDDIR)/timer.rel uip/$(BUILDDIR)/uip-fw.rel uip/$(BUILDDIR)/uip-neighbor.rel uip/$(BUILDDIR)/uip-split.rel uip/$(BUILDDIR)/uip.rel uip/$(BUILDDIR)/uip_arp.rel uip/$(BUILDDIR)/uiplib.rel httpd/$(BUILDDIR)/httpd.rel httpd/$(BUILDDIR)/page_impl.rel OBJS += uip/$(BUILDDIR)/timer.rel uip/$(BUILDDIR)/uip-fw.rel uip/$(BUILDDIR)/uip-neighbor.rel uip/$(BUILDDIR)/uip-split.rel uip/$(BUILDDIR)/uip.rel uip/$(BUILDDIR)/uip_arp.rel uip/$(BUILDDIR)/uiplib.rel httpd/$(BUILDDIR)/httpd.rel httpd/$(BUILDDIR)/page_impl.rel
+69 -58
View File
@@ -15,13 +15,12 @@
#include "uip/uip.h" #include "uip/uip.h"
#include "version.h" #include "version.h"
#include "machine.h"
#pragma codeseg BANK1 #pragma codeseg BANK1
#pragma constseg BANK1 #pragma constseg BANK1
extern __xdata uint8_t minPort; extern __code struct machine machine;
extern __xdata uint8_t maxPort;
extern __xdata uint8_t nSFPPorts;
extern __xdata uint8_t isRTL8373;
extern __xdata uint16_t mpos; extern __xdata uint16_t mpos;
extern __xdata uint8_t stpEnabled; extern __xdata uint8_t stpEnabled;
extern __code uint8_t log_to_phys_port[9]; extern __code uint8_t log_to_phys_port[9];
@@ -63,11 +62,6 @@ __xdata signed char cmd_words_b[N_WORDS];
__xdata uint8_t cmd_history[CMD_HISTORY_SIZE]; __xdata uint8_t cmd_history[CMD_HISTORY_SIZE];
__xdata uint16_t cmd_history_ptr; __xdata uint16_t cmd_history_ptr;
// Maps the physical port (starting from 0) to the logical port
__code uint8_t phys_to_log_port[6] = {
4, 5, 6, 7, 3, 8
};
inline uint8_t isletter(uint8_t l) inline uint8_t isletter(uint8_t l)
{ {
@@ -205,10 +199,7 @@ void parse_lag(void)
print_string(" member ports: "); print_string(" member ports: ");
for (uint8_t j = 0; j < 10; j++) { for (uint8_t j = 0; j < 10; j++) {
if (members & 1) { if (members & 1) {
if (!isRTL8373) write_char('0' + machine.log_to_phys_port[j]);
write_char('0' + log_to_phys_port[j]);
else
write_char('1' + j);
write_char(' '); write_char(' ');
} }
members >>= 1; members >>= 1;
@@ -233,12 +224,11 @@ void parse_lag(void)
port = cmd_buffer[cmd_words_b[w]] - '1'; port = cmd_buffer[cmd_words_b[w]] - '1';
if (isnumber(cmd_buffer[cmd_words_b[w] + 1])) if (isnumber(cmd_buffer[cmd_words_b[w] + 1]))
port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1'; port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1';
if (!isRTL8373) port = machine.phys_to_log_port[port];
port = phys_to_log_port[port];
} else { } else {
goto err; goto err;
} }
if (port > maxPort) if (port > machine.max_port)
goto err; goto err;
members |= ((uint16_t)1) << port; members |= ((uint16_t)1) << port;
w++; w++;
@@ -321,12 +311,11 @@ void parse_vlan(void)
if (cmd_buffer[cmd_words_b[w] + 2] == 't') if (cmd_buffer[cmd_words_b[w] + 2] == 't')
tagged |= ((uint16_t)1) << port; tagged |= ((uint16_t)1) << port;
} else { } else {
if (!isRTL8373) port = machine.phys_to_log_port[port];
port = phys_to_log_port[port];
if (cmd_buffer[cmd_words_b[w] + 1] == 't') if (cmd_buffer[cmd_words_b[w] + 1] == 't')
tagged |= ((uint16_t)1) << port; tagged |= ((uint16_t)1) << port;
} }
if (port > maxPort) if (port > machine.max_port)
goto err; goto err;
members |= ((uint16_t)1) << port; members |= ((uint16_t)1) << port;
} }
@@ -359,10 +348,7 @@ void parse_mirror(void)
print_string("NOT Enabled: "); print_string("NOT Enabled: ");
} }
print_string("Mirroring port: "); print_string("Mirroring port: ");
if (!isRTL8373) write_char('0' + machine.log_to_phys_port[mPort >> 1]);
write_char('0' + log_to_phys_port[mPort >> 1]);
else
write_char('0' + (mPort >> 1) + 1);
reg_read_m(RTL837x_MIRROR_CONF); reg_read_m(RTL837x_MIRROR_CONF);
uint16_t m = sfr_data[0]; uint16_t m = sfr_data[0];
m = (m << 8) | sfr_data[1]; m = (m << 8) | sfr_data[1];
@@ -387,8 +373,7 @@ void parse_mirror(void)
mirroring_port = cmd_buffer[cmd_words_b[1]] - '1'; mirroring_port = cmd_buffer[cmd_words_b[1]] - '1';
if (isnumber(cmd_buffer[cmd_words_b[1] + 1])) if (isnumber(cmd_buffer[cmd_words_b[1] + 1]))
mirroring_port = (mirroring_port + 1) * 10 + cmd_buffer[cmd_words_b[1] + 1] - '1'; mirroring_port = (mirroring_port + 1) * 10 + cmd_buffer[cmd_words_b[1] + 1] - '1';
if (!isRTL8373) mirroring_port = machine.phys_to_log_port[mirroring_port];
mirroring_port = phys_to_log_port[mirroring_port];
uint8_t w = 2; uint8_t w = 2;
while (cmd_words_b[w] > 0) { while (cmd_words_b[w] > 0) {
@@ -397,8 +382,7 @@ void parse_mirror(void)
port = cmd_buffer[cmd_words_b[w]] - '1'; port = cmd_buffer[cmd_words_b[w]] - '1';
if (isnumber(cmd_buffer[cmd_words_b[w] + 1])) { if (isnumber(cmd_buffer[cmd_words_b[w] + 1])) {
port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1'; port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1';
if (!isRTL8373) port = machine.phys_to_log_port[port];
port = phys_to_log_port[port];
if (cmd_buffer[cmd_words_b[w] + 2] == 'r') if (cmd_buffer[cmd_words_b[w] + 2] == 'r')
rx_pmask |= ((uint16_t)1) << port; rx_pmask |= ((uint16_t)1) << port;
else if (cmd_buffer[cmd_words_b[w] + 2] == 't') else if (cmd_buffer[cmd_words_b[w] + 2] == 't')
@@ -408,8 +392,7 @@ void parse_mirror(void)
tx_pmask |= ((uint16_t)1) << port; tx_pmask |= ((uint16_t)1) << port;
} }
} else { } else {
if (!isRTL8373) port = machine.phys_to_log_port[port];
port = phys_to_log_port[port];
if (cmd_buffer[cmd_words_b[w] + 1] == 'r') if (cmd_buffer[cmd_words_b[w] + 1] == 'r')
rx_pmask |= ((uint16_t)1) << port; rx_pmask |= ((uint16_t)1) << port;
else if (cmd_buffer[cmd_words_b[w] + 1] == 't') else if (cmd_buffer[cmd_words_b[w] + 1] == 't')
@@ -426,6 +409,53 @@ void parse_mirror(void)
} }
void parse_port(void)
{
print_string("\nPORT ");
uint8_t p = cmd_buffer[cmd_words_b[1]] - '1';
p = machine.phys_to_log_port[p];
print_byte(p);
if (machine.is_sfp[p]) {
print_string(" is SFP no PHY information available.\n");
return;
}
if (cmd_words_b[2] > 0 && cmd_compare(2, "10m")) {
print_string(" 10M\n");
phy_set_speed(p, PHY_SPEED_10M);
}
if (cmd_words_b[2] > 0 && cmd_compare(2, "100m")) {
print_string(" 100M\n");
phy_set_speed(p, PHY_SPEED_100M);
}
if (cmd_words_b[2] > 0 && cmd_compare(2, "2g5")) {
print_string(" 2.5G\n");
phy_set_speed(p, PHY_SPEED_2G5);
}
if (cmd_words_b[2] > 0 && cmd_compare(2, "1g")) {
print_string(" 1G\n");
phy_set_speed(p, PHY_SPEED_1G);
}
if (cmd_words_b[2] > 0 && cmd_compare(2, "auto")) {
print_string(" AUTO\n");
phy_set_speed(p, PHY_SPEED_AUTO);
}
if (cmd_words_b[2] > 0 && cmd_compare(2, "off")) {
print_string(" OFF\n");
phy_set_speed(p, PHY_OFF);
}
if (cmd_words_b[2] > 0 && cmd_compare(2, "duplex")) {
print_string(" DUPLEX\n");
if (cmd_words_b[3] > 0 && cmd_compare(3, "full"))
phy_set_duplex(p, 1);
else
phy_set_duplex(p, 0);
}
if (cmd_words_b[2] > 0 && cmd_compare(2, "show")) {
phy_show(p);
}
}
void parse_regget(void) void parse_regget(void)
{ {
uint16_t reg = 0; uint16_t reg = 0;
@@ -627,14 +657,15 @@ void cmd_parser(void) __banked
print_string("\nRESET\n\n"); print_string("\nRESET\n\n");
reset_chip(); reset_chip();
} else if (cmd_compare(0, "sfp")) { } else if (cmd_compare(0, "sfp")) {
uint8_t rate = sfp_read_reg(0, 12); print_string("\nSlot 1 - Rate: "); print_byte(sfp_read_reg(0, 12));
print_string("\nRate: "); print_byte(rate);
print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11)); print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11));
print_string("\n"); print_string("\n");
for (uint8_t i = 20; i < 60; i++) { sfp_print_info(0);
uint8_t c = sfp_read_reg(0, i); if (machine.n_sfp == 2) {
if (c) print_string("\nSlot 2 - Rate: "); print_byte(sfp_read_reg(1, 12));
write_char(c); print_string(" Encoding: "); print_byte(sfp_read_reg(1, 11));
print_string("\n");
sfp_print_info(1);
} }
} else if (cmd_compare(0, "stat")) { } else if (cmd_compare(0, "stat")) {
port_stats_print(); port_stats_print();
@@ -680,25 +711,7 @@ void cmd_parser(void) __banked
flash_region.len = 20; flash_region.len = 20;
flash_write_bytes(flash_buf); flash_write_bytes(flash_buf);
} else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) { } else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) {
print_string("\nPORT "); parse_port();
uint8_t p = cmd_buffer[cmd_words_b[1]] - '1';
print_byte(p);
if (cmd_words_b[2] > 0 && cmd_compare(2, "2g5")) {
print_string(" 2.5G\n");
phy_set_mode(p, PHY_SPEED_2G5, 0, 0);
}
if (cmd_words_b[2] > 0 && cmd_compare(2, "1g")) {
print_string(" 1G\n");
phy_set_mode(p, PHY_SPEED_1G, 0, 0);
}
if (cmd_words_b[2] > 0 && cmd_compare(2, "auto")) {
print_string(" AUTO\n");
phy_set_mode(p, PHY_SPEED_AUTO, 0, 0);
}
if (cmd_words_b[2] > 0 && cmd_compare(2, "off")) {
print_string(" OFF\n");
phy_set_mode(p, PHY_OFF, 0, 0);
}
} else if (cmd_compare(0, "ip")) { } else if (cmd_compare(0, "ip")) {
print_string("Got ip command: "); print_string("Got ip command: ");
if (!parse_ip(cmd_words_b[1])) if (!parse_ip(cmd_words_b[1]))
@@ -742,8 +755,7 @@ void cmd_parser(void) __banked
__xdata uint16_t pvid; __xdata uint16_t pvid;
uint8_t port; uint8_t port;
port = cmd_buffer[cmd_words_b[1]] - '1'; port = cmd_buffer[cmd_words_b[1]] - '1';
if (!isRTL8373) port = machine.phys_to_log_port[port];
port = phys_to_log_port[port];
if (!atoi_short(&pvid, cmd_words_b[2])) if (!atoi_short(&pvid, cmd_words_b[2]))
port_pvid_set(port, pvid); port_pvid_set(port, pvid);
} else if (cmd_compare(0, "vlan")) { } else if (cmd_compare(0, "vlan")) {
@@ -770,8 +782,7 @@ void cmd_parser(void) __banked
int8_t port = -1; int8_t port = -1;
if (cmd_words_b[3] > 0) { if (cmd_words_b[3] > 0) {
port = cmd_buffer[cmd_words_b[2]] - '1'; port = cmd_buffer[cmd_words_b[2]] - '1';
if (!isRTL8373) port = machine.phys_to_log_port[port];
port = phys_to_log_port[port];
} }
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) { if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
if (port >= 0) if (port >= 0)
+11
View File
@@ -34,6 +34,12 @@ Changes I found with my board vs [Managed version](https://github.com/up-n-atom/
We need to make a `Best`-BOM variant so we can use all the featues. We need to make a `Best`-BOM variant so we can use all the featues.
# Connectors # Connectors
## J4
* Location: Left SFP connector `J4`.
* Connected to: 10GMAC number 8, second SDS.
|`J4` SFP1 PINs | Signal | Component | GPIO | Notes | |`J4` SFP1 PINs | Signal | Component | GPIO | Notes |
|---|---|---|---|---| |---|---|---|---|---|
|2| TX_FAULT | B-R262 | --- | | |2| TX_FAULT | B-R262 | --- | |
@@ -45,6 +51,11 @@ Changes I found with my board vs [Managed version](https://github.com/up-n-atom/
|8| LOS | B-R258, T-R270 | GPIO37 | | |8| LOS | B-R258, T-R270 | GPIO37 | |
|9| TO? | B-R256 | --- | | |9| TO? | B-R256 | --- | |
## J2
* Location: Right SFP connector `J2`.
* Connected to: 10GMAC number 3, first SDS.
|`J2` SFP2 PINs | Signal | Component | GPIO | Notes | |`J2` SFP2 PINs | Signal | Component | GPIO | Notes |
|---|---|---|---|---| |---|---|---|---|---|
|2| TX_FAULT | B-R70 | --- | | |2| TX_FAULT | B-R70 | --- | |
+3 -3
View File
@@ -2,7 +2,7 @@ var txG = new BigInt64Array(10);
var txB = new BigInt64Array(10); var txB = new BigInt64Array(10);
var rxG = new BigInt64Array(10); var rxG = new BigInt64Array(10);
var rxB = new BigInt64Array(10); var rxB = new BigInt64Array(10);
const linkS = ["Disabled", "No Link", "100M", "1000M", "NO", "NO", "2.5G"]; const linkS = ["Disabled", "No Link", "100M", "1000M", "500M", "10G", "2.5G", "5G"];
var pState = new Int8Array(10); var pState = new Int8Array(10);
var pIsSFP = new Int8Array(10); var pIsSFP = new Int8Array(10);
var numPorts = 0; var numPorts = 0;
@@ -40,9 +40,9 @@ function update() {
} else { } else {
psvg.style.opacity = 1.0; psvg.style.opacity = 1.0;
pState[n] = p.link; pState[n] = p.link;
if (p.link == 5) { if (p.link == 4 || p.link == 5 || p.link == 6) {
leds[0].style.fill = "green"; leds[1].style.fill = "orange"; leds[0].style.fill = "green"; leds[1].style.fill = "orange";
} else if (p.link == 2) { } else if (p.link == 1 || p.link == 2 || p.link == 3) {
leds[0].style.fill = "green"; leds[1].style.fill = "green"; leds[0].style.fill = "green"; leds[1].style.fill = "green";
} else { } else {
leds[0].style.fill = "black"; leds[1].style.fill = "black"; leds[0].style.fill = "black"; leds[1].style.fill = "black";
+45 -41
View File
@@ -10,11 +10,13 @@
#include <stdint.h> #include <stdint.h>
#include "../phy.h" #include "../phy.h"
#include "../version.h" #include "../version.h"
#include "../machine.h"
#include "page_impl.h" #include "page_impl.h"
#pragma codeseg BANK1 #pragma codeseg BANK1
#pragma constseg BANK1 #pragma constseg BANK1
extern __code const struct machine machine;
extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE]; extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE];
extern __xdata uint16_t slen; extern __xdata uint16_t slen;
extern __xdata uint16_t cont_len; extern __xdata uint16_t cont_len;
@@ -22,15 +24,8 @@ extern __xdata uint32_t cont_addr;
extern __code uint8_t * __code hex; extern __code uint8_t * __code hex;
extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
extern __code struct uip_eth_addr uip_ethaddr; extern __code struct uip_eth_addr uip_ethaddr;
extern __code uint8_t log_to_phys_port[9];
extern __code uint8_t phys_to_log_port[6];
extern __xdata uint8_t minPort;
extern __xdata uint8_t maxPort;
extern __xdata uint8_t nSFPPorts;
extern __xdata uint8_t sfr_data[4]; extern __xdata uint8_t sfr_data[4];
extern __xdata uint8_t cpuPort;
extern __xdata uint8_t isRTL8373;
extern __xdata uint8_t sfp_pins_last; extern __xdata uint8_t sfp_pins_last;
extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
@@ -139,6 +134,20 @@ void reg_to_html(register uint16_t reg)
sfr_data_to_html(); sfr_data_to_html();
} }
void send_sfp_info(uint8_t sfp)
{
// This loops over the Vendor-name, Vendor OUI, Vendor PN and Vendor rev ASCII fields
for (uint8_t i = 20; i < 60; i++) {
if (i >= 36 && i < 40) // Skip Non-ASCII codes
continue;
uint8_t c = sfp_read_reg(sfp, i);
if (c && c != 0xa0) // a0 is the byte read from a non-existant I2C EEPROM
char_to_html(c);
}
}
void send_basic_info(void) void send_basic_info(void)
{ {
slen = strtox(outbuf, HTTP_RESPONCE_JSON); slen = strtox(outbuf, HTTP_RESPONCE_JSON);
@@ -167,7 +176,17 @@ void send_basic_info(void)
byte_to_html(uip_ethaddr.addr[5]); byte_to_html(uip_ethaddr.addr[5]);
slen += strtox(outbuf + slen, "\",\"sw_ver\":\""); slen += strtox(outbuf + slen, "\",\"sw_ver\":\"");
slen += strtox(outbuf + slen, VERSION_SW); slen += strtox(outbuf + slen, VERSION_SW);
slen += strtox(outbuf + slen, "\",\"hw_ver\":\"SWGT024-V2.0\"}"); slen += strtox(outbuf + slen, "\",\"hw_ver\":\"");
slen += strtox(outbuf + slen, machine.machine_name);
slen += strtox(outbuf + slen, "\",\"sfp_slot_0\":\"");
send_sfp_info(0);
char_to_html('"');
if (machine.n_sfp == 2) {
slen += strtox(outbuf + slen, ",\"sfp_slot_1\":\"");
send_sfp_info(1);
char_to_html('"');
}
char_to_html('}');
} }
@@ -198,7 +217,7 @@ void send_counters(char port)
print_string("sending counters\n"); print_string("sending counters\n");
port--; port--;
uint8_t i = isRTL8373 ? port - 1: phys_to_log_port[port]; uint8_t i = machine.phys_to_log_port[port];
slen += strtox(outbuf + slen, "{\"portNum\":"); slen += strtox(outbuf + slen, "{\"portNum\":");
itoa_html(i + 1); itoa_html(i + 1);
for (uint8_t j = 0; j < 0x3f; j++) { for (uint8_t j = 0; j < 0x3f; j++) {
@@ -226,10 +245,7 @@ void send_mirror(void)
} else { } else {
slen += strtox(outbuf + slen, "{\"enabled\":0,\"mPort\":"); slen += strtox(outbuf + slen, "{\"enabled\":0,\"mPort\":");
} }
if (!isRTL8373) itoa_html(machine.log_to_phys_port[mPort >> 1]);
itoa_html(log_to_phys_port[mPort >> 1]);
else
itoa_html((mPort >> 1) + 1);
reg_read_m(RTL837x_MIRROR_CONF); reg_read_m(RTL837x_MIRROR_CONF);
uint16_t m = sfr_data[0]; uint16_t m = sfr_data[0];
@@ -286,14 +302,11 @@ void send_eee(void)
uint8_t eee_ablty = sfr_data[3]; uint8_t eee_ablty = sfr_data[3];
char_to_html('['); char_to_html('[');
for (uint8_t i = minPort; i <= maxPort; i++) { for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
slen += strtox(outbuf + slen, "{\"portNum\":"); slen += strtox(outbuf + slen, "{\"portNum\":");
if (!isRTL8373) itoa_html(machine.log_to_phys_port[i]);
itoa_html(log_to_phys_port[i]);
else
itoa_html(i + 1);
if (IS_SFP(i)) { if (machine.is_sfp[i]) {
slen += strtox(outbuf + slen, ",\"isSFP\":1"); slen += strtox(outbuf + slen, ",\"isSFP\":1");
} else { } else {
slen += strtox(outbuf + slen, ",\"isSFP\":0,\"eee\":\""); slen += strtox(outbuf + slen, ",\"isSFP\":0,\"eee\":\"");
@@ -321,7 +334,7 @@ void send_eee(void)
bool_to_html(eee_ablty & (1 << i)); bool_to_html(eee_ablty & (1 << i));
} }
char_to_html('}'); char_to_html('}');
if (i < maxPort) if (i < machine.max_port)
char_to_html(','); char_to_html(',');
else else
char_to_html(']'); char_to_html(']');
@@ -335,38 +348,29 @@ void send_status(void)
print_string("sending status\n"); print_string("sending status\n");
char_to_html('['); char_to_html('[');
for (uint8_t i = minPort; i <= maxPort; i++) { for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
slen += strtox(outbuf + slen, "{\"portNum\":"); slen += strtox(outbuf + slen, "{\"portNum\":");
if (!isRTL8373) itoa_html(machine.log_to_phys_port[i]);
itoa_html(log_to_phys_port[i]);
else
itoa_html(i + 1);
if (IS_SFP(i)) { if (machine.is_sfp[i]) {
slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":"); slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":");
bool_to_html(!((sfp_pins_last >> (i == maxPort ? 0 : 4)) & 1)); bool_to_html(!(sfp_pins_last & (0x1 << ((machine.is_sfp[i] - 1) << 2))));
slen += strtox(outbuf + slen, ",\"link\":");
uint8_t rate = sfp_read_reg(i == maxPort ? 0 : 1, 12);
if (rate == 0xd)
char_to_html('2'); // 1000BX
else if (rate == 0x1f)
char_to_html('5'); // 2G5
else if (rate > 0x65 && rate < 0x70)
char_to_html('4'); // 10G "4" is not a valid value for port LINK speed
else
char_to_html('1'); // 100M ???
} else { } else {
slen += strtox(outbuf + slen, ",\"isSFP\":0,\"enabled\":"); slen += strtox(outbuf + slen, ",\"isSFP\":0,\"enabled\":");
phy_read(i, 0x1f, 0xa610); phy_read(i, 0x1f, 0xa610);
bool_to_html(SFR_DATA_8 == 0x20); bool_to_html(SFR_DATA_8 == 0x20);
}
slen += strtox(outbuf + slen, ",\"link\":"); slen += strtox(outbuf + slen, ",\"link\":");
if (i < 8)
reg_read_m(RTL837X_REG_LINKS); reg_read_m(RTL837X_REG_LINKS);
uint8_t b = sfr_data[3 - (i >> 1)]; else
reg_read_m(RTL837X_REG_LINKS_89);
uint8_t b = sfr_data[3 - ((i & 7) >> 1)];
b = (i & 1) ? b >> 4 : b & 0xf; b = (i & 1) ? b >> 4 : b & 0xf;
char_to_html('0' + b); char_to_html('0' + b);
}
STAT_GET(STAT_COUNTER_TX_PKTS, i); STAT_GET(STAT_COUNTER_TX_PKTS, i);
slen += strtox(outbuf + slen, ",\"txG\":\"0x"); slen += strtox(outbuf + slen, ",\"txG\":\"0x");
reg_to_html(RTL837X_STAT_V_HIGH); reg_to_html(RTL837X_STAT_V_HIGH);
@@ -385,7 +389,7 @@ void send_status(void)
STAT_GET(STAT_COUNTER_ERR_PKTS, i); STAT_GET(STAT_COUNTER_ERR_PKTS, i);
reg_to_html(RTL837X_STAT_V_HIGH); // 32bit RX packet errors reg_to_html(RTL837X_STAT_V_HIGH); // 32bit RX packet errors
slen += strtox(outbuf + slen, "\"}"); slen += strtox(outbuf + slen, "\"}");
if (i < maxPort) if (i < machine.max_port)
char_to_html(','); char_to_html(',');
else else
char_to_html(']'); char_to_html(']');
+91
View File
@@ -0,0 +1,91 @@
#include "machine.h"
#ifdef MACHINE_KP_9000_6XHML_X2
__code const struct machine machine = {
.machine_name = "keepLink KP-9000-6XHML-X2",
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = 50,
.sfp_port[0].pin_los = 10,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = 1,
.sfp_port[1].pin_detect = 30,
.sfp_port[1].pin_los = 37,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = 0,
.reset_pin = 46,
};
#elif defined MACHINE_KP_9000_6XH_X
__code const struct machine machine = {
.machine_name = "keepLink KP-9000-6XH-X",
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 1,
.log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6},
.phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
.sfp_port[0].pin_detect = 30,
.sfp_port[0].pin_los = 37,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = 0,
};
#elif defined MACHINE_KP_9000_9XH_X_EU
__code const struct machine machine = {
.machine_name = "keepLink KP-9000-6XH-X-EU",
.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 = 30,
.sfp_port[0].pin_los = 37,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = 0,
};
#elif defined MACHINE_SWGT024_V2_0
__code const struct machine machine = {
.machine_name = "SWGT024 V2.0",
.isRTL8373 = 0,
.min_port = 3,
.max_port = 8,
.n_sfp = 2,
.log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
.phys_to_log_port = {4, 6, 5, 7, 3, 8, 0, 0, 0},
.is_sfp= {0, 0, 0, 2, 0, 0, 0, 0, 1},
// Left SFP port (J4)
.sfp_port[0].pin_detect = 30,
.sfp_port[0].pin_los = 37,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = 0, /* GPIO 39 */
// Right SFP port (J2)
.sfp_port[1].pin_detect = 50,
.sfp_port[1].pin_los = 51,
.sfp_port[1].sds = 0,
.sfp_port[1].i2c = 1, /* GPIO 40 */
.reset_pin = 36,
};
#elif defined DEFAULT_8C_1SFP
__code const struct machine machine = {
.machine_name = "8+1 SFP Port Switch",
.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 = 30,
.sfp_port[0].pin_los = 37,
.sfp_port[0].sds = 1,
.sfp_port[0].i2c = 0,
};
#endif
+42
View File
@@ -0,0 +1,42 @@
#ifndef _MACHINE_H_
#define _MACHINE_H_
#include <stdint.h>
/*
* Select your machine type below
*/
#define MACHINE_KP_9000_6XHML_X2
// #define MACHINE_KP_9000_6XH_X
// #define MACHINE_KP_9000_9XH_X_EU
// #define MACHINE_SWGT024_V2_0
// #define MACHINE_HORACO_ZX_SG4T2
// #define DEFAULT_8C_1SFP
// #define DEFAULT_5C_1SFP
struct sfp_port
{
uint8_t pin_detect; // gpio number 0-63, 0xFF = don't have it?
uint8_t pin_los; // gpio number 0-63, 0xFF = don't have it?
uint8_t sds;
uint8_t i2c;
};
typedef struct machine {
char machine_name[30];
uint8_t isRTL8373;
uint8_t min_port;
uint8_t max_port;
uint8_t n_sfp;
uint8_t log_to_phys_port[9];
uint8_t phys_to_log_port[9]; // Starts at 0 for port 1
uint8_t is_sfp[9]; // 0 for non-SFP ports 1 or 2 for the I2C port number
// sfp_port[0] is the first SFP-port from the left on the device, sfp_port[1] the next if present
struct sfp_port sfp_port[2];
int8_t reset_pin;
};
#endif
+1
View File
@@ -11,6 +11,7 @@
/* /*
* Define PHY pages * Define PHY pages
*/ */
#define PHY_MMD_PMAPMD 1
#define PHY_MMD_AN 7 #define PHY_MMD_AN 7
#define PHY_SDS_CTRL 30 #define PHY_SDS_CTRL 30
#define PHY_MMD_CTRL 31 #define PHY_MMD_CTRL 31
+5 -8
View File
@@ -3,14 +3,15 @@
#include "uip/uip-conf.h" #include "uip/uip-conf.h"
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
// This has to be set to the number of SFP+ ports, i.e. 1 or 2
#define NSFP 2
// SCL and SDA pin numbers for SFP cage 0 and SFP cage 1 // SCL and SDA pin numbers for SFP cage 0 and SFP cage 1
#define SCL_PIN 3 #define SCL_PIN 3
#define SDA_PIN_0 4 #define SDA_PIN_0 4
#define SDA_PIN_1 3 #define SDA_PIN_1 3
#define CPU_PORT 9
// Define Port-masks for 9-port devices and 6-port devices // Define Port-masks for 9-port devices and 6-port devices
#define PMASK_9 0x1ff #define PMASK_9 0x1ff
#define PMASK_6 0x1f8 #define PMASK_6 0x1f8
@@ -41,12 +42,6 @@
// This is the standard size of an Ethernet frame header // This is the standard size of an Ethernet frame header
#define ETHER_HEADER_SIZE 14 #define ETHER_HEADER_SIZE 14
#if NSFP == 1
#define IS_SFP(port) (i == maxPort)
#else
#define IS_SFP(port) (i == maxPort || i == 3)
#endif
#define CONFIG_START 0x70000 #define CONFIG_START 0x70000
#define CONFIG_LEN 0x1000 #define CONFIG_LEN 0x1000
#define CODE0_SIZE 0x4000 #define CODE0_SIZE 0x4000
@@ -106,5 +101,7 @@ void print_string_x(__xdata char *p);
uint8_t read_flash(uint8_t bank, __code uint8_t *addr); uint8_t read_flash(uint8_t bank, __code uint8_t *addr);
void get_random_32(void); void get_random_32(void);
void read_reg_timer(uint32_t * tmr); void read_reg_timer(uint32_t * tmr);
void sfp_print_info(uint8_t sfp);
bool gpio_pin_test(uint8_t pin);
#endif #endif
+1 -1
View File
@@ -283,7 +283,7 @@ void flash_read_bulk(__xdata uint8_t *dst)
} }
void flash_read_security() void flash_read_security(void)
{ {
while (flash_read_status() & 0x1); while (flash_read_status() & 0x1);
+6 -12
View File
@@ -11,12 +11,9 @@
#include "rtl837x_sfr.h" #include "rtl837x_sfr.h"
#include "rtl837x_regs.h" #include "rtl837x_regs.h"
#include "rtl837x_igmp.h" #include "rtl837x_igmp.h"
#include "machine.h"
extern __xdata uint8_t minPort; extern __code struct machine machine;
extern __xdata uint8_t maxPort;
extern __xdata uint8_t nSFPPorts;
extern __xdata uint8_t cpuPort;
extern __xdata uint8_t isRTL8373;
void igmp_setup(void) __banked void igmp_setup(void) __banked
{ {
@@ -24,19 +21,16 @@ void igmp_setup(void) __banked
// For now, forward all unkown MC pkts (2 bits per port. 00: flood via floodmask, 01: drop, 10: trap, 11: to rport) // For now, forward all unkown MC pkts (2 bits per port. 00: flood via floodmask, 01: drop, 10: trap, 11: to rport)
REG_SET(RTL837X_MC_LOOKUPMISS_ACTIONS, 0x00000000); //0x4f78 REG_SET(RTL837X_MC_LOOKUPMISS_ACTIONS, 0x00000000); //0x4f78
// Define ports where unknown MC addresses are flooded to: // Define ports where unknown MC addresses are flooded to:
if (isRTL8373) { REG_SET(RTL837X_MC_FLOODMASK, machine.isRTL8373 ? PMASK_9 : PMASK_6);
REG_SET(RTL837X_MC_FLOODMASK, PMASK_9); // R5368-000001f8
} else {
REG_SET(RTL837X_MC_FLOODMASK, PMASK_6);
}
// Enable lookup of IPv4 MC addresses in table // Enable lookup of IPv4 MC addresses in table
reg_bit_set(RTL837X_L2_CTRL, 3); // 0x5350 reg_bit_set(RTL837X_L2_CTRL, 3); // 0x5350
// Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping, // Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping,
// bits 16-24 configure max MC group used by that port. For now all protocols are flooded (01) // bits 16-24 configure max MC group used by that port. For now all protocols are flooded (01)
for (i = minPort; i <= maxPort; i++) for (i = machine.min_port; i <= machine.max_port; i++)
REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), 0x00ff7c15); REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), 0x00ff7c15);
} }
@@ -52,6 +46,6 @@ void igmp_enable(void) __banked
// Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping, // Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping,
// bits 16-24 configure max MC group used by that port. Trap to CPU (10) // bits 16-24 configure max MC group used by that port. Trap to CPU (10)
for (i = minPort; i <= maxPort; i++) for (i = machine.min_port; i <= machine.max_port; i++)
REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), 0x00ff7c2a); // 0x00ff7000: Handling by ASIC (00) REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), 0x00ff7c2a); // 0x00ff7000: Handling by ASIC (00)
} }
+168 -14
View File
@@ -119,7 +119,7 @@ void phy_config(uint8_t phy) __banked
// p031f.a442:043c P000008.1f00a442:0430 // p031f.a442:043c P000008.1f00a442:0430
// Unknown, but clear bits 2/3 // Unknown, but clear bits 2/3
phy_modify(phy, 0x1f, 0xa442, 0x0006, 0x0000); phy_modify(phy, 0x1f, 0xa442, 0x000c, 0x0000);
delay(20); delay(20);
// P000100.1e0075b5:e084 // P000100.1e0075b5:e084
@@ -182,46 +182,200 @@ void phy_config_8224(void) __banked
/* /*
* Set Speed, duplex and flow control mode of a PHY * Set Speed of a PHY
* See e.g. RTL8221B datasheet * See e.g. RTL8221B datasheet
*/ */
void phy_set_mode(uint8_t port, uint8_t speed, uint8_t flow_control, uint8_t duplex) __banked void phy_set_speed(uint8_t port, uint8_t speed) __banked
{ {
uint16_t v; uint16_t v;
phy_read(port, 0x1f, 0xa610); phy_read(port, PHY_MMD_CTRL, 0xa610);
v = SFR_DATA_U16; v = SFR_DATA_U16;
if (speed == PHY_OFF) { if (speed == PHY_OFF) {
phy_write(port, 0x1f, 0xa610, v | 0x0800); phy_write(port, PHY_MMD_CTRL, 0xa610, v | 0x0800);
return; return;
} }
// Port is on, make sure of it: // Port is on, make sure of it:
if (v & 0x0800) if (v & 0x0800)
phy_write(port, 0x1f, 0xa610, v & 0xf7ff); phy_write(port, PHY_MMD_CTRL, 0xa610, v & 0xf7ff);
if (speed == PHY_SPEED_AUTO) { if (speed == PHY_SPEED_AUTO) {
// AN Advertisement Register (MMD 7.0x0010) // AN Advertisement Register (MMD 7.0x0010)
phy_write(port, PHY_MMD_AN, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
phy_write(port, PHY_MMD_AN, 0x10, 0x15e1);
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
phy_write(port, PHY_MMD_AN, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD
phy_write(port, PHY_MMD_AN, 0x20, 0x6081);
// GBCR (1000Base-T Control Register, MMD 31.0xA412)
phy_modify(port, PHY_MMD_CTRL, 0xa412, 0x0000, 0x0200); // Loop timing enabled
phy_write(port, PHY_MMD_AN, 0x00, 0x3200); // Restart AN phy_write(port, PHY_MMD_AN, 0x00, 0x3200); // Restart AN
} else { } else {
// AN Control Register (MMD 7.0x0000) // AN Control Register (MMD 7.0x0000)
phy_write(port, PHY_MMD_AN, 0x00, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13) phy_write(port, PHY_MMD_AN, 0x00, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13)
if (speed == PHY_SPEED_10M) {
phy_write(port, PHY_MMD_AN, 0x20, 0x6001);
phy_write(port, PHY_MMD_AN, 0x10, 0x1461);
phy_modify(port, PHY_MMD_CTRL, 0xa412, 0x0200, 0x0000);
} else if (speed == PHY_SPEED_100M) {
phy_write(port, PHY_MMD_AN, 0x20, 0x6001);
phy_write(port, PHY_MMD_AN, 0x10, 0x1581);
phy_modify(port, PHY_MMD_CTRL, 0xa412, 0x0200, 0x0000);
} else {
// AN Advertisement Register (MMD 7.0x0010) // AN Advertisement Register (MMD 7.0x0010)
phy_write(port, PHY_MMD_AN, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used
phy_write(port, PHY_MMD_AN, 0x10, 0x1001);
if (speed == PHY_SPEED_1G) { if (speed == PHY_SPEED_1G) {
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
phy_write(port, PHY_MMD_AN, 0x20, 0x6001); // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed
phy_write(port, PHY_MMD_AN, 0x20, 0x6001);
// GBCR (1000Base-T Control Register, MMD 31.0xA412) // GBCR (1000Base-T Control Register, MMD 31.0xA412)
phy_modify(port, 0x1f, 0xa412, 0x0000, 0x02000); phy_modify(port, PHY_MMD_CTRL, 0xa412, 0x0000, 0x0200);
} else if (speed == PHY_SPEED_2G5) { } else if (speed == PHY_SPEED_2G5) {
// Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020)
phy_write(port, PHY_MMD_AN, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed
phy_write(port, PHY_MMD_AN, 0x20, 0x6081);
// GBCR (1000Base-T Control Register, MMD 31.0xA412) // GBCR (1000Base-T Control Register, MMD 31.0xA412)
phy_modify(port, 0x1f, 0xa412, 0x02000, 0x0000); phy_modify(port, PHY_MMD_CTRL, 0xa412, 0x0200, 0x0000);
} }
phy_write(port, PHY_MMD_AN, 0x00, 0x3200); // Enable AN
} }
phy_write(port, PHY_MMD_AN, 0x00, 0x3000); // Enable AN
}
}
void phy_set_duplex(uint8_t port, uint8_t fullduplex) __banked
{
uint16_t v;
phy_read(port, PHY_MMD_AN, 0x00);
v = SFR_DATA_U16;
if (!(v & 0x1000)) { // AN disabled, we are in forced mode
phy_read(port, PHY_MMD_CTRL, 0xa400);
v = SFR_DATA_U16;
if (fullduplex)
v |= 0x0100;
else
v &= 0xfeff;
phy_write(port, PHY_MMD_CTRL, 0xa400, v);
return;
}
// Disable AN
phy_write(port, PHY_MMD_AN, 0x00, 0x2000);
phy_read(port, PHY_MMD_AN, 0x10);
v = SFR_DATA_U16;
if (v & 0x0060) {
if (fullduplex)
phy_modify(port, PHY_MMD_AN, 0x10, 0xffbf, 0x0040);
else
phy_modify(port, PHY_MMD_AN, 0x10, 0xffdf, 0x0020);
}
if (v & 0x0180) {
if (fullduplex)
phy_modify(port, PHY_MMD_AN, 0x10, 0xfeff, 0x0100);
else
phy_modify(port, PHY_MMD_AN, 0x10, 0xff7f, 0x0080);
}
// Restart AN
phy_write(port, PHY_MMD_AN, 0x00, 0x3000);
}
void phy_show(uint8_t port) __banked
{
uint16_t v;
phy_read(port, PHY_MMD_AN, 0x00);
v = SFR_DATA_U16;
if (!(v & 0x1000)) { // AN disabled, we are in forced mode
phy_read(port, PHY_MMD_PMAPMD, 0);
v = SFR_DATA_U16;
print_string("\nForced speed: "); print_short(v); write_char('\n');
uint8_t s1 = ((v & 0x40) ? 0x2 : 0x0) | ((v & 0x2000) ? 0x1 : 0x0);
uint8_t s2 = (v >> 2) & 0xf;
switch(s1) {
case 0:
print_string("10M\n");
break;
case 1:
print_string("100M\n");
break;
case 2:
print_string("1000M\n");
break;
case 3:
switch (s2) {
case 0:
print_string("10G\n");
break;
case 6:
print_string("2500M\n");
break;
case 7:
print_string("5G\n");
break;
default:
print_string("Unknown\n");
break;
}
break;
default:
print_string("Unknown\n");
}
phy_read(port, PHY_MMD_CTRL, 0xa400);
v = SFR_DATA_U16;
print_string("Duplex: "); print_short(v); print_string(" enabled: ");
if (v & 0x100)
print_string("yes");
else
print_string("no");
write_char('\n');
} else {
print_string("\nAN enabled, advertising:");
phy_read(port, PHY_MMD_AN, 0x10);
v = SFR_DATA_U16;
if (v & 0x0040)
print_string(" 10Base-Half");
if (v & 0x0040)
print_string(" 10Base-Full");
if (v & 0x0080)
print_string(" 100Base-Half");
if (v & 0x0100)
print_string(" 100Base-Full");
phy_read(port, PHY_MMD_CTRL, 0xa412);
v = SFR_DATA_U16;
if (v & 0x0200)
print_string(" 1000Base-Full");
phy_read(port, PHY_MMD_AN, 0x10);
v = SFR_DATA_U16;
if (v & 0x0080)
print_string(" 2500BaseN-Full");
}
phy_read(port, PHY_MMD_AN, 0x13);
v = SFR_DATA_U16;
print_string("\nLink Partner advertises:");
if (v & 0x0020)
print_string(" 10Base-Half");
if (v & 0x0040)
print_string(" 10Base-Full");
if (v & 0x0080)
print_string(" 100Base-Half");
if (v & 0x0100)
print_string(" 100Base-Full");
phy_read(port, PHY_MMD_CTRL, 0xa414);
v = SFR_DATA_U16;
if (v & 0x0400)
print_string(" 1000Base-Half");
if (v & 0x0800)
print_string(" 1000Base-Full");
phy_read(port, PHY_MMD_AN, 33);
v = SFR_DATA_U16;
if (v & 0x0020)
print_string(" 2500Base-Full");
if (v & 0x0040)
print_string(" 5000Base-Full");
if (v & 0x0800)
print_string(" 10GBase-Full");
write_char('\n');
} }
+10 -4
View File
@@ -1,15 +1,21 @@
#ifndef _RTL837X_PHY_H_ #ifndef _RTL837X_PHY_H_
#define _RTL837X_PHY_H_ #define _RTL837X_PHY_H_
#define PHY_SPEED_AUTO 0x1 #define PHY_SPEED_10M 0x2
#define PHY_SPEED_1G 0x2 #define PHY_SPEED_100M 0x3
#define PHY_SPEED_2G5 0x3 #define PHY_SPEED_1G 0x4
#define PHY_SPEED_2G5 0x5
#define PHY_SPEED_5G 0x6
#define PHY_SPEED_10G 0x7
#define PHY_SPEED_AUTO 0x10
#define PHY_OFF 0xff #define PHY_OFF 0xff
void rtl8224_phy_enable(void) __banked; void rtl8224_phy_enable(void) __banked;
void phy_config(uint8_t phy) __banked; void phy_config(uint8_t phy) __banked;
void phy_config_8224(void) __banked; void phy_config_8224(void) __banked;
void phy_set_mode(uint8_t port, uint8_t speed, uint8_t flow_control, uint8_t duplex) __banked; void phy_set_speed(uint8_t port, uint8_t speed) __banked;
void phy_set_duplex(uint8_t port, uint8_t fullduplex) __banked;
void phy_show(uint8_t port) __banked;
void phy_reset(uint8_t port) __banked; void phy_reset(uint8_t port) __banked;
#endif #endif
+50 -81
View File
@@ -13,40 +13,20 @@
#include "rtl837x_port.h" #include "rtl837x_port.h"
#include "rtl837x_phy.h" #include "rtl837x_phy.h"
#include "phy.h" #include "phy.h"
#include "machine.h"
#pragma codeseg BANK1 #pragma codeseg BANK1
#pragma constseg BANK1 #pragma constseg BANK1
extern __code uint8_t * __code hex; extern __code uint8_t * __code hex;
extern __code uint16_t bit_mask[16]; extern __code uint16_t bit_mask[16];
extern __xdata uint8_t minPort; extern __code struct machine machine;
extern __xdata uint8_t maxPort;
extern __xdata uint8_t nSFPPorts;
extern __xdata uint8_t sfr_data[4]; extern __xdata uint8_t sfr_data[4];
extern __xdata uint8_t cpuPort;
extern __xdata uint16_t vlan_ptr; extern __xdata uint16_t vlan_ptr;
extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
extern __xdata uint8_t isRTL8373;
__xdata uint32_t l2_head; __xdata uint32_t l2_head;
// The mapping of logical to physical ports on the RTL8372
// Port 6 is always an SFP+ port. Port 5 may be RTL8221 or SFP+
__code uint8_t log_to_phys_port[9] = {
0, 0, 0, 5, 1, 2, 3, 4, 6
};
#if NSFP == 2
__code uint8_t is_sfp[9] = {
0, 0, 0, 1, 0, 0, 0, 0, 1
};
#else
__code uint8_t is_sfp[9] = {
0, 0, 0, 0, 0, 0, 0, 0, 1
};
#endif
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked
{ {
print_string("\nport_mirror_set called \n"); print_string("\nport_mirror_set called \n");
@@ -153,7 +133,7 @@ void vlan_create(register uint16_t vlan, register uint16_t members, register uin
uint16_t a = (~members) ^ tagged ^ members; uint16_t a = (~members) ^ tagged ^ members;
// On RTL8372, port-bits 0-2 must be 0, although they are not members // On RTL8372, port-bits 0-2 must be 0, although they are not members
if (!isRTL8373) { if (!machine.isRTL8373) {
a &= 0x1f8; a &= 0x1f8;
tagged &= 0x3f8; tagged &= 0x3f8;
} }
@@ -184,18 +164,15 @@ void vlan_setup(void) __banked
vlan_names[0] = 0; vlan_names[0] = 0;
// Initialize VLAN table for VLAN 1, by disabling that entry // Initialize VLAN table for VLAN 1, by disabling that entry
if (isRTL8373) { REG_SET(RTL837x_TBL_DATA_IN_A, machine.isRTL8373? 0x0007ffff : 0x0007e3f8);
REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007ffff);
} else {
REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007e3f8);
}
REG_SET(RTL837X_TBL_CTRL, 0x00010303); REG_SET(RTL837X_TBL_CTRL, 0x00010303);
do { do {
reg_read_m(RTL837X_TBL_CTRL); reg_read_m(RTL837X_TBL_CTRL);
} while (sfr_data[3] & TBL_EXECUTE); } while (sfr_data[3] & TBL_EXECUTE);
// Set PVID 1 for every port. TODO: Skip unused ports! // Set PVID 1 for every port. TODO: Skip unused ports!
for (uint8_t i = minPort; i <= maxPort + 1; i++) { // Do this also for the CPU port (+1) for (uint8_t i = machine.min_port; i <= machine.max_port + 1; i++) { // Do this also for the CPU port (+1)
uint16_t reg = RTL837x_PVID_BASE_REG + ((i >> 1) << 2); uint16_t reg = RTL837x_PVID_BASE_REG + ((i >> 1) << 2);
#ifdef DEBUG #ifdef DEBUG
print_byte(i); write_char(':'); write_char(' '); print_short(reg); write_char('='); print_byte(i); write_char(':'); write_char(' '); print_short(reg); write_char('=');
@@ -231,11 +208,8 @@ void vlan_setup(void) __banked
REG_SET(RTL837X_VLAN_L2_LRN_DIS_1, 0); REG_SET(RTL837X_VLAN_L2_LRN_DIS_1, 0);
// Enable VLAN 1: Ports 0-9, i.e. including the CPU port are untagged members // Enable VLAN 1: Ports 0-9, i.e. including the CPU port are untagged members
if (isRTL8373) { REG_SET(RTL837x_TBL_DATA_IN_A, machine.isRTL8373? 0x0207ffff : 0x0207e3f8); // 02: Entry valid, 7...: membership
REG_SET(RTL837x_TBL_DATA_IN_A, 0x0207ffff); // 02: Entry valid, 7ffff: membership
} else {
REG_SET(RTL837x_TBL_DATA_IN_A, 0x0207e3f8);
}
REG_SET(RTL837X_TBL_CTRL, 0x00010303); // Write VLAN 1 REG_SET(RTL837X_TBL_CTRL, 0x00010303); // Write VLAN 1
do { do {
reg_read_m(RTL837X_TBL_CTRL); reg_read_m(RTL837X_TBL_CTRL);
@@ -266,11 +240,7 @@ uint8_t port_l2_forget(void) __banked
REG_SET(RTL837x_L2_TBL_FLUSH_CNF, 0x0); REG_SET(RTL837x_L2_TBL_FLUSH_CNF, 0x0);
// Flush L2 table for all ports by setting the ports and the flush-exec bit (bit 16) // Flush L2 table for all ports by setting the ports and the flush-exec bit (bit 16)
if (isRTL8373) { REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | (machine.isRTL8373 ? PMASK_9 : PMASK_6));
REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | PMASK_9);
} else {
REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | PMASK_6);
}
// Wait for flush completed // Wait for flush completed
do { do {
@@ -358,18 +328,14 @@ void port_l2_setup(void) __banked
port_l2_forget(); port_l2_forget();
for (uint8_t i = minPort; i <= maxPort; i++) { for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
// Limit the number of automatically learned MAC-Entries per port to 0x1040 // Limit the number of automatically learned MAC-Entries per port to 0x1040
uint16_t reg = RTL837X_L2_LRN_PORT_CONSTRAINT + (i << 2); uint16_t reg = RTL837X_L2_LRN_PORT_CONSTRAINT + (i << 2);
REG_SET(reg, 0x00001040); REG_SET(reg, 0x00001040);
// All ports may communicate with each other and CPU-Port // All ports may communicate with each other and CPU-Port
reg = RTL837X_PORT_ISOLATION_BASE + (i << 2); reg = RTL837X_PORT_ISOLATION_BASE + (i << 2);
if(isRTL8373) { REG_SET(reg, PMASK_CPU | (machine.isRTL8373? PMASK_9 : PMASK_6));
REG_SET(reg, PMASK_9 | PMASK_CPU);
} else {
REG_SET(reg, PMASK_6 | PMASK_CPU);
}
} }
// When maximim entries learned, then simply flood the packet // When maximim entries learned, then simply flood the packet
reg_bit_set(RTL837X_L2_LRN_PORT_CONSTRT_ACT, 0); reg_bit_set(RTL837X_L2_LRN_PORT_CONSTRT_ACT, 0);
@@ -381,16 +347,38 @@ void port_l2_setup(void) __banked
void port_stats_print(void) __banked void port_stats_print(void) __banked
{ {
print_string("\n Port\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n"); print_string("\n Port\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n");
for (uint8_t i = minPort; i <= maxPort; i++) { for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
write_char('1' + i); write_char('\t'); write_char('0' + machine.log_to_phys_port[i]); write_char('\t');
phy_read(i, 0x1f, 0xa610); // p001f.a610:2058
if (i <= maxPort - nSFPPorts) { if (!machine.is_sfp[i]) {
phy_read(i, 0x1f, 0xa610);
if (SFR_DATA_8 == 0x20) if (SFR_DATA_8 == 0x20)
print_string("On\t"); print_string("On\t");
else else
print_string("Off\t"); print_string("Off\t");
} else { // An SFP Module
if (i != 3) {
reg_read_m(RTL837X_REG_GPIO_00_31_INPUT);
if (!(sfr_data[0] & 0x40)) {
print_string("SFP OK\t");
} else {
print_string("NO SFP\t");
}
} else {
reg_read_m(RTL837X_REG_GPIO_32_63_INPUT);
if (!(sfr_data[1] & 0x04)) {
print_string("SFP OK\t");
} else {
print_string("NO SFP\t");
}
}
}
if (i < 8)
reg_read_m(RTL837X_REG_LINKS); reg_read_m(RTL837X_REG_LINKS);
uint8_t b = sfr_data[3 - (i >> 1)]; else
reg_read_m(RTL837X_REG_LINKS_89);
uint8_t b = sfr_data[3 - ((i & 7) >> 1)];
b = (i & 1) ? b >> 4 : b & 0xf; b = (i & 1) ? b >> 4 : b & 0xf;
switch (b) { switch (b) {
case 0: case 0:
@@ -402,6 +390,9 @@ void port_stats_print(void) __banked
case 2: case 2:
print_string("1000M\t"); print_string("1000M\t");
break; break;
case 4:
print_string("10G\t");
break;
case 5: case 5:
print_string("2.5G\t"); print_string("2.5G\t");
break; break;
@@ -409,28 +400,6 @@ void port_stats_print(void) __banked
print_string("Up\t"); print_string("Up\t");
break; break;
} }
} else { // An SFP Module TODO: This is for 1 module devices
reg_read_m(RTL837X_REG_GPIO_00_31_INPUT);
if (!(sfr_data[0] & 0x40)) {
print_string("SFP OK\t");
} else {
print_string("NO SFP\t");
}
reg_read_m(RTL837X_REG_GPIO_32_63_INPUT);
if (sfr_data[3] & 0x20) {
print_string("Down\t");
} else {
uint8_t rate = sfp_read_reg(0, 12);
if (rate == 0xd)
print_string("1000BX\t");
else if (rate == 0x1f)
print_string("2500G\t");
else if (rate > 0x65 && rate < 0x70)
print_string("10G\t");
else
print_string("Up\t");
}
}
STAT_GET(0x2f, i); STAT_GET(0x2f, i);
print_reg(RTL837X_STAT_V_LOW); write_char('\t'); print_reg(RTL837X_STAT_V_LOW); write_char('\t');
@@ -449,14 +418,14 @@ void port_stats_print(void) __banked
void port_isolate(register uint8_t port, __xdata uint16_t pmask) void port_isolate(register uint8_t port, __xdata uint16_t pmask)
{ {
if (port <= maxPort) if (port <= machine.max_port)
REG_SET(RTL837X_PORT_ISOLATION_BASE + (port << 2), pmask); REG_SET(RTL837X_PORT_ISOLATION_BASE + (port << 2), pmask);
} }
uint16_t port_isolation_get(register uint8_t port) uint16_t port_isolation_get(register uint8_t port)
{ {
if (port > maxPort) if (port > machine.max_port)
return 0; return 0;
reg_read_m(RTL837X_PORT_ISOLATION_BASE + (port << 2)); reg_read_m(RTL837X_PORT_ISOLATION_BASE + (port << 2));
@@ -466,7 +435,7 @@ uint16_t port_isolation_get(register uint8_t port)
void port_eee_enable(uint8_t port) __banked void port_eee_enable(uint8_t port) __banked
{ {
if (is_sfp[port]) if (machine.is_sfp[port])
return; return;
REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000 | EEE_2G5); REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000 | EEE_2G5);
@@ -480,7 +449,7 @@ void port_eee_enable(uint8_t port) __banked
void port_eee_disable(uint8_t port) __banked void port_eee_disable(uint8_t port) __banked
{ {
if (is_sfp[port]) if (machine.is_sfp[port])
return; return;
print_string("EEE off for "); print_byte(port); write_char('\n'); print_string("EEE off for "); print_byte(port); write_char('\n');
@@ -495,9 +464,9 @@ void port_eee_disable(uint8_t port) __banked
void port_eee_status(uint8_t port) __banked void port_eee_status(uint8_t port) __banked
{ {
print_string("Port: "); write_char('0' + log_to_phys_port[port]); print_string("Port: "); write_char('0' + machine.log_to_phys_port[port]);
print_string(": "); print_string(": ");
if (is_sfp[port]) { if (machine.is_sfp[port]) {
print_string("SFP\n"); print_string("SFP\n");
return; return;
} }
@@ -550,7 +519,7 @@ void port_eee_status(uint8_t port) __banked
void port_eee_enable_all(void) __banked void port_eee_enable_all(void) __banked
{ {
for (uint8_t i = minPort; i <= maxPort; i++) { for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
port_eee_enable(i); port_eee_enable(i);
} }
} }
@@ -558,7 +527,7 @@ void port_eee_enable_all(void) __banked
void port_eee_disable_all(void) __banked void port_eee_disable_all(void) __banked
{ {
for (uint8_t i = minPort; i <= maxPort; i++) { for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
port_eee_disable(i); port_eee_disable(i);
} }
} }
@@ -566,7 +535,7 @@ void port_eee_disable_all(void) __banked
void port_eee_status_all(void) __banked void port_eee_status_all(void) __banked
{ {
for (uint8_t i = minPort; i <= maxPort; i++) { for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
port_eee_status(i); port_eee_status(i);
} }
} }
+19 -2
View File
@@ -1,6 +1,11 @@
#ifndef _RTL837X_REGS_H_ #ifndef _RTL837X_REGS_H_
#define _RTL837X_REGS_H_ #define _RTL837X_REGS_H_
#define RTL837X_REG_CHIP_INFO 0x000c
#define RTL837X_REG_RESET 0x0024
#define RESET_SOC_BIT 0
#define RESET_NIC_BIT 2
#define RTL837X_REG_HW_CONF 0x6040 #define RTL837X_REG_HW_CONF 0x6040
// Bits 4 & 5: CLOCK DIVIDER from 125MHz for Timer // Bits 4 & 5: CLOCK DIVIDER from 125MHz for Timer
@@ -9,10 +14,17 @@
// BIT 17 set: LED solid on // BIT 17 set: LED solid on
// Bytes 0/1 hold the LED mode, e.g. serial, RTL8231? // Bytes 0/1 hold the LED mode, e.g. serial, RTL8231?
// Blink rate is defined by setAsicRegBits(0x6520,0xe00000,rate); // Blink rate is defined by setAsicRegBits(0x6520,0xe00000,rate);
#define RTL837X_REG_LED_GLB_IO_EN 0x65DC
#define RTL837X_REG_LED3_0_SET1 0x6528
#define RTL837X_REG_LED3_2_SET0 0x6544
#define RTL837X_REG_LED1_0_SET0 0x6548
// SMI control
#define RTL837X_REG_SMI_PORT0_5_ADDR 0x644C
#define RTL837X_REG_SMI_PORT6_9_ADDR 0x6450
#define RTL837X_REG_SMI_CTRL 0x6454 #define RTL837X_REG_SMI_CTRL 0x6454
#define RTL837X_REG_RESET 0x0024 #define RTL837X_REG_SMI_MAC_TYPE 0x6330
// Writing 0x01 into this register causes a reset of the entire SoC #define RTL837X_REG_SMI_PORT_POLLING 0x6334
#define RTL837X_REG_SEC_COUNTER 0x06f4 #define RTL837X_REG_SEC_COUNTER 0x06f4
#define RTL837X_REG_SEC_COUNTER2 0x06f8 #define RTL837X_REG_SEC_COUNTER2 0x06f8
@@ -32,6 +44,7 @@
#define SDS_OFF 0x1f #define SDS_OFF 0x1f
#define RTL837X_REG_LINKS 0x63f0 #define RTL837X_REG_LINKS 0x63f0
#define RTL837X_REG_LINKS_89 0x63f4
/* Each nibble encodes the link state of a port. /* Each nibble encodes the link state of a port.
Port 0 appears to be the CPU port Port 0 appears to be the CPU port
The RTL8372 serves ports 4-7, port 3 is the RTL8221 The RTL8372 serves ports 4-7, port 3 is the RTL8221
@@ -46,6 +59,7 @@
#define RTL837X_PIN_MUX_0 0x7f8c #define RTL837X_PIN_MUX_0 0x7f8c
#define RTL837X_PIN_MUX_1 0x7f90 #define RTL837X_PIN_MUX_1 0x7f90
#define RTL837X_PIN_MUX_2 0x7f94
// Output Registers // Output Registers
#define RTL837X_REG_GPIO_00_31_OUTPUT 0x3c #define RTL837X_REG_GPIO_00_31_OUTPUT 0x3c
@@ -177,6 +191,9 @@
#define RTL837X_RMA0_CONF 0x4ecc #define RTL837X_RMA0_CONF 0x4ecc
#define RTL837X_RMA_CONF 0x4f1c #define RTL837X_RMA_CONF 0x4f1c
#define RTL837X_MSTP_STATES 0x5310 #define RTL837X_MSTP_STATES 0x5310
#define RTL837X_REG_LED_RLDP_1 0x65F8
#define RTL837X_REG_LED_RLDP_2 0x65FC
#define RTL837X_REG_LED_RLDP_3 0x65FC
/* /*
* EEE * EEE
+5 -8
View File
@@ -12,12 +12,9 @@
#include "rtl837x_regs.h" #include "rtl837x_regs.h"
#include "rtl837x_stp.h" #include "rtl837x_stp.h"
#include "uip.h" #include "uip.h"
#include "machine.h"
extern __xdata uint8_t minPort; extern __code struct machine machine;
extern __xdata uint8_t maxPort;
extern __xdata uint8_t nSFPPorts;
extern __xdata uint8_t cpuPort;
extern __xdata uint8_t isRTL8373;
extern __xdata uint8_t sfr_data[4]; extern __xdata uint8_t sfr_data[4];
extern __code struct uip_eth_addr uip_ethaddr; extern __code struct uip_eth_addr uip_ethaddr;
@@ -203,7 +200,7 @@ void stp_cnf_send(uint8_t port)
void stp_timers(void) __banked void stp_timers(void) __banked
{ {
for (uint8_t i = minPort; i <= maxPort; i++) { for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
port_hello[i]--; port_hello[i]--;
if (!port_hello[i]) { if (!port_hello[i]) {
port_hello[i] = TIME_HELLO; port_hello[i] = TIME_HELLO;
@@ -219,7 +216,7 @@ void stp_setup(void) __banked
{ {
print_string("Enabling STP: "); print_string("Enabling STP: ");
sfr_data[0] = sfr_data[1] = sfr_data[2] = sfr_data[3] = 0; sfr_data[0] = sfr_data[1] = sfr_data[2] = sfr_data[3] = 0;
for (uint8_t i = minPort; i <= maxPort; i++) { for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
// Set STP port state to blocking // Set STP port state to blocking
// States are: 00 disable, 01 blocking, 10 learning, 11 forwarding // States are: 00 disable, 01 blocking, 10 learning, 11 forwarding
uint8_t bit_mask = 0b01 << ( (i << 1) & 0x7); uint8_t bit_mask = 0b01 << ( (i << 1) & 0x7);
@@ -241,7 +238,7 @@ void stp_setup(void) __banked
void stp_off(void) __banked void stp_off(void) __banked
{ {
sfr_data[0] = sfr_data[1] = sfr_data[2] = sfr_data[3] = 0; sfr_data[0] = sfr_data[1] = sfr_data[2] = sfr_data[3] = 0;
for (uint8_t i = minPort; i <= maxPort; i++) { for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
// Set STP port state to forwarding // Set STP port state to forwarding
// States are: 00 disable, 01 blocking, 10 learning, 11 forwarding // States are: 00 disable, 01 blocking, 10 learning, 11 forwarding
uint8_t bit_mask = 0b11 << ( (i << 1) & 0x7); uint8_t bit_mask = 0b11 << ( (i << 1) & 0x7);
+161 -198
View File
@@ -15,6 +15,9 @@
#include "uip/uipopt.h" #include "uip/uipopt.h"
#include "uip/uip.h" #include "uip/uip.h"
#include "uip/uip_arp.h" #include "uip/uip_arp.h"
#include "machine.h"
extern __code const struct machine machine;
extern __xdata uint16_t crc_value; extern __xdata uint16_t crc_value;
__xdata uint8_t crc_testbytes[10]; __xdata uint8_t crc_testbytes[10];
@@ -56,8 +59,6 @@ __code struct uip_eth_addr uip_ethaddr = {{ 0x1c, 0x2a, 0xa3, 0x23, 0x00, 0x02 }
__code uint8_t gatewayIP[] = { 192, 168, 2, 22}; __code uint8_t gatewayIP[] = { 192, 168, 2, 22};
__code uint8_t netmask[] = { 255, 255, 255, 0}; __code uint8_t netmask[] = { 255, 255, 255, 0};
__xdata uint8_t isRTL8373;
volatile __xdata uint32_t ticks; volatile __xdata uint32_t ticks;
volatile __xdata uint8_t sec_counter; volatile __xdata uint8_t sec_counter;
volatile __xdata uint16_t sleep_ticks; volatile __xdata uint16_t sleep_ticks;
@@ -87,10 +88,6 @@ __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2];
__xdata uint16_t rx_packet_vlan; __xdata uint16_t rx_packet_vlan;
__xdata uint8_t tx_seq; __xdata uint8_t tx_seq;
__xdata uint8_t minPort;
__xdata uint8_t maxPort;
__xdata uint8_t nSFPPorts;
__xdata uint8_t cpuPort;
__xdata uint8_t stpEnabled; __xdata uint8_t stpEnabled;
__code uint16_t bit_mask[16] = { __code uint16_t bit_mask[16] = {
@@ -101,6 +98,7 @@ __code uint16_t bit_mask[16] = {
__xdata uint8_t was_offline; __xdata uint8_t was_offline;
__xdata uint8_t linkbits_last[4]; __xdata uint8_t linkbits_last[4];
__xdata uint8_t linkbits_last_p89;
__xdata uint8_t sfp_pins_last; __xdata uint8_t sfp_pins_last;
@@ -632,7 +630,7 @@ void sds_config_mac(uint8_t sds, uint8_t mode)
case 2: case 2:
sfr_mask_data(1, 0xfc, 0x02 << 2); sfr_mask_data(1, 0xfc, 0x02 << 2);
} }
if (isRTL8373) // Set 3rd SERDES Mode to 0x2 for RTL8224 if (machine.isRTL8373) // Set 3rd SERDES Mode to 0x2 for RTL8224
sfr_mask_data(1, 0xfc, 0x02 << 2); sfr_mask_data(1, 0xfc, 0x02 << 2);
else else
sfr_data[2] &= 0x03; sfr_data[2] &= 0x03;
@@ -676,9 +674,6 @@ void sds_config(uint8_t sds, uint8_t mode)
uint8_t page = 0; uint8_t page = 0;
uint16_t v = 0; uint16_t v = 0;
print_string("\nTrying to set SDS mode to 0x");
print_byte(mode);
print_string("\n");
switch (mode) { switch (mode) {
case SDS_SGMII: case SDS_SGMII:
@@ -749,7 +744,7 @@ void sds_config(uint8_t sds, uint8_t mode)
*/ */
uint8_t sfp_read_reg(uint8_t slot, uint8_t reg) uint8_t sfp_read_reg(uint8_t slot, uint8_t reg)
{ {
if (slot == 0) { if (machine.sfp_port[slot].i2c == 0) {
reg_read_m(RTL837X_REG_I2C_CTRL); reg_read_m(RTL837X_REG_I2C_CTRL);
sfr_mask_data(1, 0xfc, SCL_PIN << 5 | SDA_PIN_0 << 2); sfr_mask_data(1, 0xfc, SCL_PIN << 5 | SDA_PIN_0 << 2);
reg_write_m(RTL837X_REG_I2C_CTRL); reg_write_m(RTL837X_REG_I2C_CTRL);
@@ -906,7 +901,10 @@ static inline uint8_t sfp_rate_to_sds_config(register uint8_t rate)
void sfp_print_info(uint8_t sfp) void sfp_print_info(uint8_t sfp)
{ {
// This loops over the Vendor-name, Vendor OUI, Vendor PN and Vendor rev ASCII fields
for (uint8_t i = 20; i < 60; i++) { for (uint8_t i = 20; i < 60; i++) {
if (i >= 36 && i < 40) // Skip Non-ASCII codes
continue;
uint8_t c = sfp_read_reg(sfp, i); uint8_t c = sfp_read_reg(sfp, i);
if (c) if (c)
write_char(c); write_char(c);
@@ -915,55 +913,48 @@ void sfp_print_info(uint8_t sfp)
} }
bool gpio_pin_test(uint8_t pin)
{
reg_read_m(RTL837X_REG_GPIO_00_31_INPUT + (pin > 31 ? 4 : 0));
return sfr_data[3-((pin >> 3) & 3)] & (1 << (pin & 7));
}
void handle_sfp(void) void handle_sfp(void)
{ {
reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); for (uint8_t sfp = 0; sfp < machine.n_sfp; sfp++) {
if ((sfp_pins_last & 0x1) && (!(sfr_data[0] & 0x40))) { if (!gpio_pin_test(machine.sfp_port[sfp].pin_detect)) {
sfp_pins_last &= ~0x01; if (sfp_pins_last & (0x1 << (sfp << 2))) {
print_string("\n<MODULE INSERTED> "); sfp_pins_last &= ~(0x01 << (sfp << 2));
print_string("\n<MODULE INSERTED> Slot: "); write_char('1' + sfp);
// Read Reg 11: Encoding, see SFF-8472 and SFF-8024 // Read Reg 11: Encoding, see SFF-8472 and SFF-8024
// Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit // Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit
delay(100); // Delay, because some modules need time to wake up delay(100); // Delay, because some modules need time to wake up
uint8_t rate = sfp_read_reg(0, 12); uint8_t rate = sfp_read_reg(sfp, 12);
print_string("Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored? print_string(" Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored?
print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11)); print_string(" Encoding: "); print_byte(sfp_read_reg(sfp, 11));
print_string(" Module: "); sfp_print_info(sfp);
print_string("\n"); print_string("\n");
print_string("\n"); sds_config(machine.sfp_port[sfp].sds, sfp_rate_to_sds_config(rate));
sfp_print_info(0); }
sds_config(1, sfp_rate_to_sds_config(rate)); } else {
if (!(sfp_pins_last & (0x1 << (sfp << 2)))) {
sfp_pins_last |= 0x01 << (sfp << 2);
print_string("\n<MODULE REMOVED> Slot: "); write_char('1' + sfp); write_char('\n');
} }
if ((!(sfp_pins_last & 0x1)) && (sfr_data[0] & 0x40)) {
sfp_pins_last |= 0x01;
print_string("\n<MODULE REMOVED>\n");
} }
reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); if (!gpio_pin_test(machine.sfp_port[sfp].pin_los)) {
if ((sfp_pins_last & 0x2) && (!(sfr_data[3] & 0x20))) { if (sfp_pins_last & (0x2 << (sfp << 2))) { // 0x2 0x08
sfp_pins_last &= ~0x02; sfp_pins_last &= ~(0x02 << (sfp << 2));
print_string("\n<SFP-RX OK>\n"); print_string("\n<SFP-RX OK> Slot: "); write_char('1' + sfp); write_char('\n');
} }
if ((!(sfp_pins_last & 0x2)) && (sfr_data[3] & 0x20)) { } else {
sfp_pins_last |= 0x02; if (!(sfp_pins_last & 0x2 << (sfp << 2))) {
print_string("\n<SFP-RX LOS>\n"); sfp_pins_last |= 0x02 << (sfp << 2);
print_string("\n<SFP-RX LOS> Slot: "); write_char('1' + sfp); write_char('\n');
} }
reg_read_m(RTL837X_REG_GPIO_32_63_INPUT);
if ((sfp_pins_last & 0x10) && (!(sfr_data[1] & 0x04))) {
sfp_pins_last &= ~0x10;
print_string("\n<MODULE 2 INSERTED> ");
// Read Reg 11: Encoding, see SFF-8472 and SFF-8024
// Read Reg 12: Signalling rate (including overhead) in 100Mbit: 0xd: 1Gbit, 0x67:10Gbit
delay(100); // Delay, because some modules need time to wake up
uint8_t rate = sfp_read_reg(1, 12);
print_string("Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored?
print_string(" Encoding: "); print_byte(sfp_read_reg(1, 11));
print_string("\n");
sfp_print_info(1);
sds_config(0, sfp_rate_to_sds_config(rate));
} }
if ((!(sfp_pins_last & 0x10)) && (sfr_data[1] & 0x04)) {
sfp_pins_last |= 0x10;
print_string("\n<MODULE 2 REMOVED>\n");
} }
} }
@@ -1006,17 +997,25 @@ void idle(void)
#endif #endif
} }
// Check for Link changes
reg_read_m(RTL837X_REG_LINKS_89);
__xdata uint8_t linkbits_p89 = sfr_data[3];
reg_read_m(RTL837X_REG_LINKS); reg_read_m(RTL837X_REG_LINKS);
if (!isRTL8373 && cmp_4(sfr_data, linkbits_last)) { if (cmp_4(sfr_data, linkbits_last) || (linkbits_p89 != linkbits_last_p89)) {
print_string("\n<new link: "); print_string("\n<new link: ");
print_long_x(sfr_data); print_byte(linkbits_p89); print_byte(sfr_data[0]); print_byte(sfr_data[1]);
print_byte(sfr_data[2]); print_byte(sfr_data[3]);
print_string(", was "); print_string(", was ");
print_long_x(linkbits_last); print_byte(linkbits_last_p89); print_byte(linkbits_last[0]); print_byte(linkbits_last[1]);
print_byte(linkbits_last[2]); print_byte(linkbits_last[3]);
print_string(">\n"); print_string(">\n");
if (nSFPPorts != 2) { linkbits_last_p89 = linkbits_p89;
if (!machine.isRTL8373 && machine.n_sfp != 2) {
uint8_t p5 = sfr_data[2] >> 4; uint8_t p5 = sfr_data[2] >> 4;
uint8_t p5_last = linkbits_last[2] >> 4; uint8_t p5_last = linkbits_last[2] >> 4;
cpy_4(linkbits_last, sfr_data); cpy_4(linkbits_last, sfr_data);
// Handle link change of the RTL8221 PHY, adjust SDS mode
if (p5_last != p5) { if (p5_last != p5) {
if (p5 == 0x5) // 2.5GBit Mode if (p5 == 0x5) // 2.5GBit Mode
sds_config(0, SDS_HISGMII); sds_config(0, SDS_HISGMII);
@@ -1029,7 +1028,6 @@ void idle(void)
} }
// Check for changes with SFP modules // Check for changes with SFP modules
handle_sfp(); handle_sfp();
/* Button pressed on KL-8xhm-x2: /* Button pressed on KL-8xhm-x2:
@@ -1217,12 +1215,13 @@ void phy_modify(uint8_t phy_id, uint8_t dev_id, uint16_t reg, uint16_t mask, uin
// Modify the reed data. // Modify the reed data.
// TODO: Check if we directly can modify SFR register directly. // TODO: Check if we directly can modify SFR register directly.
uint16_t data = SFR_DATA_U16 & ~(mask); uint16_t data = SFR_DATA_U16 & ~(mask);
data |= ~(set); data |= set;
uint16_t phy_mask = bit_mask[phy_id]; uint16_t phy_mask = bit_mask[phy_id];
// Write it back // Write it back
SFR_SMI_REG_U16 = data; SFR_SMI_REG_U16 = reg;
SFR_DATA_U16 = data;
SFR_SMI_PHYMASK = phy_mask; // SFR_C5 SFR_SMI_PHYMASK = phy_mask; // SFR_C5
SFR_SMI_DEV = smi_phy | (phy_mask >> 8); SFR_SMI_DEV = smi_phy | (phy_mask >> 8);
SFR_EXEC_GO = SFR_EXEC_WRITE_SMI; SFR_EXEC_GO = SFR_EXEC_WRITE_SMI;
@@ -1323,46 +1322,35 @@ void led_config_9xh(void)
reg_bit_set(0x65d8, 0x1d); reg_bit_set(0x65d8, 0x1d);
// r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0 // r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0
reg_read_m(0x6520); reg_read_m(RTL837X_REG_LED_MODE);
sfr_mask_data(1, 0x1f, 0x6); sfr_mask_data(1, 0x1f, 0x6);
sfr_mask_data(0, 0xe0, 0xa0); sfr_mask_data(0, 0xe0, 0xa0);
reg_write_m(0x6520); reg_write_m(RTL837X_REG_LED_MODE);
// r65f8:00000018 R65f8-0000001b // Disable RLDP (Realtek Loop Detection Protocol) LEDs on loop detection
reg_read_m(0x65f8); reg_read_m(RTL837X_REG_LED_RLDP_1);
sfr_mask_data(0, 0, 0x3); sfr_mask_data(0, 0, 0x3);
reg_write_m(0x65f8); reg_write_m(RTL837X_REG_LED_RLDP_1);
// Configure LED group for RLDP per port
REG_SET(RTL837X_REG_LED_RLDP_2, 0xffffffff); // Ports 0-7
REG_SET(RTL837X_REG_LED_RLDP_3, 0x0000000f); // Port 8
// R65fc-ffffffff reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29);
REG_SET(0x65fc, 0xffffffff); reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 27);
// Set bits 0-3 of 0x6600 to 0xf // GPIO 27 is LED
// r6600:00000000 R6600-0000000f reg_bit_set(RTL837X_PIN_MUX_0, 27);
reg_read_m(0x6600);
sfr_mask_data(0, 0, 0x0f);
reg_write_m(0x6600);
// Set bit 0x1d of 0x65dc, clear bit 1b: r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00 // Configure LED_SET_0, ledid 0/1
reg_bit_set(0x65dc, 0x1d); REG_SET(RTL837X_REG_LED1_0_SET0, 0x0041017f);
reg_bit_clear(0x65dc, 0x1b);
// r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000
reg_bit_set(RTL837X_PIN_MUX_0, 0x1b);
// R6548-0041017f
REG_SET(0x6548, 0x0041017f);
// Configure LED_SET_0 ledid 2 // Configure LED_SET_0 ledid 2
// r6544:01411000 R6544-01410044 REG_SET(RTL837X_REG_LED3_2_SET0, 0x01410044);
reg_read_m(0x6544);
sfr_data[2] = 0x00;
sfr_data[3] = 0x44;
reg_write_m(0x6544);
// r6528:00000000 R6528-0000000f // r6528:00000000 R6528-0000000f
reg_read_m(0x6528); reg_read_m(RTL837X_REG_LED3_0_SET1);
sfr_mask_data(0, 0x0f, 0x0f); sfr_mask_data(0, 0x0f, 0x0f);
reg_write_m(0x6528); reg_write_m(RTL837X_REG_LED3_0_SET1);
} }
@@ -1377,109 +1365,62 @@ void led_config(void)
sfr_data[3] = 0xb0; sfr_data[3] = 0xb0;
reg_write_m(RTL837X_REG_LED_MODE); reg_write_m(RTL837X_REG_LED_MODE);
// Clear bits 0,1 of 0x65f8 // Disable RLDP (Realtek Loop Detection Protocol) LEDs on loop detection
// r65f8:00000018 R65f8-00000018 reg_read_m(RTL837X_REG_LED_RLDP_1);
reg_read_m(0x65f8);
sfr_mask_data(0, 0x03, 0); sfr_mask_data(0, 0x03, 0);
reg_write_m(0x65f8); reg_write_m(RTL837X_REG_LED_RLDP_1);
// Configure LED group for RLDP per port
REG_SET(RTL837X_REG_LED_RLDP_2, 0xffffffff); // Ports 0-7
REG_SET(RTL837X_REG_LED_RLDP_3, 0x0000000f); // Port 8
// Set 0x65fc to 0xfffff000 reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29);
// R65fc-fffff000 reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 27);
REG_SET(0x65fc, 0xfffff000);
// Set bits 0-3 of 0x6600 to 0xf // Configure GPIO for LEDs 27-29
// r6600:00000000 R6600-0000000f if (machine.n_sfp == 2) {
reg_read_m(0x6600); reg_bit_set(RTL837X_PIN_MUX_0, 27);
sfr_mask_data(0, 0, 0x0f); reg_bit_clear(RTL837X_PIN_MUX_0, 28);
reg_write_m(0x6600); reg_bit_set(RTL837X_PIN_MUX_0, 29);
// Set bit 0x1d of 0x65dc, clear bit 1b: r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00
reg_bit_set(0x65dc, 0x1d);
reg_bit_clear(0x65dc, 0x1b);
// Set bits 1b/1d of 0x7f8c: r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000
if (nSFPPorts == 2) {
reg_bit_set(RTL837X_PIN_MUX_0, 0x1b); // R7f8c-28000000
reg_bit_clear(RTL837X_PIN_MUX_0, 0x1c); // R7f8c-28000000
reg_bit_set(RTL837X_PIN_MUX_0, 0x1d); // R7f8c-28000000
} else { } else {
reg_bit_set(RTL837X_PIN_MUX_0, 0x1d); reg_bit_set(RTL837X_PIN_MUX_0, 27);
reg_bit_set(RTL837X_PIN_MUX_0, 0x1c); reg_bit_set(RTL837X_PIN_MUX_0, 28);
reg_bit_set(RTL837X_PIN_MUX_0, 0x1b); reg_bit_set(RTL837X_PIN_MUX_0, 29);
} }
// LED setup // LED setup
// r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0 r65f8:00000018 R65f8-00000018 R65fc-fffff000 r6600:00000000 R6600-0000000f r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00 // r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0 r65f8:00000018 R65f8-00000018 R65fc-fffff000 r6600:00000000 R6600-0000000f r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00
// r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000 R6548-00410175 r6544:01411000 R6544-01410044 r6528:00000000 R6528-00000011 r6450:000020e6 R6450-000000e6 r644c:0a418820 R644c-0a400820 // r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000 R6548-00410175 r6544:01411000 R6544-01410044 r6528:00000000 R6528-00000011
// Configure LED_SET_0, ledid 0/1 // Configure LED_SET_0, ledid 0/1
// R6548-00410175 REG_SET(RTL837X_REG_LED1_0_SET0, 0x00410175);
REG_SET(0x6548, 0x00410175);
// Configure LED_SET_0 ledid 2 // Configure led-sets 2 and 3
// 6544:01411000 R6544-01410044 REG_SET(RTL837X_REG_LED3_2_SET0, 0x01410044);
reg_read_m(0x6544);
sfr_data[2] = 0x00;
sfr_data[3] = 0x44;
reg_write_m(0x6544);
// Further configure LED_SET_0 // Further configure LED_SET_0
// r6528:00000000 R6528-00000011 // r6528:00000000 R6528-00000011
reg_read_m(0x6528); reg_read_m(RTL837X_REG_LED3_0_SET1);
sfr_data[3] = 0x11; sfr_data[3] = 0x11;
reg_write_m(0x6528); reg_write_m(RTL837X_REG_LED3_0_SET1);
reg_read_m(0x6450);
sfr_mask_data(1, 0x7c, 0);
reg_write_m(0x6450);
// SDS bits f-13 set to 0: r644c:0a418820 R644c-0a400820
reg_read_m(0x644c);
sfr_mask_data(2, 0x0f, 0);
sfr_mask_data(1, 0x80, 0);
reg_write_m(0x644c);
} }
void rtl8373_revision(void) void rtl8373_revision(void)
{ {
// r000c:00300000 R000c-003a0000 r000c:203a6818 r000c:203a6818 R000c-20306818 reg_read_m(RTL837X_REG_CHIP_INFO);
reg_read_m(0x000c);
sfr_mask_data(2, 0x0a, 0x0a); // Enable reading version sfr_mask_data(2, 0x0a, 0x0a); // Enable reading version
reg_write_m(0x000c); reg_write_m(RTL837X_REG_CHIP_INFO);
delay(50); delay(50);
reg_read_m(0x000c); reg_read_m(RTL837X_REG_CHIP_INFO);
print_string("CPU revision: "); print_byte(sfr_data[2]); print_byte(sfr_data[2]); write_char('\n'); 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 sfr_mask_data(2, 0x0a, 0x00); // Enable reading version
reg_write_m(0x000c); reg_write_m(RTL837X_REG_CHIP_INFO);
} }
void rtl8373_init(void) void rtl8373_init(void)
{ {
print_string("\nrtl8373_init called\n"); print_string("\nrtl8373_init called\n");
minPort = 0;
maxPort = 8;
cpuPort = 9;
nSFPPorts = 1;
// r6330:00015555 R6330-00005555 r6330:00005555 R6330-00005555
REG_SET(0x6330, 0x00005555);
// r6334:00000000 R6334-000001f8 RTL8373: r6334:00000000 R6334-000000ff
reg_read_m(0x6334); // Also in sdsMode_set
sfr_mask_data(0, 0, 0xff);
reg_write_m(0x6334);
// Enable MDC
// r6454:00000000 R6454-00007000 RTL837X_REG_SMI_CTRL
reg_read_m(RTL837X_REG_SMI_CTRL);
sfr_mask_data(1, 0, 0x70); // Set bits 0xc-0xe to enable MDC for SMI0-SMI2
reg_write_m(RTL837X_REG_SMI_CTRL);
delay(50);
rtl8373_revision();
led_config_9xh(); led_config_9xh();
sds_init(); sds_init();
@@ -1534,10 +1475,12 @@ void rtl8373_init(void)
// r0b7c:000000d8 R0b7c-000000f8 r6040:00000030 R6040-00000031 // r0b7c:000000d8 R0b7c-000000f8 r6040:00000030 R6040-00000031
reg_bit_set(0xb7c, 5); reg_bit_set(0xb7c, 5);
// R7124-00001050 R7128-00001050 R712c-00001050 R7130-00001050 R7134-00001050 R7138-00001050
// R7124-00001050 R7128-00001050 R712c-00001050 R7130-00001050 R7134-00001050 R7138-00001050 R713c-00001050 R7140-00001050 R7144-00001050 R7148-00001050 // R713c-00001050 R7140-00001050 R7144-00001050 R7148-00001050
REG_SET(0x7124, 0x1050); REG_SET(0x7128, 0x1050); REG_SET(0x712c, 0x1050); REG_SET(0x7130, 0x1050); REG_SET(0x7134, 0x1050); REG_SET(0x7138, 0x1050); REG_SET(0x713c, 0x1050); REG_SET(0x7124, 0x1050); REG_SET(0x7128, 0x1050); REG_SET(0x712c, 0x1050);
REG_SET(0x7140, 0x1050); REG_SET(0x7144, 0x1050); REG_SET(0x7148, 0x1050); REG_SET(0x7130, 0x1050); REG_SET(0x7134, 0x1050); REG_SET(0x7138, 0x1050);
REG_SET(0x713c, 0x1050); REG_SET(0x7140, 0x1050); REG_SET(0x7144, 0x1050);
REG_SET(0x7148, 0x1050);
reg_bit_set(RTL837X_REG_HW_CONF, 0); reg_bit_set(RTL837X_REG_HW_CONF, 0);
@@ -1554,7 +1497,6 @@ void rtl8373_init(void)
sfr_mask_data(2, 0x10, 0x1f); sfr_mask_data(2, 0x10, 0x1f);
reg_write_m(0x632c); reg_write_m(0x632c);
REG_SET(0x7f94, 0);
print_string("\nrtl8373_init done\n"); print_string("\nrtl8373_init done\n");
} }
@@ -1562,36 +1504,9 @@ void rtl8373_init(void)
void rtl8372_init(void) void rtl8372_init(void)
{ {
print_string("\nrtl8372_init called\n"); print_string("\nrtl8372_init called\n");
minPort = 3;
maxPort = 8;
cpuPort = 9;
nSFPPorts = NSFP;
// r6330:00015555 R6330-00005555 r6330:00005555 R6330-00005555
REG_SET(0x6330, 0x00005555);
if (nSFPPorts == 2) {
print_string("Configuring 2nd SFP+ port\n");
REG_SET(0x6330, 0x00005515);
}
// r6334:00000000 R6334-000001f8 RTL8373: r6334:00000000 R6334-000000ff
reg_read_m(0x6334); // Also in sdsMode_set
if (nSFPPorts == 2) {
sfr_mask_data(0, 0, 0xf0);
} else {
sfr_mask_data(1, 0, 0x01); // Set bits 3-8, On RTL8373+8224 set bits 0-7
sfr_mask_data(0, 0, 0xf8);
}
reg_write_m(0x6334);
// Enable MDC
// r6454:00000000 R6454-00007000 RTL837X_REG_SMI_CTRL
reg_read_m(RTL837X_REG_SMI_CTRL);
sfr_mask_data(1, 0, 0x70); // Set bits 0xc-0xe to enable MDC for SMI0-SMI2
reg_write_m(RTL837X_REG_SMI_CTRL);
delay(50);
led_config(); led_config();
sds_init(); sds_init();
phy_config(8); // PHY configuration: External 8221B? phy_config(8); // PHY configuration: External 8221B?
phy_config(3); // PHY configuration: all internal PHYs? phy_config(3); // PHY configuration: all internal PHYs?
@@ -1621,7 +1536,7 @@ void rtl8372_init(void)
// [...] // [...]
/// ///
uint16_t reg = 0x1238 + 0x300; // Port base register for the bits we set uint16_t reg = 0x1238 + 0x300; // Port base register for the bits we set
for (char i = minPort; i <= maxPort; i++) { for (char i = machine.min_port; i <= machine.max_port; i++) {
// Bit 7 (0x40) enables replacement of the RTL-VLAN tag with an 802.1Q VLAN tag // Bit 7 (0x40) enables replacement of the RTL-VLAN tag with an 802.1Q VLAN tag
REG_SET(reg, 0xe77); REG_SET(reg, 0xe77);
reg += 0x100; reg += 0x100;
@@ -1648,6 +1563,50 @@ void rtl8372_init(void)
} }
/*
* 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)
{
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
*/
REG_SET(RTL837X_REG_SMI_MAC_TYPE, machine.n_sfp == 2 ? 0x00005515 : 0x00005555);
// Configure polling of all PHYs by the MAC to detect link-state changes
if (machine.isRTL8373) {
REG_SET(RTL837X_REG_SMI_PORT_POLLING, 0xff);
} else {
REG_SET(RTL837X_REG_SMI_PORT_POLLING, machine.n_sfp == 2 ? 0xf0 : 0x1f8);
}
// 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.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);
}
}
/* Set up serial port 0 using Timer 2 with an external trigger /* Set up serial port 0 using Timer 2 with an external trigger
* as baud generator. * as baud generator.
* The external clock generator uses a crystal at 25MHz. * The external clock generator uses a crystal at 25MHz.
@@ -1720,17 +1679,19 @@ void bootloader(void)
// Set default for SFP pins so we can start up a module already inserted // Set default for SFP pins so we can start up a module already inserted
sfp_pins_last = 0x33; // signal LOS and no module inserted (for both slots, even if only 1 present) sfp_pins_last = 0x33; // signal LOS and no module inserted (for both slots, even if only 1 present)
// We have not detected any link // We have not detected any link
linkbits_last[0] = linkbits_last[1] = linkbits_last[2] = linkbits_last[3] = 0; linkbits_last[0] = linkbits_last[1] = linkbits_last[2] = linkbits_last[3] = linkbits_last_p89 = 0;
print_string("Detecting CPU: "); print_string("Detecting CPU: ");
isRTL8373 = 0;
reg_read_m(0x4); reg_read_m(0x4);
if (sfr_data[1] == 0x73) { // Register was 0x83730000 if (sfr_data[1] == 0x73) { // Register was 0x83730000
print_string("RTL8373\n"); print_string("RTL8373\n");
isRTL8373 = 1; if (!machine.isRTL8373)
print_string("INCORRECT MACHINE!");
rtl8224_enable(); // Power on the RTL8224 rtl8224_enable(); // Power on the RTL8224
} else { } else {
print_string("RTL8372\n"); print_string("RTL8372\n");
if (machine.isRTL8373)
print_string("INCORRECT MACHINE!");
} }
// Print SW version // Print SW version
@@ -1741,18 +1702,20 @@ void bootloader(void)
flash_init(0); flash_init(0);
// Reset NIC // Reset NIC
reg_bit_set(0x24, 2); reg_bit_set(RTL837X_REG_RESET, RESET_NIC_BIT);
do { do {
reg_read(0x24); reg_read(RTL837X_REG_RESET);
} while (SFR_DATA_0 & 0x4); } while (SFR_DATA_0 & (1 << RESET_NIC_BIT));
print_string("NIC reset\n"); print_string("NIC reset\n");
uip_ipaddr(&uip_hostaddr, ownIP[0], ownIP[1], ownIP[2], ownIP[3]); uip_ipaddr(&uip_hostaddr, ownIP[0], ownIP[1], ownIP[2], ownIP[3]);
uip_ipaddr(&uip_draddr, gatewayIP[0], gatewayIP[1], gatewayIP[2], gatewayIP[3]); uip_ipaddr(&uip_draddr, gatewayIP[0], gatewayIP[1], gatewayIP[2], gatewayIP[3]);
uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]); uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]);
REG_SET(0x7f94, 0x0); REG_SET(RTL837X_PIN_MUX_2, 0x0); // Disable pins for ACL
if (isRTL8373) init_smi();
rtl8373_revision();
if (machine.isRTL8373)
rtl8373_init(); rtl8373_init();
else else
rtl8372_init(); rtl8372_init();