/* $Id: hty_stat.c,v 2.6 91/10/02 16:10:35 leynette Exp $ */
/****************************************************************/
/* hty_stat.c:  HPS Channel Status Reporter						*/
/****************************************************************/
/*																*/
/*                 Confidential Information                     */
/*      Limited Distribution to Authorized Persons Only         */
/*     Created 1987 and Protected as an Unpublished Work        */
/*          Under the U.S. Copyright Act of 1976.               */
/*         Copyright (c) 1987,'88, Systech Corporation          */
/*                  All Rights Reserved                         */
/*																*/
/*	THIS SOFTWARE IS LICENSED BY AND IS THE	CONFIDENTIAL AND 	*/
/*	PROPRIETARY PROPERTY OF SYSTECH COMPUTER CORPORATION AND 	*/
/*	MAY NOT, WITHOUT THE PRIOR WRITTEN CONSENT OF SYSTECH 		*/
/*	COMPUTER CORPORATION, BE REPRODUCED, USED OR DISCLOSED 		*/
/*	EXCEPT IN ACCORDANCE WITH A SYSTECH COMPUTER CORPORATION 	*/
/*	SOFTWARE LICENSE AGREEMENT.									*/
/****************************************************************/
/*																*/
/*   This program gets all the current parameter settings for	*/
/*   the specified channel and displays them on the screen.		*/
/*																*/
/*   Options:													*/
/*		c	display system configuration table					*/
/*		p	display asynch protocol params						*/
/*		f	display flow control params							*/
/*		i	display input params								*/
/*		o	display output params								*/
/*		e	display echo params									*/
/*		x	display extra params								*/
/*		s	display status of channel							*/
/*		t	display translate table (with i or o)				*/
/*		d	specify alternate device name						*/
/*		a	display all the channel parameters					*/
/*																*/
/****************************************************************/

/* #define DEBUG */

#include "stdio.h"
#include "hps.types.h"
#include "hps.iocb.h"
#include "hps.ioctl.h"
#include "hps.onb.h"
#include "hps.net.h"
#include "hps.asynch.h"
#include "hps.swap.h"

#ifdef HPS_STREAMS
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.h>
#include "hps_svcintf.h"
#endif

typedef struct
{
	A_IOCB iocb;
	char data[660];     /* needs to be big enough to hold group command */
} IOCB_DATA;

char  hps_intel		= 0;			/* host byte ordering	*/

IOCB_DATA ri;
int hpsfd;

char RAW_DEV[]	= RAW_DEVNAME;

extern int errno;
static short throttle;    /* display throttle statistics  */

