xref: /freebsd/usr.sbin/cxgbetool/tcb_common.c (revision 95eb4b873b6a8b527c5bd78d7191975dfca38998)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2018 Chelsio Communications, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 #include "tcb_common.h"
31 
32 /***:-----------------------------------------------------------------------
33  ***: externals
34  ***:-----------------------------------------------------------------------
35  */
36 
37 extern _TCBVAR g_tcb_info4[];
38 extern _TCBVAR g_scb_info4[];
39 extern _TCBVAR g_fcb_info4[];
40 extern void t4_display_tcb_aux_0(_TCBVAR *tvp,int aux);
41 extern void t4_display_tcb_aux_1(_TCBVAR *tvp,int aux);
42 extern void t4_display_tcb_aux_2(_TCBVAR *tvp,int aux);
43 extern void t4_display_tcb_aux_3(_TCBVAR *tvp,int aux);
44 
45 extern _TCBVAR g_tcb_info5[];
46 extern _TCBVAR g_scb_info5[];
47 extern _TCBVAR g_fcb_info5[];
48 extern void t5_display_tcb_aux_0(_TCBVAR *tvp,int aux);
49 extern void t5_display_tcb_aux_1(_TCBVAR *tvp,int aux);
50 extern void t5_display_tcb_aux_2(_TCBVAR *tvp,int aux);
51 extern void t5_display_tcb_aux_3(_TCBVAR *tvp,int aux);
52 
53 extern _TCBVAR g_tcb_info6[];
54 extern _TCBVAR g_scb_info6[];
55 extern _TCBVAR g_fcb_info6[];
56 extern void t6_display_tcb_aux_0(_TCBVAR *tvp,int aux);
57 extern void t6_display_tcb_aux_1(_TCBVAR *tvp,int aux);
58 extern void t6_display_tcb_aux_2(_TCBVAR *tvp,int aux);
59 extern void t6_display_tcb_aux_3(_TCBVAR *tvp,int aux);
60 extern void t6_display_tcb_aux_4(_TCBVAR *tvp,int aux);
61 
62 /***:-----------------------------------------------------------------------
63  ***: globals
64  ***:-----------------------------------------------------------------------
65  */
66 
67 _TCBVAR *g_tcb_info=g_tcb_info5;
68 _TCBVAR *g_scb_info=g_scb_info5;
69 _TCBVAR *g_fcb_info=g_fcb_info5;
70 static int g_tN=0;
71 
72 static int g_prntstyl=PRNTSTYL_COMP;
73 
74 static int g_got_scb=0;
75 static int g_got_fcb=0;
76 
77 
78 /***:-----------------------------------------------------------------------
79 ***: error exit functions
80 ***:-----------------------------------------------------------------------
81 */
82 
83 /**: err_exit functions
84 *:  ------------------
85 */
86 
87 void tcb_prflush(void)
88 {
89     fflush(stdout);
90     fflush(stderr);
91 }
92 
93 
94 void tcb_code_err_exit(char *fmt, ...)
95 {
96   va_list args;
97   va_start(args, fmt);
98   printf("Coding Error in: ");
99   vprintf(fmt, args);
100   printf("\n");
101   tcb_prflush();
102   va_end(args);
103   exit(1);
104 }
105 
106 /***:-----------------------------------------------------------------------
107 ***: tcb_hexdump functions
108 ***:-----------------------------------------------------------------------
109 */
110 
111 void
112 tcb_hexdump(unsigned base, unsigned char *buf, unsigned int size)
113 {
114     unsigned offset;
115 
116     for (offset = 0; offset < size; ++offset) {
117         if (!(offset % 16)) printf("\n0x%4.4x: ", base + offset);
118         else if (!(offset % 8)) printf(" ");
119         printf("%2.2x ", (unsigned char)buf[offset]);
120     }
121 }
122 
123 int tcb_strmatch_nc(char *cs, char *ct) {
124     while (*cs)
125         if (tolower(*cs++) != tolower(*ct++)) return (FALSE);
126     return (!(*ct));  /*return TRUE if *ct NULL at same time as *cs==NULL*/
127 }
128 
129 
130 /*: -------------------------------------------------------------------------
131 string functions
132 tcb_strmatch_nc:     Similar to exact match, but case insensitive.
133 */
134 
135 
136 int
137 tcb_strncmp_nc(char *cs, char *ct, int n)
138 {
139     /*case insensitive version of the standard strncmp() function */
140     int i = 0;
141     int ret;
142 
143 
144     ret = 0;
145     for (i = 0; i < n && 0 == ret && !(EOS == *cs && EOS == *ct); ++i) {
146         /* this is weird, but it matched GCC linux when strings don't
147         * have any upper case characters.
148         */
149         ret = tolower(*cs++) - tolower(*ct++);
150     }
151     return ret;
152 }
153 
154 int
155 tcb_startswith_nc(char *cs, char *ct)
156 { /* return true if cs start with ct */
157     return (0 == tcb_strncmp_nc(cs, ct, (int)strlen(ct)));
158 }
159 
160 
161 
162 
163 /***:-----------------------------------------------------------------------
164  ***: START OF WINDOWS FUNCTIONS
165  ***:-----------------------------------------------------------------------
166  */
167 
168 
169 /***:-----------------------------------------------------------------------
170  ***: print utilities
171  ***:-----------------------------------------------------------------------
172  */
173 
174 static int g_PR_indent=1;
175 
176 void PR(char *fmt, ...)
177 {
178   int fmt_len;
179   va_list args;
180   va_start(args,fmt);
181 
182   if (g_PR_indent) printf("  ");
183   g_PR_indent=0;
184   fmt_len=(int) strlen(fmt);
185   if (fmt_len>0 && fmt[fmt_len-1]=='\n') g_PR_indent=1;
186 
187   vprintf(fmt,args);
188   tcb_prflush();
189   va_end(args);
190 }
191 
192 
193 /***:-----------------------------------------------------------------------
194  ***: val()
195  ***:-----------------------------------------------------------------------
196  */
197 
198 _TCBVAR *
199 lu_tcbvar(char *name)
200 {
201   _TCBVAR *tvp=g_tcb_info;
202 
203   while (tvp->name!=NULL) {
204     if      (tcb_strmatch_nc(name,tvp->name)) return tvp;
205     else if (tcb_strmatch_nc(name,tvp->aka )) return tvp;
206     tvp+=1;
207   }
208   tcb_code_err_exit("lu_tcbvar: bad name %s\n",name);
209   return NULL;
210 }
211 
212 unsigned
213 val(char *name)
214 {
215   _TCBVAR *tvp;
216 
217   tvp=lu_tcbvar(name);
218   return tvp->val;
219 }
220 
221 ui64
222 val64(char *name)
223 {
224   _TCBVAR *tvp;
225 
226   tvp=lu_tcbvar(name);
227   return tvp->rawval;
228 }
229 
230 
231 
232 /***:-----------------------------------------------------------------------
233  ***: get_tcb_bits
234  ***:-----------------------------------------------------------------------
235  */
236 
237 
238 static int
239 get_tcb_bit(unsigned char *A, int bit)
240 {
241   int ret=0;
242   int ix,shift;
243 
244   ix = 127 - (bit>>3);
245   shift=bit&0x7;
246   /*  prdbg("  ix: %u, shift=%u\n",ix,shift); */
247   ret=(A[ix] >> shift) & 1;
248   return ret;
249 }
250 
251 static ui64
252 get_tcb_bits (unsigned char  *A, int hi, int lo)
253 {
254   ui64 ret=0;
255 
256   if (lo>hi) {
257     int temp=lo;
258     lo=hi;
259     hi=temp;
260   }
261 
262   while (hi>=lo) {
263     ret = (ret<<1) | get_tcb_bit(A,hi);
264     --hi;
265   }
266 
267   return ret;
268 }
269 
270 
271 void
272 decompress_val(_TCBVAR *tvp,unsigned ulp_type,unsigned tx_max,
273 	       unsigned rcv_nxt,unsigned rx_frag0_start_idx_raw)
274 {
275   unsigned rawval=(unsigned) tvp->rawval;
276 
277   switch(tvp->comp) {
278   case COMP_NONE: tvp->val=rawval;  break;
279   case COMP_ULP:  tvp->val=rawval;  break;
280   case COMP_TX_MAX:
281     tvp->val=(tx_max - rawval) & 0xFFFFFFFF;
282     break;
283   case COMP_RCV_NXT:
284     if (tcb_startswith_nc(tvp->name,"rx_frag")) {
285       unsigned fragx=0;
286       if (!tcb_strmatch_nc(tvp->name,"rx_frag0_start_idx_raw"))
287 	fragx=rawval;
288       tvp->val=(rcv_nxt+rx_frag0_start_idx_raw+fragx) & 0xFFFFFFFF;
289     } else {
290       tvp->val=(rcv_nxt - rawval) & 0xFFFFFFFF;
291     }
292     break;
293   case COMP_PTR: tvp->val=rawval;  break;
294   case COMP_LEN:
295     {
296       tvp->val=rawval;
297       if (PM_MODE_RDDP==ulp_type ||  PM_MODE_DDP==ulp_type ||
298 	  PM_MODE_IANDP==ulp_type) {
299 	/* TP does this internally.  Not sure if I should show the
300 	 *  unaltered value or the raw value.  For now I
301 	 *  will display the raw value.  For now I've added the code
302 	 *  mainly to stop windows compiler from warning about ulp_type
303 	 *  being an unreferenced parameter.
304 	 */
305 	tvp->val=0;
306 	tvp->val=rawval;  /* comment this out to display altered value */
307       }
308     }
309     break;
310   default:
311     tcb_code_err_exit("decompress_val, bad switch: %d",tvp->comp);
312     break;
313   }
314 
315 
316 
317 }
318 
319 
320 void
321 get_tcb_field(_TCBVAR *tvp,unsigned char *buf)
322 {
323   assert(tvp->hi-tvp->lo+1<=64);
324   assert(tvp->hi>=tvp->lo);
325 
326   tvp->rawval=get_tcb_bits(buf,tvp->lo,tvp->hi);
327   /* assume no compression and 32-bit value for now */
328   tvp->val=(unsigned) (tvp->rawval & 0xFFFFFFFF);
329 
330 
331 }
332 
333 
334 /***:-----------------------------------------------------------------------
335  ***: spr_* functions
336  ***:-----------------------------------------------------------------------
337  */
338 
339 char *
340 spr_tcp_state (unsigned state)
341 {
342   char *ret="UNKNOWN";
343 
344   if      ( 0 == state) {ret = "CLOSED";}
345   else if ( 1 == state) {ret = "LISTEN";}
346   else if ( 2 == state) {ret = "SYN_SENT";}
347   else if ( 3 == state) {ret = "SYN_RCVD";}
348   else if ( 4 == state) {ret = "ESTABLISHED";}
349   else if ( 5 == state) {ret = "CLOSE_WAIT";}
350   else if ( 6 == state) {ret = "FIN_WAIT_1";}
351   else if ( 7 == state) {ret = "CLOSING";}
352   else if ( 8 == state) {ret = "LAST_ACK";}
353   else if ( 9 == state) {ret = "FIN_WAIT_2";}
354   else if (10 == state) {ret = "TIME_WAIT";}
355   else if (11 == state) {ret = "ESTABLISHED_RX";}
356   else if (12 == state) {ret = "ESTABLISHED_TX";}
357   else if (13 == state) {ret = "SYN_PEND";}
358   else if (14 == state) {ret = "ESC_1_STATE";}
359   else if (15 == state) {ret = "ESC_2_STATE";}
360 
361   return ret;
362 }
363 
364 char *
365 spr_cctrl_sel(unsigned sel0,unsigned sel1)
366 {
367   unsigned sel=(sel1<<1) | sel0;
368   char *ret="UNKNOWN";
369 
370   if      ( 0 == sel) {ret = "Reno";}
371   else if ( 1 == sel) {ret = "Tahoe";}
372   else if ( 2 == sel) {ret = "NewReno";}
373   else if ( 3 == sel) {ret = "HighSpeed";}
374 
375   return ret;
376 }
377 
378 
379 char *
380 spr_ulp_type(unsigned ulp_type)
381 {
382   char *ret="UNKNOWN";
383 
384   /*The tp.h PM_MODE_XXX call 1 DDP and 5 IANDP, but external
385    * documentation (tcb.h" calls 5 ddp, and doesn't mention 1 or 3.
386    */
387 
388   if      ( PM_MODE_PASS  == ulp_type) {ret = "TOE";}
389   else if ( PM_MODE_DDP   == ulp_type) {ret = "DDP";}
390   else if ( PM_MODE_ISCSI == ulp_type) {ret = "ISCSI";}
391   else if ( PM_MODE_IWARP == ulp_type) {ret = "IWARP";}
392   else if ( PM_MODE_RDDP  == ulp_type) {ret = "RDMA";}
393   else if ( PM_MODE_IANDP == ulp_type) {ret = "IANDP_DDP";}
394   else if ( PM_MODE_FCOE  == ulp_type) {ret = "FCoE";}
395   else if ( PM_MODE_USER  == ulp_type) {ret = "USER";}
396   else if ( PM_MODE_TLS   == ulp_type) {ret = "TLS";}
397   else if ( PM_MODE_DTLS  == ulp_type) {ret = "DTLS";}
398 
399   return ret;
400 }
401 
402 char *
403 spr_ip_version(unsigned ip_version)
404 {
405   char *ret="UNKNOWN";
406 
407   if      ( 0 == ip_version) {ret = "IPv4";}
408   else if ( 1 == ip_version) {ret = "IPv6";}
409 
410   return ret;
411 }
412 
413 
414 
415 /***:-----------------------------------------------------------------------
416  ***: display_tcb()
417  ***:-----------------------------------------------------------------------
418  */
419 
420 void
421 display_tcb_compressed(_TCBVAR *tvp,int aux)
422 {
423 
424   if (g_tN==4) {
425     t4_display_tcb_aux_0(tvp,aux);
426     if      (1==aux) t4_display_tcb_aux_1(tvp,aux);
427     else if (2==aux) t4_display_tcb_aux_2(tvp,aux);
428     else if (3==aux) t4_display_tcb_aux_3(tvp,aux);
429 
430   } else if (g_tN==5) {
431     t5_display_tcb_aux_0(tvp,aux);
432     if      (1==aux) t5_display_tcb_aux_1(tvp,aux);
433     else if (2==aux) t5_display_tcb_aux_2(tvp,aux);
434     else if (3==aux) t5_display_tcb_aux_3(tvp,aux);
435   } else if (g_tN==6) {
436     t6_display_tcb_aux_0(tvp,aux);
437     if      (1==aux) t6_display_tcb_aux_1(tvp,aux);
438     else if (2==aux) t6_display_tcb_aux_2(tvp,aux);
439     else if (3==aux) t6_display_tcb_aux_3(tvp,aux);
440     else if (4==aux) t6_display_tcb_aux_4(tvp,aux);
441   }
442 }
443 
444 
445 
446 
447 /***:-----------------------------------------------------------------------
448  ***: parse_n_decode_tcb
449  ***:-----------------------------------------------------------------------
450  */
451 
452 
453 unsigned
454 parse_tcb( _TCBVAR *base_tvp, unsigned char *buf)
455 {   /* parse the TCB */
456   _TCBVAR *tvp=base_tvp;
457   unsigned ulp_type;
458   int aux=1;  /* assume TOE or iSCSI */
459   unsigned tx_max=0, rcv_nxt=0, rx_frag0_start_idx_raw=0;
460   int got_tx_max=0, got_rcv_nxt=0, got_rx_frag0_start_idx_raw=0;
461 
462 
463   /* parse the TCB */
464   while (tvp->name!=NULL) {
465     get_tcb_field(tvp,buf);
466     if (!got_tx_max && tcb_strmatch_nc("tx_max",tvp->name)) {
467       tx_max=tvp->val;
468       got_tx_max=1;
469     }
470     if (!got_rcv_nxt && tcb_strmatch_nc("rcv_nxt",tvp->name)) {
471       rcv_nxt=tvp->val;
472       got_rcv_nxt=1;
473     }
474     if (!got_rx_frag0_start_idx_raw &&
475 	tcb_strmatch_nc("rx_frag0_start_idx_raw",tvp->name)) {
476       rx_frag0_start_idx_raw=tvp->val;
477       got_rx_frag0_start_idx_raw=1;
478     }
479     tvp+=1;
480   }
481 
482   tvp=base_tvp;
483   ulp_type=tvp->val;  /* ULP type is always first variable in TCB */
484   if (PM_MODE_IANDP==ulp_type || PM_MODE_FCOE==ulp_type) aux=3;
485   else if (PM_MODE_RDDP==ulp_type) aux=2;
486   else if (6==g_tN && (PM_MODE_TLS==ulp_type || PM_MODE_DTLS==ulp_type)) aux=4;
487   else aux=1;
488 
489   assert(got_tx_max && got_rcv_nxt && got_rx_frag0_start_idx_raw);
490 
491   /* decompress the compressed values */
492   tvp=base_tvp;
493   while (tvp->name!=NULL) {
494     decompress_val(tvp,ulp_type,tx_max,rcv_nxt,rx_frag0_start_idx_raw);
495     tvp+=1;
496   }
497 
498   return aux;
499 }
500 
501 
502 
503 void
504 parse_scb( _TCBVAR *base_tvp, unsigned char *buf)
505 {   /* parse the SCB */
506   _TCBVAR *tvp=base_tvp;
507 
508   while (tvp->name!=NULL) {
509     if (tcb_strmatch_nc("scb_slush",tvp->name)) {
510       /* the scb_slush field is all of remaining memory */
511       tvp->rawval=0;
512       tvp->val=0;
513     } else {
514       get_tcb_field(tvp,buf);
515     }
516     tvp+=1;
517   }
518 }
519 
520 
521 void
522 parse_fcb( _TCBVAR *base_tvp, unsigned char *buf)
523 {   /* parse the FCB */
524   _TCBVAR *tvp=base_tvp;
525 
526   while (tvp->name!=NULL) {
527     get_tcb_field(tvp,buf);
528     tvp+=1;
529   }
530 }
531 
532 
533 void
534 display_list_tcb(_TCBVAR *base_tvp,int aux)
535 {
536   _TCBVAR *tvp=base_tvp;
537   while (tvp->name!=NULL) {
538     if (tvp->aux==0 || tvp->aux==aux) {
539       if (tvp->hi-tvp->lo+1<=32) {
540 	printf("  %4d:%4d %31s: %10u (0x%1x)",tvp->lo,tvp->hi,tvp->name,
541 	       (unsigned) tvp->rawval,(unsigned) tvp->rawval);
542 	if (COMP_TX_MAX==tvp->comp || COMP_RCV_NXT==tvp->comp)
543 	  printf("  -> %1u (0x%x)", tvp->val,tvp->val);
544       } else {
545 	printf("  %4d:%4d %31s: 0x%1llx",tvp->lo,tvp->hi,tvp->name,
546 	       tvp->rawval);
547       }
548       printf("\n");
549     }
550     tvp+=1;
551   }
552 }
553 
554 void
555 display_tcb(_TCBVAR *tvp,unsigned char *buf,int aux)
556 {
557   if (g_prntstyl==PRNTSTYL_VERBOSE ||
558       g_prntstyl==PRNTSTYL_RAW) {
559     tcb_hexdump(0,buf,128);
560     printf("\n");
561   }
562 
563   if (g_prntstyl==PRNTSTYL_VERBOSE ||
564       g_prntstyl==PRNTSTYL_LIST) {
565     display_list_tcb(tvp,aux);
566   }
567 
568   if (g_prntstyl==PRNTSTYL_VERBOSE ||
569       g_prntstyl==PRNTSTYL_COMP) {
570     display_tcb_compressed(tvp,aux);
571   }
572 
573 }
574 
575 void
576 parse_n_display_tcb(unsigned char *buf)
577 {
578   _TCBVAR *tvp=g_tcb_info;
579   int aux;
580 
581   aux=parse_tcb(tvp,buf);
582   display_tcb(tvp,buf,aux);
583 }
584 
585 void
586 parse_n_display_scb(unsigned char *buf)
587 {
588   _TCBVAR *tvp=g_scb_info;
589 
590   parse_scb(tvp,buf);
591   if (g_prntstyl==PRNTSTYL_VERBOSE ||
592       g_prntstyl==PRNTSTYL_RAW) {
593     tcb_hexdump(0,buf,128);
594     printf("\n");
595   }
596   if (g_prntstyl==PRNTSTYL_VERBOSE ||
597       g_prntstyl==PRNTSTYL_LIST ||
598       g_prntstyl==PRNTSTYL_COMP) {
599     display_list_tcb(tvp,0);
600   }
601 }
602 
603 void
604 parse_n_display_fcb(unsigned char *buf)
605 {
606   _TCBVAR *tvp=g_fcb_info;
607 
608   parse_fcb(tvp,buf);
609   if (g_prntstyl==PRNTSTYL_VERBOSE ||
610       g_prntstyl==PRNTSTYL_RAW) {
611     tcb_hexdump(0,buf,128);
612     printf("\n");
613   }
614 
615   if (g_prntstyl==PRNTSTYL_VERBOSE ||
616       g_prntstyl==PRNTSTYL_LIST ||
617       g_prntstyl==PRNTSTYL_COMP) {
618     display_list_tcb(tvp,0);
619   }
620 }
621 
622 void
623 parse_n_display_xcb(unsigned char *buf)
624 {
625   if      (g_got_scb) parse_n_display_scb(buf);
626   else if (g_got_fcb) parse_n_display_fcb(buf);
627   else                parse_n_display_tcb(buf);
628 }
629 
630 /***:-----------------------------------------------------------------------
631  ***: swizzle_tcb
632  ***:-----------------------------------------------------------------------
633  */
634 
635 void
636 swizzle_tcb(unsigned char *buf)
637 {
638   int i,j,k;
639 
640   for (i=0, j=128-16 ; i<j ; i+=16, j-=16) {
641     unsigned char temp;
642     for (k=0; k<16; ++k) {
643       temp=buf[i+k];
644       buf[i+k]=buf[j+k];
645       buf[j+k]=temp;
646     }
647   }
648 }
649 
650 
651 /***:-----------------------------------------------------------------------
652  ***: END OF WINDOWS FUNCTIONS
653  ***:-----------------------------------------------------------------------
654  */
655 
656 void set_tidtype(unsigned int tidtype)
657 {
658     if (tidtype == TIDTYPE_SCB)
659     {
660         g_got_scb = 1;
661     }
662     else if (tidtype == TIDTYPE_FCB)
663     {
664         g_got_fcb = 1;
665     }
666     else
667     {
668         g_got_scb = 0;
669         g_got_fcb = 0;
670     }
671 
672 }
673 
674 void
675 set_tcb_info(unsigned int tidtype, unsigned int cardtype)
676 {
677     set_tidtype(tidtype);
678 
679     g_tN = cardtype;
680     if (4 == g_tN) {
681         g_tcb_info = g_tcb_info4;
682         g_scb_info = g_scb_info4;
683         g_fcb_info = g_fcb_info4;
684     }
685     else if (5 == g_tN) {
686         g_tcb_info = g_tcb_info5;
687         g_scb_info = g_scb_info5;
688         g_fcb_info = g_fcb_info5;
689     }
690     else if (6 == g_tN) {
691         g_tcb_info = g_tcb_info6;
692         g_scb_info = g_scb_info6;
693         g_fcb_info = g_fcb_info6;
694     }
695 }
696 
697 void
698 set_print_style(unsigned int prntstyl)
699 {
700   g_prntstyl=prntstyl;
701 }
702