/* * 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; } }