main(argc, argv)
int argc;
char **argv;
{
	char c, *key, *device;

	short trans = 0;	/* display translate table */
	short conf = 0;		/* display system configuration */
	short prot = 0;		/* display asynch protocol */
	short flow = 0;		/* display flow control */
	short iflag = 0;	/* display input params (except translate table) */
	short oflag = 0;	/* display output params */
	short echo = 0;		/* display echo params */
	short xtra = 0;		/* display extra params */
	short stats = 0;	/* display channel status */
	short conly = 0;    /* configuration display without all flag  */

	short error;
	short chan = 0;
	int i, numel;
	bit16 tmp;

	i = 0;
	tmp = 0;
	hps_intel = *(char *)&tmp;

	/* initialize iocb */
	ri.iocb.hdr.len = sizeof(A_IOCB);
	ri.iocb.hdr.maj_dev = ASYNCH_DEV;
	ri.iocb.hdr.int_enab = 1;
	ri.iocb.hdr.data.hps_addr = (bit32)ri.data;
	ri.iocb.hdr.data_dir = FROM_HPS;
	if (hps_intel)
	{
		ri.iocb.command = (IOCTL<<8)|(IOCTL>>8);
	}
	else
	{
		ri.iocb.command = IOCTL;
	}

	device  = RAW_DEV;
	error   = 0;
	throttle = 0;

	/* Scan the command line */
	if (argc >= 2)
	{
		key = argv[1];
		i = argc - 2;
		while (*key)
		{
			switch (c = *key++) /* Possible values: c,p,f,i,o,e,x,s,t,d,a */
			{
				case 'a': /* display all parameters  */
					trans = 1;		/* display translate table */
					conf  = 1;	    /* display system configuration */
					prot  = 1;	    /* display asynch protocol */
					flow  = 1;	    /* display flow control */
					iflag = 1; 		/* display input prms (exc translate tbl) */
					oflag = 1;		/* display output params */
					echo  = 1;	    /* display echo params */
					xtra  = 0;	    /* display extra params */
					stats = 1;		/* display channel status */
					break;
				case 't': /* display translate table */
					trans = 1;
					break;
				case 'c': /* display system configuration */
					conf = 1;
			/*		conly = 1; 
					i++;      	*/  /* does not need channel number */
					break;
				case 'p': /* display asynch protocol */
					prot = 1;
					break;
				case 'f': /* display flow control */
					flow = 1;
					break;
				case 'i': /* display input params */
					iflag = 1;
					break;
				case 'o': /* display output params */
					oflag = 1;
					break;
				case 'e': /* display echo params */
					echo = 1;
					break;
				case 'x': /* display extra params */
					xtra = 1;
					break;
				case 's': /* display channel status */
					stats = 1;
					break;
				case 'd':	/* Set the device name */
#					ifdef DEBUG
						fprintf(stderr, "%s: DEVICE\n", argv[0]);
#					endif
					if (i == 0)
					{
						fprintf (stderr, "%s:  Need device name\n",
							argv[0]);
						usage(argv[0]);
						exit (1);
					}
					else 
					{
						device = argv[argc - i];
#						ifdef DEBUG
						fprintf (stderr, "device = %s\n", device);
#						endif
						i--;
					}
					break;

				default:
					fprintf(stderr,
						"%s: \"%c\" bad keyletter\n", argv[0], c);
					usage(argv[0]);
					error = 1;
					break;
			}
		}
	}

	/* If they only want the system configuration, they don't need	*/
	/* to specify a channel.  Otherwise, they do.  Because of the	*/
	/* way the program handles the i variable, you need to increment*/
	/* it if this is the case.										*/

	if (!(trans + prot + flow + iflag + oflag + echo + xtra + stats)
		&& (conf))
	{	
		conly = 1;				/* Does not need channel number */
		i++;
	}

	if (i == 0)
	{
		fprintf (stderr, "%s:  Need to specify a channel number\n",
			argv[0]);
		usage(argv[0]);
		exit (1);
	}
	else 
	{
		if (conly)
			chan = 0;
		else  
			chan = atoi(argv[argc - i]);
	}

	if (error)
		exit(1);

	if (iflag == 0 && oflag == 0)
		if (trans)
		{
			fprintf(stderr, 
			 "%s: Must specify input and/or output with translate option\n", 
			 argv[0]);
			usage(argv[0]);
			exit(1);
		}

	/* Open HPS interface */
	if ((hpsfd = open(device, 2)) < 0)
	{
		fprintf(stderr, "%s: Cannot open device %s\n", argv[0], device);
		exit(1);
	}

	if (conf)
		disp_conf(chan, argv[0]); /* display system configuration */
	if (prot)
		disp_prot(chan, argv[0]); /* display asynch protocol */
	if (flow)
		disp_flow(chan, argv[0]); /* display flow control */
	if (iflag)
		disp_input(chan, trans, argv[0]); /* display input params */
	if (oflag)
		disp_output(chan, trans, argv[0]); /* display output params */
	if (echo)
		disp_echo(chan, argv[0]); /* display echo params */
	if (xtra)
		disp_extra(chan, argv[0]); /* display extra params */
	if (stats)
		disp_stats(chan, argv[0]); /* display channel status */

#	ifdef DEBUG
		fprintf(stderr, "%s: Done\n", argv[0]);
#	endif
	exit(0);
}


disp_conf(chan, pname) /* display system configuration */
char *pname;
{
	A_CONF *p_conf;
	register i,count;

     /********************************************************************
        CAUTION - there is a bug in 01D and earlier that makes GETC
        hang up the HPS eventually!!  Do not use this in any of those
        versions!!!!!  To overcome this problem, an IOCB issuing a 
	   group command is sent to the host.  Since this command was
	   implemented in 03A,  a E_NOCOMMAND error message returned (0x03 in
	   the mailbox) verifies that the current version of the TCS software is
	   pre-03A.
     ********************************************************************/

	if (r_read(hpsfd, chan, AIOC_GETV, 512, pname) < 0)
		return(0);
	else
	{      
		printf("      SYSTEM CONFIGURATION  \n\n");
		p_conf = (A_CONF *)ri.data;

		if (r_read(hpsfd, chan, AIOC_GETC, 512, pname) < 0)
			return(0);

		count = 0;
		printf("channel #     station id         port #\n\n");
		for (i=0; p_conf->c_station != 0; i++)
		{
			printf("     %3d          %3d            %3d\n",i,
				p_conf->c_station,p_conf->c_number);
			p_conf++;  /* inc to next word  */
			count++;
		}
		if (count == 0)
			fprintf(stderr, "%s: Host adapter to cluster controller mapping configuration may not have been downloaded yet.\nRun the configuration utility to set up the network.\n", pname);
	}    
	printf("\n");
}


