From: woods@robohack.UUCP (Greg A. Woods)
Newsgroups: comp.sys.att,u3b.tech
Subject: Re: Hardware Flow Control on EPORTS
Date: 11 Oct 92 18:53:27 GMT
Organization: Elegant Communications Inc.

In article <1992Oct7.020935.5215@dlss2> james@dlss2 (James Cummings) writes:
> 	How does one go about setting hardware flow control on a 3B2 with
> EPORTS?  I can see how you might go aboiut this with a printer port in
> the model file, but I'm unsure how you might do this with a port used for
> logins.

The hardware flow control (RTS/CTS) on the EPORTS board must be
enabled by either the epstty program, or by explicit ioctl() calls
from a C program.  The included code has proved useful to me in
experimenting with the EPORTS.  In theory this code could easily be
modified to run in conjunction with uugetty from a respawn line in
/etc/inittab.  It would have to block on open(), just like uugetty,
then twiddle the port *after* it thought uugetty had done its first
TCSETA, watch for login to start, twiddle again (i.e. after getty had
done the second TCSETA, then wait for the lock to go away.  It could
also do the twiddling so outgoing calls used HFC too.  I've not yet
done this.  Examples from this code may also prove useful if you wish
to modify one of the public domain uugetty's.  Sorry, I do not have
any like patches available.

(NOTE: <sccsid.h> is *not* in any way compatible with AT&T's
<sys/sccsid.h>, and if you don't have a copy of my version, just
comment out the include....)

#include <sys/types.h>
#include <sys/ep_dep.h>
#include <sys/queue.h>
#include <sys/eppc.h>
#include <sys/ep_lla.h>
#include <stdio.h>
#include <fcntl.h>
#include <termio.h>
#include <signal.h>

#define SID	"@(#)cmd:epctl.c	1.3	92/10/11 14:42:23 (woods)"
#include <sccsid.h>

extern void	usage();
extern void	pretty();

int
main(argc, argv)
	int	argc;
	char	*argv[];
{
	struct etty	etio;
	struct termio	tio;
	ushort	obaud;
	int	fd;
	int	opt;
	int	errflg = 0;
	int	bflg = 0;	/* -B	send break */
	int	cflg = 0;	/* -c	clear hfc */
	int	fflg = 0;	/* -f	fix stuck port */
	int	pflg = 0;	/* -p	print et_state */
	int	sflg = 0;	/* -s	set hfc */
	int	rflg = 0;	/* -r	read one char */
	int	wflg = 0;	/* -w	write one char */
	int	kp[10];		/* -k p	kill process p */
	int	nkp = 0;	/* number of processes to kill */
	int	signo = SIGTERM;/* -K s	use signal s to kill 'em */
	char	*argv0;
	extern int	optind;
	extern char	*optarg;

	argv0 = argv[0];
	while ((opt = getopt(argc, argv, "cfk:prswBK:")) != EOF) {
		switch (opt) {
		case 'c':
			cflg = 1;
			break;
		case 'f':
			fflg = 1;
			break;
		case 'p':
			pflg = 1;
			break;
		case 'r':
			rflg++;
			break;
		case 's':
			sflg = 1;
			break;
		case 'w':
			wflg++;
			break;
		case 'B':
			bflg = 1;
			break;
		case 'K':
			signo = atoi(optarg);
			break;
		case 'k':
			kp[nkp++] = atoi(optarg);
			break;
		default:
			errflg++;
		}
	}
	if (errflg || (argc - optind) != 1 || (cflg + sflg + fflg) > 1) {
		usage(argv0);
		exit(2);
	}
	if ((fd = open(argv[optind], O_NDELAY | O_RDWR, 0)) == EOF) {
		perror(argv[optind]);
		exit(1);
	}
	if (ioctl(fd, EP_GETA, (char *) &etio) == EOF)
		perror("EP_GETA");
	else {
		if (pflg)
			pretty(&etio);
		else if (!cflg && !sflg && !fflg && !bflg) {
			if (etio.et_state & HFC_SET)
				(void) puts("hfc");
			else
				(void) puts("-hfc");
		}
	}
	if (fflg) {
		while (nkp--) {
			if (kill(kp[nkp], signo) == EOF) {
				(void) fprintf(stderr, "kill(%d, %d)", kp[nkp], signo);
				perror(" ");
			}
		}
		if (ioctl(fd, EP_FCREL, (char *) 0) == EOF)	/* release?? */
			perror("EP_FCREL");
		if (etio.et_state & HFC_SET) {
			if (ioctl(fd, EP_NHFC, (char *) 0) == EOF)	/* kill HFC */
				perror("EP_NHFC");
		}
#if 0
		if (ioctl(fd, EP_BRK, (char *) 0) == EOF)	/* EINVAL */
			perror("EP_BRK");
		if (ioctl(fd, EP_DISC, (char *) 0) == EOF)	/* EINVAL */
			perror("EP_DISK");
#endif
		if (ioctl(fd, TCXONC, (char *) 0) == EOF)	/* stop */
			perror("TCXONC");
		if (ioctl(fd, TCFLSH, (char *) 2) == EOF)	/* flush I/O */
			perror("TCFLSH");
		if (bflg) {					/* break? */
			if (ioctl(fd, TCSBRK, (char *) 0) == EOF)
				perror("TCSBRK");
		}
 		if (ioctl(fd, TCGETA, (char *) &tio) == EOF)
			perror("TCGETA");
		obaud = tio.c_cflag & CBAUD;
		tio.c_cflag &= ~CBAUD;				/* ~DTR */
		tio.c_cflag |= B0;
		tio.c_cflag |= CLOCAL;				/* ignore mctl */
		tio.c_cflag &= ~(CREAD | HUPCL | RCV1EN | XMT1EN);/* stop reader */
		tio.c_iflag &= ~(IXON | IXOFF | IXANY);		/* clear SFC */
		tio.c_oflag = 0;
		if (ioctl(fd, TCSETA, (char *)& tio) == EOF)
			perror("TCSETA");
		if (ioctl(fd, TCFLSH, (char *) 2) == EOF)	/* flush I/O */
			perror("TCFLSH");
		if (ioctl(fd, EP_FCREL, (char *) 0) == EOF)	/* release?? */
			perror("EP_FCREL");
		if (ioctl(fd, TCXONC, (char *) 0) == EOF)	/* stop */
			perror("TCXONC");
#if 0
		if (ioctl(fd, TCXONC, (char *) 1) == EOF)	/* start */
			perror("TCXONC");
		if (bflg) {					/* break? */
			if (ioctl(fd, TCSBRK, (char *) 0) == EOF)
				perror("TCSBRK");
		}
 		if (ioctl(fd, TCGETA, (char *) &tio) == EOF)
			perror("TCGETA");
		tio.c_cflag = 0;
		tio.c_cflag |= obaud;
		tio.c_cflag |= (CREAD | HUPCL | RCV1EN | XMT1EN);/* start reader */
		tio.c_iflag = 0;
		tio.c_oflag = 0;
		if (ioctl(fd, TCSETA, (char *)& tio) == EOF)
			perror("TCSETA");
#endif
	} else if (bflg) {
		if (ioctl(fd, TCSBRK, (char *) 0) == EOF)	/* break */
			perror("TCSBRK");
	}
	if (sflg) {
		if (etio.et_state & HFC_SET) {
			if (ioctl(fd, EP_NHFC, (char *) 0) == EOF)
				perror("EP_NHFC");
		}
		if (ioctl(fd, EP_GETA, (char *) &etio) == EOF)
			perror("EP_GETA");
		else if (etio.et_state & SFC_SET) {
			if (ioctl(fd, TCGETA, (char *) &tio) == EOF)
				perror("TCGETA");
			tio.c_iflag &= ~(IXON | IXOFF | IXANY);	/* clear SFC */
			if (ioctl(fd, TCSETA, (char *)& tio) == EOF)
				perror("TCSETA");
		}
		if (ioctl(fd, EP_HFC, (char *) 0) == EOF)
			perror("EP_HFC");
	}
	if (cflg) {
		if (etio.et_state & HFC_SET) {
			if (ioctl(fd, EP_NHFC, (char *) 0) == EOF)
				perror("EP_NHFC");
		}
	}
	if (pflg && (sflg || cflg || (bflg && !fflg))) {
		if (ioctl(fd, EP_GETA, (char *) &etio) == EOF)
			perror("EP_GETA");
		else
			pretty(&etio);
	}
	for (; rflg; rflg--) {
		if (read(fd, &opt, 1) == EOF)
			perror("read()");
		if (pflg && (opt & 0xff))
			putchar(opt & 0xff);
	}
	opt = '\0';
	for (; wflg; wflg--) {
		if (write(fd, &opt, 1) == EOF)
			perror("write()");
	}
	if (close(fd) == EOF) {
		perror("close()");
		errflg++;
	}
	exit(errflg);
	/* NOTREACHED */
}

void
usage(av0)
	char	*av0;
{
	(void) fprintf(stderr, "Usage: %s [-c | -s | -f] [-k p] [-K s] [-B] [-r] [-w] [-p] device\n", av0);
}

void
pretty(ep)
	struct etty	*ep;
{
	int	nc = 0;

	(void) fputs("et_state = ", stdout);
	if (ep->et_state & EOPEN)
		(void) printf("EOPEN"), nc++;
	if (ep->et_state & WQENTRY)
		(void) printf("%sWQENTRY", nc ? ", " : ""), nc++;
	if (ep->et_state & BUFFERS_SUPPLIED)
		(void) printf("%sBUFFERS_SUPPLIED", nc ? ", " : ""), nc++;
	if (ep->et_state & HFC_SET)
		(void) printf("%sHFC_SET", nc ? ", " : ""), nc++;
	if (ep->et_state & SFC_SET)
		(void) printf("%sSFC_SET", nc ? ", " : ""), nc++;
	if (ep->et_state & BUFFER_SAVED)
		(void) printf("%sBUFFER_SAVED", nc ? ", " : ""), nc++;
	if (ep->et_state & EPCLOSE)
		(void) printf("%sEPCLOSE", nc ? ", " : "");
	putchar('\n');
	return;
}
-- 
						Greg A. Woods

woods@robohack.UUCP, woods@Elegant.COM  VE3TCP	UniForum Canada & ECI
+1 416 443-1734 [home] +1 416 362-9772 [work]	Toronto, Ontario; CANADA