static char rcsid[] = "$Header: co.c,v 800.0 85/08/06 14:07:09 root Exp $";
static char sccsid[] = "%W% %Y% %Q% %G%";

/*
 * Synertek Asyncronous Communication Interface Adapter SY6551
 *
 *	Copyright 1981 UniSoft Corporation
 */
#include "../h/types.h"
#include "../h/ioctl.h"
#include "../h/param.h"
#include "../h/conf.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/tty.h"
#include "../h/systm.h"
#include "../h/uio.h"
#include "../white/acia.h"

struct tty co_tty[1];
int	costart();
char	partab[];

coinit()
{
	kbinit();
}

coopen(dev, flag)
	dev_t dev;
{
	register struct tty *tp;
	register d;

#ifdef HOWFAR
	printf("coopen: %d\n", d);
#endif
	tp = &co_tty[0];
	tp->t_oproc = costart;
	spl4();
	if ((tp->t_state&TS_ISOPEN) == 0) {
		tp->t_state = TS_ISOPEN|TS_CARR_ON;
		spl0();
		tp->t_flags = EVENP|ODDP|ECHO|XTABS|CRMOD|
				CRTBS|CRTERA|CRTKIL|CTLECH;
		ttychars(tp);
		tp->t_ispeed = tp->t_ospeed = B9600;  /* Phony speed */
		dsopen();
		kbopen();
	}
	spl0();
	tp->t_line = NTTYDISC;	/* new tty line discipline */
	(*linesw[tp->t_line].l_open)(dev, tp);
#ifdef HOWFAR
	printf("coopen: returing\n");
#endif
}

coclose(dev, flag)
	dev_t	dev;
{
	register struct tty *tp;

	tp = &co_tty[0];
	mouse_close(tp);
	(*linesw[tp->t_line].l_close)(tp);
	ttyclose(tp);
}

coread(dev, uio)
	dev_t	dev;
	struct	uio *uio;
{
	register struct tty *tp;

	tp = &co_tty[0];
	(*linesw[tp->t_line].l_read)(tp, uio);
}

cowrite(dev, uio)
	dev_t	dev;
	struct	uio *uio;
{
	register struct tty *tp;

	tp = &co_tty[0];
	(*linesw[tp->t_line].l_write)(tp, uio);
}


coioctl(dev, cmd, addr, flag)
	dev_t	dev;
	caddr_t	addr;
{
	register struct tty *tp = &co_tty[minor(dev)];
	register int error;

#ifdef notdef	/* not yet */
	if (cmd == TIOCGWINSIZ) {
		register struct window_params *w =
		    (struct window_params *)addr;
		w->w_nlines = 35;
		w->w_ncols = 80;
		return 0;
	}
#endif notdef
#define TIOCSIMCHARS _IOW(_IO_TTY, 98, int)
	if (cmd == TIOCSIMCHARS)
		return dssimchars(*(int *)addr != 0);
	error = mouse_ioctl(tp, cmd, addr, flag);
	if (error >= 0)
		return error;
	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag);
	if (error >= 0)
		return (error);
	error = ttioctl(tp, cmd, addr, flag);
	if (error < 0)
		error = ENOTTY;
	return(error);
}


coinput(c)
{
	register struct tty *tp;

	tp = &co_tty[0];
	if (tp->t_state&TS_ISOPEN)
		(*linesw[tp->t_line].l_rint)(c, tp);
}


/*
 * Output to the console is completely synchronous; there is no xmitter
 * interrupt to jab us in the side.  This routine is a crude attempt to
 * simulate asynchrony by pushing out a few characters, then scheduling
 * another call if there are still more characters in the q.
 * The tension is between fine-grained control over ^S on one hand, and
 * reasonable output speed/overhead on the other.
 *
 * 841114 experimenting with spl1.  If it works, then this routine is
 *	far too complicated. (sbs)
 */
int	co_howmany = 16; 			/* 16 is tunable */
costart(tp)
	register struct tty *tp;
{
	register c, n, s;
	int old;
#include "log.h"
#if NLOG > 0
	char	logchar;
#endif NLOG
	s = spl5();
	if (tp->t_state&(TS_BUSY|TS_TTSTOP)) {
		splx(s);
		return;
	}
	tp->t_state =| TS_BUSY;
	old = dsupdcursor(0);	/* kill cursor: see ds.c */
	for (n = co_howmany; --n >= 0 && (c = getc(&tp->t_outq)) >= 0;) {
		/* spl1(); -- sbs 850208 */
		dsputch(c);
		/* spl5(); -- sbs (I don sack cloths and ashes) */
#if NLOG > 0
		logchar = c; log_data(&logchar, 1, 2/*LOGTYPE_CONSOLE*/);
#endif NLOG
	}
	dsupdcursor(old);	/* restore cursor: see ds.c */
	tp->t_state &= ~TS_BUSY;
	if (tp->t_state&TS_ASLEEP) {
		tp->t_state &= ~TS_ASLEEP;
		wakeup((caddr_t)&tp->t_outq);
	}
	splx(s);
	if (n < 0)
		timeout(costart, tp, 1);
}


/*
 * Print a character on console.
 * Attempts to save and restore device
 * status.
 */
coputchar(c)
	register c;
{
	static init = 0;
	int s;

	s = spl7();
	if (init == 0) {
		init++;
		dsopen();
	}
	if (c == '\n')
		dsputch('\r');
	dsputch(c);
	splx(s);
}