disp_prot(chan, pname) /* display asynch protocol */
char *pname;
{
	A_PROT *p_prot;

	p_prot = (A_PROT *)ri.data;

	if (r_read(hpsfd, chan, AIOC_GETA, sizeof(A_PROT), pname) < 0)
		return(0);

	printf("      ASYNCH PROTOCOL  \n\n");
	printf("          Baud  Char len  Parity  Stop bits\n");
	printf("Receive:  ");
	print_baud(p_prot->a_r.a_bps);
	printf("  %d     ", p_prot->a_r.a_length);
	switch (p_prot->a_r.a_parity)
	{
		case A_ODD:   printf("odd     "); break;
		case A_EVEN:  printf("even    "); break;
		case A_MARK:  printf("mark    "); break;
		case A_SPACE: printf("space   "); break;
		case A_NONE:  printf("none    "); break;
		case A_EITHER:printf("either  "); break;
	}

	switch (p_prot->a_r.a_stops)
	{
		case A_STOP1: printf("1 stop bit\n"); break;
		case A_STOP15:printf("1.5 stop bits\n"); break;
		case A_STOP2: printf("2 stop bits\n"); break;
	}

	printf("Transmit: ");
	print_baud(p_prot->a_t.a_bps);
	printf("  %d     ", p_prot->a_t.a_length);
	switch (p_prot->a_t.a_parity)
	{
		case A_ODD:   printf("odd     "); break;
		case A_EVEN:  printf("even    "); break;
		case A_MARK:  printf("mark    "); break;
		case A_SPACE: printf("space   "); break;
		case A_NONE:  printf("none    "); break;
		case A_EITHER:printf("either  "); break;
	}

	switch (p_prot->a_t.a_stops)
	{
		case A_STOP1: printf("1 stop bit\n"); break;
		case A_STOP15:printf("1.5 stop bits\n"); break;
		case A_STOP2: printf("2 stop bits\n"); break;
	}
	printf("\n");
}


print_baud(bps)
{
	switch (bps)
	{
		case A_45  : printf("45.5    "); break;
		case A_50  : printf("50      "); break;
		case A_75  : printf("75      "); break;
		case A_110 : printf("110     "); break;
		case A_134 : printf("134.5   "); break;
		case A_150 : printf("150     "); break;
		case A_200 : printf("200     "); break;
		case A_300 : printf("300     "); break;
		case A_600 : printf("600     "); break;
		case A_1050: printf("1050    "); break;
		case A_1200: printf("1200    "); break;
		case A_1800: printf("1800    "); break;
		case A_2000: printf("2000    "); break;
		case A_2400: printf("2400    "); break;
		case A_3000: printf("3000    "); break;
		case A_3600: printf("3600    "); break;
		case A_4200: printf("4200    "); break;
		case A_4800: printf("4800    "); break;
		case A_5400: printf("5400    "); break;
		case A_6000: printf("6000    "); break;
		case A_6600: printf("6600    "); break;
		case A_7200: printf("7200    "); break;
		case A_7800: printf("7800    "); break;
		case A_8400: printf("8400    "); break;
		case A_9000: printf("9000    "); break;
		case A_9600: printf("9600    "); break;
		case A_102K: printf("10.2K   "); break;
		case A_108K: printf("10.8K   "); break;
		case A_192K: printf("19.2K   "); break;
		case A_384K: printf("38.4K   "); break;
		case A_EXT : printf("External   "); break;
		case A_EXT16: printf("Ext / 16   "); break;
		default:     printf("INVALID    "); break;
	}
}


disp_flow(chan, pname) /* display flow control */
char *pname;
{
	A_FLOW *p_flow;

	p_flow = (A_FLOW *)ri.data;

	if (r_read(hpsfd, chan, AIOC_GETF, sizeof(A_FLOW), pname) < 0)
		return(0);

	printf("FLOW CONTROL: ");
	if (!p_flow->f_type) printf("none\n");
	else
	{
		if (p_flow->f_type & FL_IXONXOFF) printf("Input XON/XOFF ");
		if (p_flow->f_type & FL_OXONXOFF) printf("Output XON/XOFF ");
		if (p_flow->f_type & FL_IETXACK) printf("Input ETX/ACK ");
		if (p_flow->f_type & FL_OETXACK) printf("Output ETX/ACK ");
		if (p_flow->f_type & FL_IRTSCTS) printf("Input RTS/CTS ");
		if (p_flow->f_type & FL_ORTSCTS) printf("Output RTS/CTS ");
		if (p_flow->f_type & FL_IDSRDTR) printf("Input DSR/DTR ");
		if (p_flow->f_type & FL_ODSRDTR) printf("Output DSR/DTR ");
		printf("\n");
		printf("High water: %d, Low water: %d, ", p_flow->f_hiwater, 
										  p_flow->f_lowater);
		if (p_flow->f_type & FL_IXONXOFF || p_flow->f_type & FL_OXONXOFF)
			printf("XON: 0x%x, XOFF: 0x%x, ", p_flow->f_xon, p_flow->f_xoff);
		if (p_flow->f_type & FL_IETXACK || p_flow->f_type & FL_OETXACK)
			printf("ETX: 0x%x, ACK: 0x%x, ", p_flow->f_xon, p_flow->f_xoff);
		printf("Flags: ");
		if (p_flow->f_flags & FL_SPACE) printf("SPACE ");
		if (p_flow->f_flags & FL_MARK) printf("MARK ");
		if (p_flow->f_flags & FL_IXANY) printf("IXANY ");
		printf("\n");
	}
	printf("\n");
}


