Commit | Line | Data |
---|---|---|
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 | ||
11 | struct 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 | ||
18 | struct device { | |
19 | short lpcsr, lpbuf; | |
20 | }; | |
21 | int lp_cnt = 1; | |
22 | ||
23 | struct 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 | ||
37 | lpopen(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 | ||
56 | lpclose(dev) | |
57 | { | |
58 | register unit; | |
59 | ||
60 | unit = dev&07; | |
61 | lpoutput(unit, FORM); | |
62 | lp_dt[unit].flag = 0; | |
63 | } | |
64 | ||
65 | lpwrite(dev) | |
66 | { | |
67 | register c; | |
68 | ||
69 | while ((c=cpass())>=0) | |
70 | lpoutput(dev&07, c); | |
71 | } | |
72 | ||
73 | lpoutput(dev, c) | |
74 | register 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 | ||
149 | lpputc(dev, c) | |
150 | register 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 | ||
165 | lpintr(dev) | |
166 | register 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 | ||
180 | lpioctl(dev, cmd, addr, flag) | |
181 | register caddr_t addr; | |
182 | { | |
183 | register int m; | |
184 | struct lp *lp; | |
185 | struct {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 | } |