Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / stallion / stlstats / stlstats.c
1 /*****************************************************************************/
2
3 /*
4  * stlstats.c  -- stallion intelligent multiport stats display.
5  *
6  * Copyright (c) 1994-1998 Greg Ungerer (gerg@stallion.oz.au).
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Greg Ungerer.
20  * 4. Neither the name of the author nor the names of any co-contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * $FreeBSD: src/usr.sbin/stallion/stlstats/stlstats.c,v 1.9.2.1 2001/08/30 12:29:58 murray Exp $
37  * $DragonFly: src/usr.sbin/stallion/stlstats/stlstats.c,v 1.2 2003/06/17 04:30:03 dillon Exp $
38  */
39
40 /*****************************************************************************/
41
42 #include <err.h>
43 #include <fcntl.h>
44 #include <ncurses.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <time.h>
49 #include <unistd.h>
50 #include <sys/stat.h>
51 #include <sys/ioctl.h>
52
53 #include <machine/cdk.h>
54 #include <machine/comstats.h>
55
56 /*****************************************************************************/
57
58 char    *version = "2.0.0";
59 char    *defdevice = "/dev/staliomem0";
60
61 char    *ctrldevice;
62 int     ctrlfd;
63 int     displaybrdnr = 0;
64 int     displaypanelnr = 0;
65 int     displayportnr = 0;
66 int     displayportbank = 0;
67
68 #define MAXBRDS         8
69 #define MAXPORTS        32
70
71 combrd_t        brdstats;
72 comstats_t      stats[MAXPORTS];
73
74 char    *line = "                                                                                ";
75
76 /*****************************************************************************/
77
78 /*
79  *      Declare internal function prototypes here.
80  */
81 static void     usage(void);
82 void    useportdevice(char *devname);
83 void    localexit(int nr);
84 void    menuport();
85 void    displayport();
86 void    menuallports();
87 void    displayallports();
88 void    getallstats();
89 void    getbrdstats();
90 void    clearportstats();
91 void    clearallstats();
92
93 /*****************************************************************************/
94
95 static void usage()
96 {
97         fprintf(stderr, "%s\n%s\n",
98         "usage: stlstats [-hVi] [-c control-device] [-b board-number]",
99         "                [-p port-number] [-d port-device]");
100         exit(0);
101 }
102
103 /*****************************************************************************/
104
105 void useportdevice(char *devname)
106 {
107         struct stat     statinfo;
108         int             portnr, portcnt;
109         int             i;
110
111         if (stat(devname, &statinfo) < 0)
112                 errx(1, "port device %s does not exist", devname);
113         if ((statinfo.st_mode & S_IFMT) != S_IFCHR)
114                 errx(1, "port device %s is not a char device", devname);
115
116         displaybrdnr = (statinfo.st_rdev & 0x00700000) >> 20;
117         portnr = (statinfo.st_rdev & 0x1f) |
118                 ((statinfo.st_rdev & 0x00010000) >> 11);
119         getbrdstats();
120         if (brdstats.ioaddr == 0)
121                 errx(1, "device %s does not exist", devname);
122
123         for (portcnt = 0, i = 0; (i < brdstats.nrpanels); i++) {
124                 if ((portnr >= portcnt) &&
125                     (portnr < (portcnt + brdstats.panels[i].nrports)))
126                         break;
127                 portcnt += brdstats.panels[i].nrports;
128         }
129         if (i >= brdstats.nrpanels)
130                 errx(1, "device %s does not exist", devname);
131         displaypanelnr = i;
132         displayportnr = portnr - portcnt;
133         if (displayportnr >= 16)
134                 displayportbank = 16;
135 }
136
137 /*****************************************************************************/
138
139 /*
140  *      Get the board stats for the current display board.
141  */
142
143 void getbrdstats()
144 {
145         brdstats.brd = displaybrdnr;
146         if (ioctl(ctrlfd, COM_GETBRDSTATS, &brdstats) < 0)
147                 memset((combrd_t *) &brdstats, 0, sizeof(combrd_t));
148 }
149
150 /*****************************************************************************/
151
152 /*
153  *      Zero out stats for the current display port.
154  */
155
156 void clearportstats()
157 {
158         stats[displayportnr].brd = displaybrdnr;
159         stats[displayportnr].panel = displaypanelnr;
160         stats[displayportnr].port = displayportnr;
161         ioctl(ctrlfd, COM_CLRPORTSTATS, &stats[displayportnr]);
162 }
163
164 /*****************************************************************************/
165
166 /*
167  *      Zero out all stats for all ports on all boards.
168  */
169
170 void clearallstats()
171 {
172         int     brdnr, panelnr, portnr;
173
174         for (brdnr = 0; (brdnr < MAXBRDS); brdnr++) {
175                 for (panelnr = 0; (panelnr < COM_MAXPANELS); panelnr++) {
176                         for (portnr = 0; (portnr < MAXPORTS); portnr++) {
177                                 stats[0].brd = brdnr;
178                                 stats[0].panel = panelnr;
179                                 stats[0].port = portnr;
180                                 ioctl(ctrlfd, COM_CLRPORTSTATS, &stats[0]);
181                         }
182                 }
183         }
184 }
185
186 /*****************************************************************************/
187
188 /*
189  *      Get the stats for the current display board/panel.
190  */
191
192 void getallstats()
193 {
194         int     i;
195
196         for (i = 0; (i < brdstats.panels[displaypanelnr].nrports); i++) {
197                 stats[i].brd = displaybrdnr;
198                 stats[i].panel = displaypanelnr;
199                 stats[i].port = i;
200                 if (ioctl(ctrlfd, COM_GETPORTSTATS, &stats[i]) < 0) {
201                         warn("ioctl(COM_GETPORTSTATS) failed");
202                         localexit(1);
203                 }
204         }
205 }
206
207 /*****************************************************************************/
208
209 /*
210  *      Display the per ports stats screen.
211  */
212
213 void displayport()
214 {
215         mvprintw(0, 0, "STALLION SERIAL PORT STATISTICS");
216         mvprintw(2, 0,
217                 "Board=%d  Type=%d  HwID=%02x  State=%06x  TotalPorts=%d",
218                 displaybrdnr, brdstats.type, brdstats.hwid, brdstats.state,
219                 brdstats.nrports);
220         mvprintw(3, 0, "Panel=%d  HwID=%02x  Ports=%d", displaypanelnr,
221                 brdstats.panels[displaypanelnr].hwid,
222                 brdstats.panels[displaypanelnr].nrports);
223
224         attron(A_REVERSE);
225         mvprintw(5, 0, line);
226         mvprintw(5, 0, "Port=%d ", displayportnr);
227         attroff(A_REVERSE);
228
229         mvprintw(7,  0, "STATE:      State=%08x", stats[displayportnr].state);
230         mvprintw(7, 29, "Tty=%08x", stats[displayportnr].ttystate);
231         mvprintw(7, 47, "Flags=%08x", stats[displayportnr].flags);
232         mvprintw(7, 65, "HwID=%02x", stats[displayportnr].hwid);
233
234         mvprintw(8,  0, "CONFIG:     Cflag=%08x", stats[displayportnr].cflags);
235         mvprintw(8, 29, "Iflag=%08x", stats[displayportnr].iflags);
236         mvprintw(8, 47, "Oflag=%08x", stats[displayportnr].oflags);
237         mvprintw(8, 65, "Lflag=%08x", stats[displayportnr].lflags);
238
239         mvprintw(10,  0, "TX DATA:    Total=%d", stats[displayportnr].txtotal);
240         mvprintw(10, 29, "Buffered=%d      ", stats[displayportnr].txbuffered);
241         mvprintw(11,  0, "RX DATA:    Total=%d", stats[displayportnr].rxtotal);
242         mvprintw(11, 29, "Buffered=%d      ", stats[displayportnr].rxbuffered);
243         mvprintw(12,  0, "RX ERRORS:  Parity=%d", stats[displayportnr].rxparity);
244         mvprintw(12, 29, "Framing=%d", stats[displayportnr].rxframing);
245         mvprintw(12, 47, "Overrun=%d", stats[displayportnr].rxoverrun);
246         mvprintw(12, 65, "Lost=%d", stats[displayportnr].rxlost);
247
248         mvprintw(14,  0, "FLOW TX:    Xoff=%d", stats[displayportnr].txxoff);
249         mvprintw(14, 29, "Xon=%d", stats[displayportnr].txxon);
250 #if 0
251         mvprintw(14, 47, "CTSoff=%d", stats[displayportnr].txctsoff);
252         mvprintw(14, 65, "CTSon=%d", stats[displayportnr].txctson);
253 #endif
254         mvprintw(15,  0, "FLOW RX:    Xoff=%d", stats[displayportnr].rxxoff);
255         mvprintw(15, 29, "Xon=%d", stats[displayportnr].rxxon);
256         mvprintw(15, 47, "RTSoff=%d", stats[displayportnr].rxrtsoff);
257         mvprintw(15, 65, "RTSon=%d", stats[displayportnr].rxrtson);
258
259         mvprintw(17,  0, "OTHER:      TXbreaks=%d",
260                 stats[displayportnr].txbreaks);
261         mvprintw(17, 29, "RXbreaks=%d", stats[displayportnr].rxbreaks);
262         mvprintw(17, 47, "Modem=%d", stats[displayportnr].modem);
263
264         mvprintw(19, 0, "SIGNALS:    DCD=%d    DTR=%d    CTS=%d    RTS=%d    "
265                 "DSR=%d    RI=%d",
266                 (stats[displayportnr].signals & TIOCM_CD) ? 1 : 0,
267                 (stats[displayportnr].signals & TIOCM_DTR) ? 1 : 0,
268                 (stats[displayportnr].signals & TIOCM_CTS) ? 1 : 0,
269                 (stats[displayportnr].signals & TIOCM_RTS) ? 1 : 0,
270                 (stats[displayportnr].signals & TIOCM_DSR) ? 1 : 0,
271                 (stats[displayportnr].signals & TIOCM_RI) ? 1 : 0);
272
273         attron(A_REVERSE);
274         mvprintw(22, 0, line);
275         attroff(A_REVERSE);
276
277         mvprintw(24, 19, "(q=Quit,0123456789abcdef=Port,Z=ZeroStats)");
278         refresh();
279 }
280
281 /*****************************************************************************/
282
283 /*
284  *      Continuously update and display the per ports stats screen.
285  *      Also checks for keyboard input, and processes it as appropriate.
286  */
287
288 void menuport()
289 {
290         int     ch, done;
291
292         clear();
293         done = 0;
294
295         while ((ch = getch()) != 27) {
296                 switch (ch) {
297                 case ERR:
298                         break;
299                 case '\f':
300                         refresh();
301                         break;
302                 case 'a':
303                 case 'b':
304                 case 'c':
305                 case 'd':
306                 case 'e':
307                 case 'f':
308                         ch = (ch - 'a' + '0' + 10);
309                         /* fall thru */
310                 case '0':
311                 case '1':
312                 case '2':
313                 case '3':
314                 case '4':
315                 case '5':
316                 case '6':
317                 case '7':
318                 case '8':
319                 case '9':
320                         ch -= '0';
321                         if (ch >= brdstats.panels[displaypanelnr].nrports) {
322                                 beep();
323                         } else {
324                                 displayportnr = displayportbank + ch;
325                                 clear();
326                         }
327                         break;
328                 case 'Z':
329                         clearportstats();
330                         clear();
331                         break;
332                 case 'q':
333                         done = 1;
334                         break;
335                 default:
336                         beep();
337                         break;
338                 }
339
340                 if (done)
341                         break;
342
343                 getallstats();
344                 displayport();
345         }
346 }
347
348 /*****************************************************************************/
349
350 /*
351  *      Display the all ports stats screen.
352  */
353
354 void displayallports()
355 {
356         int     i, nrports, portnr;;
357
358         nrports = brdstats.panels[displaypanelnr].nrports;
359
360         mvprintw(0, 0, "STALLION SERIAL PORT STATISTICS");
361         mvprintw(2, 0, "Board=%d  Type=%d  HwID=%02x  State=%06x  TotalPorts=%d",
362                 displaybrdnr, brdstats.type, brdstats.hwid, brdstats.state,
363                 brdstats.nrports);
364         mvprintw(3, 0, "Panel=%d  HwID=%02x  Ports=%d", displaypanelnr,
365                 brdstats.panels[displaypanelnr].hwid, nrports);
366
367         attron(A_REVERSE);
368         mvprintw(5, 0, "Port  State   Tty    Flags  Cflag Iflag Oflag Lflag "
369                 "Sigs    TX Total   RX Total ");
370         attroff(A_REVERSE);
371
372         if (nrports > 0) {
373                 if (nrports > 16)
374                         nrports = 16;
375                 portnr = displayportbank;
376                 for (i = 0; (i < nrports); i++, portnr++) {
377                         mvprintw((6 + i), 1, "%2d", portnr);
378                         mvprintw((6 + i), 5, "%06x", stats[portnr].state);
379                         mvprintw((6 + i), 12, "%06x", stats[portnr].ttystate);
380                         mvprintw((6 + i), 19, "%08x", stats[portnr].flags);
381                         mvprintw((6 + i), 28, "%05x", stats[portnr].cflags);
382                         mvprintw((6 + i), 34, "%05x", stats[portnr].iflags);
383                         mvprintw((6 + i), 40, "%05x", stats[portnr].oflags);
384                         mvprintw((6 + i), 46, "%05x", stats[portnr].lflags);
385                         mvprintw((6 + i), 52, "%04x", stats[portnr].signals);
386                         mvprintw((6 + i), 58, "%10d", stats[portnr].txtotal);
387                         mvprintw((6 + i), 69, "%10d", stats[portnr].rxtotal);
388                 }
389         } else {
390                 mvprintw(12, 32, "NO BOARD %d FOUND", displaybrdnr);
391                 i = 16;
392         }
393
394         attron(A_REVERSE);
395         mvprintw((6 + i), 0, line);
396         attroff(A_REVERSE);
397
398         mvprintw(24, 14,
399                 "(q=Quit,01234567=Board,n=Panels,p=Ports,Z=ZeroStats)");
400         refresh();
401 }
402
403 /*****************************************************************************/
404
405 /*
406  *      Continuously update and display the all ports stats screen.
407  *      Also checks for keyboard input, and processes it as appropriate.
408  */
409
410 void menuallports()
411 {
412         int     ch, done;
413
414         clear();
415         getbrdstats();
416
417         done = 0;
418         while ((ch = getch()) != 27) {
419                 switch (ch) {
420                 case ERR:
421                         break;
422                 case '\f':
423                         refresh();
424                         break;
425                 case '0':
426                 case '1':
427                 case '2':
428                 case '3':
429                 case '4':
430                 case '5':
431                 case '6':
432                 case '7':
433                         displaybrdnr = ch - '0';
434                         displaypanelnr = 0;
435                         getbrdstats();
436                         if (brdstats.state == 0)
437                                 beep();
438                         clear();
439                         break;
440                 case 'n':
441                         if (brdstats.panels[displaypanelnr].nrports > 16) {
442                                 if (displayportbank == 0) {
443                                         displayportbank = 16;
444                                         clear();
445                                         break;
446                                 }
447                         }
448                         displayportbank = 0;
449                         displaypanelnr++;
450                         if (displaypanelnr >= brdstats.nrpanels)
451                                 displaypanelnr = 0;
452                         clear();
453                         break;
454                 case 'p':
455                         if (brdstats.panels[displaypanelnr].nrports > 0) {
456                                 displayportnr = displayportbank;
457                                 menuport();
458                                 clear();
459                         } else {
460                                 beep();
461                         }
462                         break;
463                 case 'Z':
464                         clearallstats();
465                         clear();
466                         break;
467                 case 'q':
468                         done = 1;
469                         break;
470                 default:
471                         beep();
472                         break;
473                 }
474
475                 if (done)
476                         break;
477
478                 getallstats();
479                 displayallports();
480         }
481 }
482
483 /*****************************************************************************/
484
485 /* 
486  *      A local exit routine - shuts down curses before exiting.
487  */
488
489 void localexit(int nr)
490 {
491         refresh();
492         endwin();
493         exit(nr);
494 }
495
496 /*****************************************************************************/
497
498 int main(int argc, char *argv[])
499 {
500         struct stat     statinfo;
501         int             c, useport;
502         char            *portdev;
503
504         ctrldevice = defdevice;
505         useport = 0;
506
507         while ((c = getopt(argc, argv, "hvVb:p:d:c:")) != -1) {
508                 switch (c) {
509                 case 'V':
510                         printf("stlstats version %s\n", version);
511                         exit(0);
512                         break;
513                 case 'h':
514                         usage();
515                         break;
516                 case 'b':
517                         displaybrdnr = atoi(optarg);
518                         break;
519                 case 'p':
520                         displaypanelnr = atoi(optarg);
521                         break;
522                 case 'd':
523                         useport++;
524                         portdev = optarg;
525                         break;
526                 case 'c':
527                         ctrldevice = optarg;
528                         break;
529                 case '?':
530                 default:
531                         usage();
532                         break;
533                 }
534         }
535
536 /*
537  *      Check that the control device exits and is a character device.
538  */
539         if (stat(ctrldevice, &statinfo) < 0)
540                 errx(1, "control device %s does not exist", ctrldevice);
541         if ((statinfo.st_mode & S_IFMT) != S_IFCHR)
542                 errx(1, "control device %s is not a char device", ctrldevice);
543         if ((ctrlfd = open(ctrldevice, O_RDWR)) < 0)
544                 errx(1, "open of %s failed", ctrldevice);
545
546 /*
547  *      Validate the panel number supplied by user. We do this now since we
548  *      need to have parsed the entire command line first.
549  */
550         getbrdstats();
551         if (displaypanelnr >= brdstats.nrpanels)
552                 displaypanelnr = 0;
553
554         if (useport)
555                 useportdevice(portdev);
556
557 /*
558  *      Everything is now ready, lets go!
559  */
560         initscr();
561         cbreak();
562         halfdelay(5);
563         noecho();
564         clear();
565         if (useport) {
566                 menuport();
567                 clear();
568         }
569         menuallports();
570         refresh();
571         endwin();
572
573         close(ctrlfd);
574         printf("\n");
575         exit(0);
576 }
577
578 /*****************************************************************************/