add USL's copyright notice
[unix-history] / usr / src / sys / kern / tty_subr.c
CommitLineData
5dc2581e 1/*-
7a6e4544
KB
2 * Copyright (c) 1982, 1986, 1993
3 * The Regents of the University of California. All rights reserved.
adb35f79
KB
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
5dc2581e
KB
9 *
10 * %sccs.include.proprietary.c%
da7c5cc6 11 *
adb35f79 12 * @(#)tty_subr.c 8.3 (Berkeley) %G%
da7c5cc6 13 */
8f6119af 14
38a01dbe
KB
15#include <sys/param.h>
16#include <sys/systm.h>
17#include <sys/buf.h>
18#include <sys/ioctl.h>
19#include <sys/proc.h>
20#include <sys/tty.h>
21#include <sys/clist.h>
11bd398c 22
48575cec 23char cwaiting;
1cd441c7
KS
24struct cblock *cfree, *cfreelist;
25int cfreecount, nclist;
11bd398c 26
e39f9ea6
MT
27#define setquote(cp) \
28 setbit(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \
29 (int)(cp)&CROUND)
30#define isquote(cp) \
31 isset(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \
32 (int)(cp)&CROUND)
33#define cbptr(x) ((struct cblock *)(x))
34
3789a403
MK
35/*
36 * Initialize clist by freeing all character blocks.
37 */
7121fdf0
KB
38void
39clist_init()
3789a403
MK
40{
41 register int ccp;
42 register struct cblock *cp;
43
44 ccp = (int) cfree;
45 ccp = (ccp + CROUND) & ~CROUND;
46 for(cp = (struct cblock *) ccp; cp < &cfree[nclist - 1]; cp++) {
47 cp->c_next = cfreelist;
48 cfreelist = cp;
49 cfreecount += CBSIZE;
50 }
51}
52
11bd398c
BJ
53/*
54 * Character list get/put
55 */
56getc(p)
88a7a62a 57 register struct clist *p;
11bd398c
BJ
58{
59 register struct cblock *bp;
60 register int c, s;
61
a8170d5d 62 s = spltty();
11bd398c
BJ
63 if (p->c_cc <= 0) {
64 c = -1;
65 p->c_cc = 0;
66 p->c_cf = p->c_cl = NULL;
67 } else {
e39f9ea6
MT
68 c = *p->c_cf & 0377;
69 if (isquote(p->c_cf))
70 c |= TTY_QUOTE;
71 p->c_cf++;
11bd398c 72 if (--p->c_cc<=0) {
e39f9ea6
MT
73 bp = cbptr(p->c_cf-1);
74 bp = cbptr((int)bp & ~CROUND);
11bd398c
BJ
75 p->c_cf = NULL;
76 p->c_cl = NULL;
77 bp->c_next = cfreelist;
78 cfreelist = bp;
48575cec
BJ
79 cfreecount += CBSIZE;
80 if (cwaiting) {
81 wakeup(&cwaiting);
82 cwaiting = 0;
83 }
11bd398c 84 } else if (((int)p->c_cf & CROUND) == 0){
e39f9ea6 85 bp = cbptr(p->c_cf);
11bd398c
BJ
86 bp--;
87 p->c_cf = bp->c_next->c_info;
88 bp->c_next = cfreelist;
89 cfreelist = bp;
48575cec
BJ
90 cfreecount += CBSIZE;
91 if (cwaiting) {
92 wakeup(&cwaiting);
93 cwaiting = 0;
94 }
11bd398c
BJ
95 }
96 }
97 splx(s);
01b0e233 98 return (c);
11bd398c
BJ
99}
100
101/*
102 * copy clist to buffer.
103 * return number of bytes moved.
104 */
105q_to_b(q, cp, cc)
961945a8
SL
106 register struct clist *q;
107 register char *cp;
fd402d46 108 int cc;
11bd398c
BJ
109{
110 register struct cblock *bp;
fd402d46 111 register int s, nc;
11bd398c
BJ
112 char *acp;
113
114 if (cc <= 0)
01b0e233 115 return (0);
a8170d5d 116 s = spltty();
11bd398c
BJ
117 if (q->c_cc <= 0) {
118 q->c_cc = 0;
119 q->c_cf = q->c_cl = NULL;
48575cec 120 splx(s);
01b0e233 121 return (0);
11bd398c
BJ
122 }
123 acp = cp;
11bd398c 124
a8170d5d 125 while (cc) {
01b0e233 126 nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND);
65ae7af4
JSP
127 nc = min(nc, cc);
128 nc = min(nc, q->c_cc);
a8170d5d
MK
129 (void) bcopy(q->c_cf, cp, (unsigned)nc);
130 q->c_cf += nc;
131 q->c_cc -= nc;
132 cc -= nc;
133 cp += nc;
134 if (q->c_cc <= 0) {
e39f9ea6
MT
135 bp = cbptr(q->c_cf - 1);
136 bp = cbptr((int)bp & ~CROUND);
11bd398c
BJ
137 q->c_cf = q->c_cl = NULL;
138 bp->c_next = cfreelist;
139 cfreelist = bp;
48575cec
BJ
140 cfreecount += CBSIZE;
141 if (cwaiting) {
142 wakeup(&cwaiting);
143 cwaiting = 0;
144 }
11bd398c
BJ
145 break;
146 }
147 if (((int)q->c_cf & CROUND) == 0) {
e39f9ea6 148 bp = cbptr(q->c_cf);
11bd398c
BJ
149 bp--;
150 q->c_cf = bp->c_next->c_info;
151 bp->c_next = cfreelist;
152 cfreelist = bp;
48575cec
BJ
153 cfreecount += CBSIZE;
154 if (cwaiting) {
155 wakeup(&cwaiting);
156 cwaiting = 0;
157 }
11bd398c
BJ
158 }
159 }
160 splx(s);
01b0e233 161 return (cp-acp);
11bd398c
BJ
162}
163
11bd398c
BJ
164/*
165 * Return count of contiguous characters
166 * in clist starting at q->c_cf.
167 * Stop counting if flag&character is non-null.
168 */
169ndqb(q, flag)
961945a8 170 register struct clist *q;
fd402d46 171 int flag;
11bd398c 172{
fd402d46 173 register int cc, s;
11bd398c 174
a8170d5d 175 s = spltty();
11bd398c
BJ
176 if (q->c_cc <= 0) {
177 cc = -q->c_cc;
178 goto out;
179 }
180 cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
181 cc -= (int)q->c_cf;
182 if (q->c_cc < cc)
183 cc = q->c_cc;
184 if (flag) {
185 register char *p, *end;
186
187 p = q->c_cf;
188 end = p;
189 end += cc;
190 while (p < end) {
191 if (*p & flag) {
48575cec
BJ
192 cc = (int)p;
193 cc -= (int)q->c_cf;
11bd398c
BJ
194 break;
195 }
196 p++;
197 }
198 }
199out:
200 splx(s);
01b0e233 201 return (cc);
11bd398c
BJ
202}
203
11bd398c 204/*
48575cec 205 * Flush cc bytes from q.
11bd398c 206 */
7121fdf0 207void
11bd398c 208ndflush(q, cc)
88a7a62a 209 register struct clist *q;
fd402d46 210 register int cc;
11bd398c 211{
88a7a62a
SL
212 register struct cblock *bp;
213 char *end;
214 int rem, s;
11bd398c 215
a8170d5d 216 s = spltty();
01b0e233 217 if (q->c_cc <= 0)
11bd398c 218 goto out;
48575cec 219 while (cc>0 && q->c_cc) {
e39f9ea6 220 bp = cbptr((int)q->c_cf & ~CROUND);
48575cec
BJ
221 if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
222 end = q->c_cl;
223 } else {
224 end = (char *)((int)bp + sizeof (struct cblock));
225 }
226 rem = end - q->c_cf;
227 if (cc >= rem) {
228 cc -= rem;
229 q->c_cc -= rem;
11bd398c 230 q->c_cf = bp->c_next->c_info;
48575cec
BJ
231 bp->c_next = cfreelist;
232 cfreelist = bp;
233 cfreecount += CBSIZE;
234 if (cwaiting) {
235 wakeup(&cwaiting);
236 cwaiting = 0;
237 }
11bd398c 238 } else {
48575cec
BJ
239 q->c_cc -= cc;
240 q->c_cf += cc;
241 if (q->c_cc <= 0) {
242 bp->c_next = cfreelist;
243 cfreelist = bp;
244 cfreecount += CBSIZE;
245 if (cwaiting) {
246 wakeup(&cwaiting);
247 cwaiting = 0;
248 }
249 }
250 break;
11bd398c 251 }
48575cec
BJ
252 }
253 if (q->c_cc <= 0) {
11bd398c 254 q->c_cf = q->c_cl = NULL;
48575cec 255 q->c_cc = 0;
11bd398c
BJ
256 }
257out:
258 splx(s);
259}
b8f09f36 260
48575cec 261
11bd398c 262putc(c, p)
fd402d46 263 int c;
88a7a62a 264 register struct clist *p;
11bd398c
BJ
265{
266 register struct cblock *bp;
267 register char *cp;
fd402d46 268 register int s;
11bd398c 269
a8170d5d 270 s = spltty();
e39f9ea6 271 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { /* no cblocks yet */
11bd398c
BJ
272 if ((bp = cfreelist) == NULL) {
273 splx(s);
01b0e233 274 return (-1);
11bd398c
BJ
275 }
276 cfreelist = bp->c_next;
48575cec 277 cfreecount -= CBSIZE;
11bd398c 278 bp->c_next = NULL;
e39f9ea6 279 bzero(bp->c_quote, CBQSIZE);
11bd398c
BJ
280 p->c_cf = cp = bp->c_info;
281 } else if (((int)cp & CROUND) == 0) {
e39f9ea6 282 bp = cbptr(cp) - 1; /* pointer arith */
11bd398c
BJ
283 if ((bp->c_next = cfreelist) == NULL) {
284 splx(s);
01b0e233 285 return (-1);
11bd398c
BJ
286 }
287 bp = bp->c_next;
288 cfreelist = bp->c_next;
48575cec 289 cfreecount -= CBSIZE;
11bd398c
BJ
290 bp->c_next = NULL;
291 cp = bp->c_info;
292 }
e39f9ea6
MT
293 if (c&TTY_QUOTE)
294 setquote(cp);
11bd398c
BJ
295 *cp++ = c;
296 p->c_cc++;
297 p->c_cl = cp;
298 splx(s);
01b0e233 299 return (0);
11bd398c
BJ
300}
301
11bd398c
BJ
302/*
303 * copy buffer to clist.
304 * return number of bytes not transfered.
305 */
306b_to_q(cp, cc, q)
88a7a62a
SL
307 register char *cp;
308 struct clist *q;
309 register int cc;
11bd398c
BJ
310{
311 register char *cq;
312 register struct cblock *bp;
fd402d46 313 register int s, nc;
a8170d5d 314 int acc;
11bd398c
BJ
315
316 if (cc <= 0)
01b0e233 317 return (0);
a8170d5d
MK
318 acc = cc;
319 s = spltty();
320 if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
321 if ((bp = cfreelist) == NULL)
322 goto out;
323 cfreelist = bp->c_next;
324 cfreecount -= CBSIZE;
e39f9ea6 325 bzero(bp->c_quote, CBQSIZE);
a8170d5d
MK
326 bp->c_next = NULL;
327 q->c_cf = cq = bp->c_info;
328 }
329
330 while (cc) {
11bd398c 331 if (((int)cq & CROUND) == 0) {
e39f9ea6 332 bp = cbptr(cq) - 1;
a8170d5d
MK
333 if ((bp->c_next = cfreelist) == NULL)
334 goto out;
11bd398c
BJ
335 bp = bp->c_next;
336 cfreelist = bp->c_next;
48575cec 337 cfreecount -= CBSIZE;
e39f9ea6 338 bzero(bp->c_quote, CBQSIZE);
11bd398c 339 bp->c_next = NULL;
a8170d5d 340 cq = bp->c_info;
11bd398c 341 }
65ae7af4 342 nc = min(cc, sizeof (struct cblock) - ((int)cq & CROUND));
a8170d5d
MK
343 (void) bcopy(cp, cq, (unsigned)nc);
344 cp += nc;
345 cq += nc;
346 cc -= nc;
11bd398c 347 }
a8170d5d
MK
348out:
349 q->c_cl = cq;
350 q->c_cc += acc - cc;
351 splx(s);
42cc3b3d 352 return (cc);
11bd398c
BJ
353}
354
b8f09f36
BJ
355/*
356 * Given a non-NULL pointter into the list (like c_cf which
357 * always points to a real character if non-NULL) return the pointer
358 * to the next character in the list or return NULL if no more chars.
359 *
360 * Callers must not allow getc's to happen between nextc's so that the
361 * pointer becomes invalid. Note that interrupts are NOT masked.
362 */
363char *
e39f9ea6 364nextc(p, cp, c)
88a7a62a
SL
365 register struct clist *p;
366 register char *cp;
e39f9ea6 367 register int *c;
b8f09f36
BJ
368{
369
370 if (p->c_cc && ++cp != p->c_cl) {
e39f9ea6
MT
371 if (((int)cp & CROUND) == 0) {
372 cp = (cbptr(cp))[-1].c_next->c_info;
373 }
374 *c = *cp;
375 if (isquote(cp))
376 *c |= TTY_QUOTE;
b8f09f36
BJ
377 return (cp);
378 }
379 return (0);
380}
381
382/*
383 * Remove the last character in the list and return it.
384 */
385unputc(p)
88a7a62a 386 register struct clist *p;
b8f09f36
BJ
387{
388 register struct cblock *bp;
389 register int c, s;
390 struct cblock *obp;
391
a8170d5d 392 s = spltty();
b8f09f36
BJ
393 if (p->c_cc <= 0)
394 c = -1;
395 else {
396 c = *--p->c_cl;
e39f9ea6
MT
397 if (isquote(p->c_cl))
398 c |= TTY_QUOTE;
b8f09f36 399 if (--p->c_cc <= 0) {
e39f9ea6
MT
400 bp = cbptr(p->c_cl);
401 bp = cbptr((int)bp & ~CROUND);
b8f09f36
BJ
402 p->c_cl = p->c_cf = NULL;
403 bp->c_next = cfreelist;
404 cfreelist = bp;
48575cec 405 cfreecount += CBSIZE;
e39f9ea6 406 } else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) {
b8f09f36 407 p->c_cl = (char *)((int)p->c_cl & ~CROUND);
e39f9ea6
MT
408
409 bp = cbptr(p->c_cf);
410 bp = cbptr((int)bp & ~CROUND);
411 while (bp->c_next != cbptr(p->c_cl))
b8f09f36
BJ
412 bp = bp->c_next;
413 obp = bp;
414 p->c_cl = (char *)(bp + 1);
415 bp = bp->c_next;
416 bp->c_next = cfreelist;
417 cfreelist = bp;
48575cec 418 cfreecount += CBSIZE;
b8f09f36
BJ
419 obp->c_next = NULL;
420 }
421 }
422 splx(s);
423 return (c);
424}
425
426/*
427 * Put the chars in the from que
428 * on the end of the to que.
b8f09f36 429 */
7121fdf0 430void
b8f09f36 431catq(from, to)
88a7a62a 432 struct clist *from, *to;
b8f09f36 433{
e39f9ea6 434#ifdef notdef
a8170d5d 435 char bbuf[CBSIZE*4];
e39f9ea6 436#endif
fd402d46 437 register int s, c;
a8170d5d
MK
438
439 s = spltty();
440 if (to->c_cc == 0) {
441 *to = *from;
442 from->c_cc = 0;
443 from->c_cf = NULL;
444 from->c_cl = NULL;
445 splx(s);
446 return;
447 }
448 splx(s);
e39f9ea6 449#ifdef notdef
a8170d5d
MK
450 while (from->c_cc > 0) {
451 c = q_to_b(from, bbuf, sizeof bbuf);
452 (void) b_to_q(bbuf, c, to);
453 }
e39f9ea6
MT
454#endif
455 /* XXX - FIX */
456 while ((c = getc(from)) >= 0)
457 putc(c, to);
b8f09f36
BJ
458}
459
a8170d5d 460#ifdef unneeded
11bd398c 461/*
01b0e233 462 * Integer (short) get/put using clists.
11bd398c 463 */
a8170d5d 464typedef u_short word_t;
961945a8 465
11bd398c 466getw(p)
d0b37068 467 register struct clist *p;
11bd398c 468{
a8170d5d
MK
469 register int s, c;
470 register struct cblock *bp;
471
472 if (p->c_cc <= 1)
473 return(-1);
474 if (p->c_cc & 01) {
475 c = getc(p);
c6d44403 476#if BYTE_ORDER == LITTLE_ENDIAN
01b0e233
MK
477 return (c | (getc(p)<<8));
478#else
479 return (getc(p) | (c<<8));
480#endif
a8170d5d
MK
481 }
482 s = spltty();
e39f9ea6 483#if BYTE_ORDER == LITTLE_ENDIAN
fb1db32c 484 c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1];
01b0e233
MK
485#else
486 c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0];
487#endif
488 p->c_cf += sizeof (word_t);
489 p->c_cc -= sizeof (word_t);
a8170d5d 490 if (p->c_cc <= 0) {
e39f9ea6
MT
491 bp = cbptr(p->c_cf-1);
492 bp = cbptr((int)bp & ~CROUND);
a8170d5d
MK
493 p->c_cf = NULL;
494 p->c_cl = NULL;
495 bp->c_next = cfreelist;
496 cfreelist = bp;
497 cfreecount += CBSIZE;
498 if (cwaiting) {
499 wakeup(&cwaiting);
500 cwaiting = 0;
501 }
502 } else if (((int)p->c_cf & CROUND) == 0) {
e39f9ea6 503 bp = cbptr(p->c_cf);
a8170d5d
MK
504 bp--;
505 p->c_cf = bp->c_next->c_info;
506 bp->c_next = cfreelist;
507 cfreelist = bp;
508 cfreecount += CBSIZE;
509 if (cwaiting) {
510 wakeup(&cwaiting);
511 cwaiting = 0;
512 }
513 }
514 splx(s);
515 return (c);
11bd398c 516}
48575cec 517
11bd398c 518putw(c, p)
d0b37068 519 register struct clist *p;
a8170d5d 520 word_t c;
11bd398c 521{
fd402d46 522 register int s;
a8170d5d
MK
523 register struct cblock *bp;
524 register char *cp;
11bd398c 525
a8170d5d 526 s = spltty();
11bd398c
BJ
527 if (cfreelist==NULL) {
528 splx(s);
529 return(-1);
530 }
a8170d5d 531 if (p->c_cc & 01) {
c6d44403 532#if BYTE_ORDER == LITTLE_ENDIAN
a8170d5d
MK
533 (void) putc(c, p);
534 (void) putc(c>>8, p);
01b0e233
MK
535#else
536 (void) putc(c>>8, p);
537 (void) putc(c, p);
538#endif
a8170d5d
MK
539 } else {
540 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
541 if ((bp = cfreelist) == NULL) {
542 splx(s);
543 return (-1);
544 }
545 cfreelist = bp->c_next;
546 cfreecount -= CBSIZE;
547 bp->c_next = NULL;
548 p->c_cf = cp = bp->c_info;
549 } else if (((int)cp & CROUND) == 0) {
e39f9ea6 550 bp = cbptr(cp) - 1;
a8170d5d
MK
551 if ((bp->c_next = cfreelist) == NULL) {
552 splx(s);
553 return (-1);
554 }
555 bp = bp->c_next;
556 cfreelist = bp->c_next;
557 cfreecount -= CBSIZE;
558 bp->c_next = NULL;
559 cp = bp->c_info;
560 }
01b0e233 561#if defined(vax)
a8170d5d 562 *(word_t *)cp = c;
01b0e233
MK
563#else
564 ((u_char *)cp)[0] = c>>8;
565 ((u_char *)cp)[1] = c;
566#endif
567 p->c_cl = cp + sizeof (word_t);
568 p->c_cc += sizeof (word_t);
a8170d5d 569 }
11bd398c 570 splx(s);
961945a8 571 return (0);
11bd398c 572}
1524bcb8 573#endif /* unneeded */