32V/usr/src/sys/dev/lp.c

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

/*
 *  Line printer driver
 */

#include "../h/param.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/tty.h"
#include "../h/uba.h"

struct device *lp_addr[] = { (struct device *)(UBA0_DEV+0177514) };

#define	LPPRI	PZERO+10
#define	LPLOWAT	50
#define	LPHIWAT	100
#define LPMAX 2

struct device {
	short	lpcsr, lpbuf;
};
int lp_cnt = 1;

struct lp {
	struct	clist l_outq;
	char	flag, ind;
	short	ccc, mcc, mlc;
	short	line, col;
} lp_dt[LPMAX];

#define	OPEN	010
#define	CAP	020
#define	NOCR	040
#define	ASLP	0100

#define	FORM	014

lpopen(dev, flag)
{
	register unit;
	register struct lp *lp;

	unit = dev&07;
	if (unit >= lp_cnt || unit >= LPMAX ||
	 (lp = &lp_dt[unit])->flag || lp_addr[unit]->lpcsr <0 ) {
		u.u_error = EIO;
		return;
	}
	lp->flag = (dev&077)|OPEN;
	lp->ind = 4;
	lp->col = 80;
	lp->line = 66;
	lp_addr[unit]->lpcsr |= IENABLE;
	lpoutput(unit, FORM);
}

lpclose(dev)
{
	register unit;

	unit = dev&07;
	lpoutput(unit, FORM);
	lp_dt[unit].flag = 0;
}

lpwrite(dev)
{
	register c;

	while ((c=cpass())>=0)
		lpoutput(dev&07, c);
}

lpoutput(dev, c)
register dev, c;
{
	register struct lp *lp;

	lp = &lp_dt[dev];
	if(lp->flag&CAP) {
		if(c>='a' && c<='z')
			c += 'A'-'a'; else
		switch(c) {
		case '{':
			c = '(';
			goto esc;
		case '}':
			c = ')';
			goto esc;
		case '`':
			c = '\'';
			goto esc;
		case '|':
			c = '!';
			goto esc;
		case '~':
			c = '^';
		esc:
			lpoutput(dev, c);
			lp->ccc--;
			c = '-';
		}
	}
	switch(c) {
	case '\t':
		lp->ccc = ((lp->ccc+8-lp->ind) & ~7) + lp->ind;
		return;
	case '\n':
		lp->mlc++;
		if(lp->mlc >= lp->line )
			c = FORM;
	case FORM:
		lp->mcc = 0;
		if (lp->mlc) {
			lpputc(dev, c);
			if(c == FORM)
				lp->mlc = 0;
		}
	case '\r':
		lp->ccc = lp->ind;
		return;
	case 010:
		if(lp->ccc > lp->ind)
			lp->ccc--;
		return;
	case ' ':
		lp->ccc++;
		return;
	default:
		if(lp->ccc < lp->mcc) {
			if (lp->flag&NOCR) {
				lp->ccc++;
				return;
			}
			lpputc(dev, '\r');
			lp->mcc = 0;
		}
		if(lp->ccc < lp->col) {
			while(lp->ccc > lp->mcc) {
				lpputc(dev, ' ');
				lp->mcc++;
			}
			lpputc(dev, c);
			lp->mcc++;
		}
		lp->ccc++;
	}
}

lpputc(dev, c)
register dev, c;
{
	register struct lp *lp;

	lp = &lp_dt[dev];
	spl4();
	while (lp->l_outq.c_cc > LPHIWAT) {
		lp->flag |= ASLP;
		sleep(lp, LPPRI);
	}
	putc(c, &lp->l_outq);
	lpintr(dev);
	spl0();
}

lpintr(dev)
register dev;
{
	register struct lp *lp;
	register c;

	lp = &lp_dt[dev];
	while (lp_addr[dev]->lpcsr&DONE && (c = getc(&lp->l_outq)) >= 0)
		lp_addr[dev]->lpbuf = c;
	if (lp->l_outq.c_cc <= LPLOWAT && lp->flag&ASLP) {
		lp->flag &= ~ASLP;
		wakeup(lp);
	}
}

lpioctl(dev, cmd, addr, flag)
register caddr_t addr;
{
register int m;
struct lp *lp;
struct {char lsg_flag, lsg_ind; short lsg_line, lsg_col;} lpios;

	lp = &lp_dt[dev];
	switch (cmd) {

	case ('v'<<8)+0:
		lpios.lsg_flag = lp->flag;
		lpios.lsg_ind = lp->ind;
		lpios.lsg_line = lp->line;
		lpios.lsg_col = lp->col;
		copyout(&lpios, addr, sizeof lpios);
		return;

	case ('v'<<8)+1:
		m = copyin(addr, &lpios, sizeof lpios);
		if (m == -1) {
			u.u_error = EFAULT;
			return;
		}
		lp->flag = lpios.lsg_flag;
		lp->ind = lpios.lsg_ind;
		lp->line = lpios.lsg_line;
		lp->col = lpios.lsg_col;
		return;

	default:
		u.u_error = ENOTTY;
		return;
	}
}