diff --git a/cmd_parser.c b/cmd_parser.c index 1218939..8f2893a 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -44,6 +44,9 @@ extern __xdata struct dhcp_state dhcp_state; __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; __xdata uint16_t vlan_ptr; + +__xdata char port_names[9][PORT_NAME_SIZE]; + extern __xdata uint16_t management_vlan; __xdata uint8_t gpio_last_value[8] = { 0 }; @@ -56,18 +59,23 @@ __xdata uint8_t hexvalue[4] = { 0 }; __xdata uint8_t cmd_buffer[CMD_BUF_SIZE]; __xdata uint8_t cmd_available; -__xdata uint8_t line_ptr; -__xdata char is_white; __xdata char save_cmd; __xdata uint8_t ip[4]; -#define N_WORDS CMD_BUF_SIZE -__xdata signed char cmd_words_b[N_WORDS]; +// These variables combined create a Fixed-capacity vector/bounded buffer. +// `N_WORDS`: The total number of command arguments that can be tracked. +// `cmd_words_len` stores the number of arguments found inside `cmd_buffer` +// `cmd_words_b` stores the index into `cmd_buffer`, check `cmd_words_len` is index is valid. +#define N_WORDS 15 +__xdata uint8_t cmd_words_len; +__xdata uint8_t cmd_words_b[N_WORDS]; __xdata uint8_t cmd_history[CMD_HISTORY_SIZE]; __xdata uint16_t cmd_history_ptr; +// Error set by commands +__xdata uint8_t err_status; inline uint8_t isletter(uint8_t l) { @@ -88,26 +96,35 @@ inline uint8_t isnumber(uint8_t l) } -uint8_t cmd_compare(uint8_t start, uint8_t * __code cmd) +uint8_t cmd_compare(uint8_t start, __code uint8_t * cmd) { - if ((start > 0) && (cmd_words_b[start] <= 0) )// nothing on this word -> no match + if (cmd_words_len == 0 || start > (cmd_words_len - 1)) { return 0; - - signed char i; - signed char j = 0; - for (i = cmd_words_b[start]; i != cmd_words_b[start + 1] && cmd_buffer[i] != ' '; i++) { - i &= CMD_BUF_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]) // end of command reached, but cmd_buffer has more characters, so no match - return 0; - 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]) // next word reached and command fully matched - return 1; + uint8_t i = cmd_words_b[start]; + uint8_t j = 0; + + do { + uint8_t c = cmd[j]; + uint8_t b = cmd_buffer[i]; + + // cmd is garanteerd to be NULL-terminated. + if (c == '\0') { + if ((b == ' ') || (b == '\0')) { + // Match + return 1; + } + break; + } + if (b != c) { + break; + } + + j += 1; + i += 1; + } while (i < CMD_BUF_SIZE); + + // No match return 0; } @@ -165,35 +182,38 @@ uint8_t atoi_hex(uint8_t idx) } -uint8_t atoi_byte(register uint8_t *out, register uint8_t idx) +uint8_t atoi_byte(__xdata uint8_t *out, uint8_t idx) { - __xdata uint8_t err = 1; - *out = 0; + uint8_t err = 1; + uint8_t num = 0; while (isnumber(cmd_buffer[idx])) { err = 0; - *out = (*out * 10) + cmd_buffer[idx] - '0'; + num = (num * 10) + cmd_buffer[idx] - '0'; idx++; } + + *out = num; return err; } -uint8_t atoi_short(register uint16_t *vlan, register uint8_t idx) +uint8_t atoi_short(__xdata uint16_t *vlan, uint8_t idx) { - __xdata uint8_t err = 1; - *vlan = 0; + uint8_t err = 1; while (isnumber(cmd_buffer[idx])) { err = 0; - *vlan = (*vlan * 10) + cmd_buffer[idx] - '0'; + uint8_t val = cmd_buffer[idx] - '0'; + *vlan = (*vlan * 10) + val; idx++; } + return err; } -uint8_t parse_ip(register uint8_t idx) +uint8_t parse_ip(uint8_t idx) { __xdata uint8_t b; @@ -243,12 +263,12 @@ void parse_lag(void) return; } - if (cmd_words_b[2] <= 0 || !isnumber(cmd_buffer[cmd_words_b[1]])) + if (cmd_words_len < 2 || !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) { + while (w < cmd_words_len) { // 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]])) { @@ -279,7 +299,7 @@ void parse_lag_hash(void) group = cmd_buffer[cmd_words_b[1]] - '0'; uint8_t w = 2; - while (cmd_words_b[w + 1] > 0) { + while (w < cmd_words_len) { if (cmd_compare(w, "spa")) hash |= LAG_HASH_SOURCE_PORT_NUMBER; else if (cmd_compare(w, "smac")) @@ -311,7 +331,7 @@ void parse_vlan(void) vlan_settings.members = 0; vlan_settings.tagged = 0; if (!atoi_short(&vlan_settings.vlan, cmd_words_b[1])) { - if (cmd_words_b[2] > 0 && cmd_buffer[cmd_words_b[2]] == 'd' && cmd_words_b[3] < 0) { + if (cmd_words_len == 3 && cmd_buffer[cmd_words_b[2]] == 'd') { vlan_delete(vlan_settings.vlan); return; } @@ -324,7 +344,7 @@ void parse_vlan(void) return; } uint8_t w = 2; - if (cmd_words_b[w] > 0 && isletter(cmd_buffer[cmd_words_b[w]])) { + if (cmd_words_len > w && isletter(cmd_buffer[cmd_words_b[w]])) { register uint8_t i = 0; vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 8) & 0xf]; vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 4) & 0xf] ; @@ -337,7 +357,7 @@ void parse_vlan(void) w++; print_string("<\n"); } - while (cmd_words_b[w] > 0) { + while (cmd_words_len > w) { __xdata uint8_t port; if (isnumber(cmd_buffer[cmd_words_b[w]])) { port = cmd_buffer[cmd_words_b[w]] - '1'; @@ -357,13 +377,13 @@ void parse_vlan(void) w++; } vlan_create(); - } else if (cmd_words_b[1] > 0 && cmd_compare(1, "show")) { + } else if (cmd_compare(1, "show")) { vlan_dump(); } else { goto err; } - if (cmd_words_b[2] > 0 && isletter(cmd_buffer[cmd_words_b[2]])) { + if (cmd_words_len >= 3 && 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'); } @@ -372,7 +392,75 @@ err: print_string("Error: vlan (|show) [port][t/u]...\n"); } -bool vlan_ingress_mode_parse(char c, vlan_ingress_mode_t *mode) + +void parse_isolate(void) +{ + __xdata uint16_t members = 0; + + if (cmd_words_len < 3) + goto err; + + print_string("\nISOLATE "); + + __xdata int8_t port_configured = cmd_buffer[cmd_words_b[1]] - '1'; + port_configured = machine.phys_to_log_port[port_configured]; + if (isnumber(cmd_buffer[cmd_words_b[1] + 1])) // CPU-port, logical port 9 + port_configured = (port_configured + 1) * 10 + cmd_buffer[cmd_words_b[1] + 1] - '1'; + if (port_configured < 0 || port_configured > 9) + goto err; + + print_byte(port_configured); write_char('\n'); + + if (cmd_compare(2, "show")) { + members = port_isolation_get(port_configured); + for (uint8_t i = 0; i < 10; i++) { + if (members & 1) { + if (i < 9) + write_char(machine.log_to_phys_port[i] + '0'); + else + print_string("CPU"); + write_char(' '); + } + members >>= 1; + } + return; + } + + if (cmd_compare(2, "off")) { + for (uint8_t i = machine.min_port; i < machine.max_port; i++) + members |= ((uint16_t)1) << i; + members |= 0x200; // CPU-port + port_isolate(port_configured, members); + return; + } + + uint8_t w = 2; + while (w < cmd_words_len) { + __xdata 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'; // logical port + if (port != 9) // CPU port is logical port 9 + goto err; + } else { + port = machine.phys_to_log_port[port]; + if (port < machine.min_port || port > machine.max_port) + goto err; + } + members |= ((uint16_t)1) << port; + } + w++; + } + port_isolate(port_configured, members); + return; + +err: + print_string("Error: isolate [show|off] [port]...\n"); +} + + +bool vlan_ingress_mode_parse(char c, __xdata vlan_ingress_mode_t *mode) { switch (c) { case 'u': @@ -392,7 +480,7 @@ bool vlan_ingress_mode_parse(char c, vlan_ingress_mode_t *mode) void parse_ingress(void) { - if (cmd_words_b[1] <= 0) { + if (cmd_words_len < 2) { goto err; } __xdata uint8_t log_port = 0; @@ -410,24 +498,25 @@ void parse_ingress(void) } return; } else { - for(uint8_t w = 1; cmd_words_b[w] > 0; w++) { - if (!isnumber(cmd_buffer[cmd_words_b[w]])) { + for(uint8_t w = 1; w < cmd_words_len; w++) { + uint8_t p = cmd_buffer[cmd_words_b[w]]; + if (!isnumber(p)) { continue; } - if (cmd_buffer[cmd_words_b[w]] - '1' > 9) { - print_string("Invalid physical port number: "); write_char(cmd_buffer[cmd_words_b[w]]); write_char('\n'); + if (p - '1' > 9) { + print_string("Invalid physical port number: "); write_char(p); write_char('\n'); continue; } - log_port = machine.phys_to_log_port[cmd_buffer[cmd_words_b[w]] - '1']; + log_port = machine.phys_to_log_port[p - '1']; if (!vlan_ingress_mode_parse(cmd_buffer[cmd_words_b[w] + 1], &mode)) { - print_string("Invalid ingress mode for port "); write_char(cmd_buffer[cmd_words_b[w]]); print_string(" in ingress command\n"); + print_string("Invalid ingress mode for port "); write_char(p); print_string(" in ingress command\n"); goto err; } if (!port_ingress_filter(log_port, mode)) { - print_string("Error setting ingress filter for port "); write_char(cmd_buffer[cmd_words_b[w]]); write_char('\n'); + print_string("Error setting ingress filter for port "); write_char(p); write_char('\n'); return; } - print_string("Port "); write_char(cmd_buffer[cmd_words_b[w]]); + print_string("Port "); write_char(p); print_string(" ingress filter set to: "); print_port_ingress_filter_mode(mode); write_char('\n'); } @@ -469,18 +558,19 @@ void parse_mirror(void) return; } - if (!isnumber(cmd_buffer[cmd_words_b[1]])) { - print_string("Port missing: mirror [port][t/r]...\n"); + if (cmd_words_len < 2 || !isnumber(cmd_buffer[cmd_words_b[1]])) { + print_string("Port/command missing: mirror [status/off/ [port][t/r]]...\n"); 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]; + mirroring_port = machine.phys_to_log_port[mirroring_port]; + uint8_t w = 2; - while (cmd_words_b[w] > 0) { + while (w < cmd_words_len) { uint8_t port; if (isnumber(cmd_buffer[cmd_words_b[w]])) { port = cmd_buffer[cmd_words_b[w]] - '1'; @@ -515,20 +605,47 @@ void parse_mirror(void) void parse_port(void) { - print_string("\nPORT "); + if (cmd_words_len < 3) { + print_string("\nUsage:" \ + "\nport [show|on|off]" \ + "\nport [10m|100m|1g|2g5|duplex] [half|full]" \ + "\nport name [custom port name]\n"); + return; + } + + if (cmd_buffer[cmd_words_b[1]] < '1' || cmd_buffer[cmd_words_b[1]] > '9' || cmd_buffer[cmd_words_b[1] + 1] != ' ' ) { + print_string("Illegal port number\n"); + return; + } phy_settings.port = cmd_buffer[cmd_words_b[1]] - '1'; phy_settings.port = machine.phys_to_log_port[phy_settings.port]; - print_byte(phy_settings.port); - if (machine.is_sfp[phy_settings.port]) { - 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]"); + if (phy_settings.port > machine.max_port || phy_settings.port < machine.min_port) { + print_string("This machine has no port with the specified number\n"); return; } + + print_string("Logical Port: "); print_byte(phy_settings.port); write_char('\n'); phy_settings.duplex = PHY_DUPLEX_BOTH; - if (cmd_compare(2, "10m")) { + + if (cmd_compare(2, "show")) { + print_string("Name: "); + print_string_x(port_names[phy_settings.port]); + if (!machine.is_sfp[phy_settings.port]) { + phy_show(phy_settings.port); + } + } else if (cmd_compare(2, "name")) { + uint8_t i = 0; + while ( (i < PORT_NAME_SIZE-1) && (cmd_buffer[cmd_words_b[3] + i] != '\0') ) { + port_names[phy_settings.port][i] = cmd_buffer[cmd_words_b[3] + i]; + i++; + } + port_names[phy_settings.port][i] = '\0'; + print_string("\nName set to: \""); + print_string_x(port_names[phy_settings.port]); + print_string("\"\n"); + } else if (machine.is_sfp[phy_settings.port]) { + print_string(" is SFP no PHY information available.\n"); + } else if (cmd_compare(2, "10m")) { print_string(" 10M\n"); phy_settings.speed = PHY_SPEED_10M; if (cmd_compare(3, "half")) @@ -571,9 +688,8 @@ void parse_port(void) else phy_settings.speed = PHY_DUPLEX_HALF; phy_set_duplex(); - } - if (cmd_compare(2, "show")) { - phy_show(phy_settings.port); + } else { + print_string("Unknown port command\n"); } } @@ -594,7 +710,7 @@ void parse_mtu(void) p = cmd_buffer[cmd_words_b[1]] - '1'; p = machine.phys_to_log_port[p]; print_byte(p); - if (cmd_words_b[2] <= 0) { + if (cmd_words_len != 3) { print_string("mtu [port] [size]\n"); return; } @@ -627,7 +743,7 @@ void parse_regget(void) { uint16_t reg = 0; - if (cmd_words_b[1] < 0) { + if (cmd_words_len != 2) { goto err; } @@ -662,7 +778,7 @@ void parse_regset(void) { uint16_t reg = 0; - if (cmd_words_b[2] < 0) { + if (cmd_words_len != 2) { goto err; } @@ -710,7 +826,7 @@ void parse_sdsget(void) { __xdata uint8_t sds_id, page, reg, hex_size; - if (cmd_words_b[1] < 0 || cmd_words_b[2] < 0 || cmd_words_b[3] < 0) { + if (cmd_words_len != 4) { goto err; } @@ -754,7 +870,7 @@ void parse_sdsset(void) __xdata uint8_t sds_id, page, reg, hex_size; __xdata uint16_t val; - if (cmd_words_b[1] < 0 || cmd_words_b[2] < 0 || cmd_words_b[3] < 0 || cmd_words_b[4] < 0) { + if (cmd_words_len != 5) { goto err; } @@ -809,7 +925,7 @@ void parse_phyget(void) __xdata uint8_t phy_id, dev_id, hex_size; __xdata uint16_t reg; - if (cmd_words_b[1] < 0 || cmd_words_b[2] < 0 || cmd_words_b[3] < 0) { + if (cmd_words_len != 4) { goto err; } @@ -855,7 +971,7 @@ void parse_physet(void) __xdata uint8_t phy_id, dev_id, hex_size; __xdata uint16_t reg, val; - if (cmd_words_b[1] < 0 || cmd_words_b[2] < 0 || cmd_words_b[3] < 0 || cmd_words_b[4] < 0) { + if (cmd_words_len != 5) { goto err; } @@ -925,11 +1041,15 @@ void parse_rnd(void) 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]; + // cmd_words_len can be more then 2 if a space in the password. + if (cmd_words_len >= 2) { + uint8_t i = cmd_words_b[1]; + uint8_t c = 0; + uint8_t j = 0; + do { + c = cmd_buffer[i++]; + passwd[j++] = c; + } while (c != '\0' && j < 20); passwd[j] = '\0'; return; } @@ -943,7 +1063,7 @@ void parse_eee(void) __xdata uint8_t speed = EEE_2G5; __xdata uint8_t speed_word = 0; // Check if word 2 is a speed (contains 'g' or 'm') or a port number - if (cmd_words_b[3] > 0) { + if (cmd_words_len >= 3) { uint8_t idx = cmd_words_b[2]; // Skip digits to check if there's a letter after while (isnumber(cmd_buffer[idx])) @@ -956,7 +1076,7 @@ void parse_eee(void) port = cmd_buffer[cmd_words_b[2]] - '1'; port = machine.phys_to_log_port[port]; // Check if word 3 is a speed - if (cmd_words_b[4] > 0) + if (cmd_words_len >= 4) speed_word = 3; } } @@ -1000,7 +1120,7 @@ void parse_bw(void) __xdata uint8_t port; __xdata uint32_t bw = 0; - if (cmd_words_b[3] < 0) // Check for at least 2 arguments + if (cmd_words_len < 2) // Check for at least 2 arguments goto err; port = cmd_buffer[cmd_words_b[2]] - '1'; @@ -1014,7 +1134,7 @@ void parse_bw(void) return; } - if (cmd_words_b[4] < 0) // Check for at least 3 arguments + if (cmd_words_len < 4) // Check for at least 4 arguments goto err; if (cmd_compare(3, "drop")) { @@ -1069,36 +1189,51 @@ err: } // Parse command into words -uint8_t cmd_tokenize(void) __banked +// cmd_words_len contains the number of words found. +// cmd_words_b[] contains only start of a word offset. +void 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; + err_status = ERR_OK; + uint8_t line_ptr = 0; + uint8_t is_white = 1; uint8_t word = 0; - cmd_words_b[0] = -1; - while (cmd_buffer[line_ptr] && line_ptr < CMD_BUF_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 == CMD_BUF_SIZE - 1) - return 1; - cmd_words_b[word++] = line_ptr; - cmd_words_b[word++] = -1; + uint8_t c = 0; - return 0; + while(1) { + c = cmd_buffer[line_ptr]; + + if (c == '\0') { + // Store the word count + cmd_words_len = word; + break; + } + + if (line_ptr == CMD_BUF_SIZE - 1) { + err_status = ERR_CMD_TOO_LONG; + return; + } + + if (is_white && c != ' ') { + is_white = 0; + + cmd_words_b[word++] = line_ptr; + if (word >= N_WORDS) { + cmd_words_len = 0; + print_string("\nSyntax error: too many arguments."); + err_status = ERR_TOO_MANY_ARGUMENTS; + return; + } + } else if (c == ' ') { + is_white = 1; + } + + line_ptr++; + } } // Print GPIO status @@ -1147,6 +1282,7 @@ void cmd_parser(void) __banked print_string_x(&cmd_buffer[0]); write_char('<'); write_char('\n'); print_string("CMD-words: "); + print_byte(cmd_words_len); write_char(' '); print_byte(cmd_words_b[0]); write_char(' '); print_byte(cmd_words_b[1]); write_char(' '); print_byte(cmd_words_b[2]); write_char(' '); @@ -1155,7 +1291,7 @@ void cmd_parser(void) __banked 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_words_len >= 1) { if (cmd_compare(0, "reset")) { print_string("\nRESET\n\n"); reset_chip(); @@ -1174,30 +1310,33 @@ void cmd_parser(void) __banked } } 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]] == 's') { - print_string("\nSECURITY REGISTERS\n"); - // The following will only show something else than 0xff if it was programmed for a managed switch - print_string("Region 1: "); - flash_region.addr = 0x0001000; - flash_region.len = 40; - flash_read_security(); - print_string("\nRegion 2: "); - flash_region.addr = 0x0002000; - flash_region.len = 40; - flash_read_security(); - print_string("\nRegion 3: "); - 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]] == '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 (note: only 4 bytes are likely correct here!)\n"); - flash_read_uid(); - } else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) { + } else if (cmd_compare(0, "flash") && cmd_words_len == 2) { + uint8_t c = cmd_buffer[cmd_words_b[1]]; + if (c == 's') { + print_string("\nSECURITY REGISTERS\n"); + // The following will only show something else than 0xff if it was programmed for a managed switch + print_string("Region 1: "); + flash_region.addr = 0x0001000; + flash_region.len = 40; + flash_read_security(); + print_string("\nRegion 2: "); + flash_region.addr = 0x0002000; + flash_region.len = 40; + flash_read_security(); + print_string("\nRegion 3: "); + flash_region.addr = 0x0003000; + flash_region.len = 40; + flash_read_security(); + } else if (c == 'j') { + print_string("\nJEDEC ID\n"); + flash_read_jedecid(); + } else if (c == 'u') { + print_string("\nUNIQUE ID (note: only 4 bytes are likely correct here!)\n"); + flash_read_uid(); + } + } else if (cmd_compare(0, "port")) { parse_port(); - } else if (cmd_compare(0, "mtu") && cmd_words_b[1] > 0) { + } else if (cmd_compare(0, "mtu")) { parse_mtu(); } else if (cmd_compare(0, "syslog")) { if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) { @@ -1242,7 +1381,7 @@ void cmd_parser(void) __banked } else if (cmd_compare(0, "ip")) { if (cmd_compare(1, "dhcp")) { dhcp_start(); - } else if (cmd_words_b[2] < 0) { + } else if (cmd_words_len == 1) { 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); @@ -1270,7 +1409,7 @@ void cmd_parser(void) __banked } } } else if (cmd_compare(0, "gw")) { - if (cmd_words_b[2] < 0) { + if (cmd_words_len == 1) { 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); @@ -1285,7 +1424,7 @@ void cmd_parser(void) __banked } write_char('\n'); } else if (cmd_compare(0, "netmask")) { - if (cmd_words_b[2] < 0) { + if (cmd_words_len == 1) { 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); @@ -1321,7 +1460,7 @@ void cmd_parser(void) __banked stp_off(); stpEnabled = 0; } - } else if (cmd_compare(0, "pvid") && cmd_words_b[1] > 0 && cmd_words_b[2] > 0) { + } else if (cmd_compare(0, "pvid") && cmd_words_len == 3) { __xdata uint16_t pvid; uint8_t port; port = cmd_buffer[cmd_words_b[1]] - '1'; @@ -1330,6 +1469,8 @@ void cmd_parser(void) __banked port_pvid_set(port, pvid); } else if (cmd_compare(0, "vlan")) { parse_vlan(); + } else if (cmd_compare(0, "isolate")) { + parse_isolate(); } else if (cmd_compare(0, "mirror")) { parse_mirror(); } else if (cmd_compare(0, "lag")) { @@ -1389,22 +1530,21 @@ void cmd_parser(void) __banked } - 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); - } + if (save_cmd && cmd_words_len) { + // Find end of the cmd-buffer, looking for the NULL-byte. + uint8_t i = cmd_words_b[cmd_words_len - 1]; + do { + i++; + } while(cmd_buffer[i] != '\0'); + + // Copy last cmd-buffer to history. + 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); } } } @@ -1420,15 +1560,20 @@ void clear_command_history(void) __banked #define FLASH_READ_BURST_SIZE 0x100 #define PASSWORD "1234" + +#if CONFIG_LEN % FLASH_READ_BURST_SIZE + #error "CONFIG_LEN not a multiple of FLASH_READ_BURST_SIZE" +#endif void execute_config(void) __banked { __xdata uint32_t pos = CONFIG_START; - __xdata uint16_t len_left = CONFIG_LEN; + __xdata uint8_t pages_left = CONFIG_LEN / FLASH_READ_BURST_SIZE; // Set default password, it can be overwritten in the configuration file strtox(passwd, PASSWORD); save_cmd = 0; + uint8_t cmd_idx = 0; do { flash_region.addr = pos; flash_region.len = FLASH_READ_BURST_SIZE; @@ -1437,24 +1582,36 @@ void execute_config(void) __banked __xdata uint8_t cfg_idx = 0; uint8_t c = 0; do { - for (uint8_t cmd_idx = 0; cmd_idx < (CMD_BUF_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) + if (cmd_idx >= (CMD_BUF_SIZE - 1)) { + cmd_buffer[cmd_idx] = '\0'; + print_string("ERROR: Command too long: "); + print_string_x(cmd_buffer); + write_char('\n'); + err_status = ERR_CMD_TOO_LONG; + goto config_done; + } + c = flash_buf[cfg_idx++]; + if (c == 0 || c == '\n') { + cmd_buffer[cmd_idx] = '\0'; + if (cmd_idx) { + cmd_tokenize(); + if (err_status != ERR_OK) goto config_done; - break; + cmd_parser(); } - - cmd_buffer[cmd_idx] = c; + if (c == 0) + goto config_done; + cmd_idx = 0; + continue; } - } while(cfg_idx); - len_left -= FLASH_READ_BURST_SIZE; + cmd_buffer[cmd_idx] = c; + cmd_idx++; + } while (cfg_idx); + + pages_left--; pos += FLASH_READ_BURST_SIZE; - } while(len_left); + } while(pages_left); config_done: // Start saving commands to cmd_history diff --git a/dhcp.c b/dhcp.c index 80ad865..3712827 100644 --- a/dhcp.c +++ b/dhcp.c @@ -82,7 +82,7 @@ struct dhcp_pkt { __xdata uint32_t long_value; -void dhcp_print_ip(uint8_t *a) +void dhcp_print_ip(__xdata uint8_t *a) { itoa(a[0]); write_char('.'); itoa(a[1]); write_char('.'); @@ -216,7 +216,7 @@ void dhcp_send_request(void) } -void ip_opt(uint8_t * __xdata ip) +void ip_opt(__xdata uint8_t * ip) { dhcp_state.opt_ptr++; uint8_t len = DHCP_OPT[dhcp_state.opt_ptr++]; diff --git a/dhcp.h b/dhcp.h index b9cb7c4..f51feb0 100644 --- a/dhcp.h +++ b/dhcp.h @@ -35,7 +35,7 @@ struct dhcp_state { uint32_t rebind; uint32_t renewal; - struct uip_udp_conn *conn; + __xdata struct uip_udp_conn *conn; }; typedef struct dhcp_state uip_udp_appstate_t; diff --git a/html/main.js b/html/main.js index b29ccbe..8e50017 100644 --- a/html/main.js +++ b/html/main.js @@ -9,6 +9,7 @@ var pAdvertised = new Int8Array(10); var numPorts = 0; var logToPhysPort = new Int8Array(10); var physToLogPort = new Int8Array(10); +var portNames = new Array(10); var currentRequests = []; var currentCallback; function drawPorts() { @@ -136,6 +137,7 @@ function update(callback) { let n = p.portNum; logToPhysPort[p.logPort] = n; physToLogPort[n-1] = p.logPort; + portNames[p.logPort] = p.name; let pid = "port" + n; let ttid = "tt_" + n; n--; @@ -148,12 +150,17 @@ function update(callback) { var leds = psvg.contentDocument.getElementsByClassName("led"); if (leds[0] == null || leds[0].style == null) continue; + const portName = p.name || portNames[p.logPort] || ''; + var iHTML = ""; + if (portName) iHTML += ""; if (p.enabled == 0) { pState[n] = -1; bgs[0].style.fill = "red"; leds[0].style.fill = "black"; leds[1].style.fill = "black"; psvg.style.opacity = 0.4; - tt.innerHTML = "Not enabled."; + iHTML += ""; + iHTML += "
Name:" + portName + "
Status:Not enabled.
"; + tt.innerHTML = iHTML; } else { psvg.style.opacity = 1.0; pState[n] = p.link; @@ -165,7 +172,6 @@ function update(callback) { leds[0].style.fill = "black"; leds[1].style.fill = "black"; psvg.style.opacity = 0.4 } - var iHTML = ""; iHTML += ""; if (p.isSFP) { pAdvertised[n] = 0; diff --git a/html/ports.html b/html/ports.html index 84fe41e..9e27808 100644 --- a/html/ports.html +++ b/html/ports.html @@ -11,7 +11,7 @@

