BSD 4 development
[unix-history] / usr / src / sys / newdev / lp.c
CommitLineData
4a5dfccf
BJ
1/*
2 * Line printer driver
3 */
4
5#include "../h/param.h"
6#include "../h/dir.h"
7#include "../h/user.h"
8#include "../h/tty.h"
9#include "../h/uba.h"
10
11struct device *lp_addr[] = { (struct device *)(UBA0_DEV+0177514) };
12
13#define LPPRI PZERO+10
14#define LPLOWAT 50
15#define LPHIWAT 100
16#define LPMAX 2
17
18struct device {
19 short lpcsr, lpbuf;
20};
21int lp_cnt = 1;
22
23struct lp {
24 struct clist l_outq;
25 char flag, ind;
26 short ccc, mcc, mlc;
27 short line, col;
28} lp_dt[LPMAX];
29
30#define OPEN 010
31#define CAP 020
32#define NOCR 040
33#define ASLP 0100
34
35#define FORM 014
36
37lpopen(dev, flag)
38{
39 register unit;
40 register struct lp *lp;
41
42 unit = dev&07;
43 if (unit >= lp_cnt || unit >= LPMAX ||
44 (lp = &lp_dt[unit])->flag || lp_addr[unit]->lpcsr <0 ) {
45 u.u_error = EIO;
46 return;
47 }
48 lp->flag = (dev&077)|OPEN;
49 lp->ind = 4;
50 lp->col = 80;
51 lp->line = 66;
52 lp_addr[unit]->lpcsr |= IENABLE;
53 lpoutput(unit, FORM);
54}
55
56lpclose(dev)
57{
58 register unit;
59
60 unit = dev&07;
61 lpoutput(unit, FORM);
62 lp_dt[unit].flag = 0;
63}
64
65lpwrite(dev)
66{
67 register c;
68
69 while ((c=cpass())>=0)
70 lpoutput(dev&07, c);
71}
72
73lpoutput(dev, c)
74register dev, c;
75{
76 register struct lp *lp;
77
78 lp = &lp_dt[dev];
79 if(lp->flag&CAP) {
80 if(c>='a' && c<='z')
81 c += 'A'-'a'; else
82 switch(c) {
83 case '{':
84 c = '(';
85 goto esc;
86 case '}':
87 c = ')';
88 goto esc;
89 case '`':
90 c = '\'';
91 goto esc;
92 case '|':
93 c = '!';
94 goto esc;
95 case '~':
96 c = '^';
97 esc:
98 lpoutput(dev, c);
99 lp->ccc--;
100 c = '-';
101 }
102 }
103 switch(c) {
104 case '\t':
105 lp->ccc = ((lp->ccc+8-lp->ind) & ~7) + lp->ind;
106 return;
107 case '\n':
108 lp->mlc++;
109 if(lp->mlc >= lp->line )
110 c = FORM;
111 case FORM:
112 lp->mcc = 0;
113 if (lp->mlc) {
114 lpputc(dev, c);
115 if(c == FORM)
116 lp->mlc = 0;
117 }
118 case '\r':
119 lp->ccc = lp->ind;
120 return;
121 case 010:
122 if(lp->ccc > lp->ind)
123 lp->ccc--;
124 return;
125 case ' ':
126 lp->ccc++;
127 return;
128 default:
129 if(lp->ccc < lp->mcc) {
130 if (lp->flag&NOCR) {
131 lp->ccc++;
132 return;
133 }
134 lpputc(dev, '\r');
135 lp->mcc = 0;
136 }
137 if(lp->ccc < lp->col) {
138 while(lp->ccc > lp->mcc) {
139 lpputc(dev, ' ');
140 lp->mcc++;
141 }
142 lpputc(dev, c);
143 lp->mcc++;
144 }
145 lp->ccc++;
146 }
147}
148
149lpputc(dev, c)
150register dev, c;
151{
152 register struct lp *lp;
153
154 lp = &lp_dt[dev];
155 spl4();
156 while (lp->l_outq.c_cc > LPHIWAT) {
157 lp->flag |= ASLP;
158 sleep(lp, LPPRI);
159 }
160 putc(c, &lp->l_outq);
161 lpintr(dev);
162 spl0();
163}
164
165lpintr(dev)
166register dev;
167{
168 register struct lp *lp;
169 register c;
170
171 lp = &lp_dt[dev];
172 while (lp_addr[dev]->lpcsr&DONE && (c = getc(&lp->l_outq)) >= 0)
173 lp_addr[dev]->lpbuf = c;
174 if (lp->l_outq.c_cc <= LPLOWAT && lp->flag&ASLP) {
175 lp->flag &= ~ASLP;
176 wakeup(lp);
177 }
178}
179
180lpioctl(dev, cmd, addr, flag)
181register caddr_t addr;
182{
183register int m;
184struct lp *lp;
185struct {char lsg_flag, lsg_ind; short lsg_line, lsg_col;} lpios;
186
187 lp = &lp_dt[dev];
188 switch (cmd) {
189
190 case ('v'<<8)+0:
191 lpios.lsg_flag = lp->flag;
192 lpios.lsg_ind = lp->ind;
193 lpios.lsg_line = lp->line;
194 lpios.lsg_col = lp->col;
195 copyout(&lpios, addr, sizeof lpios);
196 return;
197
198 case ('v'<<8)+1:
199 m = copyin(addr, &lpios, sizeof lpios);
200 if (m == -1) {
201 u.u_error = EFAULT;
202 return;
203 }
204 lp->flag = lpios.lsg_flag;
205 lp->ind = lpios.lsg_ind;
206 lp->line = lpios.lsg_line;
207 lp->col = lpios.lsg_col;
208 return;
209
210 default:
211 u.u_error = ENOTTY;
212 return;
213 }
214}