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