Port Configuration

Link speed:" + linkS[p.link + 1] + "
- +
Port Current Link SpeedSet SpeedDisabledApply
Port Name Current Link SpeedSet SpeedDisabledApply

Configure Maximum Frame Size (MTU) forwarded at Port

diff --git a/html/ports.js b/html/ports.js index dedd741..6fc4f40 100644 --- a/html/ports.js +++ b/html/ports.js @@ -19,6 +19,8 @@ function createPortTable() { console.log("Table row: " + i + "pState: " + pState[i-2]); const tr = tbl.insertRow(); let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i}`)); + let portName = portNames[physToLogPort[i-1]] || ''; + td = tr.insertCell(); td.appendChild(document.createTextNode(portName)); td = tr.insertCell(); td.innerHTML = linkS[pState[i] + 1]; td = tr.insertCell(); td.innerHTML = sSelect.replaceAll("speed_sel", "speed_sel_" + i); td = tr.insertCell(); td.innerHTML = dSwitch.replaceAll("disable_port", "disable_port_" + i) @@ -66,7 +68,7 @@ function updatePortTable() { for (let i = 1; i <= numPorts ; i++) { if (pIsSFP[i-1]) continue; - tbl.rows[i].cells[1].innerHTML = `${linkS[pState[i-1]+1]}`; + tbl.rows[i].cells[2].innerHTML = `${linkS[pState[i-1]+1]}`; if (!clicked[i] && pState[i - 1] < 0) { document.getElementById('speed_sel_' + i).disabled = true; document.getElementById('disable_port_' + i).checked = true; diff --git a/html/stat.html b/html/stat.html index cb5cbfe..03b0367 100644 --- a/html/stat.html +++ b/html/stat.html @@ -38,7 +38,7 @@

Port Statistics

- +
Port link TX Good TX Bad RX Good RX Bad All Counters
Port Name link TX Good TX Bad RX Good RX Bad All Counters
diff --git a/html/stat.js b/html/stat.js index 51a7e10..8cb2afc 100644 --- a/html/stat.js +++ b/html/stat.js @@ -162,17 +162,19 @@ function fillStats() { if (tbl.rows.length > 1) { for (let i = 0; i < numPorts; i++) { console.log("Table Update row: " + i + " state " + pState[i] + " is " + linkS[pState[i] +1]); - tbl.rows[i+1].cells[1].innerHTML = `${linkS[pState[i]+1]}`; - tbl.rows[i+1].cells[2].innerHTML = `${txG[i]} pkts`; - tbl.rows[i+1].cells[3].innerHTML = `${txB[i]} pkts`; - tbl.rows[i+1].cells[4].innerHTML = `${rxG[i]} pkts`; - tbl.rows[i+1].cells[5].innerHTML = `${rxB[i]} pkts`; + tbl.rows[i+1].cells[2].innerHTML = `${linkS[pState[i]+1]}`; + tbl.rows[i+1].cells[3].innerHTML = `${txG[i]} pkts`; + tbl.rows[i+1].cells[4].innerHTML = `${txB[i]} pkts`; + tbl.rows[i+1].cells[5].innerHTML = `${rxG[i]} pkts`; + tbl.rows[i+1].cells[6].innerHTML = `${rxB[i]} pkts`; } } else { for (let i = 0; i < numPorts; i++) { console.log("Table row: " + i); const tr = tbl.insertRow(); let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i+1}`)); + let portName = portNames[physToLogPort[i]] || ''; + td = tr.insertCell(); td.appendChild(document.createTextNode(portName)); td = tr.insertCell(); td.appendChild(document.createTextNode(`${linkS[pState[i]+1]}`)); td = tr.insertCell(); td.appendChild(document.createTextNode(`${txG[i]} pkts`)); td = tr.insertCell();td.appendChild(document.createTextNode(`${txB[i]} pkts`)); diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 3273e57..e9f8082 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -97,7 +97,7 @@ void itoa_html(uint8_t v) char_to_html('0' + (v % 10)); } -void string_to_html(register char *s) +void string_to_html(__code char *s) { while (*s) char_to_html(*s++); } @@ -638,6 +638,11 @@ void send_status(void) itoa_html(machine.log_to_phys_port[i]); slen += strtox(outbuf + slen, ",\"logPort\":"); itoa_html(i); + slen += strtox(outbuf + slen, ",\"name\":\""); + for (uint8_t j = 0; j < PORT_NAME_SIZE && port_names[i][j]; j++) { + char_to_html(port_names[i][j]); + } + slen += strtox(outbuf + slen, "\""); if (machine.is_sfp[i]) { slen += strtox(outbuf + slen, ",\"isSFP\":1,\"enabled\":"); diff --git a/rtl837x_common.h b/rtl837x_common.h index 10cf1f8..bd2701a 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -36,12 +36,20 @@ extern __xdata uint8_t sbuf[SBUF_SIZE]; // Size of the TCP Output buffer #define TCP_OUTBUF_SIZE 2500 +// Size of the port name, including the terminating null byte +#define PORT_NAME_SIZE 32 + // Size of the memory area dedicated to VLAN-names #define VLAN_NAMES_SIZE 1024 // Size of the flash buffer used for writing to flash, must be a multiple of the flash page size (0x100) #define FLASH_BUF_SIZE 512 +// Errors for commands +#define ERR_OK 0 +#define ERR_TOO_MANY_ARGUMENTS 1 +#define ERR_CMD_TOO_LONG 2 + // For RX data, a propriatary RTL FRAME is inserted. Instead of 0x0800 for IPv4, // the RTL_FRAME_TAG_ID is used as part of an 8-byte tag. When VLAN is activated, // the VLAN tag is inserted after the RTL tag @@ -95,6 +103,8 @@ struct flash_region_t { uint16_t len; }; +extern __xdata char port_names[9][PORT_NAME_SIZE]; + extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2]; extern __xdata struct uip_eth_addr uip_ethaddr; @@ -141,7 +151,7 @@ uint16_t strcpy(register __xdata uint8_t *dst, register const char *s); void tcpip_output(void); uint8_t read_flash(uint8_t bank, __code uint8_t *addr); void get_random_32(void); -void read_reg_timer(uint32_t * tmr); +void read_reg_timer(__xdata uint32_t * tmr); void sfp_print_info(uint8_t sfp); bool gpio_pin_test(uint8_t pin); void set_sys_led_state(uint8_t state); diff --git a/rtl837x_phy.c b/rtl837x_phy.c index 0846e9c..994551c 100644 --- a/rtl837x_phy.c +++ b/rtl837x_phy.c @@ -367,12 +367,15 @@ void phy_show(uint8_t port) __banked print_string("5G"); break; default: - print_string("10M"); + print_string("Down"); + } + + if ( (((v & 0x0600) >> 7) | ((v & 0x0030) >> 4)) <= 6) { // Link is up + if (v & 0x8) + print_string(" full duplex"); + else + print_string(" half duplex"); } - if (v & 0x8) - print_string(" full duplex"); - else - print_string(" half duplex"); phy_read(port, PHY_MMD_AN, PHY_ANEG_CTRL); v = SFR_DATA_U16; diff --git a/rtl837x_port.c b/rtl837x_port.c index 250687e..ba22a0e 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -463,14 +463,14 @@ void port_stats_print(void) __banked } -void port_isolate(register uint8_t port, __xdata uint16_t pmask) +void port_isolate(register uint8_t port, __xdata uint16_t pmask) __banked { if (port <= machine.max_port) REG_SET(RTL837X_PORT_ISOLATION_BASE + (port << 2), pmask); } -uint16_t port_isolation_get(register uint8_t port) +uint16_t port_isolation_get(register uint8_t port) __banked { if (port > machine.max_port) return 0; diff --git a/rtl837x_port.h b/rtl837x_port.h index 20132fb..9be1680 100644 --- a/rtl837x_port.h +++ b/rtl837x_port.h @@ -61,4 +61,7 @@ void port_eee_status(uint8_t port) __banked; void print_port_ingress_filter_mode(vlan_ingress_mode_t mode) __banked; bool port_ingress_vlan_filter_set(__xdata uint8_t port, __xdata bool enabled) __banked; bool port_ingress_vlan_filter_get(__xdata uint8_t port) __banked; +void port_isolate(register uint8_t port, __xdata uint16_t pmask) __banked; +uint16_t port_isolation_get(register uint8_t port) __banked; + #endif diff --git a/rtlplayground.c b/rtlplayground.c index c50d7ae..8baaa21 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -711,7 +711,7 @@ void cpy_4(__xdata uint8_t dest[], __xdata uint8_t source[]) } -void read_reg_timer(uint32_t * tmr) +void read_reg_timer(__xdata uint32_t * tmr) { uint8_t * val = (uint8_t *)tmr; SFR_REG_ADDR_U16 = RTL837X_REG_SEC_COUNTER; @@ -1997,7 +1997,7 @@ void check_and_flash_update_image(void) __xdata uint16_t i = 0; __xdata uint16_t j = 0; __xdata uint8_t * __xdata bptr; - print_string("found update image! Checking integrity"); + print_string("found update image!\nChecking integrity"); flash_init(0); // Re-initialize flash for non-DIO operation, otherwise flashing will fail set_sys_led_state(SYS_LED_FAST); crc_value = 0x0000; diff --git a/uip/timer.c b/uip/timer.c index cb52151..fd1531c 100644 --- a/uip/timer.c +++ b/uip/timer.c @@ -64,7 +64,7 @@ * */ void -timer_set(struct timer *t, clock_time_t interval) +timer_set(__xdata struct timer *t, clock_time_t interval) { t->interval = interval; t->start = clock_time(); @@ -84,7 +84,7 @@ timer_set(struct timer *t, clock_time_t interval) * \sa timer_restart() */ void -timer_reset(struct timer *t) +timer_reset(__xdata struct timer *t) { t->start += t->interval; } @@ -104,7 +104,7 @@ timer_reset(struct timer *t) * \sa timer_reset() */ void -timer_restart(struct timer *t) +timer_restart(__xdata struct timer *t) { t->start = clock_time(); } @@ -121,7 +121,7 @@ timer_restart(struct timer *t) * */ int -timer_expired(struct timer *t) +timer_expired(__xdata struct timer *t) { return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval; } diff --git a/uip/timer.h b/uip/timer.h index 057bea4..ef13f78 100644 --- a/uip/timer.h +++ b/uip/timer.h @@ -76,10 +76,10 @@ struct timer { clock_time_t interval; }; -void timer_set(struct timer *t, clock_time_t interval); -void timer_reset(struct timer *t); -void timer_restart(struct timer *t); -int timer_expired(struct timer *t); +void timer_set(__xdata struct timer *t, clock_time_t interval); +void timer_reset(__xdata struct timer *t); +void timer_restart(__xdata struct timer *t); +int timer_expired(__xdata struct timer *t); #endif /* __TIMER_H__ */ diff --git a/uip/uip.c b/uip/uip.c index d65d5d7..ee07a04 100644 --- a/uip/uip.c +++ b/uip/uip.c @@ -241,7 +241,7 @@ __xdata struct uip_stats uip_stat; #if ! UIP_ARCH_ADD32 void -uip_add32(u8_t *op32, u16_t op16) +uip_add32(u8_t __xdata * op32, u16_t op16) { uip_acc32[3] = op32[3] + (op16 & 0xff); uip_acc32[2] = op32[2] + (op16 >> 8); @@ -465,8 +465,8 @@ uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport) __banke #endif /* UIP_ACTIVE_OPEN */ /*---------------------------------------------------------------------------*/ #if UIP_UDP -struct uip_udp_conn * -uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) __banked +__xdata struct uip_udp_conn * +uip_udp_new(__xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport) __banked { __xdata struct uip_udp_conn *conn; @@ -1901,7 +1901,7 @@ htons(u16_t val) } /*---------------------------------------------------------------------------*/ void -uip_send(register __xdata const void *data, register uint16_t len) __banked +uip_send(__xdata const void *data, __xdata uint16_t len) __banked { if(len > 0) { uip_slen = len; diff --git a/uip/uip.h b/uip/uip.h index 2433512..d28f295 100644 --- a/uip/uip.h +++ b/uip/uip.h @@ -495,7 +495,7 @@ void uip_unlisten(u16_t port) __banked; * or NULL if no connection could be allocated. * */ -__xdata struct uip_conn *uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t port) __banked; +__xdata struct uip_conn *uip_connect(__xdata uip_ipaddr_t *ripaddr, __xdata u16_t port) __banked; @@ -535,7 +535,7 @@ __xdata struct uip_conn *uip_connect(register __xdata uip_ipaddr_t *ripaddr, __x * * \hideinitializer */ -void uip_send(register __xdata const void *data, register uint16_t len) __banked; +void uip_send(__xdata const void *data, __xdata uint16_t len) __banked; /** * The length of any incoming data that is currently avaliable (if avaliable) @@ -763,7 +763,7 @@ void uip_send(register __xdata const void *data, register uint16_t len) __banked * \return The uip_udp_conn structure for the new connection or NULL * if no connection could be allocated. */ -struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) __banked; +__xdata struct uip_udp_conn *uip_udp_new(__xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport) __banked; /** * Removed a UDP connection. @@ -880,8 +880,8 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) __banked; */ #if !UIP_CONF_IPV6 #define uip_ipaddr_copy(dest, src) do { \ - ((u16_t *)dest)[0] = ((u16_t *)src)[0]; \ - ((u16_t *)dest)[1] = ((u16_t *)src)[1]; \ + ((__xdata u16_t *)dest)[0] = ((__xdata u16_t *)src)[0]; \ + ((__xdata u16_t *)dest)[1] = ((__xdata u16_t *)src)[1]; \ } while(0) #else /* !UIP_CONF_IPV6 */ #define uip_ipaddr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t)) @@ -908,8 +908,8 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) __banked; * \hideinitializer */ #if !UIP_CONF_IPV6 -#define uip_ipaddr_cmp(addr1, addr2) (((__xdata u16_t *)addr1)[0] == ((u16_t *)addr2)[0] && \ - ((__xdata u16_t *)addr1)[1] == ((u16_t *)addr2)[1]) +#define uip_ipaddr_cmp(addr1, addr2) (((__xdata u16_t *)addr1)[0] == ((__xdata u16_t *)addr2)[0] && \ + ((__xdata u16_t *)addr1)[1] == ((__xdata u16_t *)addr2)[1]) #define uip_ipaddr_cmpx(addr1, addr2) (((__xdata u16_t *)addr1)[0] == ((__xdata u16_t *)addr2)[0] && \ ((__xdata u16_t *)addr1)[1] == ((__xdata u16_t *)addr2)[1]) #define uip_ipaddr_cmpc(addr1, addr2) (((__xdata u16_t *)addr1)[0] == ((__code u16_t *)addr2)[0] && \ diff --git a/uip/uip_arch.h b/uip/uip_arch.h index 71fd84b..f4547d6 100644 --- a/uip/uip_arch.h +++ b/uip/uip_arch.h @@ -81,7 +81,7 @@ * * \param op16 A 16-bit integer in host byte order. */ -void uip_add32(u8_t *op32, u16_t op16); +void uip_add32(__xdata u8_t * op32, u16_t op16); /** * Calculate the Internet checksum over a buffer.