disp_input(chan, trans, pname) /* display input params */
char *pname;
{
	A_IPARAM *p_iparam;
	int i;
	bit16 stmp;

	p_iparam = (A_IPARAM *)ri.data;

	if (r_read(hpsfd, chan, AIOC_GETI, sizeof(A_IPARAM), pname) < 0)
		return(0);

	if (hps_intel)
	{
		SWAP_2BYTE(&stmp, &p_iparam->i_ntraps);
		p_iparam->i_ntraps  = stmp;
		SWAP_2BYTE(&stmp, &p_iparam->i_ntline);
		p_iparam->i_ntline  = stmp;
		SWAP_2BYTE(&stmp, &p_iparam->i_nsynch);
		p_iparam->i_nsynch  = stmp;
		SWAP_2BYTE(&stmp, &p_iparam->i_nescape);
		p_iparam->i_nescape = stmp;
		SWAP_2BYTE(&stmp, &p_iparam->i_except);
		p_iparam->i_except  = stmp;
		SWAP_2BYTE(&stmp, &p_iparam->i_blocks);
		p_iparam->i_blocks  = stmp;
	}


	printf("INPUT PROCESSING:\n");
	if (p_iparam->i_blocks & I_MARKFF) printf("  MARKFF\n");
	if (p_iparam->i_blocks & I_MSBZ) printf("  Strip MSB\n");
	if (p_iparam->i_blocks & I_UCONLY) 
	{
		if (p_iparam->i_options & I_SHIFT)
			printf("  Keyboard is upper-case only (shift = 0x%x)\n",
				p_iparam->i_shift);
		else
			printf("  Keyboard is upper-case only (no shift)\n");
	}
	if (p_iparam->i_blocks & I_TRAP)
	{
		printf("  Trap special characters: \n  ");
		for (i=0; i<p_iparam->i_ntraps; i++)
		{
			printf("0x%x (", p_iparam->i_traps[i]);
			if (p_iparam->i_tflags[i] & I_DELETE) printf("DELETE,");
			if (p_iparam->i_tflags[i] & I_FLUSHI) printf("FLUSHI,");
			if (p_iparam->i_tflags[i] & I_FLUSHO) printf("FLUSHO,");
			if (p_iparam->i_tflags[i] & I_EVENT) printf("EVENT");
			printf("), ");
		}
		printf("\n");
	}
	if (p_iparam->i_blocks & I_XLATE) 
	{
		printf("  Translate characters\n");
		if (p_iparam->i_options & I_XLATE_ESC)
		{
			printf("    Make I_XLATE sensitive to escapes: ");
			for (i=0; i<p_iparam->i_nescape; i++)
				printf("0x%x ", p_iparam->i_escape[i]);
			printf("\n");
		}
		if (p_iparam->i_options & I_XLATE_NON)
			printf("    Translate unless escaped\n");
		if (p_iparam->i_options & I_XLATE_CN)
			printf("    Translate CR to NL\n");
		if (p_iparam->i_options & I_XLATE_NC)
			printf("    Translate NL to CR\n");
	}

	if (p_iparam->i_blocks & I_EXTEND) printf("  Parse SI/SO code extension\n");
	if (p_iparam->i_blocks & I_ECHO) printf("  Echo\n");
	if (p_iparam->i_blocks & I_EDIT) 
	{
		printf("  Edit lines\n    ");
		for (i=0; i<p_iparam->i_ntline; i++)
		{
			printf("0x%x (", p_iparam->i_tline[i]);
			if (p_iparam->i_tlflags[i] & I_DELETE) printf("DELETE,");
			printf("), ");
		}
		printf("\n");
	}
	if (p_iparam->i_blocks & I_THROTTLE) 
	{
		printf("  Throttle raw input\n");
		throttle = 1;
	}
	if (p_iparam->i_blocks & I_SYNCH) 
	{
		printf("  Indicate synchronized traps\n  ");
		for (i=0; i<p_iparam->i_nsynch; i++)
		{
			printf("0x%x (", p_iparam->i_synch[i]);
			if (p_iparam->i_sflags[i] & I_DELETE) printf("DELETE,");
			if (p_iparam->i_sflags[i] & I_FLUSHI) printf("FLUSHI,");
			if (p_iparam->i_sflags[i] & I_FLUSHO) printf("FLUSHO,");
			if (p_iparam->i_sflags[i] & I_EVENT) printf("EVENT");
			printf("), ");
		}
		printf("\n");
	}

	if (p_iparam->i_blocks & I_XERRS) 
	{
		printf("  Process line exceptions\n");
		switch (p_iparam->i_except & I_BBITS)
		{
			case I_BIGNORE:
				printf("    Ignore BREAK condition\n");
				break;
			case I_BINPUT:
				printf("    Encode BREAK into input (0x%x)\n",
					p_iparam->i_break);
				break;
			case I_BMARK:
				printf("    Mark BREAK into input 0xFF 0x00 (0x%x)\n",
					p_iparam->i_break);
				break;
			case I_BTRAP:
				printf("    BREAK --> asynch trap\n");
				break;
			case I_BSTRAP:
				printf("    BREAK --> synch trap\n");
				break;
			case I_BDATA:
				printf("    BREAK (null) into input\n");
				break;
			case I_BRKINT:
				printf("    BREAK --> Asynch trap, and flush buffers\n");
				break;
			default:
				printf("    BREAK *** INVALID SELECTION ** 0x%x\n", 
					p_iparam->i_except & I_BBITS);
				break;
		}

		switch (p_iparam->i_except & I_PBITS)
		{
			case I_PIGNORE:
				printf("    Ignore parity errors\n");
				break;
			case I_PINPUT:
				printf("    Encode parity error into input (0x%x)\n",
					p_iparam->i_parity);
				break;
			case I_PMARK:
				printf("    Mark parity error into input 0xFF 0x00 (0x%x)\n",
					p_iparam->i_parity);
				break;
			case I_PTRAP:
				printf("    Parity error --> asynch trap\n");
				break;
			case I_PSTRAP:
				printf("    Parity error --> synch trap\n");
				break;
			case I_PDATA:
				printf("    Parity error data into input\n");
				break;
			default:
				printf("    PARITY *** INVALID SELECTION ** 0x%x\n", 
					p_iparam->i_except & I_PBITS);
				break;
		}

		switch (p_iparam->i_except & I_FBITS)
		{
			case I_FIGNORE:
				printf("    Ignore framing errors\n");
				break;
			case I_FINPUT:
				printf("    Encode frame error into input (0x%x)\n",
					p_iparam->i_framing);
				break;
			case I_FMARK:
				printf("    Mark frame error into input 0xFF 0x00 (0x%x)\n",
					p_iparam->i_framing);
				break;
			case I_FTRAP:
				printf("    Frame error --> asynch trap\n");
				break;
			case I_FSTRAP:
				printf("    Frame error --> synch trap\n");
				break;
			case I_FDATA:
				printf("    Frame error data into input\n");
				break;
			default:
				printf("    Frame error *** INVALID SELECTION ** 0x%x\n", 
					p_iparam->i_except & I_FBITS);
				break;
		}

		switch (p_iparam->i_except & I_OBITS)
		{
			case I_OIGNORE:
				printf("    Ignore overrun errors\n");
				break;
			case I_OINPUT:
				printf("    Encode O'run error into input (0x%x)\n",
					p_iparam->i_overrun);
				break;
			case I_OMARK:
				printf("    Mark O'run error into input 0xFF 0x00 (0x%x)\n",
					p_iparam->i_overrun);
				break;
			case I_OTRAP:
				printf("    O'run error --> asynch trap\n");
				break;
			case I_OSTRAP:
				printf("    O'run error --> synch trap\n");
				break;
			case I_ODATA:
				printf("    O'run error data into input\n");
				break;
			default:
				printf("    O'run error *** INVALID SELECTION ** 0x%x\n", 
					p_iparam->i_except & I_OBITS);
				break;
		}

		switch (p_iparam->i_except & I_CBITS)
		{
			case I_CIGNORE:
				printf("    Ignore modem status changes\n");
				break;
			case I_CTRAP:
				printf("    Modem status change --> asynch trap\n");
				break;
			case I_CSTRAP:
				printf("    Modem status change --> synch trap\n");
				break;
			default:
				printf("    Modem status change *** INVALID SELECTION ** 0x%x\n", 
					p_iparam->i_except & I_CBITS);
				break;
		}
	}

	if (p_iparam->i_blocks & I_XLATE && trans)
	{
		printf("Translate table:");
		for (i = 0; i < 256; i++)
		{
			if ((i % 16)== 0) printf("\n");
			printf("%02x ", p_iparam->i_xtab[i]);
		}
		printf("\n");
	}
	printf("\n");
}


