I'm so fastidious (clean up after tef)
[unix-history] / usr / src / sys / kern / tty_subr.c
CommitLineData
42cc3b3d 1/* tty_subr.c 6.6 84/11/15 */
8f6119af 2
94368568
JB
3#include "param.h"
4#include "systm.h"
5#include "conf.h"
6#include "buf.h"
7#include "tty.h"
8#include "clist.h"
11bd398c 9
48575cec 10char cwaiting;
11bd398c
BJ
11
12/*
13 * Character list get/put
14 */
15getc(p)
88a7a62a 16 register struct clist *p;
11bd398c
BJ
17{
18 register struct cblock *bp;
19 register int c, s;
20
7eb2e67e 21 s = spl5();
11bd398c
BJ
22 if (p->c_cc <= 0) {
23 c = -1;
24 p->c_cc = 0;
25 p->c_cf = p->c_cl = NULL;
26 } else {
27 c = *p->c_cf++ & 0377;
28 if (--p->c_cc<=0) {
29 bp = (struct cblock *)(p->c_cf-1);
30 bp = (struct cblock *) ((int)bp & ~CROUND);
31 p->c_cf = NULL;
32 p->c_cl = NULL;
33 bp->c_next = cfreelist;
34 cfreelist = bp;
48575cec
BJ
35 cfreecount += CBSIZE;
36 if (cwaiting) {
37 wakeup(&cwaiting);
38 cwaiting = 0;
39 }
11bd398c
BJ
40 } else if (((int)p->c_cf & CROUND) == 0){
41 bp = (struct cblock *)(p->c_cf);
42 bp--;
43 p->c_cf = bp->c_next->c_info;
44 bp->c_next = cfreelist;
45 cfreelist = bp;
48575cec
BJ
46 cfreecount += CBSIZE;
47 if (cwaiting) {
48 wakeup(&cwaiting);
49 cwaiting = 0;
50 }
11bd398c
BJ
51 }
52 }
53 splx(s);
54 return(c);
55}
56
57/*
58 * copy clist to buffer.
59 * return number of bytes moved.
60 */
61q_to_b(q, cp, cc)
961945a8
SL
62 register struct clist *q;
63 register char *cp;
11bd398c
BJ
64{
65 register struct cblock *bp;
66 register int s;
67 char *acp;
68
69 if (cc <= 0)
70 return(0);
7eb2e67e 71 s = spl5();
11bd398c
BJ
72 if (q->c_cc <= 0) {
73 q->c_cc = 0;
74 q->c_cf = q->c_cl = NULL;
48575cec 75 splx(s);
11bd398c
BJ
76 return(0);
77 }
78 acp = cp;
79 cc++;
80
81 while (--cc) {
82 *cp++ = *q->c_cf++;
83 if (--q->c_cc <= 0) {
84 bp = (struct cblock *)(q->c_cf-1);
85 bp = (struct cblock *)((int)bp & ~CROUND);
86 q->c_cf = q->c_cl = NULL;
87 bp->c_next = cfreelist;
88 cfreelist = bp;
48575cec
BJ
89 cfreecount += CBSIZE;
90 if (cwaiting) {
91 wakeup(&cwaiting);
92 cwaiting = 0;
93 }
11bd398c
BJ
94 break;
95 }
96 if (((int)q->c_cf & CROUND) == 0) {
97 bp = (struct cblock *)(q->c_cf);
98 bp--;
99 q->c_cf = bp->c_next->c_info;
100 bp->c_next = cfreelist;
101 cfreelist = bp;
48575cec
BJ
102 cfreecount += CBSIZE;
103 if (cwaiting) {
104 wakeup(&cwaiting);
105 cwaiting = 0;
106 }
11bd398c
BJ
107 }
108 }
109 splx(s);
110 return(cp-acp);
111}
112
11bd398c
BJ
113/*
114 * Return count of contiguous characters
115 * in clist starting at q->c_cf.
116 * Stop counting if flag&character is non-null.
117 */
118ndqb(q, flag)
961945a8 119 register struct clist *q;
11bd398c 120{
961945a8
SL
121 register cc;
122 int s;
11bd398c 123
7eb2e67e 124 s = spl5();
11bd398c
BJ
125 if (q->c_cc <= 0) {
126 cc = -q->c_cc;
127 goto out;
128 }
129 cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
130 cc -= (int)q->c_cf;
131 if (q->c_cc < cc)
132 cc = q->c_cc;
133 if (flag) {
134 register char *p, *end;
135
136 p = q->c_cf;
137 end = p;
138 end += cc;
139 while (p < end) {
140 if (*p & flag) {
48575cec
BJ
141 cc = (int)p;
142 cc -= (int)q->c_cf;
11bd398c
BJ
143 break;
144 }
145 p++;
146 }
147 }
148out:
149 splx(s);
150 return(cc);
151}
152
48575cec
BJ
153
154
11bd398c 155/*
48575cec 156 * Flush cc bytes from q.
11bd398c
BJ
157 */
158ndflush(q, cc)
88a7a62a
SL
159 register struct clist *q;
160 register cc;
11bd398c 161{
88a7a62a
SL
162 register struct cblock *bp;
163 char *end;
164 int rem, s;
11bd398c 165
7eb2e67e 166 s = spl5();
0a30ed64 167 if (q->c_cc <= 0) {
11bd398c
BJ
168 goto out;
169 }
48575cec
BJ
170 while (cc>0 && q->c_cc) {
171 bp = (struct cblock *)((int)q->c_cf & ~CROUND);
172 if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
173 end = q->c_cl;
174 } else {
175 end = (char *)((int)bp + sizeof (struct cblock));
176 }
177 rem = end - q->c_cf;
178 if (cc >= rem) {
179 cc -= rem;
180 q->c_cc -= rem;
11bd398c 181 q->c_cf = bp->c_next->c_info;
48575cec
BJ
182 bp->c_next = cfreelist;
183 cfreelist = bp;
184 cfreecount += CBSIZE;
185 if (cwaiting) {
186 wakeup(&cwaiting);
187 cwaiting = 0;
188 }
11bd398c 189 } else {
48575cec
BJ
190 q->c_cc -= cc;
191 q->c_cf += cc;
192 if (q->c_cc <= 0) {
193 bp->c_next = cfreelist;
194 cfreelist = bp;
195 cfreecount += CBSIZE;
196 if (cwaiting) {
197 wakeup(&cwaiting);
198 cwaiting = 0;
199 }
200 }
201 break;
11bd398c 202 }
48575cec
BJ
203 }
204 if (q->c_cc <= 0) {
11bd398c 205 q->c_cf = q->c_cl = NULL;
48575cec 206 q->c_cc = 0;
11bd398c
BJ
207 }
208out:
209 splx(s);
210}
b8f09f36 211
48575cec 212
11bd398c 213putc(c, p)
88a7a62a 214 register struct clist *p;
11bd398c
BJ
215{
216 register struct cblock *bp;
217 register char *cp;
218 register s;
219
7eb2e67e 220 s = spl5();
11bd398c
BJ
221 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
222 if ((bp = cfreelist) == NULL) {
223 splx(s);
224 return(-1);
225 }
226 cfreelist = bp->c_next;
48575cec 227 cfreecount -= CBSIZE;
11bd398c
BJ
228 bp->c_next = NULL;
229 p->c_cf = cp = bp->c_info;
230 } else if (((int)cp & CROUND) == 0) {
231 bp = (struct cblock *)cp - 1;
232 if ((bp->c_next = cfreelist) == NULL) {
233 splx(s);
234 return(-1);
235 }
236 bp = bp->c_next;
237 cfreelist = bp->c_next;
48575cec 238 cfreecount -= CBSIZE;
11bd398c
BJ
239 bp->c_next = NULL;
240 cp = bp->c_info;
241 }
242 *cp++ = c;
243 p->c_cc++;
244 p->c_cl = cp;
245 splx(s);
246 return(0);
247}
248
48575cec
BJ
249
250
11bd398c
BJ
251/*
252 * copy buffer to clist.
253 * return number of bytes not transfered.
254 */
255b_to_q(cp, cc, q)
88a7a62a
SL
256 register char *cp;
257 struct clist *q;
258 register int cc;
11bd398c
BJ
259{
260 register char *cq;
261 register struct cblock *bp;
262 register s, acc;
263
264 if (cc <= 0)
42cc3b3d 265 return (0);
9e8d8813
TF
266 while (cc > 0) {
267 s = spl6();
268 if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
269 if ((bp = cfreelist) == NULL) {
270 splx(s);
271 break;
272 }
273 q->c_cf = cq = bp->c_info;
274 goto middle;
275 }
11bd398c 276 if (((int)cq & CROUND) == 0) {
42cc3b3d 277 bp = &((struct cblock *)cq)[-1];
9e8d8813
TF
278 if ((bp->c_next = cfreelist) == NULL) {
279 splx(s);
280 break;
281 }
11bd398c 282 bp = bp->c_next;
9e8d8813 283 cq = bp->c_info;
42cc3b3d 284 middle:
11bd398c 285 cfreelist = bp->c_next;
48575cec 286 cfreecount -= CBSIZE;
11bd398c 287 bp->c_next = NULL;
42cc3b3d
SL
288 acc = MIN(cc, CBSIZE);
289 } else {
290 acc = (char *)((int)&cq[CBSIZE] &~ CROUND) - cq;
291 if (acc > cc)
292 acc = cc;
11bd398c 293 }
42cc3b3d 294 bcopy((caddr_t)cp, cq, acc);
9e8d8813
TF
295 q->c_cl = &cq[acc];
296 q->c_cc += acc;
297 splx(s);
298 cp += acc;
299 cc -= acc;
11bd398c 300 }
42cc3b3d 301 return (cc);
11bd398c
BJ
302}
303
b8f09f36
BJ
304/*
305 * Given a non-NULL pointter into the list (like c_cf which
306 * always points to a real character if non-NULL) return the pointer
307 * to the next character in the list or return NULL if no more chars.
308 *
309 * Callers must not allow getc's to happen between nextc's so that the
310 * pointer becomes invalid. Note that interrupts are NOT masked.
311 */
312char *
313nextc(p, cp)
88a7a62a
SL
314 register struct clist *p;
315 register char *cp;
b8f09f36
BJ
316{
317
318 if (p->c_cc && ++cp != p->c_cl) {
319 if (((int)cp & CROUND) == 0)
320 return (((struct cblock *)cp)[-1].c_next->c_info);
321 return (cp);
322 }
323 return (0);
324}
325
326/*
327 * Remove the last character in the list and return it.
328 */
329unputc(p)
88a7a62a 330 register struct clist *p;
b8f09f36
BJ
331{
332 register struct cblock *bp;
333 register int c, s;
334 struct cblock *obp;
335
7eb2e67e 336 s = spl5();
b8f09f36
BJ
337 if (p->c_cc <= 0)
338 c = -1;
339 else {
340 c = *--p->c_cl;
341 if (--p->c_cc <= 0) {
342 bp = (struct cblock *)p->c_cl;
343 bp = (struct cblock *)((int)bp & ~CROUND);
344 p->c_cl = p->c_cf = NULL;
345 bp->c_next = cfreelist;
346 cfreelist = bp;
48575cec 347 cfreecount += CBSIZE;
b8f09f36
BJ
348 } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
349 p->c_cl = (char *)((int)p->c_cl & ~CROUND);
350 bp = (struct cblock *)p->c_cf;
351 bp = (struct cblock *)((int)bp & ~CROUND);
352 while (bp->c_next != (struct cblock *)p->c_cl)
353 bp = bp->c_next;
354 obp = bp;
355 p->c_cl = (char *)(bp + 1);
356 bp = bp->c_next;
357 bp->c_next = cfreelist;
358 cfreelist = bp;
48575cec 359 cfreecount += CBSIZE;
b8f09f36
BJ
360 obp->c_next = NULL;
361 }
362 }
363 splx(s);
364 return (c);
365}
366
367/*
368 * Put the chars in the from que
369 * on the end of the to que.
370 *
371 * SHOULD JUST USE q_to_b AND THEN b_to_q HERE.
372 */
373catq(from, to)
88a7a62a 374 struct clist *from, *to;
b8f09f36
BJ
375{
376 register c;
377
378 while ((c = getc(from)) >= 0)
379 (void) putc(c, to);
380}
381
11bd398c 382/*
961945a8 383 * Integer (short) get/put
11bd398c
BJ
384 * using clists
385 */
961945a8
SL
386typedef short word_t;
387union chword {
388 word_t word;
389 struct {
390 char Ch[sizeof (word_t)];
391 } Cha;
392#define ch Cha.Ch
393};
394
11bd398c 395getw(p)
d0b37068 396 register struct clist *p;
11bd398c 397{
961945a8
SL
398 register int i;
399 union chword x;
400
401 if (p->c_cc < sizeof (word_t))
402 return (-1);
403 for (i = 0; i < sizeof (word_t); i++)
404 x.ch[i] = getc(p);
405 return (x.word);
11bd398c 406}
48575cec 407
11bd398c 408putw(c, p)
d0b37068 409 register struct clist *p;
11bd398c
BJ
410{
411 register s;
961945a8
SL
412 register int i;
413 union chword x;
11bd398c 414
7eb2e67e 415 s = spl5();
11bd398c
BJ
416 if (cfreelist==NULL) {
417 splx(s);
418 return(-1);
419 }
961945a8
SL
420 x.word = c;
421 for (i = 0; i < sizeof (word_t); i++)
422 (void) putc(x.ch[i], p);
11bd398c 423 splx(s);
961945a8 424 return (0);
11bd398c 425}