diff --git a/Makefile b/Makefile index f6987b9..abf61de 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)rtlplayground.bin create_build_dir: 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 += 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 diff --git a/cmd_parser.c b/cmd_parser.c index 3794f2e..f59c427 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -15,13 +15,12 @@ #include "uip/uip.h" #include "version.h" +#include "machine.h" + #pragma codeseg BANK1 #pragma constseg BANK1 -extern __xdata uint8_t minPort; -extern __xdata uint8_t maxPort; -extern __xdata uint8_t nSFPPorts; -extern __xdata uint8_t isRTL8373; +extern __code struct machine machine; extern __xdata uint16_t mpos; extern __xdata uint8_t stpEnabled; 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 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) { @@ -205,10 +199,7 @@ void parse_lag(void) print_string(" member ports: "); for (uint8_t j = 0; j < 10; j++) { if (members & 1) { - if (!isRTL8373) - write_char('0' + log_to_phys_port[j]); - else - write_char('1' + j); + write_char('0' + machine.log_to_phys_port[j]); write_char(' '); } members >>= 1; @@ -233,12 +224,11 @@ void parse_lag(void) port = 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'; - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; } else { goto err; } - if (port > maxPort) + if (port > machine.max_port) goto err; members |= ((uint16_t)1) << port; w++; @@ -321,12 +311,11 @@ void parse_vlan(void) if (cmd_buffer[cmd_words_b[w] + 2] == 't') tagged |= ((uint16_t)1) << port; } else { - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; if (cmd_buffer[cmd_words_b[w] + 1] == 't') tagged |= ((uint16_t)1) << port; } - if (port > maxPort) + if (port > machine.max_port) goto err; members |= ((uint16_t)1) << port; } @@ -359,10 +348,7 @@ void parse_mirror(void) print_string("NOT Enabled: "); } print_string("Mirroring port: "); - if (!isRTL8373) - write_char('0' + log_to_phys_port[mPort >> 1]); - else - write_char('0' + (mPort >> 1) + 1); + write_char('0' + machine.log_to_phys_port[mPort >> 1]); reg_read_m(RTL837x_MIRROR_CONF); uint16_t m = sfr_data[0]; m = (m << 8) | sfr_data[1]; @@ -387,8 +373,7 @@ void parse_mirror(void) mirroring_port = 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'; - if (!isRTL8373) - mirroring_port = phys_to_log_port[mirroring_port]; + mirroring_port = machine.phys_to_log_port[mirroring_port]; uint8_t w = 2; while (cmd_words_b[w] > 0) { @@ -397,8 +382,7 @@ void parse_mirror(void) port = 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'; - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; if (cmd_buffer[cmd_words_b[w] + 2] == 'r') rx_pmask |= ((uint16_t)1) << port; else if (cmd_buffer[cmd_words_b[w] + 2] == 't') @@ -408,8 +392,7 @@ void parse_mirror(void) tx_pmask |= ((uint16_t)1) << port; } } else { - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; if (cmd_buffer[cmd_words_b[w] + 1] == 'r') rx_pmask |= ((uint16_t)1) << port; 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) { uint16_t reg = 0; @@ -627,18 +657,19 @@ void cmd_parser(void) __banked print_string("\nRESET\n\n"); reset_chip(); } else if (cmd_compare(0, "sfp")) { - uint8_t rate = sfp_read_reg(0, 12); - print_string("\nRate: "); print_byte(rate); + print_string("\nSlot 1 - Rate: "); print_byte(sfp_read_reg(0, 12)); print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11)); print_string("\n"); - for (uint8_t i = 20; i < 60; i++) { - uint8_t c = sfp_read_reg(0, i); - if (c) - write_char(c); + sfp_print_info(0); + if (machine.n_sfp == 2) { + print_string("\nSlot 2 - Rate: "); print_byte(sfp_read_reg(1, 12)); + print_string(" Encoding: "); print_byte(sfp_read_reg(1, 11)); + print_string("\n"); + sfp_print_info(1); } } else if (cmd_compare(0, "stat")) { port_stats_print(); - } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') { + } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') { print_string("\nPRINT SECURITY REGISTERS\n"); // The following will only show something else than 0xff if it was programmed for a managed switch flash_region.addr = 0x0001000; @@ -680,25 +711,7 @@ void cmd_parser(void) __banked flash_region.len = 20; flash_write_bytes(flash_buf); } else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) { - print_string("\nPORT "); - 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); - } + parse_port(); } else if (cmd_compare(0, "ip")) { print_string("Got ip command: "); if (!parse_ip(cmd_words_b[1])) @@ -742,8 +755,7 @@ void cmd_parser(void) __banked __xdata uint16_t pvid; uint8_t port; port = cmd_buffer[cmd_words_b[1]] - '1'; - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; if (!atoi_short(&pvid, cmd_words_b[2])) port_pvid_set(port, pvid); } else if (cmd_compare(0, "vlan")) { @@ -770,8 +782,7 @@ void cmd_parser(void) __banked int8_t port = -1; if (cmd_words_b[3] > 0) { port = cmd_buffer[cmd_words_b[2]] - '1'; - if (!isRTL8373) - port = phys_to_log_port[port]; + port = machine.phys_to_log_port[port]; } if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) { if (port >= 0) diff --git a/doc/devices/SWTG024AS.md b/doc/devices/SWTG024AS.md index 5c7e40a..6554e7b 100644 --- a/doc/devices/SWTG024AS.md +++ b/doc/devices/SWTG024AS.md @@ -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. # Connectors + +## J4 + +* Location: Left SFP connector `J4`. +* Connected to: 10GMAC number 8, second SDS. + |`J4` SFP1 PINs | Signal | Component | GPIO | Notes | |---|---|---|---|---| |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 | | |9| TO? | B-R256 | --- | | +## J2 + +* Location: Right SFP connector `J2`. +* Connected to: 10GMAC number 3, first SDS. + |`J2` SFP2 PINs | Signal | Component | GPIO | Notes | |---|---|---|---|---| |2| TX_FAULT | B-R70 | --- | | diff --git a/html/main.js b/html/main.js index eac133e..5d5246e 100644 --- a/html/main.js +++ b/html/main.js @@ -2,7 +2,7 @@ var txG = new BigInt64Array(10); var txB = new BigInt64Array(10); var rxG = 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 pIsSFP = new Int8Array(10); var numPorts = 0; @@ -40,9 +40,9 @@ function update() { } else { psvg.style.opacity = 1.0; 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"; - } 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"; } else { leds[0].style.fill = "black"; leds[1].style.fill = "black"; diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 21c4b38..0b97815 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -10,11 +10,13 @@ #include #include "../phy.h" #include "../version.h" +#include "../machine.h" #include "page_impl.h" #pragma codeseg BANK1 #pragma constseg BANK1 +extern __code const struct machine machine; extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE]; extern __xdata uint16_t slen; extern __xdata uint16_t cont_len; @@ -22,15 +24,8 @@ extern __xdata uint32_t cont_addr; extern __code uint8_t * __code hex; extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; 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 cpuPort; -extern __xdata uint8_t isRTL8373; extern __xdata uint8_t sfp_pins_last; 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(); } + +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) { slen = strtox(outbuf, HTTP_RESPONCE_JSON); @@ -167,7 +176,17 @@ void send_basic_info(void) byte_to_html(uip_ethaddr.addr[5]); slen += strtox(outbuf + slen, "\",\"sw_ver\":\""); 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"); 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\":"); itoa_html(i + 1); for (uint8_t j = 0; j < 0x3f; j++) { @@ -226,10 +245,7 @@ void send_mirror(void) } else { slen += strtox(outbuf + slen, "{\"enabled\":0,\"mPort\":"); } - if (!isRTL8373) - itoa_html(log_to_phys_port[mPort >> 1]); - else - itoa_html((mPort >> 1) + 1); + itoa_html(machine.log_to_phys_port[mPort >> 1]); reg_read_m(RTL837x_MIRROR_CONF); uint16_t m = sfr_data[0]; @@ -286,14 +302,11 @@ void send_eee(void) uint8_t eee_ablty = sfr_data[3]; 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\":"); - if (!isRTL8373) - itoa_html(log_to_phys_port[i]); - else - itoa_html(i + 1); + itoa_html(machine.log_to_phys_port[i]); - if (IS_SFP(i)) { + if (machine.is_sfp[i]) { slen += strtox(outbuf + slen, ",\"isSFP\":1"); } else { slen += strtox(outbuf + slen, ",\"isSFP\":0,\"eee\":\""); @@ -321,7 +334,7 @@ void send_eee(void) bool_to_html(eee_ablty & (1 << i)); } char_to_html('}'); - if (i < maxPort) + if (i < machine.max_port) char_to_html(','); else char_to_html(']'); @@ -335,38 +348,29 @@ void send_status(void) print_string("sending status\n"); 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\":"); - if (!isRTL8373) - itoa_html(log_to_phys_port[i]); - else - itoa_html(i + 1); - - if (IS_SFP(i)) { - slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":"); - bool_to_html(!((sfp_pins_last >> (i == maxPort ? 0 : 4)) & 1)); - - 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 ??? + itoa_html(machine.log_to_phys_port[i]); + + if (machine.is_sfp[i]) { + slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":"); + bool_to_html(!(sfp_pins_last & (0x1 << ((machine.is_sfp[i] - 1) << 2)))); } else { - slen += strtox(outbuf + slen, ",\"isSFP\":0,\"enabled\":"); + slen += strtox(outbuf + slen, ",\"isSFP\":0,\"enabled\":"); phy_read(i, 0x1f, 0xa610); 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); - uint8_t b = sfr_data[3 - (i >> 1)]; - b = (i & 1) ? b >> 4 : b & 0xf; - char_to_html('0' + b); - } + else + reg_read_m(RTL837X_REG_LINKS_89); + uint8_t b = sfr_data[3 - ((i & 7) >> 1)]; + b = (i & 1) ? b >> 4 : b & 0xf; + char_to_html('0' + b); + STAT_GET(STAT_COUNTER_TX_PKTS, i); slen += strtox(outbuf + slen, ",\"txG\":\"0x"); reg_to_html(RTL837X_STAT_V_HIGH); @@ -385,7 +389,7 @@ void send_status(void) STAT_GET(STAT_COUNTER_ERR_PKTS, i); reg_to_html(RTL837X_STAT_V_HIGH); // 32bit RX packet errors slen += strtox(outbuf + slen, "\"}"); - if (i < maxPort) + if (i < machine.max_port) char_to_html(','); else char_to_html(']'); diff --git a/machine.c b/machine.c new file mode 100644 index 0000000..d0275a1 --- /dev/null +++ b/machine.c @@ -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 diff --git a/machine.h b/machine.h new file mode 100644 index 0000000..aa518bd --- /dev/null +++ b/machine.h @@ -0,0 +1,42 @@ +#ifndef _MACHINE_H_ +#define _MACHINE_H_ + +#include + +/* + * 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 + diff --git a/phy.h b/phy.h index e73edd4..38eb088 100644 --- a/phy.h +++ b/phy.h @@ -11,6 +11,7 @@ /* * Define PHY pages */ +#define PHY_MMD_PMAPMD 1 #define PHY_MMD_AN 7 #define PHY_SDS_CTRL 30 #define PHY_MMD_CTRL 31 diff --git a/rtl837x_common.h b/rtl837x_common.h index 06e4a23..7b03e09 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -3,14 +3,15 @@ #include "uip/uip-conf.h" #include +#include -// 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 #define SCL_PIN 3 #define SDA_PIN_0 4 #define SDA_PIN_1 3 +#define CPU_PORT 9 + // Define Port-masks for 9-port devices and 6-port devices #define PMASK_9 0x1ff #define PMASK_6 0x1f8 @@ -41,12 +42,6 @@ // This is the standard size of an Ethernet frame header #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_LEN 0x1000 #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); void get_random_32(void); void read_reg_timer(uint32_t * tmr); +void sfp_print_info(uint8_t sfp); +bool gpio_pin_test(uint8_t pin); #endif diff --git a/rtl837x_flash.c b/rtl837x_flash.c index 4df0604..7020e02 100644 --- a/rtl837x_flash.c +++ b/rtl837x_flash.c @@ -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); diff --git a/rtl837x_igmp.c b/rtl837x_igmp.c index 032efca..d1ca647 100644 --- a/rtl837x_igmp.c +++ b/rtl837x_igmp.c @@ -11,12 +11,9 @@ #include "rtl837x_sfr.h" #include "rtl837x_regs.h" #include "rtl837x_igmp.h" +#include "machine.h" -extern __xdata uint8_t minPort; -extern __xdata uint8_t maxPort; -extern __xdata uint8_t nSFPPorts; -extern __xdata uint8_t cpuPort; -extern __xdata uint8_t isRTL8373; +extern __code struct machine machine; 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) REG_SET(RTL837X_MC_LOOKUPMISS_ACTIONS, 0x00000000); //0x4f78 + // Define ports where unknown MC addresses are flooded to: - if (isRTL8373) { - REG_SET(RTL837X_MC_FLOODMASK, PMASK_9); // R5368-000001f8 - } else { - REG_SET(RTL837X_MC_FLOODMASK, PMASK_6); - } + REG_SET(RTL837X_MC_FLOODMASK, machine.isRTL8373 ? PMASK_9 : PMASK_6); // Enable lookup of IPv4 MC addresses in table reg_bit_set(RTL837X_L2_CTRL, 3); // 0x5350 // 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) - 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); } @@ -52,6 +46,6 @@ void igmp_enable(void) __banked // 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) - 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) } diff --git a/rtl837x_phy.c b/rtl837x_phy.c index 780f6d3..a535a06 100644 --- a/rtl837x_phy.c +++ b/rtl837x_phy.c @@ -119,7 +119,7 @@ void phy_config(uint8_t phy) __banked // p031f.a442:043c P000008.1f00a442:0430 // Unknown, but clear bits 2/3 - phy_modify(phy, 0x1f, 0xa442, 0x0006, 0x0000); + phy_modify(phy, 0x1f, 0xa442, 0x000c, 0x0000); delay(20); // 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 */ -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; - phy_read(port, 0x1f, 0xa610); + phy_read(port, PHY_MMD_CTRL, 0xa610); v = SFR_DATA_U16; if (speed == PHY_OFF) { - phy_write(port, 0x1f, 0xa610, v | 0x0800); + phy_write(port, PHY_MMD_CTRL, 0xa610, v | 0x0800); return; } // Port is on, make sure of it: if (v & 0x0800) - phy_write(port, 0x1f, 0xa610, v & 0xf7ff); + phy_write(port, PHY_MMD_CTRL, 0xa610, v & 0xf7ff); if (speed == PHY_SPEED_AUTO) { // 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) - 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 } else { // AN Control Register (MMD 7.0x0000) phy_write(port, PHY_MMD_AN, 0x00, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13) - // 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 - if (speed == PHY_SPEED_1G) { - // 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 - // GBCR (1000Base-T Control Register, MMD 31.0xA412) - phy_modify(port, 0x1f, 0xa412, 0x0000, 0x02000); - } else if (speed == PHY_SPEED_2G5) { - // 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 - // GBCR (1000Base-T Control Register, MMD 31.0xA412) - phy_modify(port, 0x1f, 0xa412, 0x02000, 0x0000); + 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) + // 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) { + // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) + // 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) + phy_modify(port, PHY_MMD_CTRL, 0xa412, 0x0000, 0x0200); + } else if (speed == PHY_SPEED_2G5) { + // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) + // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed + phy_write(port, PHY_MMD_AN, 0x20, 0x6081); + // GBCR (1000Base-T Control Register, MMD 31.0xA412) + 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'); } diff --git a/rtl837x_phy.h b/rtl837x_phy.h index fac191c..49a13c6 100644 --- a/rtl837x_phy.h +++ b/rtl837x_phy.h @@ -1,15 +1,21 @@ #ifndef _RTL837X_PHY_H_ #define _RTL837X_PHY_H_ -#define PHY_SPEED_AUTO 0x1 -#define PHY_SPEED_1G 0x2 -#define PHY_SPEED_2G5 0x3 +#define PHY_SPEED_10M 0x2 +#define PHY_SPEED_100M 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 void rtl8224_phy_enable(void) __banked; void phy_config(uint8_t phy) __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; #endif diff --git a/rtl837x_port.c b/rtl837x_port.c index 26c5dd1..bb96983 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -13,40 +13,20 @@ #include "rtl837x_port.h" #include "rtl837x_phy.h" #include "phy.h" +#include "machine.h" #pragma codeseg BANK1 #pragma constseg BANK1 extern __code uint8_t * __code hex; extern __code uint16_t bit_mask[16]; -extern __xdata uint8_t minPort; -extern __xdata uint8_t maxPort; -extern __xdata uint8_t nSFPPorts; +extern __code struct machine machine; extern __xdata uint8_t sfr_data[4]; -extern __xdata uint8_t cpuPort; extern __xdata uint16_t vlan_ptr; extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; -extern __xdata uint8_t isRTL8373; - __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 { 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; // On RTL8372, port-bits 0-2 must be 0, although they are not members - if (!isRTL8373) { + if (!machine.isRTL8373) { a &= 0x1f8; tagged &= 0x3f8; } @@ -184,18 +164,15 @@ void vlan_setup(void) __banked vlan_names[0] = 0; // Initialize VLAN table for VLAN 1, by disabling that entry - if (isRTL8373) { - REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007ffff); - } else { - REG_SET(RTL837x_TBL_DATA_IN_A, 0x0007e3f8); - } + REG_SET(RTL837x_TBL_DATA_IN_A, machine.isRTL8373? 0x0007ffff : 0x0007e3f8); + REG_SET(RTL837X_TBL_CTRL, 0x00010303); do { reg_read_m(RTL837X_TBL_CTRL); } while (sfr_data[3] & TBL_EXECUTE); // 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); #ifdef DEBUG 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); // Enable VLAN 1: Ports 0-9, i.e. including the CPU port are untagged members - if (isRTL8373) { - 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_DATA_IN_A, machine.isRTL8373? 0x0207ffff : 0x0207e3f8); // 02: Entry valid, 7...: membership + REG_SET(RTL837X_TBL_CTRL, 0x00010303); // Write VLAN 1 do { 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); // 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 | PMASK_9); - } else { - REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | PMASK_6); - } + REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | (machine.isRTL8373 ? PMASK_9 : PMASK_6)); // Wait for flush completed do { @@ -358,18 +328,14 @@ void port_l2_setup(void) __banked 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 uint16_t reg = RTL837X_L2_LRN_PORT_CONSTRAINT + (i << 2); REG_SET(reg, 0x00001040); // All ports may communicate with each other and CPU-Port reg = RTL837X_PORT_ISOLATION_BASE + (i << 2); - if(isRTL8373) { - REG_SET(reg, PMASK_9 | PMASK_CPU); - } else { - REG_SET(reg, PMASK_6 | PMASK_CPU); - } + REG_SET(reg, PMASK_CPU | (machine.isRTL8373? PMASK_9 : PMASK_6)); } // When maximim entries learned, then simply flood the packet reg_bit_set(RTL837X_L2_LRN_PORT_CONSTRT_ACT, 0); @@ -381,56 +347,59 @@ void port_l2_setup(void) __banked void port_stats_print(void) __banked { print_string("\n Port\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n"); - for (uint8_t i = minPort; i <= maxPort; i++) { - write_char('1' + i); write_char('\t'); - phy_read(i, 0x1f, 0xa610); // p001f.a610:2058 - if (i <= maxPort - nSFPPorts) { + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + write_char('0' + machine.log_to_phys_port[i]); write_char('\t'); + + if (!machine.is_sfp[i]) { + phy_read(i, 0x1f, 0xa610); if (SFR_DATA_8 == 0x20) print_string("On\t"); else print_string("Off\t"); - reg_read_m(RTL837X_REG_LINKS); - uint8_t b = sfr_data[3 - (i >> 1)]; - b = (i & 1) ? b >> 4 : b & 0xf; - switch (b) { - case 0: - print_string("Down\t"); - break; - case 1: - print_string("100M\t"); - break; - case 2: - print_string("1000M\t"); - break; - case 5: - print_string("2.5G\t"); - break; - default: - print_string("Up\t"); - 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 { // 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 { - 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"); + 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); + else + reg_read_m(RTL837X_REG_LINKS_89); + uint8_t b = sfr_data[3 - ((i & 7) >> 1)]; + b = (i & 1) ? b >> 4 : b & 0xf; + switch (b) { + case 0: + print_string("Down\t"); + break; + case 1: + print_string("100M\t"); + break; + case 2: + print_string("1000M\t"); + break; + case 4: + print_string("10G\t"); + break; + case 5: + print_string("2.5G\t"); + break; + default: + print_string("Up\t"); + break; + } STAT_GET(0x2f, i); 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) { - if (port <= maxPort) + if (port <= machine.max_port) REG_SET(RTL837X_PORT_ISOLATION_BASE + (port << 2), pmask); } uint16_t port_isolation_get(register uint8_t port) { - if (port > maxPort) + if (port > machine.max_port) return 0; 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 { - if (is_sfp[port]) + if (machine.is_sfp[port]) return; 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 { - if (is_sfp[port]) + if (machine.is_sfp[port]) return; 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 { - 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(": "); - if (is_sfp[port]) { + if (machine.is_sfp[port]) { print_string("SFP\n"); return; } @@ -550,7 +519,7 @@ void port_eee_status(uint8_t port) __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); } } @@ -558,7 +527,7 @@ void port_eee_enable_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); } } @@ -566,7 +535,7 @@ void port_eee_disable_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); } } diff --git a/rtl837x_regs.h b/rtl837x_regs.h index fb4b6b9..156d23f 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -1,18 +1,30 @@ #ifndef _RTL837X_REGS_H_ #define _RTL837X_REGS_H_ -#define RTL837X_REG_HW_CONF 0x6040 +#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 // Bits 4 & 5: CLOCK DIVIDER from 125MHz for Timer -#define RTL837X_REG_LED_MODE 0x6520 +#define RTL837X_REG_LED_MODE 0x6520 // Defines the LED Mode for steering the Port LEDS and the System LED // BIT 17 set: LED solid on // Bytes 0/1 hold the LED mode, e.g. serial, RTL8231? // Blink rate is defined by setAsicRegBits(0x6520,0xe00000,rate); - -#define RTL837X_REG_SMI_CTRL 0x6454 -#define RTL837X_REG_RESET 0x0024 -// Writing 0x01 into this register causes a reset of the entire SoC +#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_MAC_TYPE 0x6330 +#define RTL837X_REG_SMI_PORT_POLLING 0x6334 #define RTL837X_REG_SEC_COUNTER 0x06f4 #define RTL837X_REG_SEC_COUNTER2 0x06f8 @@ -31,7 +43,8 @@ #define SDS_10GR 0x1a #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. Port 0 appears to be the CPU port 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_1 0x7f90 +#define RTL837X_PIN_MUX_2 0x7f94 // Output Registers #define RTL837X_REG_GPIO_00_31_OUTPUT 0x3c @@ -177,6 +191,9 @@ #define RTL837X_RMA0_CONF 0x4ecc #define RTL837X_RMA_CONF 0x4f1c #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 diff --git a/rtl837x_stp.c b/rtl837x_stp.c index 2e6c08a..54207e4 100644 --- a/rtl837x_stp.c +++ b/rtl837x_stp.c @@ -12,12 +12,9 @@ #include "rtl837x_regs.h" #include "rtl837x_stp.h" #include "uip.h" +#include "machine.h" -extern __xdata uint8_t minPort; -extern __xdata uint8_t maxPort; -extern __xdata uint8_t nSFPPorts; -extern __xdata uint8_t cpuPort; -extern __xdata uint8_t isRTL8373; +extern __code struct machine machine; extern __xdata uint8_t sfr_data[4]; extern __code struct uip_eth_addr uip_ethaddr; @@ -203,7 +200,7 @@ void stp_cnf_send(uint8_t port) 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]--; if (!port_hello[i]) { port_hello[i] = TIME_HELLO; @@ -219,7 +216,7 @@ void stp_setup(void) __banked { print_string("Enabling STP: "); 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 // States are: 00 disable, 01 blocking, 10 learning, 11 forwarding uint8_t bit_mask = 0b01 << ( (i << 1) & 0x7); @@ -241,7 +238,7 @@ void stp_setup(void) __banked void stp_off(void) __banked { 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 // States are: 00 disable, 01 blocking, 10 learning, 11 forwarding uint8_t bit_mask = 0b11 << ( (i << 1) & 0x7); diff --git a/rtlplayground.c b/rtlplayground.c index 073ca78..052498e 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -15,6 +15,9 @@ #include "uip/uipopt.h" #include "uip/uip.h" #include "uip/uip_arp.h" +#include "machine.h" + +extern __code const struct machine machine; extern __xdata uint16_t crc_value; __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 netmask[] = { 255, 255, 255, 0}; -__xdata uint8_t isRTL8373; - volatile __xdata uint32_t ticks; volatile __xdata uint8_t sec_counter; 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 uint8_t tx_seq; -__xdata uint8_t minPort; -__xdata uint8_t maxPort; -__xdata uint8_t nSFPPorts; -__xdata uint8_t cpuPort; __xdata uint8_t stpEnabled; __code uint16_t bit_mask[16] = { @@ -101,6 +98,7 @@ __code uint16_t bit_mask[16] = { __xdata uint8_t was_offline; __xdata uint8_t linkbits_last[4]; +__xdata uint8_t linkbits_last_p89; __xdata uint8_t sfp_pins_last; @@ -632,7 +630,7 @@ void sds_config_mac(uint8_t sds, uint8_t mode) case 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); else sfr_data[2] &= 0x03; @@ -676,9 +674,6 @@ void sds_config(uint8_t sds, uint8_t mode) uint8_t page = 0; uint16_t v = 0; - print_string("\nTrying to set SDS mode to 0x"); - print_byte(mode); - print_string("\n"); switch (mode) { 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) { - if (slot == 0) { + if (machine.sfp_port[slot].i2c == 0) { reg_read_m(RTL837X_REG_I2C_CTRL); sfr_mask_data(1, 0xfc, SCL_PIN << 5 | SDA_PIN_0 << 2); 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) { + // 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) write_char(c); @@ -915,55 +913,48 @@ void sfp_print_info(uint8_t sfp) } -void handle_sfp(void) +bool gpio_pin_test(uint8_t pin) { - reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); - if ((sfp_pins_last & 0x1) && (!(sfr_data[0] & 0x40))) { - sfp_pins_last &= ~0x01; - print_string("\n "); - // 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(0, 12); - 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("\n"); - print_string("\n"); - sfp_print_info(0); - sds_config(1, sfp_rate_to_sds_config(rate)); - } - if ((!(sfp_pins_last & 0x1)) && (sfr_data[0] & 0x40)) { - sfp_pins_last |= 0x01; - print_string("\n\n"); - } + reg_read_m(RTL837X_REG_GPIO_00_31_INPUT + (pin > 31 ? 4 : 0)); + return sfr_data[3-((pin >> 3) & 3)] & (1 << (pin & 7)); +} - reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); - if ((sfp_pins_last & 0x2) && (!(sfr_data[3] & 0x20))) { - sfp_pins_last &= ~0x02; - print_string("\n\n"); - } - if ((!(sfp_pins_last & 0x2)) && (sfr_data[3] & 0x20)) { - sfp_pins_last |= 0x02; - print_string("\n\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 "); - // 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\n"); +void handle_sfp(void) +{ + for (uint8_t sfp = 0; sfp < machine.n_sfp; sfp++) { + if (!gpio_pin_test(machine.sfp_port[sfp].pin_detect)) { + if (sfp_pins_last & (0x1 << (sfp << 2))) { + sfp_pins_last &= ~(0x01 << (sfp << 2)); + print_string("\n Slot: "); write_char('1' + sfp); + // 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(sfp, 12); + print_string(" Rate: "); print_byte(rate); // Normally 1, but 0 for DAC, can be ignored? + print_string(" Encoding: "); print_byte(sfp_read_reg(sfp, 11)); + print_string(" Module: "); sfp_print_info(sfp); + print_string("\n"); + sds_config(machine.sfp_port[sfp].sds, sfp_rate_to_sds_config(rate)); + } + } else { + if (!(sfp_pins_last & (0x1 << (sfp << 2)))) { + sfp_pins_last |= 0x01 << (sfp << 2); + print_string("\n Slot: "); write_char('1' + sfp); write_char('\n'); + } + } + + if (!gpio_pin_test(machine.sfp_port[sfp].pin_los)) { + if (sfp_pins_last & (0x2 << (sfp << 2))) { // 0x2 0x08 + sfp_pins_last &= ~(0x02 << (sfp << 2)); + print_string("\n Slot: "); write_char('1' + sfp); write_char('\n'); + } + } else { + if (!(sfp_pins_last & 0x2 << (sfp << 2))) { + sfp_pins_last |= 0x02 << (sfp << 2); + print_string("\n Slot: "); write_char('1' + sfp); write_char('\n'); + } + } } } @@ -1006,17 +997,25 @@ void idle(void) #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); - if (!isRTL8373 && cmp_4(sfr_data, linkbits_last)) { + if (cmp_4(sfr_data, linkbits_last) || (linkbits_p89 != linkbits_last_p89)) { print_string("\n\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_last = linkbits_last[2] >> 4; cpy_4(linkbits_last, sfr_data); + // Handle link change of the RTL8221 PHY, adjust SDS mode if (p5_last != p5) { if (p5 == 0x5) // 2.5GBit Mode sds_config(0, SDS_HISGMII); @@ -1029,7 +1028,6 @@ void idle(void) } // Check for changes with SFP modules - handle_sfp(); /* 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. // TODO: Check if we directly can modify SFR register directly. uint16_t data = SFR_DATA_U16 & ~(mask); - data |= ~(set); + data |= set; uint16_t phy_mask = bit_mask[phy_id]; // 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_DEV = smi_phy | (phy_mask >> 8); SFR_EXEC_GO = SFR_EXEC_WRITE_SMI; @@ -1323,46 +1322,35 @@ void led_config_9xh(void) reg_bit_set(0x65d8, 0x1d); // 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(0, 0xe0, 0xa0); - reg_write_m(0x6520); + reg_write_m(RTL837X_REG_LED_MODE); - // r65f8:00000018 R65f8-0000001b - reg_read_m(0x65f8); + // Disable RLDP (Realtek Loop Detection Protocol) LEDs on loop detection + reg_read_m(RTL837X_REG_LED_RLDP_1); 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_SET(0x65fc, 0xffffffff); + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29); + reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 27); - // Set bits 0-3 of 0x6600 to 0xf - // r6600:00000000 R6600-0000000f - reg_read_m(0x6600); - sfr_mask_data(0, 0, 0x0f); - reg_write_m(0x6600); + // GPIO 27 is LED + reg_bit_set(RTL837X_PIN_MUX_0, 27); - // 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); - - // 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 0/1 + REG_SET(RTL837X_REG_LED1_0_SET0, 0x0041017f); // Configure LED_SET_0 ledid 2 - // r6544:01411000 R6544-01410044 - reg_read_m(0x6544); - sfr_data[2] = 0x00; - sfr_data[3] = 0x44; - reg_write_m(0x6544); + REG_SET(RTL837X_REG_LED3_2_SET0, 0x01410044); // r6528:00000000 R6528-0000000f - reg_read_m(0x6528); + reg_read_m(RTL837X_REG_LED3_0_SET1); 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; reg_write_m(RTL837X_REG_LED_MODE); - // Clear bits 0,1 of 0x65f8 -// r65f8:00000018 R65f8-00000018 - reg_read_m(0x65f8); + // Disable RLDP (Realtek Loop Detection Protocol) LEDs on loop detection + reg_read_m(RTL837X_REG_LED_RLDP_1); sfr_mask_data(0, 0x03, 0); - reg_write_m(0x65f8); - - // Set 0x65fc to 0xfffff000 - // R65fc-fffff000 - REG_SET(0x65fc, 0xfffff000); - - // Set bits 0-3 of 0x6600 to 0xf - // r6600:00000000 R6600-0000000f - 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 - 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 + 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 + + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29); + reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 27); + + // Configure GPIO for LEDs 27-29 + if (machine.n_sfp == 2) { + reg_bit_set(RTL837X_PIN_MUX_0, 27); + reg_bit_clear(RTL837X_PIN_MUX_0, 28); + reg_bit_set(RTL837X_PIN_MUX_0, 29); } else { - reg_bit_set(RTL837X_PIN_MUX_0, 0x1d); - reg_bit_set(RTL837X_PIN_MUX_0, 0x1c); - reg_bit_set(RTL837X_PIN_MUX_0, 0x1b); + reg_bit_set(RTL837X_PIN_MUX_0, 27); + reg_bit_set(RTL837X_PIN_MUX_0, 28); + reg_bit_set(RTL837X_PIN_MUX_0, 29); } // 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 - // 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 - // R6548-00410175 - REG_SET(0x6548, 0x00410175); + REG_SET(RTL837X_REG_LED1_0_SET0, 0x00410175); - // Configure LED_SET_0 ledid 2 - // 6544:01411000 R6544-01410044 - reg_read_m(0x6544); - sfr_data[2] = 0x00; - sfr_data[3] = 0x44; - reg_write_m(0x6544); + // Configure led-sets 2 and 3 + REG_SET(RTL837X_REG_LED3_2_SET0, 0x01410044); // Further configure LED_SET_0 // r6528:00000000 R6528-00000011 - reg_read_m(0x6528); + reg_read_m(RTL837X_REG_LED3_0_SET1); sfr_data[3] = 0x11; - reg_write_m(0x6528); - - 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); + reg_write_m(RTL837X_REG_LED3_0_SET1); } void rtl8373_revision(void) { - // r000c:00300000 R000c-003a0000 r000c:203a6818 r000c:203a6818 R000c-20306818 - - reg_read_m(0x000c); + reg_read_m(RTL837X_REG_CHIP_INFO); sfr_mask_data(2, 0x0a, 0x0a); // Enable reading version - reg_write_m(0x000c); + reg_write_m(RTL837X_REG_CHIP_INFO); 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'); sfr_mask_data(2, 0x0a, 0x00); // Enable reading version - reg_write_m(0x000c); + reg_write_m(RTL837X_REG_CHIP_INFO); } void rtl8373_init(void) { 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(); sds_init(); @@ -1534,10 +1475,12 @@ void rtl8373_init(void) // r0b7c:000000d8 R0b7c-000000f8 r6040:00000030 R6040-00000031 reg_bit_set(0xb7c, 5); - - // R7124-00001050 R7128-00001050 R712c-00001050 R7130-00001050 R7134-00001050 R7138-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(0x7140, 0x1050); REG_SET(0x7144, 0x1050); REG_SET(0x7148, 0x1050); + // R7124-00001050 R7128-00001050 R712c-00001050 R7130-00001050 R7134-00001050 R7138-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(0x7140, 0x1050); REG_SET(0x7144, 0x1050); + REG_SET(0x7148, 0x1050); reg_bit_set(RTL837X_REG_HW_CONF, 0); @@ -1554,7 +1497,6 @@ void rtl8373_init(void) sfr_mask_data(2, 0x10, 0x1f); reg_write_m(0x632c); - REG_SET(0x7f94, 0); print_string("\nrtl8373_init done\n"); } @@ -1562,36 +1504,9 @@ void rtl8373_init(void) void rtl8372_init(void) { 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(); + sds_init(); phy_config(8); // PHY configuration: External 8221B? 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 - 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 REG_SET(reg, 0xe77); 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 * as baud generator. * 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 sfp_pins_last = 0x33; // signal LOS and no module inserted (for both slots, even if only 1 present) // 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: "); - isRTL8373 = 0; reg_read_m(0x4); if (sfr_data[1] == 0x73) { // Register was 0x83730000 print_string("RTL8373\n"); - isRTL8373 = 1; + if (!machine.isRTL8373) + print_string("INCORRECT MACHINE!"); rtl8224_enable(); // Power on the RTL8224 } else { print_string("RTL8372\n"); + if (machine.isRTL8373) + print_string("INCORRECT MACHINE!"); } // Print SW version @@ -1741,18 +1702,20 @@ void bootloader(void) flash_init(0); // Reset NIC - reg_bit_set(0x24, 2); + reg_bit_set(RTL837X_REG_RESET, RESET_NIC_BIT); do { - reg_read(0x24); - } while (SFR_DATA_0 & 0x4); + reg_read(RTL837X_REG_RESET); + } while (SFR_DATA_0 & (1 << RESET_NIC_BIT)); print_string("NIC reset\n"); 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_netmask, netmask[0], netmask[1], netmask[2], netmask[3]); - REG_SET(0x7f94, 0x0); - if (isRTL8373) + REG_SET(RTL837X_PIN_MUX_2, 0x0); // Disable pins for ACL + init_smi(); + rtl8373_revision(); + if (machine.isRTL8373) rtl8373_init(); else rtl8372_init();