disp_output(chan, trans, pname) /* display output params */
char *pname;
{
	A_OPARAM *p_oparam;
	int i;
	bit16 stmp;

	p_oparam = (A_OPARAM *)ri.data;

	if (r_read(hpsfd, chan, AIOC_GETO, sizeof(A_OPARAM), pname) < 0)
		return(0);

	if (hps_intel)
	{
		SWAP_2BYTE(&stmp, &p_oparam->o_nspec);
		p_oparam->o_nspec   = stmp;
		SWAP_2BYTE(&stmp, &p_oparam->o_lowat);
		p_oparam->o_lowat   = stmp;
		SWAP_2BYTE(&stmp, &p_oparam->o_hiwat);
		p_oparam->o_hiwat   = stmp;
		SWAP_2BYTE(&stmp, &p_oparam->o_blocks);
		p_oparam->o_blocks  = stmp;
	}
	printf("      OUTPUT PARAMETERS  \n\n");
	printf("Output buffer lowat: %d, hiwat: %d\n",
			p_oparam->o_lowat, p_oparam->o_hiwat);
	printf("Output Processing: ");
	if (!p_oparam->o_blocks) printf("none ");
	if (p_oparam->o_blocks & O_NOEOT) printf("Filter EOT, ");
	if (p_oparam->o_blocks & O_XTABS) printf("Expand tabs, ");
	if (p_oparam->o_blocks & O_XLATE) printf("Translate, ");
	if (p_oparam->o_blocks & O_SHIFTUC) 
		printf("Shift UC (0x%x), ", p_oparam->o_shift);
	if (p_oparam->o_blocks & O_XNL) printf("Xlate NL to CR-LF, ");
	if (p_oparam->o_blocks & O_EXTEND) printf("Generate SI/SO, ");
	if (p_oparam->o_blocks & O_NLZERO) printf("NL moves to col 0, ");
	if (p_oparam->o_blocks & O_LPR) printf("LPR buffering, ");
	if (p_oparam->o_blocks & O_NOCR) printf("No CR at col 0, ");
	if (p_oparam->o_blocks & O_NOFF) printf("No form-feed at TOF, ");
	printf("\n");

	if (p_oparam->o_blocks & O_SHIFTSP) 
	{
		printf("Shift special chars (0x%x)\n", p_oparam->o_shift);
		printf("Special outchars: ");
		if (p_oparam->o_nspec) printf("None ");
		for (i = 0; i < p_oparam->o_nspec; i++)
			printf("0x%x ", p_oparam->o_spec[i]);
		printf("\n");
	}

	if (p_oparam->o_blocks & O_DELAYS) 
	{
		printf("Enable output delays\n");
		print_delay("Backspace delay: ", p_oparam->o_bsdly, p_oparam->o_fill);
		print_delay("Carriage return delay: ",
			p_oparam->o_crdly, p_oparam->o_fill);
		print_delay("Form feed delay: ", p_oparam->o_ffdly, p_oparam->o_fill);
		print_delay("Horizontal tab delay: ", 
			p_oparam->o_htdly, p_oparam->o_fill);
		print_delay("Line feed delay: ", p_oparam->o_lfdly, p_oparam->o_fill);
		print_delay("Vertical tab delay: ", 
			p_oparam->o_vtdly, p_oparam->o_fill);
	}

	if (p_oparam->o_blocks & O_XLATE && trans)
	{
		printf("Translate table:");
		for (i = 0; i < 256; i++)
		{
			if ((i % 16)== 0) printf("\n");
			printf("%02x ", p_oparam->o_xtab[i]);
		}
		printf("\n");
	}
	printf("\n");
}


