/* * A Command parser for RTL Switch configuration */ // #define DEBUG // #define REGDBG 1 #include "rtl837x_common.h" #include "rtl837x_port.h" #include "rtl837x_flash.h" #include "rtl837x_phy.h" #include "rtl837x_regs.h" #include "rtl837x_sfr.h" #include "rtl837x_stp.h" #include "rtl837x_igmp.h" #include "dhcp.h" #include "uip/uip.h" #include "version.h" #include "machine.h" #include "phy.h" #pragma codeseg BANK1 #pragma constseg BANK1 extern __code struct machine machine; extern __xdata uint8_t stpEnabled; extern __code uint8_t log_to_phys_port[9]; extern volatile __xdata uint32_t ticks; extern volatile __xdata uint8_t sfr_data[4]; extern __code uint8_t * __code greeting; extern __code uint8_t * __code hex; extern __xdata uint8_t flash_buf[512]; extern __xdata struct flash_region_t flash_region; extern __xdata char passwd[21]; extern __xdata struct dhcp_state dhcp_state; __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; __xdata uint16_t vlan_ptr; __xdata uint8_t gpio_last_value[8] = { 0 }; // Temporatly for str to hex convertion value. // Support up to 32_bits. __xdata uint8_t hexvalue[4] = { 0 }; // Buffer for writing to flash 0x1fd000, copy to 0x1fe000 __xdata uint8_t cmd_buffer[SBUF_SIZE]; __xdata uint8_t cmd_available; __xdata uint8_t l; __xdata uint8_t line_ptr; __xdata char is_white; __xdata char save_cmd; __xdata uint8_t ip[4]; #define N_WORDS SBUF_SIZE __xdata signed char cmd_words_b[N_WORDS]; __xdata uint8_t cmd_history[CMD_HISTORY_SIZE]; __xdata uint16_t cmd_history_ptr; inline uint8_t isletter(uint8_t l) { // return (l >= 'a' && l <= 'z') || (l >= 'A' && l <= 'Z'); // Make it lowercase l |= 0x20; l -= 'a'; return (l <= ('z'-'a')); } inline uint8_t isnumber(uint8_t l) { // return (l >= '0' && l <= '9'); l -= '0'; return (l <= ('9'-'0')); } uint8_t cmd_compare(uint8_t start, uint8_t * __code cmd) { signed char i; signed char j = 0; for (i = cmd_words_b[start]; i != cmd_words_b[start + 1] && cmd_buffer[i] != ' '; i++) { i &= SBUF_SIZE - 1; // print_byte(i); write_char(':'); print_byte(j); write_char('#'); print_string("\n"); // write_char('>'); write_char(cmd[j]); write_char('-'); write_char(cmd_buffer[i]); print_string("\n"); if (!cmd[j] && !isletter(cmd_buffer[i])) return 1; if (cmd_buffer[i] != cmd[j++]) break; } // write_char('.'); print_byte(i); write_char(':'); print_byte(j); write_char(','); print_byte (cmd[j-1]); // write_char(','); print_byte(cmd[j]); if (i == cmd_words_b[start + 1] || (cmd_buffer[i] == ' ' && !cmd[j])) return 1; return 0; } /* Converts ascii-hex array into value. returns number of hexvalue[] entries has been written. return value = 0 means error. */ uint8_t atoi_hex(uint8_t idx) { uint8_t h_idx = 0; uint8_t val = 0; uint8_t c; while(1) { c = cmd_buffer[idx]; if (c == '\0' || c == ' ') { break; } // swap hex nibbles val = (val >> 4) | (val << 4); if (c - '0' < 10) { val |= c - '0'; } else { c |= 0x20; c -= 'a'; if (c > 5) { h_idx = 0; break; } val |= c + 10; } idx++; hexvalue[h_idx >> 1] = val; if (h_idx & 1 == 1) { val = 0; } h_idx++; } return ((h_idx + 1) >> 1); } uint8_t atoi_short(register uint16_t *vlan, register uint8_t idx) { uint8_t err = 1; *vlan = 0; while (isnumber(cmd_buffer[idx])) { err = 0; *vlan = (*vlan * 10) + cmd_buffer[idx] - '0'; idx++; } return err; } uint8_t parse_ip(register uint8_t idx) { __xdata uint8_t b; for (b = 0; b < 4; b++) { ip[b] = 0; while (isnumber(cmd_buffer[idx])) { ip[b] = (ip[b] * 10) + cmd_buffer[idx] - '0'; idx++; } if (b < 3 && cmd_buffer[idx++] != '.') { print_string("Error in IP format, expecting '.'\n"); return -1; } } return 0; } void parse_lag(void) { __xdata uint8_t group; __xdata uint16_t members = 0; if (cmd_words_b[1] > 0 && cmd_compare(1, "show")) { print_string("LAG status:\n"); for (uint8_t i = 0; i < 4; i++) { write_char(' '); write_char('1' + i); reg_read_m(RTL837X_TRK_MBR_CTRL_BASE + (i << 2)); members = ((uint16_t)sfr_data[2]) << 8 | sfr_data[3]; if (!members) { print_string(" disabled\n"); continue; } print_string(" member ports: "); for (uint8_t j = 0; j < 10; j++) { if (members & 1) { write_char('0' + machine.log_to_phys_port[j]); write_char(' '); } members >>= 1; } print_string(" (hash: 0x"); reg_read_m(RTL837X_TRK_HASH_CTRL_BASE + (i << 2)); print_byte(sfr_data[3]); print_string(")\n"); } return; } if (cmd_words_b[2] <= 0 || !isnumber(cmd_buffer[cmd_words_b[1]])) goto err; group = cmd_buffer[cmd_words_b[1]] - '0'; uint8_t w = 2; while (cmd_words_b[w + 1] > 0) { // write_char('|'); print_byte(w); write_char(':'); write_char(cmd_buffer[cmd_words_b[w]]); write_char('-'); uint8_t port; if (isnumber(cmd_buffer[cmd_words_b[w]])) { 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'; port = machine.phys_to_log_port[port]; } else { goto err; } if (port > machine.max_port) goto err; members |= ((uint16_t)1) << port; w++; } port_lag_members_set(group, members); return; err: print_string("Error: lag [port]..."); } void parse_lag_hash(void) { __xdata uint8_t group; __xdata uint8_t hash = 0; group = cmd_buffer[cmd_words_b[1]] - '0'; uint8_t w = 2; while (cmd_words_b[w + 1] > 0) { if (cmd_compare(w, "spa")) hash |= LAG_HASH_SOURCE_PORT_NUMBER; else if (cmd_compare(w, "smac")) hash |= LAG_HASH_L2_SMAC; else if (cmd_compare(w, "dmac")) hash |= LAG_HASH_L2_DMAC; else if (cmd_compare(w, "sip")) hash |= LAG_HASH_L3_SIP; else if (cmd_compare(w, "dip")) hash |= LAG_HASH_L3_DIP; else if (cmd_compare(w, "sport")) hash |= LAG_HASH_L4_SPORT; else if (cmd_compare(w, "dport")) hash |= LAG_HASH_L4_DPORT; else { print_string("Error: invalid hash type:"); print_string_x(&cmd_buffer[cmd_words_b[w]]); write_char('\n'); } w++; } port_lag_hash_set(group, hash); } void parse_vlan(void) { __xdata uint16_t vlan; __xdata uint16_t members = 0; __xdata uint16_t tagged = 0; if (!atoi_short(&vlan, cmd_words_b[1])) { if (cmd_words_b[2] > 0 && cmd_buffer[cmd_words_b[2]] == 'd' && cmd_words_b[3] < 0) { vlan_delete(vlan); return; } uint8_t w = 2; write_char('#'); print_byte(cmd_words_b[w] ); write_char('#'); write_char(cmd_buffer[cmd_words_b[w]]); if (cmd_words_b[w] > 0 && isletter(cmd_buffer[cmd_words_b[w]])) { register uint8_t i = 0; vlan_names[vlan_ptr++] = hex[(vlan >> 8) & 0xf]; vlan_names[vlan_ptr++] = hex[(vlan >> 4) & 0xf] ; vlan_names[vlan_ptr++] = hex[vlan & 0xf]; print_string("COPYING: >"); while(cmd_buffer[cmd_words_b[w] + i] != ' ') { write_char(cmd_buffer[cmd_words_b[w] + i]); vlan_names[vlan_ptr++] = cmd_buffer[cmd_words_b[w] + i++]; } vlan_names[vlan_ptr++] = ' '; vlan_names[vlan_ptr] = '\0'; w++; print_string("<\n"); } while (cmd_words_b[w] > 0) { uint8_t port; if (isnumber(cmd_buffer[cmd_words_b[w]])) { 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 (cmd_buffer[cmd_words_b[w] + 2] == 't') tagged |= ((uint16_t)1) << port; } else { port = machine.phys_to_log_port[port]; if (cmd_buffer[cmd_words_b[w] + 1] == 't') tagged |= ((uint16_t)1) << port; } if (port > machine.max_port) goto err; members |= ((uint16_t)1) << port; } w++; } vlan_create(vlan, members, tagged); } if (cmd_words_b[2] > 0 && isletter(cmd_buffer[cmd_words_b[2]])) { print_string("vlan_ptr "); print_short(vlan_ptr); write_char(':'); write_char('>'); print_string_x(&vlan_names[0]); write_char('<'); write_char('\n'); } return; err: print_string("Error: vlan [port][t/u]..."); } void parse_mirror(void) { __xdata uint8_t mirroring_port; __xdata uint16_t rx_pmask = 0; __xdata uint16_t tx_pmask = 0; if (cmd_words_b[1] > 0 && cmd_compare(1, "status")) { reg_read_m(RTL837x_MIRROR_CTRL); uint8_t mPort = sfr_data[3]; if (mPort & 1) { print_string("Enabled: "); } else { print_string("NOT Enabled: "); } print_string("Mirroring port: "); 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]; print_string(", Port mask RX: "); print_short(m); m = sfr_data[2]; m = (m << 8) | sfr_data[3]; print_string(", Port mask TX: "); print_short(m); write_char('\n'); return; } else if (cmd_words_b[1] > 0 && cmd_compare(1, "off")) { port_mirror_del(); return; } if (!isnumber(cmd_buffer[cmd_words_b[1]])) { print_string("Port missing: mirror [port][t/r]..."); return; } 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'; mirroring_port = machine.phys_to_log_port[mirroring_port]; uint8_t w = 2; while (cmd_words_b[w] > 0) { uint8_t port; if (isnumber(cmd_buffer[cmd_words_b[w]])) { 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'; 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') tx_pmask |= ((uint16_t)1) << port; else { rx_pmask |= ((uint16_t)1) << port; tx_pmask |= ((uint16_t)1) << port; } } else { 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') tx_pmask |= ((uint16_t)1) << port; else { rx_pmask |= ((uint16_t)1) << port; tx_pmask |= ((uint16_t)1) << port; } } } w++; } port_mirror_set(mirroring_port, rx_pmask, tx_pmask); } 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) { print_string("\nport [show|on|off|10m|100m|1g|2g5] [half|full]"); return; } if (cmd_compare(2, "10m")) { print_string(" 10M\n"); if (cmd_words_b[3] > 0 && cmd_compare(3, "half")) phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_HALF); else if (cmd_words_b[3] > 0 && cmd_compare(3, "full")) phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_FULL); else phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_BOTH); } else if (cmd_compare(2, "100m")) { print_string(" 100M\n"); if (cmd_words_b[3] > 0 && cmd_compare(3, "half")) phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_HALF); else if (cmd_words_b[3] > 0 && cmd_compare(3, "full")) phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_FULL); else phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_BOTH); } else if (cmd_compare(2, "2g5")) { print_string(" 2.5G\n"); phy_set_speed(p, PHY_SPEED_2G5, PHY_DUPLEX_BOTH); } else if (cmd_compare(2, "1g")) { print_string(" 1G\n"); phy_set_speed(p, PHY_SPEED_1G, PHY_DUPLEX_BOTH); } else if (cmd_compare(2, "auto")) { print_string(" AUTO\n"); phy_set_speed(p, PHY_SPEED_AUTO, PHY_DUPLEX_BOTH); } else if (cmd_compare(2, "off")) { print_string(" OFF\n"); phy_set_speed(p, PHY_OFF, PHY_DUPLEX_BOTH); } else if (cmd_compare(2, "on")) { print_string(" ON\n"); phy_set_speed(p, PHY_SPEED_AUTO, PHY_DUPLEX_BOTH); } else if (cmd_compare(2, "duplex")) { print_string(" DUPLEX\n"); if (cmd_words_b[3] > 0 && cmd_compare(3, "full")) phy_set_duplex(p, PHY_DUPLEX_FULL); else phy_set_duplex(p, PHY_DUPLEX_HALF); } if (cmd_words_b[2] > 0 && cmd_compare(2, "show")) { phy_show(p); } } void parse_mtu(void) { __xdata uint16_t mtu; uint8_t p; if (cmd_words_b[1] > 0 && cmd_compare(1, "show")) { for (p = machine.min_port; p <= machine.max_port; p++) { reg_read_m(RTL8373_REG_MAC_L2_PORT_MAX_LEN + ((uint16_t) p << 8)); mtu = SFR_DATA_U16 & 0x3fff; print_string("Port "); print_byte(machine.log_to_phys_port[p]); write_char(' '); print_short(mtu); write_char('\n'); } } p = cmd_buffer[cmd_words_b[1]] - '1'; p = machine.phys_to_log_port[p]; print_byte(p); if (cmd_words_b[2] <= 0) { print_string("mtu [port] [size]"); return; } atoi_short(&mtu, cmd_words_b[2]); if (mtu > 0x3fff) { print_string("Maximum MTU is 16383\n"); return; } REG_WRITE(RTL8373_REG_MAC_L2_PORT_MAX_LEN + ((uint16_t) p << 8), (mtu >> 10) & 0xf, (mtu >> 2) & 0xff, ((mtu & 0x3) << 6) | ((mtu >> 8) & 0x3f), mtu & 0xff); } 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; if (cmd_words_b[1] < 0) { goto err; } uint8_t hex_size = atoi_hex(cmd_words_b[1]); if (hex_size == 0 || hex_size > 2) { goto err; } reg = hexvalue[0]; if (hex_size == 2) { reg <<= 8; reg |= hexvalue[1]; } print_string("REGGET: "); print_short(reg); print_string(": VAL: "); reg_read_m(reg); print_sfr_data(); return; err: print_string("usage: regget \n\tlike: regget 0BB0 or regget 0c"); return; } void parse_regset(void) { uint16_t reg = 0; if (cmd_words_b[2] < 0) { goto err; } uint8_t hex_size = atoi_hex(cmd_words_b[1]); if (hex_size == 0 || hex_size > 2) { goto err; } reg = hexvalue[0]; if (hex_size == 2) { reg <<= 8; reg |= hexvalue[1]; } hex_size = atoi_hex(cmd_words_b[2]); if (hex_size == 0 || hex_size > 4) { goto err; } // zero sfr memory data sfr_set_zero(); // copy data over sfr memory uint8_t offset = 4 - hex_size; while(hex_size) { hex_size -= 1; sfr_data[offset + hex_size] = hexvalue[hex_size]; } print_string("REGSET: "); print_short(reg); reg_write_m(reg); print_string(": VAL: "); print_sfr_data(); return; err: print_string("usage: regset \n\tlike regset 0b abcd1234."); } void parse_rnd(void) { // In order to get a new random numner, this bit has to be set each time! reg_bit_set(RTL837X_RLDP_RLPP, RLDP_RND_EN); reg_read_m(RTL837X_RAND_NUM1); print_byte(sfr_data[2]); print_byte(sfr_data[3]); reg_read_m(RTL837X_RAND_NUM0); print_byte(sfr_data[0]); print_byte(sfr_data[1]); print_byte(sfr_data[2]); print_byte(sfr_data[3]); write_char('\n'); } void parse_passwd(void) { if (cmd_words_b[2] > 0) { signed char i; signed char j = 0; for (i = cmd_words_b[1]; (i != cmd_words_b[2] && i - cmd_words_b[1] < 20); i++) passwd[j++] = cmd_buffer[i]; passwd[j] = '\0'; return; } print_string("Missing password\n"); } // Parse command into words uint8_t cmd_tokenize(void) __banked { #ifdef DEBUG print_string("Tokenizing command\n"); print_string_x(&cmd_buffer[0]); write_char('<'); write_char('\n'); #endif line_ptr = 0; is_white = 1; uint8_t word = 0; cmd_words_b[0] = -1; while (cmd_buffer[line_ptr] && line_ptr < SBUF_SIZE - 1) { if (is_white && cmd_buffer[line_ptr] != ' ') { is_white = 0; cmd_words_b[word++] = line_ptr; } if (cmd_buffer[line_ptr] == ' ') is_white = 1; line_ptr++; if (word >= N_WORDS - 1) { print_string("\ntoo many arguments, truncated"); return 1; } } if (line_ptr == SBUF_SIZE - 1) return 1; cmd_words_b[word++] = line_ptr; cmd_words_b[word++] = -1; return 0; } // Print GPIO status void print_gpio_status(void) { for (uint8_t idx = 0; idx < 2; idx++) { reg_read(RTL837X_REG_GPIO_00_31_INPUT + (idx * 4)); print_string("GPIO "); write_char(idx + '0'); write_char(':'); write_char(' '); print_byte(SFR_DATA_24); print_byte(SFR_DATA_16); print_byte(SFR_DATA_8); print_byte(SFR_DATA_0); write_char(' '); print_byte( gpio_last_value[(idx *4)] ^ SFR_DATA_24); gpio_last_value[(idx *4)] = SFR_DATA_24; print_byte( gpio_last_value[(idx *4) + 1] ^ SFR_DATA_16); gpio_last_value[(idx *4) + 1] = SFR_DATA_16; print_byte( gpio_last_value[(idx *4) + 2] ^ SFR_DATA_8); gpio_last_value[(idx *4) + 2] = SFR_DATA_8; print_byte( gpio_last_value[(idx *4) + 3] ^ SFR_DATA_0); gpio_last_value[(idx *4) + 3] = SFR_DATA_0; write_char('\n'); } } // Show software version void print_sw_version(void) __banked { print_string("Software version: "); print_string(VERSION_SW); print_string("\nBuild: " __DATE__ " " __TIME__); print_string("\nHardware: "); print_string(machine.machine_name); write_char('\n'); } // Identify command void cmd_parser(void) __banked { #ifdef DEBUG print_long(ticks); print_string("Parsing command\n"); print_string_x(&cmd_buffer[0]); write_char('<'); write_char('\n'); print_string("CMD-words: "); print_byte(cmd_words_b[0]); write_char(' '); print_byte(cmd_words_b[1]); write_char(' '); print_byte(cmd_words_b[2]); write_char(' '); print_byte(cmd_words_b[3]); write_char(' '); print_byte(cmd_words_b[4]); write_char(' '); print_byte(cmd_words_b[5]); write_char(' '); print_byte(cmd_words_b[6]); write_char('\n'); #endif if (cmd_words_b[0] >= 0 && cmd_words_b[1] >= 0) { if (cmd_compare(0, "reset")) { print_string("\nRESET\n\n"); reset_chip(); } else if (cmd_compare(0, "sfp")) { 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"); 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(); } 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; flash_region.len = 40; flash_read_security(); flash_region.addr = 0x0002000; flash_region.len = 40; flash_read_security(); flash_region.addr = 0x0003000; flash_region.len = 40; flash_read_security(); } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'd') { print_string("\nDUMPING FLASH\n"); flash_region.addr = 0; flash_region.len = 255; flash_dump(255); } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') { print_string("\nJEDEC ID\n"); flash_read_jedecid(); } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'u') { print_string("\nUNIQUE ID\n"); flash_read_uid(); } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 's') { print_string("\nFLASH FAST MODE\n"); // Switch to flash 62.5 MHz mode flash_init(1); print_string("\nNow dumping flash\n"); flash_region.addr = 0; flash_region.len = 255; flash_dump(255); } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'e') { print_string("\nFLASH erase\n"); flash_region.addr = 0x20000; flash_sector_erase(); } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'w') { print_string("\nFLASH write\n"); for (uint8_t i = 0; i < 20; i++) flash_buf[i] = greeting[i]; flash_region.addr = 0x200000; flash_region.len = 20; flash_write_bytes(flash_buf); } else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) { parse_port(); } else if (cmd_compare(0, "mtu") && cmd_words_b[1] > 0) { parse_mtu(); } else if (cmd_compare(0, "ip")) { if (cmd_words_b[2] > 0 && cmd_compare(1, "dhcp")) { dhcp_start(); } else if (cmd_words_b[2] < 0) { print_string("Current IP: "); itoa(uip_hostaddr[0]); write_char('.'); itoa(uip_hostaddr[0] >> 8); write_char('.'); itoa(uip_hostaddr[1]); write_char('.'); itoa(uip_hostaddr[1] >> 8); if (dhcp_state.state == DHCP_LEASING) { print_string(" (dhcp, renewal in sec: "); print_short(dhcp_state.dhcp_timer); write_char(')'); } else { print_string(" (static)"); } write_char('\n'); } else { if (dhcp_state.state) dhcp_stop(); if (!parse_ip(cmd_words_b[1])) { uip_ipaddr(&uip_hostaddr, ip[0], ip[1], ip[2], ip[3]); print_string("Setting ip: "); itoa(ip[0]); write_char('.'); itoa(ip[1]); write_char('.'); itoa(ip[2]); write_char('.'); itoa(ip[3]); write_char('\n'); } else { print_string("Invalid IP address\n"); print_string("Error: ip [|dhcp]\n"); print_string(" The dhcp option enables the dhcp client, calling ip without options prints the current IP\n"); print_string(" Calling with a valid IP address will stop any ongoing dhcp client and set the IP address\n"); } } } else if (cmd_compare(0, "gw")) { if (cmd_words_b[2] < 0) { print_string("Current gw: "); itoa(uip_draddr[0]); write_char('.'); itoa(uip_draddr[0] >> 8); write_char('.'); itoa(uip_draddr[1]); write_char('.'); itoa(uip_draddr[1] >> 8); } else { if (!parse_ip(cmd_words_b[1])) uip_ipaddr(&uip_draddr, ip[0], ip[1], ip[2], ip[3]); else print_string("Invalid IP address\n"); print_string("Setting gw: "); itoa(ip[0]); write_char('.'); itoa(ip[1]); write_char('.'); itoa(ip[2]); write_char('.'); itoa(ip[3]); } write_char('\n'); } else if (cmd_compare(0, "netmask")) { if (cmd_words_b[2] < 0) { print_string("Current netmask: "); itoa(uip_netmask[0]); write_char('.'); itoa(uip_netmask[0] >> 8); write_char('.'); itoa(uip_netmask[1]); write_char('.'); itoa(uip_netmask[1] >> 8); } else { if (!parse_ip(cmd_words_b[1])) uip_ipaddr(&uip_netmask, ip[0], ip[1], ip[2], ip[3]); else print_string("Invalid IP address\n"); print_string("Setting netmask: "); itoa(ip[0]); write_char('.'); itoa(ip[1]); write_char('.'); itoa(ip[2]); write_char('.'); itoa(ip[3]); } write_char('\n'); } else if (cmd_compare(0, "l2")) { if (cmd_words_b[1] > 0 && cmd_compare(1, "forget")) port_l2_forget(); else port_l2_learned(); } else if (cmd_compare(0, "igmp")) { if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) igmp_enable(); else if (cmd_words_b[1] > 0 && cmd_compare(1, "show")) igmp_show(); else igmp_setup(); // Reverts to default with IP-MC being flooded } else if (cmd_compare(0, "stp")) { if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) { print_string("STP enabled\n"); stpEnabled = 1; stp_setup(); } else { print_string("STP disabled\n"); stp_off(); stpEnabled = 0; } } else if (cmd_compare(0, "pvid") && cmd_words_b[1] > 0 && cmd_words_b[2] > 0) { __xdata uint16_t pvid; uint8_t port; port = cmd_buffer[cmd_words_b[1]] - '1'; 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")) { parse_vlan(); } else if (cmd_compare(0, "mirror")) { parse_mirror(); } else if (cmd_compare(0, "lag")) { parse_lag(); } else if (cmd_compare(0, "laghash")) { parse_lag_hash(); } else if (cmd_compare(0, "sds")) { print_reg(RTL837X_REG_SDS_MODES); } else if (cmd_compare(0, "gpio")) { print_gpio_status(); } else if (cmd_compare(0, "regget")) { parse_regget(); } else if (cmd_compare(0, "regset")) { parse_regset(); } else if (cmd_compare(0, "rnd")) { parse_rnd(); } else if (cmd_compare(0, "passwd")) { parse_passwd(); } else if (cmd_compare(0, "eee")) { int8_t port = -1; if (cmd_words_b[3] > 0) { port = cmd_buffer[cmd_words_b[2]] - '1'; port = machine.phys_to_log_port[port]; } if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) { if (port >= 0) port_eee_enable(port); else port_eee_enable_all(); } else if (cmd_words_b[1] > 0 && cmd_compare(1, "off")) { if (port >= 0) port_eee_disable(port); else port_eee_disable_all(); } else if (cmd_words_b[1] > 0 && cmd_compare(1, "status")) { if (port >= 0) port_eee_status(port); else port_eee_status_all(); } } else if (cmd_compare(0, "version")) { print_sw_version(); } else if (cmd_compare(0, "time")) { print_string(" Tick counter: "); print_long(ticks); print_string(" Sec Counter: "); reg_read_m(RTL837X_REG_SEC_COUNTER); print_sfr_data(); write_char('\n'); } else if (cmd_compare(0, "history")) { __xdata uint16_t p = (cmd_history_ptr + 1) & CMD_HISTORY_MASK; __xdata uint8_t found_begin = 0; // print_string("History ptr: "); // print_short(cmd_history_ptr); write_char('\n'); while (p != cmd_history_ptr) { // print_short(p); write_char(' '); if (!cmd_history[p] || cmd_history[p] == '\n') found_begin = 1; if (found_begin && cmd_history[p]) write_char(cmd_history[p]); p = (p + 1) & CMD_HISTORY_MASK; } } if (save_cmd) { uint8_t i; for (i = 0; i < N_WORDS; i++) { if (cmd_words_b[i] < 0) break; } if (i < N_WORDS) { i = cmd_words_b[--i]; cmd_history_ptr = (cmd_history_ptr + i) & CMD_HISTORY_MASK; __xdata uint16_t p = cmd_history_ptr; cmd_history[cmd_history_ptr++] = '\n'; do { i--; cmd_history[--p & CMD_HISTORY_MASK] = cmd_buffer[i]; } while (i); } } } } #define FLASH_READ_BURST_SIZE 0x100 #define PASSWORD "1234" void execute_config(void) __banked { __xdata uint32_t pos = CONFIG_START; __xdata uint16_t len_left = CONFIG_LEN; // Set default password, it can be overwritten in the configuration file strtox(passwd, PASSWORD); save_cmd = 0; do { flash_region.addr = pos; flash_region.len = FLASH_READ_BURST_SIZE; flash_read_bulk(flash_buf); uint8_t cfg_idx = 0; uint8_t c = 0; do { for (uint8_t cmd_idx = 0; cmd_idx < (SBUF_SIZE - 1); cmd_idx++) { c = flash_buf[cfg_idx++]; if (c == 0 || c == '\n') { cmd_buffer[cmd_idx] = '\0'; if (cmd_idx && !cmd_tokenize()) cmd_parser(); if (c == 0) goto config_done; break; } cmd_buffer[cmd_idx] = c; } } while(cfg_idx); len_left -= FLASH_READ_BURST_SIZE; pos += FLASH_READ_BURST_SIZE; } while(len_left); config_done: // Start saving commands to cmd_history save_cmd = 1; for (cmd_history_ptr = 0; cmd_history_ptr < CMD_HISTORY_SIZE; cmd_history_ptr++) cmd_history[cmd_history_ptr] = 0; cmd_history_ptr = 0; }