Xinu7/src/serve11/sys/ttywrite.c

/* ttywrite.c - ttywrite, writcopy */

#include <conf.h>
#include <kernel.h>
#include <tty.h>
#include <io.h>
#include <slu.h>

/*------------------------------------------------------------------------
 *  ttywrite - write one or more characters to a tty device
 *------------------------------------------------------------------------
 */
ttywrite(devptr, buff, count)
struct	devsw	*devptr;
char	*buff;
int	count;
{
	register struct tty *ttyp;
	int ncopied;
	char ps;

	if (count < 0)
		return(SYSERR);
	if (count == 0)
		return(OK);
	disable(ps);
	ttyp = &tty[devptr->dvminor];
	count -= (ncopied = writcopy(buff, ttyp, count));
	buff += ncopied;
	for ( ; count>0 ; count--)
		ttyputc(devptr, *buff++);
	restore(ps);
	return(OK);
}

/*------------------------------------------------------------------------
 *  writcopy - high-speed copy from user's buffer into system buffer
 *------------------------------------------------------------------------
 */
LOCAL writcopy(buff, ttyp, count)
char	*buff;
struct	tty *ttyp;
int	count;
{
	register int	avail;
	register char	*cp, *qhead, *qend, *uend;

	avail = scount(ttyp->osem);
	qhead = &ttyp->obuff[ttyp->ohead];
	qend  = &ttyp->obuff[OBUFLEN];
	cp    = buff;
	uend  = buff + count;
	while (avail-- > 1 && cp < uend) {
		if (*cp == NEWLINE && ttyp->ocrlf) {
			*qhead++ = RETURN;
			--avail;
			if ( qhead >= qend )
				qhead = ttyp->obuff;
		}
		*qhead++ = *cp++;
		if ( qhead >= qend )
			qhead = ttyp->obuff;
	}					/* avail decremented one*/
	ttyp->ohead = qhead - ttyp->obuff;	/* extra time when loop	*/
	sreset(ttyp->osem, ++avail);		/* condition fails.	*/
	(ttyp->ioaddr)->ctstat = SLUENABLE;
	return(cp - buff);
}