print_delay(s, delay, fill)
char *s;
{
	printf("%s: %d ", s, delay & D_VALUE);
	if (delay & D_TIMED) 
		printf("Timed, ");
	else
		printf("Fill (0x%x), ", fill);
	if (delay & D_FIXED) 
		printf("Fixed\n");
	else
		printf("Proportional\n");
}


disp_echo(chan, pname) /* display echo params */
char *pname;
{
	A_EPARAM *p_eparam;
	int i;
	bit16 stmp;

	p_eparam = (A_EPARAM *)ri.data;

	if (r_read(hpsfd, chan, AIOC_GETE, sizeof(A_EPARAM), pname) < 0)
		return(0);

	if (hps_intel)
	{
		SWAP_2BYTE(&stmp, &p_eparam->e_modes);
		p_eparam->e_modes   = stmp;
	}

	printf("      ECHO PARAMETERS  \n\n");
	printf("Echo delete ");
	if (!(p_eparam->e_modes & E_CRT)) printf("None ");
	if (p_eparam->e_modes & E_CRT) printf("CRT style: ");
	if (p_eparam->e_modes & E_LPR) printf("LPR style: ");
	if (throttle) 
	{
		printf("\n\n Minimum Timeout Period = %d\n",p_eparam->e_chars[0]);
		printf("Minimum Number of Characters = %d\n\n",p_eparam->e_chars[1]);
	}
	else
	{
		if (p_eparam->e_modes & E_CHAR) 
			printf("Char (0x%x) ", p_eparam->e_chars[0]);
		if (p_eparam->e_modes & E_WORD) 
			printf("Word (0x%x) ", p_eparam->e_chars[1]);
		if (p_eparam->e_modes & E_LINE) 
			printf("Line (0x%x) ", p_eparam->e_chars[2]);
		if (p_eparam->e_modes & E_RETYPE) 
			printf("Retype (0x%x) ", p_eparam->e_chars[3]);
		printf("\n");
	}
	if (p_eparam->e_modes & E_CTRL) printf("Echo controls as ^X\n");
	if (p_eparam->e_modes & E_ALARM) printf("Echo overrun as alarm\n");
	if (p_eparam->e_modes & E_NEWLINE) 
		printf("Echo newline after line delete\n");
	if (p_eparam->e_modes & E_NLONLY) printf("Echo newline chars only\n");
	if (p_eparam->e_modes & E_ERONLY) printf("Echo char-delete sequence\n");
	if (p_eparam->e_modes & E_NOEOT) printf("Do not echo ASCII EOT\n");
	if (p_eparam->e_modes & E_CLEANUP) printf("Retype fouled input\n");
	if (p_eparam->e_modes & E_NOERASE) 
		printf("Dont use CRT erase for line delete\n");
	if (p_eparam->e_modes & E_BACKSPACE) 
		printf("Echo backspace after echoing e_backspace\n");

	if (p_eparam->e_modes & E_CRT)
	{
		printf("   CRT del sequence: ");
		for (i=0; p_eparam->e_crtdel[i]; i++)
			printf("0x%x ", p_eparam->e_crtdel[i]);
		printf("\n");
	}

	if (p_eparam->e_modes & E_ALARM)
	{
		printf("   Alarm sequence: ");
		for (i=0; p_eparam->e_alarm[i]; i++)
			printf("0x%x ", p_eparam->e_alarm[i]);
		printf("\n");
	}

	if (p_eparam->e_modes & E_LPR)
	{
		printf("LPR start del: 0x%x", p_eparam->e_start);
		printf("  LPR stop del: 0x%x\n", p_eparam->e_stop);
	}
	printf("\n");
}


