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