Interdata732/usr/sys/lp.c

Compare this file to the similar file:
Show the results in this format:

#
/*
 *  Line printer driver
 */

#include "param.h"
#include "conf.h"
#include "user.h"
#include "tty.h"

/* Configuration */

#define LPPRI	75	/* line printer wakeup priority */
#define LPLWAT 70        /* line printer low water mark */
#define LPHWAT 150       /* line printer high water mark */

#define LPWIDTH	131	/* page width (not 132, as lp auto prints on 132nd char */
#define LPDEPTH	60	/* lines per page */

int	lpaddr	0x62;	/* printer address */

/* Printer status & commands */

#define ENABLE	0x40
#define DISARM	0xc0

#define NO_PAPER	0x40
#define INTLOCK		0x10
#define DU		0x01


struct {    /* info about the printer */
	struct clist outq;	/* output char queue */
	char flag;	/* current mode */
	char state;	/* internal status */
	int mcc;	/* actual column posn */
	int ccc;	/* logical column posn */
	int mlc;	/* curr line # */
	int mxc;	/* max line width */
	int mxl;	/* max page depth */
} lp;

#define	P_WASTE	ECHO	/* if on, printer wastes paper */
#define IND	XTABS	/* if on, lines are indented 8 spaces */

#define FORM 0x0c
#define VTAB 0x0b


/*
 *    open - line printer
 */

lpopen(dev, flag)
{
	if(lp.state&ISOPEN || (ss(lpaddr)&(NO_PAPER|INTLOCK|DU))) {
		u.u_error = EIO;
		return;
	}

	trace(01<<8,"lpopen",0);

	lp.state = ISOPEN;
	if (lp.mxc == 0) {
		lp.mxc = LPWIDTH;
		lp.mxl = LPDEPTH;
	}
	oc(lpaddr, ENABLE);
	lpcanon(FORM);
}

/*
 *   close - line printer
 */

lpclose(dev, flag)
{

	lpcanon(FORM);
	trace(01<<8,"lpclose",0);
	lp.state = 0;
}

/*
 *     user write to line printer
 */

lpwrite()
{
	register c;

	while ((c=cpass()) >= 0)
		lpcanon(c);
}

/*
 * lpcanon - character transformations
 */

lpcanon(ac)
{
	register char c;
	register char *p;

	c = ac;

	if (c == '_')
		c =| 0x80;   /*
			      *   Interdata line printer i/face
			      *   turns x'5f' into x'3c' .....
			      *
			      *   But it isn't smart enough to
			      *   regognize x'df', fortunately.
			      */
	if (lp.flag & RAW) {
		lpoutput(c);
		return;
	}

	if (lp.flag & LCASE) {		/* Uppercase-only printer */
		if (c>='a' && c<='z')
			c =+ 'A'-'a';
		else {
			p = "({)}!|^~'`";
			while (*p++)
				if (c == *p++) {
					lpcanon(p[-2]);
					lp.ccc--;
					c = '-';
					break;
				}
		}
	}

	switch(c&0x7f) {

	case '\t':
		lp.ccc = (lp.ccc + 8) & ~7;
		return;

	case FORM:
	case '\n':
		if(lp.mcc != 0 || lp.mlc != 0 || lp.flag & P_WASTE) {
			if(lp.mcc) {
				lpoutput('\r');  /* cause line to print */
			}
			lp.mlc++;
			if(lp.mlc > lp.mxl && lp.mxl)
				c = FORM;
			lpoutput(c);
			if (c == FORM)
				lp.mlc = 0;
			lp.mcc = 0;
		}   /* now fall through to '\r' code */

	case '\r':
		lp.ccc = 0;
		if (lp.flag & IND)
			lp.ccc = 8;
		return;

	case '\b':
		if (lp.ccc > 0)
			lp.ccc--;
		return;

	case 0x07:
		lpoutput(c); /* ring bell, no char advance */
		return;

	case ' ':
		lp.ccc++;
		return;

	case VTAB:
		if(lp.mcc)
			lpcanon('\n');
		while(lp.mlc & 7)
			lpcanon('\n');
		return;

	default:
		if ((c & 0x7f) < 0x20)	/* non printing - ignore */
			return;
		if(lp.ccc < lp.mcc) {
			lpoutput('\r');    /* cause overprint */
			lp.mcc = 0;
		}
		if (lp.ccc < lp.mxc) {
			while(lp.ccc > lp.mcc) {
				lpoutput(' ');
				lp.mcc++;
			}
			lpoutput(c);
			lp.mcc++;
		}
		lp.ccc++;
	}
}


/*
 *   start transmission to printer
 */

lpstart()
{
	register c;
	register s;

	trace(02<<8,"lpstart",lpaddr);
	trace(01<<8,"lpstat",ss(lpaddr));

	while( (s = ss(lpaddr)) == 0
		&&    (c = getc(&lp.outq)) >= 0  ) {
			trace(010<<8,"lpchar",c);
			wd(lpaddr, c);
		}
	trace(01<<8,"lpstat",s);
}


/*
 *   line printer interrupt
 */

lpint(dev, stat)
{
	trace(02<<8,"lpint",stat);

/***	if(stat & DU)
		printf("\nline printer offline\n");
	else if (stat & NO_PAPER)
		printf("\nline printer paper out\n");
	else {			***/   if(!(stat & (DU|NO_PAPER))) {
		lpstart();
		if(lp.outq.c_cc <= LPLWAT && lp.state & ASLEEP) {
			trace(04<<8,"lpwakeup",lp.outq.c_cc);
			lp.state =& ~ASLEEP;
			wakeup(&lp);
		}
	}
}

/*
 *  write a character to line printer
 */

lpoutput(c)
{
	trace(02<<8,"lpoutput",c);
	spl(4);
	while(lp.outq.c_cc >= LPHWAT) {
		lp.state =| ASLEEP;
		trace(04<<8,"lpsleep",lp.outq.c_cc);
		sleep(&lp, LPPRI);
	}

	putc(c, &lp.outq);
	lpstart();
	spl(0);
}

/*
 * allow several line printer attributes to be dynamically altered
 */

lpsgtty(dev, av)
int *av;
{
	register *v;

	if(v=av) {
		*v++ = 0;
		v->lobyte = lp.mxc;
		v->hibyte = lp.mxl;
		v[1] = lp.flag;
		return(1);
	}
	v = u.u_arg;
	lp.mxc = (++v)->lobyte;
	lp.mxl = v->hibyte;
	lp.flag = v[1];
	return(0);
}