disp_extra(chan, pname) /* display extra params */
char *pname;
{
	A_XPARAM *p_xparam;

	printf("      EXTRA PARAMETERS  \n\n");
	p_xparam = (A_XPARAM *)ri.data;

	if (r_read(hpsfd, chan, AIOC_GETX, sizeof(A_XPARAM), pname) < 0)
		return(0);

/*	printf("LPR lines/page: %d  ", p_xparam->p_lines);
	printf("LPR cols/page: %d  ", p_xparam->p_cols);
	printf("LPR indent: %d\n", p_xparam->p_indent);

	printf("\nBackspace over char: 0x%x\n", p_xparam->e_backspace);
	printf("\n");     */
}


disp_stats(chan, pname) /* display channel status */
char *pname;
{
	A_STAT *p_stats;
	bit16 stmp;

	p_stats = (A_STAT *)ri.data;

	if (r_read(hpsfd, chan, AIOC_GETS, sizeof(A_STAT), pname) < 0)
		return(0);

	if (hps_intel)
	{
		SWAP_2BYTE(&stmp, &p_stats->s_modem);
		p_stats->s_modem     = stmp;
		SWAP_2BYTE(&stmp, &p_stats->s_in_chars);
		p_stats->s_in_chars  = stmp;
		SWAP_2BYTE(&stmp, &p_stats->s_out_chars);
		p_stats->s_out_chars = stmp;
	}

	printf("      CHANNEL STATUS  \n\n");
	printf("Modem signals: ");
	if (!p_stats->s_modem) printf("none ");
	if (p_stats->s_modem & A_DTR) printf("DTR ");
	if (p_stats->s_modem & A_DSR) printf("DSR ");
	if (p_stats->s_modem & A_CTS) printf("CTS ");
	if (p_stats->s_modem & A_RTS) printf("RTS ");
	if (p_stats->s_modem & A_CD) printf("CD ");
	if (p_stats->s_modem & A_ONLINE) printf("ONLINE ");
	printf("\n");

	printf("Input chars on board: %d,  ", p_stats->s_in_chars);
	printf("Output chars on board: %d\n", p_stats->s_out_chars);
	printf("\n");
}


