2 * Copyright (C) 2012-2013 Czech Technical University in Prague
4 * Created on: Aug 23, 2013
7 * - Jan Dolezal <pm.jenik@gmail.com>
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
30 * File : cmd_netstats.c
33 * This file contains commands for net statistics (ethernet interface and LwIP)
37 #include "cmd_netstats.h"
46 #include "lwip/stats.h"
48 #define INTERFACE_INSTANCE_NUMBER 0
50 int cmd_do_read_linkstat(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
52 if (!isPostInitialized()) {
53 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
56 struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
57 if (rpp_eth_phylinkstat(INTERFACE_INSTANCE_NUMBER))
58 rpp_sci_printf("%c%c%d : UP\r\n", netif->name[0], netif->name[1], netif->num);
60 rpp_sci_printf("%c%c%d : DOWN\r\n", netif->name[0], netif->name[1], netif->num);
64 int cmd_do_read_mac(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
66 if (!isPostInitialized()) {
67 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
71 rpp_eth_get_macAddrStr(INTERFACE_INSTANCE_NUMBER,macaddr);
72 rpp_sci_printf((const char *)"%s\n", macaddr);
76 int cmd_do_read_ip(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
78 if (!isPostInitialized()) {
79 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
82 struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
84 rpp_eth_getIPDecimalStr(netif->ip_addr, ipString);
85 rpp_sci_printf("Address: %s\r\n", ipString);
86 rpp_eth_getIPDecimalStr(netif->netmask, ipString);
87 rpp_sci_printf("Netmask: %s\r\n", ipString);
88 rpp_eth_getIPDecimalStr(netif->gw, ipString);
89 rpp_sci_printf("Gateway: %s\r\n", ipString);
96 /* --- EMAC DESCRIPTOR FORMAT ---
99 * OFFSET | 31 16 | 15 0
100 * ------------------------------------------------------------------------------------
101 * 0 | *Next Descriptor Pointer
102 * 1 | *Data Buffer Pointer
103 * 2 | Buffer Offset | Buffer Length
104 * 3 | Flags | Packet Length
108 boolean_t bd_SOP(volatile struct emac_tx_bd *bufferDescriptor)
110 return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_SOP);
113 boolean_t bd_EOP(volatile struct emac_tx_bd *bufferDescriptor)
115 return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_EOP);
118 boolean_t bd_OWNER(volatile struct emac_tx_bd *bufferDescriptor)
120 return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_OWNER);
123 boolean_t bd_EOQ(volatile struct emac_tx_bd *bufferDescriptor)
125 return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_EOQ);
128 uint32_t bd_addr(uint16_t bd_num)
130 return EMAC_CTRL_RAM_BASE_m(0) + bd_num*sizeof(struct emac_tx_bd);
133 volatile struct emac_tx_bd *findPreviousBD(volatile struct emac_tx_bd *bufferDescriptor)
135 volatile struct emac_tx_bd *temporary = bufferDescriptor - 1;
137 /* first try space before given bd */
138 if ((uint32_t)temporary >= EMAC_CTRL_RAM_BASE_m(0) && temporary->next == bufferDescriptor)
140 temporary = bufferDescriptor->next;
141 while (temporary != bufferDescriptor && temporary != NULL) {
142 if (temporary->next == bufferDescriptor)
144 temporary = (temporary + 1); /* going through memory, if you want to go through bd chains put here 'temporary = temporary->next;' */
145 if ( (uint32_t)(temporary+1) > EMAC_CTRL_RAM_BASE_m(0)+SIZE_EMAC_CTRL_RAM) /* when out of CPPI RAM */
146 temporary = (struct emac_tx_bd *)EMAC_CTRL_RAM_BASE_m(0); /* continue scanning from the beginning */
148 return (struct emac_tx_bd *)-1; /* not found */
151 void print_bd_content(volatile struct emac_tx_bd *bufferDescriptor, boolean_t humanReadable)
155 rpp_sci_printf("Buffer Descriptor at 0x%08x\n", bufferDescriptor);
156 rpp_sci_printf("Next BD:\t0x%08x\n", bufferDescriptor->next);
157 rpp_sci_printf("Data ptr:\t0x%08x\n", bufferDescriptor->bufptr);
158 rpp_sci_printf("Buf offset:\t%d\tBuf length:\t%d\n", (bufferDescriptor->bufoff_len >> 16), (bufferDescriptor->bufoff_len & 0xffff));
160 rpp_sci_printf("Flags:\t\t0x%04x\t", (bufferDescriptor->flags_pktlen >> 16));
163 data = bufferDescriptor->flags_pktlen;
164 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" : "");
166 rpp_sci_printf("Pkt length:\t%d\n", (bufferDescriptor->flags_pktlen & 0xffff));
167 rpp_sci_printf("Pbuf ptr:\t0x%08x\n", bufferDescriptor->pbuf);
171 * mode: 0 flags -> param says which flag (0-15)
172 * 1 bd->next == NULL, no param
174 void print_bds_state(uint8_t mode, uint8_t param)
176 volatile struct emac_tx_bd *bufferDescriptor = (struct emac_tx_bd *)EMAC_CTRL_RAM_BASE_m(0);
179 rpp_sci_printf("TX:");
180 while (index < 409) {
183 if (!(index%50)) rpp_sci_printf("\n");
186 rpp_sci_printf("\nRX: ");
188 if (bufferDescriptor->flags_pktlen & ((1 << 15) >> (param%16)))
193 else if (mode == 1) {
194 if (bufferDescriptor->next == NULL)
203 rpp_sci_printf("\n");
208 unsigned long readNum(uint8_t minamount, uint8_t maxamount, boolean_t hex)
210 unsigned long out = 0;
211 uint8_t input_buffer[BUF_SIZE];
212 uint8_t buf_index = 0;
216 input = rpp_sci_getc();
217 if (input == '\b' && buf_index > 0) {
218 input_buffer[buf_index] = '\0';
224 else if (buf_index >= maxamount)
226 else if (input <= '9' && input >= '0') {
227 input_buffer[buf_index] = input - '0';
231 else if (hex && (input <= 'f' && input >= 'a')) {
232 input_buffer[buf_index] = input - ('a' - 10);
236 else if (hex && (input <= 'F' && input >= 'A')) {
237 input_buffer[buf_index] = input - ('A' - 10);
238 echo((input + ('a' - 'A')));
241 } while ( (input != '\r' && input != '\n' && buf_index < BUF_SIZE) || buf_index < minamount);
242 input = 0; /* use as index */
243 while (input < buf_index) {
245 out = (out << 4) + input_buffer[input];
247 out = (out*10) + input_buffer[input];
253 int cmd_do_bufferdescriptors(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
257 volatile struct emac_tx_bd *bufferDescriptor;
258 boolean_t run = TRUE, interactive = FALSE, overview = FALSE;
261 boolean_t isrRun = FALSE, rb = FALSE, tb = FALSE;
264 /* if eth not initialized return */
265 if (!isPostInitialized()) {
266 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
270 /* examine parameters */
271 for (pindex = 1; param[pindex] != 0; pindex++) {
272 if (strncmp((char *)param[pindex], "-i", 3) == 0) {
276 else if (strncmp((char *)param[pindex], "-o", 3) == 0) {
281 else if (strncmp((char *)param[pindex], "-r", 3) == 0) {
285 else if (strncmp((char *)param[pindex], "-rb", 4) == 0) {
289 else if (strncmp((char *)param[pindex], "-tb", 4) == 0) {
295 struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
297 rpp_sci_printf("netif err\n");
303 input = rpp_sci_getc();
305 if (input == 'b') { /* print buffer descriptor at given address */
306 rpp_sci_printf("-? 0x");
307 bufferDescriptor = (struct emac_tx_bd *)readNum(8,8,TRUE);
308 rpp_sci_printf("\n");
309 /* check it fits EMAC CPPI RAM */
310 /*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)
312 print_bd_content(bufferDescriptor, FALSE);
316 rpp_sci_printf("address not from BD CPPI RAM range\n");
319 input = rpp_sci_getc();
320 if (input == 'n') { /* next */
321 bufferDescriptor = bufferDescriptor->next;
322 if (bufferDescriptor != NULL)
323 print_bd_content(bufferDescriptor, FALSE);
325 rpp_sci_printf("NULL\n");
329 else if (input == 'p') { /* previous */
330 bufferDescriptor = findPreviousBD(bufferDescriptor);
331 if ((int32_t)bufferDescriptor != -1) {
332 if (bufferDescriptor == NULL) {
333 rpp_sci_printf("NULL\n");
337 print_bd_content(bufferDescriptor, FALSE);
341 rpp_sci_printf("not found\n");
345 else if (input == 'r') { /* reprint */
346 if ((int32_t)bufferDescriptor == -1 || bufferDescriptor == NULL) break;
347 print_bd_content(bufferDescriptor, FALSE);
353 if (input == 'q') { /* quit */
358 else if (input == 's') /* general statistics */
360 else if (input == 't') { /* print tx channel */
361 print_tx_channel_stat();
364 else if (input == 'r') { /* print rx channel */
365 print_rx_channel_stat();
369 else if (input == 'a') { /* autocheck consistency of buffer descriptors */
372 else if (input == 'o') { /* overview */
373 uint8_t mode = rpp_sci_getc() - '0';
374 uint8_t param = rpp_sci_getc() - '0';
375 print_bds_state(mode, param);
377 else if (input == 'c') /* convert */
378 rpp_sci_printf("0x%08x", bd_addr((uint16_t)readNum(1, 3, FALSE)));
383 rpp_sci_printf(" --- OVERVIEWS ---\n");
384 rpp_sci_printf("bd->next points to NULL\n");
385 print_bds_state(1, 0);
386 rpp_sci_printf("bds with EMAC_DSC_FLAG_SOP\n");
387 print_bds_state(0, 0);
388 rpp_sci_printf("bds with EMAC_DSC_FLAG_EOP\n");
389 print_bds_state(0, 1);
390 rpp_sci_printf("bds with EMAC_DSC_FLAG_OWNER\n");
391 print_bds_state(0, 2);
392 rpp_sci_printf("bds with EMAC_DSC_FLAG_EOQ\n");
393 print_bds_state(0, 3);
394 rpp_sci_printf("bds with EMAC_DSC_FLAG_TDOWNCMPLT\n");
395 print_bds_state(0, 4);
396 rpp_sci_printf("bds with EMAC_DSC_FLAG_PASSCRC\n");
397 print_bds_state(0, 5);
398 rpp_sci_printf("\nPress any key ...\r");
400 /* These flags are not so much important */
401 rpp_sci_printf("bds with EMAC_DSC_FLAG_JABBER\n");
402 print_bds_state(0, 6);
403 rpp_sci_printf("bds with EMAC_DSC_FLAG_OVERSIZE\n");
404 print_bds_state(0, 7);
405 rpp_sci_printf("bds with EMAC_DSC_FLAG_FRAGMENT\n");
406 print_bds_state(0, 8);
407 rpp_sci_printf("bds with EMAC_DSC_FLAG_UNDERSIZED\n");
408 print_bds_state(0, 9);
409 rpp_sci_printf("bds with EMAC_DSC_FLAG_CONTROL\n");
410 print_bds_state(0, 10);
411 rpp_sci_printf("bds with EMAC_DSC_FLAG_OVERRUN\n");
412 print_bds_state(0, 11);
413 rpp_sci_printf("bds with EMAC_DSC_FLAG_CODEERROR\n");
414 print_bds_state(0, 12);
415 rpp_sci_printf("bds with EMAC_DSC_FLAG_ALIGNERROR\n");
416 print_bds_state(0, 13);
417 rpp_sci_printf("bds with EMAC_DSC_FLAG_CRCERROR\n");
418 print_bds_state(0, 14);
419 rpp_sci_printf("bds with EMAC_DSC_FLAG_NOMATCH\n");
420 print_bds_state(0, 15);
424 rpp_sci_printf(" --- NUMBER OF ISR RUNS ---\n");
425 rpp_sci_printf("TxIsr: %d", countEMACCore0TxIsr);
426 rpp_sci_printf("RxIsr: %d", countEMACCore0RxIsr);
436 int cmd_do_dhcp(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
438 if (!isPostInitialized()) {
439 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
442 rpp_sci_printf("not implemented yet.");
447 #if LWIP_STATS_DISPLAY
448 int cmd_do_lwip(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
450 if (!isPostInitialized()) {
451 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
455 rpp_sci_printf("\n");
460 int cmd_do_ethinit(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
462 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 */
466 rpp_sci_printf("already initialized\n");
469 rpp_sci_printf("initialization of physical part of ethernet failed\n");
472 rpp_sci_printf("DHCP couldn't be started due to insufficient memory\n");
475 rpp_sci_printf("cable is not connected\n");
478 rpp_sci_printf("ethinit DONE\n");
485 cmd_des_t const cmd_des_linkstat = {
487 "ethlinkstat","Print current status of ethernet interface",
489 "### Command syntax ###\n"
493 "### Description ###\n"
495 "This command reads PHY link status assigned to ethernet interface and\n"
496 "prints interface name and informs about PHY's status to the output.\n"
505 CMD_HANDLER(cmd_do_read_linkstat), (void *)&cmd_list_netstats
508 cmd_des_t const cmd_des_mac = {
510 "ethmac","Print current MAC address of ethernet interface",
512 "### Command syntax ###\n"
516 "### Description ###\n"
518 "This command obtains MAC address from ethernet interface structure\n"
519 "and prints it to the output.\n"
524 " 12:34:56:78:9a:bc\n",
525 CMD_HANDLER(cmd_do_read_mac), (void *)&cmd_list_netstats
528 cmd_des_t const cmd_des_ip = {
530 "ethip","Print current IP address of network interface",
532 "### Command syntax ###\n"
536 "### Description ###\n"
538 "This command reads current IP address, netmask and gateway of network\n"
539 "interface and prints these to the output.\n"
544 " Address: 192.168.247.1\n"
545 " Netmask: 255.255.255.0\n"
546 " Gateway: 192.168.247.255\n",
547 CMD_HANDLER(cmd_do_read_ip), (void *)&cmd_list_netstats
550 cmd_des_t const cmd_des_bufferdescriptors = {
552 "ethbd","Examine emac buffer descriptors",
554 "### Command syntax ###\n"
558 "### Description ###\n"
559 "After startup you use keys to control what will be done.\n"
562 "- s - general statistics\n"
563 "- t - transmit channel status\n"
564 "- r - receive channel status\n"
565 "- b - after giving address of bd it prints bd content\n"
566 "- a - checks consistency of buffer descriptors\n"
572 CMD_HANDLER(cmd_do_bufferdescriptors), (void *)&cmd_list_netstats
576 cmd_des_t const cmd_des_dhcp = {
578 "dhcp","Prints and controls DHCP",
580 "### Command syntax ###\n"
584 "### Description ###\n"
593 CMD_HANDLER(cmd_do_dhcp), (void *)&cmd_list_netstats
597 #if LWIP_STATS_DISPLAY
598 cmd_des_t const cmd_des_lwip = {
600 "lwip","Prints statistics for the LwIP stack",
602 "### Command syntax ###\n"
606 "### Description ###\n"
608 "Sections printed:\n"
619 "MEM TCP_PCB_LISTEN\n"
623 "MEM TCPIP_MSG_API\n"
624 "MEM TCPIP_MSG_INPKT\n"
630 "Shown sections depends on modules compiled in.\n",
631 CMD_HANDLER(cmd_do_lwip), (void *)&cmd_list_netstats
633 #endif /* if LWIP_STATS_DISPLAY */
635 cmd_des_t const cmd_des_ethinit = {
637 "ethinit","Post OS startup eth initialization",
639 "### Command syntax ###\n"
643 "### Description ###\n"
644 "This command finishes autonegotiation of PHY and initialize LwIP stack.\n"
650 CMD_HANDLER(cmd_do_ethinit), (void *)&cmd_list_netstats
653 /** List of commands for lwip, defined as external */
654 cmd_des_t const *cmd_list_netstats[] = {
658 &cmd_des_bufferdescriptors,
662 #if LWIP_STATS_DISPLAY