2 * Copyright (C) 2012-2013 Czech Technical University in Prague
4 * Created on: Aug 23, 2013
7 * - Jan Dolezal <pm.jenik@gmail.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 * File : cmd_netstats.c
25 * This file contains commands for net statistics (ethernet interface and LwIP)
29 #include "cmd_netstats.h"
38 #include "lwip/stats.h"
40 #define INTERFACE_INSTANCE_NUMBER 0
42 int cmd_do_read_linkstat(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
44 if(!isPostInitialized())
46 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
49 struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
50 if(rpp_eth_phylinkstat(INTERFACE_INSTANCE_NUMBER))
51 rpp_sci_printf("%c%c%d : UP\r\n", netif->name[0], netif->name[1], netif->num);
53 rpp_sci_printf("%c%c%d : DOWN\r\n", netif->name[0], netif->name[1], netif->num);
57 int cmd_do_read_mac(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
59 if(!isPostInitialized())
61 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
65 rpp_eth_get_macAddrStr(INTERFACE_INSTANCE_NUMBER,macaddr);
66 rpp_sci_printf((const char*)"%s\n", macaddr);
70 int cmd_do_read_ip(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
72 if(!isPostInitialized())
74 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
77 struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
79 rpp_eth_getIPDecimalStr(netif->ip_addr, ipString);
80 rpp_sci_printf("Address: %s\r\n", ipString);
81 rpp_eth_getIPDecimalStr(netif->netmask, ipString);
82 rpp_sci_printf("Netmask: %s\r\n", ipString);
83 rpp_eth_getIPDecimalStr(netif->gw, ipString);
84 rpp_sci_printf("Gateway: %s\r\n", ipString);
91 /* --- EMAC DESCRIPTOR FORMAT ---
94 * OFFSET | 31 16 | 15 0
95 * ------------------------------------------------------------------------------------
96 * 0 | *Next Descriptor Pointer
97 * 1 | *Data Buffer Pointer
98 * 2 | Buffer Offset | Buffer Length
99 * 3 | Flags | Packet Length
103 boolean_t bd_SOP(volatile struct emac_tx_bd *bufferDescriptor)
105 return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_SOP);
108 boolean_t bd_EOP(volatile struct emac_tx_bd *bufferDescriptor)
110 return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_EOP);
113 boolean_t bd_OWNER(volatile struct emac_tx_bd *bufferDescriptor)
115 return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_OWNER);
118 boolean_t bd_EOQ(volatile struct emac_tx_bd *bufferDescriptor)
120 return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_EOQ);
123 uint32_t bd_addr(uint16_t bd_num)
125 return EMAC_CTRL_RAM_BASE_m(0) + bd_num*sizeof(struct emac_tx_bd);
128 volatile struct emac_tx_bd *findPreviousBD(volatile struct emac_tx_bd *bufferDescriptor)
130 volatile struct emac_tx_bd *temporary = bufferDescriptor - 1;
132 /* first try space before given bd */
133 if((uint32_t) temporary >= EMAC_CTRL_RAM_BASE_m(0) && temporary->next == bufferDescriptor)
135 temporary = bufferDescriptor->next;
136 while(temporary != bufferDescriptor && temporary != NULL)
138 if(temporary->next == bufferDescriptor)
140 temporary = (temporary + 1); /* going through memory, if you want to go through bd chains put here 'temporary = temporary->next;' */
141 if( (uint32_t)(temporary+1) > EMAC_CTRL_RAM_BASE_m(0)+SIZE_EMAC_CTRL_RAM){ /* when out of CPPI RAM */
142 temporary = (struct emac_tx_bd *) EMAC_CTRL_RAM_BASE_m(0); /* continue scanning from the beginning */
145 return (struct emac_tx_bd *)-1; /* not found */
148 void print_bd_content(volatile struct emac_tx_bd *bufferDescriptor, boolean_t humanReadable)
151 rpp_sci_printf("Buffer Descriptor at 0x%08x\n", bufferDescriptor);
152 rpp_sci_printf("Next BD:\t0x%08x\n", bufferDescriptor->next);
153 rpp_sci_printf("Data ptr:\t0x%08x\n", bufferDescriptor->bufptr);
154 rpp_sci_printf("Buf offset:\t%d\tBuf length:\t%d\n", (bufferDescriptor->bufoff_len >> 16), (bufferDescriptor->bufoff_len & 0xffff));
157 rpp_sci_printf("Flags:\t\t0x%04x\t", (bufferDescriptor->flags_pktlen >> 16));
161 data = bufferDescriptor->flags_pktlen;
162 rpp_sci_printf("Flags:\t%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", (data & EMAC_DSC_FLAG_SOP)?"SOP":"", (data & EMAC_DSC_FLAG_EOP)?"EOP":"", (data & EMAC_DSC_FLAG_OWNER)?"OWNER":"", (data & EMAC_DSC_FLAG_EOQ)?"EOQ":"", (data & EMAC_DSC_FLAG_TDOWNCMPLT)?"TDWN":"", (data & EMAC_DSC_FLAG_PASSCRC)?"PSCRC":"", (data & EMAC_DSC_FLAG_JABBER)?"JBR":"", (data & EMAC_DSC_FLAG_OVERSIZE)?"OVSZ":"", (data & EMAC_DSC_FLAG_FRAGMENT)?"FRGM":"", (data & EMAC_DSC_FLAG_UNDERSIZED)?"UNSZ":"", (data & EMAC_DSC_FLAG_CONTROL)?"CTRL":"", (data & EMAC_DSC_FLAG_OVERRUN)?"OVRUN":"", (data & EMAC_DSC_FLAG_CODEERROR)?"CODEERR":"", (data & EMAC_DSC_FLAG_ALIGNERROR)?"ALGNERR":"", (data & EMAC_DSC_FLAG_CRCERROR)?"CRCERR":"", (data & EMAC_DSC_FLAG_NOMATCH)?"NOMATCH":"");
164 rpp_sci_printf("Pkt length:\t%d\n", (bufferDescriptor->flags_pktlen & 0xffff));
165 rpp_sci_printf("Pbuf ptr:\t0x%08x\n", bufferDescriptor->pbuf);
169 * mode: 0 flags -> param says which flag (0-15)
170 * 1 bd->next == NULL, no param
172 void print_bds_state(uint8_t mode, uint8_t param)
174 volatile struct emac_tx_bd *bufferDescriptor = (struct emac_tx_bd *) EMAC_CTRL_RAM_BASE_m(0);
176 rpp_sci_printf("TX:");
181 if(!(index%50))rpp_sci_printf("\n");
184 rpp_sci_printf("\nRX: ");
187 if(bufferDescriptor->flags_pktlen & ((1 << 15) >> (param%16))){
193 if(bufferDescriptor->next == NULL){
202 rpp_sci_printf("\n");
207 unsigned long readNum(uint8_t minamount, uint8_t maxamount, boolean_t hex){
208 unsigned long out = 0;
209 uint8_t input_buffer[BUF_SIZE];
210 uint8_t buf_index = 0;
213 input = rpp_sci_getc();
214 if(input == '\b' && buf_index>0){
215 input_buffer[buf_index] = '\0';
220 }else if(buf_index>=maxamount){
222 }else if(input <= '9' && input >= '0'){
223 input_buffer[buf_index] = input - '0';
226 }else if(hex && (input <= 'f' && input >= 'a')){
227 input_buffer[buf_index] = input - ('a' - 10);
230 }else if(hex && (input <= 'F' && input >= 'A')){
231 input_buffer[buf_index] = input - ('A' - 10);
232 echo((input + ('a' - 'A')));
235 }while( (input != '\r' && input != '\n' && buf_index<BUF_SIZE) || buf_index<minamount);
236 input = 0; /* use as index */
237 while(input < buf_index){
239 out = (out << 4) + input_buffer[input];
241 out = (out*10) + input_buffer[input];
248 int cmd_do_bufferdescriptors(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
252 volatile struct emac_tx_bd *bufferDescriptor;
253 boolean_t run = TRUE, interactive = FALSE, overview = FALSE;
255 boolean_t isrRun = FALSE, rb = FALSE, tb = FALSE;
258 /* if eth not initialized return */
259 if(!isPostInitialized())
261 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
265 /* examine parameters */
266 for(pindex = 1;param[pindex] != 0;pindex++)
268 if (strncmp((char *) param[pindex], "-i", 3) == 0) {
271 } else if (strncmp((char *) param[pindex], "-o", 3) == 0) {
276 else if (strncmp((char *) param[pindex], "-r", 3) == 0) {
280 else if (strncmp((char *) param[pindex], "-rb", 4) == 0) {
283 } else if (strncmp((char *) param[pindex], "-tb", 4) == 0) {
289 struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
292 rpp_sci_printf("netif err\n");
298 input = rpp_sci_getc();
300 if(input == 'b'){ /* print buffer descriptor at given address */
301 rpp_sci_printf("-? 0x");
302 bufferDescriptor = (struct emac_tx_bd *) readNum(8,8,TRUE);
303 rpp_sci_printf("\n");
304 /* check it fits EMAC CPPI RAM */
305 /*if(bufferDescriptor >= EMAC_CTRL_RAM_BASE_m(INTERFACE_INSTANCE_NUMBER) && (bufferDescriptor + sizeof(struct emac_tx_bd)) <= EMAC_CTRL_RAM_BASE_m(INTERFACE_INSTANCE_NUMBER) + SIZE_EMAC_CTRL_RAM)
307 print_bd_content(bufferDescriptor, FALSE);
311 rpp_sci_printf("address not from BD CPPI RAM range\n");
314 input = rpp_sci_getc();
315 if (input == 'n'){ /* next */
316 bufferDescriptor = bufferDescriptor->next;
317 if(bufferDescriptor != NULL){
318 print_bd_content(bufferDescriptor, FALSE);
320 rpp_sci_printf("NULL\n");
323 }else if(input == 'p'){ /* previous */
324 bufferDescriptor = findPreviousBD(bufferDescriptor);
325 if((int32_t)bufferDescriptor != -1)
327 if(bufferDescriptor == NULL){
328 rpp_sci_printf("NULL\n");
331 print_bd_content(bufferDescriptor, FALSE);
336 rpp_sci_printf("not found\n");
339 }else if(input == 'r'){ /* reprint */
340 if((int32_t)bufferDescriptor == -1 || bufferDescriptor == NULL)break;
341 print_bd_content(bufferDescriptor, FALSE);
346 if (input == 'q'){ /* quit */
351 else if(input == 's'){ /* general statistics */
353 }else if(input == 't'){ /* print tx channel */
354 print_tx_channel_stat();
356 }else if(input == 'r'){ /* print rx channel */
357 print_rx_channel_stat();
361 else if(input == 'a'){ /* autocheck consistency of buffer descriptors */
363 }else if(input == 'o'){ /* overview */
364 uint8_t mode = rpp_sci_getc() - '0';
365 uint8_t param = rpp_sci_getc() - '0';
366 print_bds_state(mode, param);
367 }else if(input == 'c'){ /* convert */
368 rpp_sci_printf("0x%08x", bd_addr((uint16_t)readNum(1, 3, FALSE)));
374 rpp_sci_printf(" --- OVERVIEWS ---\n");
375 rpp_sci_printf("bd->next points to NULL\n");
376 print_bds_state(1, 0);
377 rpp_sci_printf("bds with EMAC_DSC_FLAG_SOP\n");
378 print_bds_state(0, 0);
379 rpp_sci_printf("bds with EMAC_DSC_FLAG_EOP\n");
380 print_bds_state(0, 1);
381 rpp_sci_printf("bds with EMAC_DSC_FLAG_OWNER\n");
382 print_bds_state(0, 2);
383 rpp_sci_printf("bds with EMAC_DSC_FLAG_EOQ\n");
384 print_bds_state(0, 3);
385 rpp_sci_printf("bds with EMAC_DSC_FLAG_TDOWNCMPLT\n");
386 print_bds_state(0, 4);
387 rpp_sci_printf("bds with EMAC_DSC_FLAG_PASSCRC\n");
388 print_bds_state(0, 5);
389 rpp_sci_printf("\nPress any key ...\r");
391 /* These flags are not so much important */
392 rpp_sci_printf("bds with EMAC_DSC_FLAG_JABBER\n");
393 print_bds_state(0, 6);
394 rpp_sci_printf("bds with EMAC_DSC_FLAG_OVERSIZE\n");
395 print_bds_state(0, 7);
396 rpp_sci_printf("bds with EMAC_DSC_FLAG_FRAGMENT\n");
397 print_bds_state(0, 8);
398 rpp_sci_printf("bds with EMAC_DSC_FLAG_UNDERSIZED\n");
399 print_bds_state(0, 9);
400 rpp_sci_printf("bds with EMAC_DSC_FLAG_CONTROL\n");
401 print_bds_state(0, 10);
402 rpp_sci_printf("bds with EMAC_DSC_FLAG_OVERRUN\n");
403 print_bds_state(0, 11);
404 rpp_sci_printf("bds with EMAC_DSC_FLAG_CODEERROR\n");
405 print_bds_state(0, 12);
406 rpp_sci_printf("bds with EMAC_DSC_FLAG_ALIGNERROR\n");
407 print_bds_state(0, 13);
408 rpp_sci_printf("bds with EMAC_DSC_FLAG_CRCERROR\n");
409 print_bds_state(0, 14);
410 rpp_sci_printf("bds with EMAC_DSC_FLAG_NOMATCH\n");
411 print_bds_state(0, 15);
415 rpp_sci_printf(" --- NUMBER OF ISR RUNS ---\n");
416 rpp_sci_printf("TxIsr: %d", countEMACCore0TxIsr);
417 rpp_sci_printf("RxIsr: %d", countEMACCore0RxIsr);
427 int cmd_do_dhcp(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
429 if(!isPostInitialized())
431 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
434 rpp_sci_printf("not implemented yet.");
439 #if LWIP_STATS_DISPLAY
440 int cmd_do_lwip(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
442 if(!isPostInitialized())
444 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
448 rpp_sci_printf("\n");
453 int cmd_do_ethinit(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
455 int8_t retVal = rpp_eth_init_postInit(0, NULL); /* post OS startup init of eth (LwIP) for application usage -- waits for a while, for auto-negotiation of ethernet speed and DHCP if used */
459 rpp_sci_printf("already initialized\n");
462 rpp_sci_printf("initialization of physical part of ethernet failed\n");
465 rpp_sci_printf("DHCP couldn't be started due to insufficient memory\n");
468 rpp_sci_printf("cable is not connected\n");
471 rpp_sci_printf("ethinit DONE\n");
478 cmd_des_t const cmd_des_linkstat={
480 "ethlinkstat","Print current status of ethernet interface",
482 "### Command syntax ###\n"
486 "### Description ###\n"
488 "This command reads PHY link status assigned to ethernet interface and\n"
489 "prints interface name and informs about PHY's status to the output.\n"
498 CMD_HANDLER(cmd_do_read_linkstat), (void *)&cmd_list_netstats
501 cmd_des_t const cmd_des_mac={
503 "ethmac","Print current MAC address of ethernet interface",
505 "### Command syntax ###\n"
509 "### Description ###\n"
511 "This command obtains MAC address from ethernet interface structure\n"
512 "and prints it to the output.\n"
517 " 12:34:56:78:9a:bc\n",
518 CMD_HANDLER(cmd_do_read_mac), (void *)&cmd_list_netstats
521 cmd_des_t const cmd_des_ip={
523 "ethip","Print current IP address of network interface",
525 "### Command syntax ###\n"
529 "### Description ###\n"
531 "This command reads current IP address, netmask and gateway of network\n"
532 "interface and prints these to the output.\n"
537 " Address: 192.168.247.1\n"
538 " Netmask: 255.255.255.0\n"
539 " Gateway: 192.168.247.255\n",
540 CMD_HANDLER(cmd_do_read_ip), (void *)&cmd_list_netstats
543 cmd_des_t const cmd_des_bufferdescriptors={
545 "ethbd","Examine emac buffer descriptors",
547 "### Command syntax ###\n"
551 "### Description ###\n"
552 "After startup you use keys to control what will be done.\n"
555 "- s - general statistics\n"
556 "- t - transmit channel status\n"
557 "- r - receive channel status\n"
558 "- b - after giving address of bd it prints bd content\n"
559 "- a - checks consistency of buffer descriptors\n"
565 CMD_HANDLER(cmd_do_bufferdescriptors), (void *)&cmd_list_netstats
569 cmd_des_t const cmd_des_dhcp={
571 "dhcp","Prints and controls DHCP",
573 "### Command syntax ###\n"
577 "### Description ###\n"
586 CMD_HANDLER(cmd_do_dhcp), (void *)&cmd_list_netstats
590 #if LWIP_STATS_DISPLAY
591 cmd_des_t const cmd_des_lwip={
593 "lwip","Prints statistics for the LwIP stack",
595 "### Command syntax ###\n"
599 "### Description ###\n"
601 "Sections printed:\n"
612 "MEM TCP_PCB_LISTEN\n"
616 "MEM TCPIP_MSG_API\n"
617 "MEM TCPIP_MSG_INPKT\n"
623 "Shown sections depends on modules compiled in.\n"
625 CMD_HANDLER(cmd_do_lwip), (void *)&cmd_list_netstats
629 cmd_des_t const cmd_des_ethinit={
631 "ethinit","Post OS startup eth initialization",
633 "### Command syntax ###\n"
637 "### Description ###\n"
638 "This command finishes autonegotiation of PHY and initialize LwIP stack.\n"
645 CMD_HANDLER(cmd_do_ethinit), (void *)&cmd_list_netstats
648 /** List of commands for lwip, defined as external */
649 cmd_des_t const *cmd_list_netstats[]={
653 &cmd_des_bufferdescriptors,
657 #if LWIP_STATS_DISPLAY