diff --git a/cmd_parser.c b/cmd_parser.c index d65e179..6c91ad2 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -457,6 +457,21 @@ void parse_port(void) } +void sfp_print_measurements(uint8_t sfp) +{ + print_string("Options: "); print_byte(sfp_read_reg(sfp, 92)); write_char('\n'); + if (!(sfp_read_reg(sfp, 92) & 0x40)) + return; + print_string("Temp: "); print_byte(sfp_read_reg(sfp, 224)); print_byte(sfp_read_reg(sfp, 225)); write_char('\n'); + print_string("Vcc: "); print_byte(sfp_read_reg(sfp, 226)); print_byte(sfp_read_reg(sfp, 227)); write_char('\n'); + print_string("TX Bias: "); print_byte(sfp_read_reg(sfp, 228)); print_byte(sfp_read_reg(sfp, 229)); write_char('\n'); + print_string("TX Power: "); print_byte(sfp_read_reg(sfp, 230)); print_byte(sfp_read_reg(sfp, 231)); write_char('\n'); + print_string("RX Power: "); print_byte(sfp_read_reg(sfp, 232)); print_byte(sfp_read_reg(sfp, 233)); write_char('\n'); + print_string("Laser: "); print_byte(sfp_read_reg(sfp, 234)); print_byte(sfp_read_reg(sfp, 235)); write_char('\n'); + print_string("State: "); print_byte(sfp_read_reg(sfp, 238)); write_char('\n'); +} + + void parse_regget(void) { uint16_t reg = 0; @@ -662,11 +677,13 @@ void cmd_parser(void) __banked print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11)); print_string("\n"); sfp_print_info(0); + sfp_print_measurements(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); + sfp_print_measurements(1); } } else if (cmd_compare(0, "stat")) { port_stats_print(); diff --git a/html/eee.html b/html/eee.html index d7c78c8..e5ec472 100644 --- a/html/eee.html +++ b/html/eee.html @@ -1,6 +1,5 @@ - EEE Configuration diff --git a/html/index.html b/html/index.html index 765f065..04532db 100644 --- a/html/index.html +++ b/html/index.html @@ -1,6 +1,5 @@ - diff --git a/html/lag.html b/html/lag.html index 85c6dff..29b2b66 100644 --- a/html/lag.html +++ b/html/lag.html @@ -1,6 +1,5 @@ - Link Aggregation Configuration diff --git a/html/main.js b/html/main.js index 5d5246e..5a7473d 100644 --- a/html/main.js +++ b/html/main.js @@ -6,6 +6,36 @@ const linkS = ["Disabled", "No Link", "100M", "1000M", "500M", "10G", "2.5G", "5 var pState = new Int8Array(10); var pIsSFP = new Int8Array(10); var numPorts = 0; +const logToPhysPort = [0, 0, 0, 5, 1, 2, 3, 4, 6]; +const physToLogPort = [ 4, 5, 6, 7, 3, 8]; +function drawPorts() { + var f = document.getElementById('ports'); + console.log("DRAWING PORTS: ", numPorts); + for (let i = 0; i < numPorts; i++) { + console.log("DRAWING isSFP: ", pIsSFP[i]); + const d = document.createElement("div"); + d.classList.add('tooltip'); + const s = document.createElement("span"); + s.classList.add("tooltiptext"); + s.innerHTML = "Tooltip text"; + s.id="tt_" + (i+1); + const l = document.createElement("object"); + d.appendChild(l); + d.appendChild(s); + l.type = "image/svg+xml"; + if (!pIsSFP[i]) { + l.data = "port.svg"; + l.width ="40"; + l.height ="40"; + } else { + l.data = "sfp.svg"; + l.width = "60"; + l.height = "60"; + } + l.id="port" + (i+1); + f.appendChild(d); + } +} function update() { var xhttp = new XMLHttpRequest(); @@ -25,9 +55,11 @@ function update() { p = s[i]; let n = p.portNum; let pid = "port" + n; + let ttid = "tt_" + n; n--; txG[n] = BigInt(p.txG); txB[n] = BigInt(p.txB); rxG[n] = BigInt(p.rxG); rxB[n] = BigInt(p.rxB); var psvg = document.getElementById(pid); + var tt = document.getElementById(ttid); if (psvg == null || !psvg.contentDocument) continue; var bgs = psvg.contentDocument.getElementsByClassName("bg"); @@ -37,6 +69,7 @@ function update() { bgs[0].style.fill = "red"; leds[0].style.fill = "black"; leds[1].style.fill = "black"; psvg.style.opacity = 0.4; + tt.innerHTML = "Not enabled."; } else { psvg.style.opacity = 1.0; pState[n] = p.link; @@ -48,6 +81,22 @@ function update() { leds[0].style.fill = "black"; leds[1].style.fill = "black"; psvg.style.opacity = 0.4 } + var iHTML = ""; + iHTML += ""; + if (p.isSFP) { + iHTML += ""; + iHTML += ""; + iHTML += ""; + if (p.sfp_options & 0x40) { + iHTML += ""; + iHTML += ""; + iHTML += ""; + iHTML += ""; + iHTML += ""; + } + } + iHTML += "
Link speed:" + linkS[p.link + 1] + "
Vendor:" + p.sfp_vendor + "
Model:" + p.sfp_model + "
Serial:" + p.sfp_serial + "
Temp:" + (Number(p.sfp_temp) >> 8) + "." + ((Number(p.sfp_temp) & 0xff)/256.0 * 100).toFixed(0) + " ℃
Vcc:" + (Number(p.sfp_vcc) / 10000.0).toFixed(2) + " V
TX-Bias:" + (Number(p.sfp_txbias) / 500.0).toFixed(1) + " mA
TX-Power:" + (Number(p.sfp_txpower) / 10.0).toFixed(0) + " mW
RX-Power:" + (Number(p.sfp_rxpower) / 10.0).toFixed(0) + " mW
"; + tt.innerHTML = iHTML; } } } diff --git a/html/mirror.html b/html/mirror.html index 0b8ea8e..edf5b77 100644 --- a/html/mirror.html +++ b/html/mirror.html @@ -1,6 +1,5 @@ - Mirror Configuration diff --git a/html/ports.js b/html/ports.js deleted file mode 100644 index 0a2fe2a..0000000 --- a/html/ports.js +++ /dev/null @@ -1,24 +0,0 @@ -const logToPhysPort = [0, 0, 0, 5, 1, 2, 3, 4, 6]; -const physToLogPort = [ 4, 5, 6, 7, 3, 8]; - -function drawPorts() { - var f = document.getElementById('ports'); - console.log("DRAWING PORTS: ", numPorts); - for (let i = 0; i < numPorts; i++) { - console.log("DRAWING isSFP: ", pIsSFP[i]); - const l = document.createElement("object"); - l.type = "image/svg+xml"; - if (!pIsSFP[i]) { - l.data = "port.svg"; - l.width ="40"; - l.height ="40"; - } else { - l.data = "sfp.svg"; - l.width = "60"; - l.height = "60"; - } - l.id="port" + (i+1); - f.appendChild(l); - } - console.log("DRAWING DONE "); -} diff --git a/html/stat.html b/html/stat.html index 467f0bf..5cfaf05 100644 --- a/html/stat.html +++ b/html/stat.html @@ -1,6 +1,5 @@ - FreeSwitchOS Port Statistics diff --git a/html/style.css b/html/style.css index a4edf4d..477cca1 100644 --- a/html/style.css +++ b/html/style.css @@ -26,7 +26,7 @@ li a:hover { } table, th, td { - border: 1px solid navy; + border: 1px solid #226; padding: 8px; } table { @@ -84,7 +84,6 @@ object { .row {display: flex;} .rcol {flex: 90%;} .lcol {flex: 10%;} -span::before{ content:''; position: absolute; top: 40px; left:0; width: 100%; height: 2px; background: #aaf;} /* Login page */ .login_page {margin: 0; padding: 0; background: #aaf; height: 100vh; overflow: hidden;} @@ -118,3 +117,46 @@ margin: 30px 0; .txt_field span::before{ content:''; position: absolute; top: 40px; left:0; width: 100%; height: 2px; background: #aaf;} .txt_field input:focus ~ label, .txt_field input:valid ~ label { top: -5px; color: #aaf; } + +.tooltip { + position: relative; display: inline-block; cursor: pointer; +} + + +.tooltiptext { + visibility: hidden; + width: 260px; + background-color: #226; + color: #fff; + text-align: center; + border-radius: 6px; + padding: 5px 0; + position: absolute; + z-index: 1; + top: 80%; + left: 50%; + margin-left: -130px; +} + +.tooltiptext::after { + content: ""; + position: absolute; + bottom: 100%; + left: 50%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: transparent transparent black transparent; +} + + +.tooltip:hover .tooltiptext { + visibility: visible; + opacity: 1; +} +.tt_table { + width: 100%; font-size:90%; +} +.tt_table td { + text-align: left; +} diff --git a/html/vlan.html b/html/vlan.html index 8bc66f9..a3f91e0 100644 --- a/html/vlan.html +++ b/html/vlan.html @@ -1,6 +1,5 @@ - FreeSwitchOS VLAN Configuration diff --git a/httpd/httpd.c b/httpd/httpd.c index 8f6c923..fa9b4cb 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -593,7 +593,7 @@ void httpd_appcall(void) slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: "); slen += strtox(outbuf + slen, mime_strings[f_data[entry].mime]); - slen += strtox(outbuf + slen, "\r\nCache-Control: max-age=60, must-revalidate\r\n\r\n"); + slen += strtox(outbuf + slen, "; charset=UTF-8\r\nCache-Control: max-age=60, must-revalidate\r\n\r\n"); len_left = f_data[entry].len; if (len_left > (TCP_OUTBUF_SIZE - slen)) { cont_len = len_left - (TCP_OUTBUF_SIZE - slen); diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 0b97815..6a64760 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -34,6 +34,11 @@ extern __xdata uint16_t cmd_history_ptr; extern __xdata struct flash_region_t flash_region; +extern __xdata char sfp_module_vendor[2][17]; +extern __xdata char sfp_module_model[2][17]; +extern __xdata char sfp_module_serial[2][17]; +extern __xdata uint8_t sfp_options[2]; + __code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"; __code uint8_t * __code HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"; @@ -148,6 +153,40 @@ void send_sfp_info(uint8_t sfp) } +void sfp_send_data(uint8_t slot, uint8_t reg, uint8_t len) +{ + if (reg & 0x80) { // Configure SFP readings address (0x51) as I2C device address + reg &= 0x7f; + REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16) | len & 0xf, 0x51 >> 5, (0x51 << 3) & 0xff); + } else { + REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16) | len & 0xf, 0x50 >> 5, (0x50 << 3) & 0xff); + } + + reg_read_m(RTL837X_REG_I2C_CTRL); + sfr_mask_data(1, 0xfc, machine.sfp_port[slot].i2c == 0 ? SCL_PIN << 5 | SDA_PIN_0 << 2 : SCL_PIN << 5 | SDA_PIN_1 << 2 ); + reg_write_m(RTL837X_REG_I2C_CTRL); + + REG_WRITE(RTL837X_REG_I2C_IN, 0, 0, 0, reg); + + // Execute I2C Read + reg_bit_set(RTL837X_REG_I2C_CTRL, 0); + + // Wait for execution to finish + do { + reg_read_m(RTL837X_REG_I2C_CTRL); + } while (sfr_data[3] & 0x1); + + for (uint8_t i = 0; i < len & 0xf; i++) { + if (!(i & 0x3)) + reg_read_m(RTL837X_REG_I2C_OUT + (i >> 2)); + if (len & 0x80) + char_to_html(sfr_data[3 - (i & 0x3)]); + else + byte_to_html(sfr_data[3 - (i & 0x3)]); + } +} + + void send_basic_info(void) { slen = strtox(outbuf, HTTP_RESPONCE_JSON); @@ -354,7 +393,38 @@ void send_status(void) 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)))); + if (!(sfp_pins_last & (0x1 << ((machine.is_sfp[i] - 1) << 2)))) { + bool_to_html(1); + slen += strtox(outbuf + slen,",\"sfp_options\":\"0x"); + byte_to_html(sfp_options[machine.is_sfp[i]-1]); + if (sfp_options[machine.is_sfp[i]-1] & 0x40) { + sfp_send_data(machine.is_sfp[i] - 1, 92, 1); + slen += strtox(outbuf + slen,"\",\"sfp_temp\":\"0x"); + sfp_send_data(machine.is_sfp[i] - 1, 224, 2); + slen += strtox(outbuf + slen,"\",\"sfp_vcc\":\"0x"); + sfp_send_data(machine.is_sfp[i] - 1, 226, 2); + slen += strtox(outbuf + slen,"\",\"sfp_txbias\":\"0x"); + sfp_send_data(machine.is_sfp[i] - 1, 228, 2); + slen += strtox(outbuf + slen,"\",\"sfp_txpower\":\"0x"); + sfp_send_data(machine.is_sfp[i] - 1, 230, 2); + slen += strtox(outbuf + slen,"\",\"sfp_rxpower\":\"0x"); + sfp_send_data(machine.is_sfp[i] - 1, 232, 2); + slen += strtox(outbuf + slen,"\",\"sfp_state\":\"0x"); + sfp_send_data(machine.is_sfp[i] - 1, 238, 1); + } + slen += strtox(outbuf + slen,"\",\"sfp_vendor\":\""); + for (register uint8_t s = 0; s < 16; s++) + outbuf[slen++] = sfp_module_vendor[machine.is_sfp[i]-1][s]; + slen += strtox(outbuf + slen,"\",\"sfp_model\":\""); + for (register uint8_t s = 0; s < 16; s++) + outbuf[slen++] = sfp_module_model[machine.is_sfp[i]-1][s]; + slen += strtox(outbuf + slen,"\",\"sfp_serial\":\""); + for (register uint8_t s = 0; s < 16; s++) + outbuf[slen++] = sfp_module_serial[machine.is_sfp[i]-1][s]; + char_to_html('"'); + } else { + bool_to_html(0); + } } else { slen += strtox(outbuf + slen, ",\"isSFP\":0,\"enabled\":"); phy_read(i, 0x1f, 0xa610); diff --git a/rtl837x_common.h b/rtl837x_common.h index 7bf1d9f..ef8d4d6 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -101,6 +101,7 @@ void print_reg(uint16_t reg); uint8_t sfp_read_reg(uint8_t slot, uint8_t reg); void reg_bit_set(uint16_t reg_addr, char bit); void reg_bit_clear(uint16_t reg_addr, char bit); +void sfr_mask_data(uint8_t n, uint8_t mask, uint8_t set); void sfr_set_zero(void); void reset_chip(void); void memcpy(__xdata void * __xdata dst, __xdata const void * __xdata src, uint16_t len); diff --git a/rtl837x_phy.c b/rtl837x_phy.c index 1c8c9e6..20fd80e 100644 --- a/rtl837x_phy.c +++ b/rtl837x_phy.c @@ -348,7 +348,6 @@ void phy_show(uint8_t port) __banked break; default: print_string("Unknown\n"); - break; } break; default: diff --git a/rtlplayground.c b/rtlplayground.c index 5f81c54..7beb6b3 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -101,7 +101,10 @@ __xdata uint8_t was_offline; __xdata uint8_t linkbits_last[4]; __xdata uint8_t linkbits_last_p89; __xdata uint8_t sfp_pins_last; - +__xdata char sfp_module_vendor[2][17]; +__xdata char sfp_module_model[2][17]; +__xdata char sfp_module_serial[2][17]; +__xdata uint8_t sfp_options[2]; #define ETHERTYPE_OFFSET (12 + VLAN_TAG_SIZE + RTL_TAG_SIZE) @@ -745,16 +748,17 @@ void sds_config(uint8_t sds, uint8_t mode) */ uint8_t sfp_read_reg(uint8_t slot, uint8_t reg) { - 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); + if (reg & 0x80) { // Configure SFP readings address (0x51) as I2C device address + reg &= 0x7f; + REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16) | 1, 0x51 >> 5, (0x51 << 3) & 0xff); } else { - reg_read_m(RTL837X_REG_I2C_CTRL); - sfr_mask_data(1, 0xfc, SCL_PIN << 5 | SDA_PIN_1 << 2); - reg_write_m(RTL837X_REG_I2C_CTRL); + REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16) | 1, 0x50 >> 5, (0x50 << 3) & 0xff); } + reg_read_m(RTL837X_REG_I2C_CTRL); + sfr_mask_data(1, 0xfc, machine.sfp_port[slot].i2c == 0 ? SCL_PIN << 5 | SDA_PIN_0 << 2 : SCL_PIN << 5 | SDA_PIN_1 << 2 ); + reg_write_m(RTL837X_REG_I2C_CTRL); + REG_WRITE(RTL837X_REG_I2C_IN, 0, 0, 0, reg); // Execute I2C Read @@ -922,6 +926,20 @@ void sfp_print_info(uint8_t sfp) } +void sfp_get_info(uint8_t sfp) +{ + for (uint8_t i = 20; i < 36; i++) + sfp_module_vendor[sfp][i-20] = sfp_read_reg(sfp, i); + sfp_module_vendor[sfp][16] = '\0'; + for (uint8_t i = 40; i < 56; i++) + sfp_module_model[sfp][i-40] = sfp_read_reg(sfp, i); + sfp_module_model[sfp][16] = '\0'; + for (uint8_t i = 68; i < 84; i++) + sfp_module_serial[sfp][i-68] = sfp_read_reg(sfp, i); + sfp_module_serial[sfp][16] = '\0'; +} + + bool gpio_pin_test(uint8_t pin) { reg_read_m(RTL837X_REG_GPIO_00_31_INPUT + (pin > 31 ? 4 : 0)); @@ -944,6 +962,8 @@ void handle_sfp(void) print_string(" Encoding: "); print_byte(sfp_read_reg(sfp, 11)); print_string(" Module: "); sfp_print_info(sfp); print_string("\n"); + sfp_options[sfp] = sfp_read_reg(sfp, 92); + sfp_get_info(sfp); sds_config(machine.sfp_port[sfp].sds, sfp_rate_to_sds_config(rate)); } } else { @@ -1646,7 +1666,9 @@ void setup_i2c(void) { REG_SET(RTL837X_REG_I2C_MST_IF_CTRL, 0); // Configure SFP EEPROM address (0x50) as I2C device address - REG_SET(RTL837X_REG_I2C_CTRL, 0x1L << I2C_MEM_ADDR_WIDTH | 0x50 << I2C_DEV_ADDR); + // Configure SFP readings address (0x51) as I2C device address + REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16), 0x50 >> 5, (0x50 << 3) & 0xff); + REG_SET(RTL837X_REG_I2C_CTRL2, 0); // HW Control register, enable I2C? diff --git a/tools/httpd_sim.c b/tools/httpd_sim.c index 3463d23..625894d 100644 --- a/tools/httpd_sim.c +++ b/tools/httpd_sim.c @@ -21,6 +21,7 @@ time_t last_session_use; uint64_t txG[PORTS], txB[PORTS], rxG[PORTS], rxB[PORTS]; char txG_buff[20], txB_buff[20], rxG_buff[20], rxB_buff[20]; +char sfp_temp[8], sfp_vcc[8], sfp_txbias[8], sfp_txpower[8], sfp_rxpower[8], sfp_laser[8], sfp_options[6]; char num_buff[20]; char upload_buffer[4194304]; // 4MB @@ -142,6 +143,33 @@ void send_status(int s) json_object_object_add(v, "txB", json_object_new_string(txB_buff)); json_object_object_add(v, "rxG", json_object_new_string(rxG_buff)); json_object_object_add(v, "rxB", json_object_new_string(rxB_buff)); + if (i >= 5) { + uint16_t temp = 0x28fb + rand() / (RAND_MAX / 100); + uint16_t vcc = 0x7eda + rand() / (RAND_MAX / 100); + uint16_t txbias = 0x0d24 +rand() / (RAND_MAX / 100); + uint16_t txpower = 0x14bd + rand() / (RAND_MAX / 100); + uint16_t rxpower = 0; + uint16_t laser = 0; + uint16_t options = 0x68; + + sprintf(sfp_options, "0x%02x", options); + sprintf(sfp_temp, "0x%04x", temp); + sprintf(sfp_vcc, "0x%04x", vcc); + sprintf(sfp_txbias, "0x%04x", txbias); + sprintf(sfp_txpower, "0x%04x", txpower); + sprintf(sfp_rxpower, "0x%04x", rxpower); + sprintf(sfp_laser, "0x%04x", laser); + json_object_object_add(v, "sfp_vendor", json_object_new_string("OEM")); + json_object_object_add(v, "sfp_model", json_object_new_string("10G-SFP+")); + json_object_object_add(v, "sfp_serial", json_object_new_string("12345678")); + json_object_object_add(v, "sfp_options", json_object_new_string(sfp_options)); + json_object_object_add(v, "sfp_temp", json_object_new_string(sfp_temp)); + json_object_object_add(v, "sfp_vcc", json_object_new_string(sfp_vcc)); + json_object_object_add(v, "sfp_txbias", json_object_new_string(sfp_txbias)); + json_object_object_add(v, "sfp_txpower", json_object_new_string(sfp_txpower)); + json_object_object_add(v, "sfp_rxpower", json_object_new_string(sfp_rxpower)); + json_object_object_add(v, "sfp_laser", json_object_new_string(sfp_laser)); + } json_object_array_add(ports, v); } last_called = now;