/*
 * Raw Read
 *   Use to send a "get" type IOCTL directly to the board.
 */
r_read(rawdev, chan, cmd, len, pname)
int   chan;
short cmd;
int   len;
char *pname;
{
	extern int errno;

#ifdef HPS_STREAMS
	struct strbuf	ctlbuf;
	struct strbuf	datbuf;
	long			ctlcmd;
	int				gflags;
	
	if (len + sizeof(A_IOCB) > MAXIOCBSZ)
	{
		fprintf (stderr, "user data exceeded maxium ioctl msg size\n");
		return(-1);
	}
#endif	

   ri.iocb.hdr.min_dev = chan;
   ri.iocb.hdr.data_len = len;
   ri.iocb.hdr.mail.hps_addr = 0xFFFFFFFF;
   if (hps_intel)
   {
       SWAP_2BYTE(&ri.iocb.cmd_modifier, &cmd);
   }
   else
       ri.iocb.cmd_modifier = cmd;

#ifdef HPS_STREAMS
	ctlbuf.maxlen = 0;
	ctlbuf.len    = sizeof(long);
	ctlbuf.buf    = (char *)&ctlcmd;
	ctlcmd        = HPS_DOIOCB;
	datbuf.maxlen = 0;
	datbuf.len    = sizeof(ri);
	datbuf.buf    = (char *)&ri;

	if (putmsg(hpsfd,&ctlbuf,&datbuf,0) < 0)
	{
		printf("Error: putmsg failed\n");
		return(-1);
	}

	ctlbuf.len    = 0;
	ctlbuf.maxlen = sizeof(long);
	ctlbuf.buf    = (char *)&ctlcmd;
	datbuf.len    = 0;
	datbuf.maxlen = sizeof(ri);
	datbuf.buf    = (char *)&ri;
	gflags        = 0;
	ctlcmd        = 0;
	bzero((char *)&ri,sizeof(ri));

	if (getmsg(hpsfd,&ctlbuf,&datbuf,&gflags) != 0)
	{
		printf("Error: getmsg failed\n");
		return(-1);
	}

#elif BSD
   read ( rawdev, &ri, sizeof(A_IOCB) + len );
#else
   ioctl (rawdev, DO_IOCB, &ri);
#endif
	if (ri.iocb.hdr.mail.hps_addr >> 16)
	{
		if (errno)
		{
			perror(pname);
		}
		else
		{
			if ((ri.iocb.hdr.mail.hps_addr >> 16) == E_CLOSED)
			{
				fprintf(stderr,"%s: tty line %d not open:enable the port\n",
						pname, chan);
			}
			else 
			{
				if(ri.iocb.hdr.mail.hps_addr >> 16)
					errtab(ri.iocb.hdr.mail.hps_addr >> 16, pname);
			}
		}
			
		return(-1);
	}

#ifdef DEBUG
	fprintf(stderr, "r_read chan = %d, cmd = %d, len = %d \n", chan, cmd, len);
#endif
}


usage(name)
char *name;
{
	fprintf (stderr, "%s: usage: %s [cpfioexstda] [<device>] chan_num\n", 
			name, name);
}


/*
 * MODIFICATION HISTORY:
 *
 * $Log:	hty_stat.c,v $
 * Revision 1.1.2.1  92/06/24  13:53:43  marker
 * Branch RISCOS_5_01_2_FIXES off of trunk.
 * 
 * Revision 2.6  91/10/02  16:10:35  leynette
 * Changed check for if AIOC_GETV and ...hps_addr >> 16 == ECLOSED to remove
 * the AIOC_GETV from the check.  It be bogus...
 * INTERNAL
 * 
 * Revision 2.5  91/10/02  12:38:43  leynette
 * Added printf statement back in to tell the user that the tty line needs to
 * be enabled in order to run this util.; deleted call to close() because
 * this util. will always complain and we really don't care!
 * ENHANCEMENT
 * 
 * Revision 2.4  91/09/03  17:39:31  annette
 * Changed error message handling.
 * INTERNAL
 * 
 * Revision 2.3  91/07/24  12:43:15  annette
 * Changed hardcoded 256 in r_read to 512.
 * SPR=590, SPR=598
 * 
 * Revision 2.2  91/01/10  17:23:34  dave
 * Modify header; add footer.
 * COSMETIC
 * 
 */
