#ifdef	ournix
#include "ournix.h"
#endif
char sccsID[] = "@(#) stty.c V1.1 Copyright Julian H. Stacey 89-05-14" ;

/* This program sets msdos ibm/pc COM1: serial line speed */
#ifndef	SMALL_EXE	/* { */
#include <stdio.h>
#endif		/* SMALL_EXE } */

char syntax[] = 
	"[speed [port [data_bits [stop [par_enable [parity_type]]]]]]\n" ;
char set_to[] =
    "Setting %ld baud for COM%d: with %d data bits, %d stop bits, %s parity.\n";

extern long atol() ;
char	**ARGV ;

main(argc,argv)
	int	argc ;
	char	**argv ;
	{
	int	port_no =	   0	;	/* 0-3 			*/
	long	speed =		9600 	;	/* 115200 - 0 		*/
	short	data_bits =	   8	;	/* data bits in data byte */
	short	stop_bits = 	   1	;	/* stop bits in data byte */
	short	parity = 	   0	;	/* 0 = no parity 	*/
	short	type = 		   1	;	/* 0 = even, 1 = odd	*/
	int	divisor 		;	

	unsigned uart_address ;	/* Address of Intel 8250 Asynch Coms Ctlr */

	ARGV = argv ;
#ifdef	VSL	/* { */
#include	"../../include/vsl.h"
#endif		/* } */
#ifndef	SMALL_EXE	/* { */
	if (argc == 1) printf(
		"%s\t\tSyntax:\n%s %s\n(ALL values must be numeric).\n",
		sccsID,*argv,syntax) ;
#endif		/* SMALL_EXE } */
	if (--argc > 0) speed = atol(*++argv) ;
	/* 1.8432 MHz Clock with divide by 16 */
	     if (speed== 115200L) 	divisor =    1 ;
	else if (speed==  57600L)	divisor =    2 ;
	else if (speed==  38400L)	divisor =    3 ;
	else if (speed==  19200L)	divisor =    6 ;
	else if (speed==   9600L)	divisor =   12 ;
	else if (speed==   4800L)	divisor =   24 ;
	else if (speed==   2400L)	divisor =   48 ;
	else if (speed==   1800L)	divisor =   64 ;
	else if (speed==   1200L)	divisor =   96 ;
	else if (speed==    600L)	divisor =  192 ;
	else if (speed==    300L)	divisor =  384 ;
	else if (speed==    200L)	divisor =  576 ;
	else if (speed==    150L)	divisor =  768 ;
	else if (speed==    134L)	divisor =  860 ; /* 859.7015 */
	else if (speed==    110L)	divisor = 1047 ; /* 1047.2727 */
	else if (speed==     75L)	divisor = 1536 ;
	else if (speed==     50L)	divisor = 2304 ;
	else	{
		speed = 9600L ;
		divisor =   12 ; 
		}

	if (--argc > 0) port_no = 	atoi(*++argv) - 1 ;
	if (--argc > 0) data_bits = 	atoi(*++argv) ;
	if (--argc > 0) stop_bits = 	atoi(*++argv) ;
	if (--argc > 0) parity = 	atoi(*++argv) ;
	if (--argc > 0) type = 		atoi(*++argv) ;

#ifndef	SMALL_EXE	/* { */
		printf(set_to, speed, port_no + 1, data_bits,stop_bits,
			(parity)?((type)?"odd":"even"):"no");
#endif		/* SMALL_EXE } */

	/* Finished deciding what user wants */

#ifdef	MSDOS
/* this program is only expected to run on DOS, but for syntax checking,
   I try to let it compile on Unix */
#define	BIOS_DATA_SEG	((int far *)0x400000)	/* ie 0x40:0 */
#else
#define	BIOS_DATA_SEG	((int *)1)
#endif
	if ((uart_address = *(BIOS_DATA_SEG + port_no )) == 0)
		{
#ifndef	SMALL_EXE	/* { */
		printf("Serial port COM%d: not installed\n", port_no + 1);
#endif		/* SMALL_EXE } */
		exit(1);
		}

	/* set coms line */

#define	UART_LINE	3 /* 8250 line control reg */
	outp(uart_address + UART_LINE,0x80) ;	/* select divisor latch */
	outp(uart_address + 0,divisor) ;	/* baud rate divisor LSB */
	outp(uart_address + 1, 0) ;		/* baud rate divisor MSB */
	outp(uart_address + UART_LINE,
			(	/* 01: 0=5, 1=6, 2=7, 3=8 bit */
				  (data_bits == 5) ? 0 : 
				( (data_bits == 6) ? 1 : 
				( (data_bits == 7) ? 2 :
					/* 8 bits */ 3 ) )
									)	
			| ( /* 2:  stop bits: 0=1, 1=2	*/
				(stop_bits == 1) ? 0 : (1 << 2)		)
			| ( /* 3:  parity: 0 = off	*/
				(parity) ? (1 << 3) : 0 		)
			| ( /* 4:  1 = even parity (inc data) */
				(type) ? 0 : ( 1 << 4)			)
			| ( 0 /* 5:  0 = stick inverted parity  */	)
			| ( 0 /* 6:  0 = dont force break */		)
			| ( 0 /* 7:  1 = force divisor latch */		)
			) ;
	exit(0);
	}
	/* End of program */
