alloc tables at boot time version
[unix-history] / usr / src / sys / kern / tty_subr.c
CommitLineData
d4df41fe 1/* tty_subr.c 4.7 %G% */
8f6119af 2
11bd398c 3#include "../h/param.h"
11bd398c
BJ
4#include "../h/systm.h"
5#include "../h/conf.h"
6#include "../h/buf.h"
48575cec 7#include "../h/tty.h"
d4df41fe 8#include "../h/clist.h"
11bd398c 9
48575cec 10char cwaiting;
11bd398c
BJ
11
12/*
13 * Character list get/put
14 */
15getc(p)
16register struct clist *p;
17{
18 register struct cblock *bp;
19 register int c, s;
20
21 s = spl6();
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
48575cec
BJ
57#if HAVTR > 0
58trgetc(p)
59register struct clist *p;
60{
61 register struct cblock *bp;
62 register int c, s;
63
64 if (p->c_cc <= 0) {
65 c = -1;
66 p->c_cc = 0;
67 p->c_cf = NULL;
68 } else {
69 c = *p->c_cf++ & 0377;
70 if (--p->c_cc<=0) {
71 p->c_cf = NULL;
72 } else if (((int)p->c_cf & CROUND) == 0) {
73 bp = (struct cblock *)(p->c_cf);
74 bp--;
75 p->c_cf = bp->c_next->c_info;
76 }
77 }
78 return(c);
79}
80#endif
81
11bd398c
BJ
82/*
83 * copy clist to buffer.
84 * return number of bytes moved.
85 */
86q_to_b(q, cp, cc)
87register struct clist *q;
88register char *cp;
89{
90 register struct cblock *bp;
91 register int s;
92 char *acp;
93
94 if (cc <= 0)
95 return(0);
96 s = spl6();
97 if (q->c_cc <= 0) {
98 q->c_cc = 0;
99 q->c_cf = q->c_cl = NULL;
48575cec 100 splx(s);
11bd398c
BJ
101 return(0);
102 }
103 acp = cp;
104 cc++;
105
106 while (--cc) {
107 *cp++ = *q->c_cf++;
108 if (--q->c_cc <= 0) {
109 bp = (struct cblock *)(q->c_cf-1);
110 bp = (struct cblock *)((int)bp & ~CROUND);
111 q->c_cf = q->c_cl = NULL;
112 bp->c_next = cfreelist;
113 cfreelist = bp;
48575cec
BJ
114 cfreecount += CBSIZE;
115 if (cwaiting) {
116 wakeup(&cwaiting);
117 cwaiting = 0;
118 }
11bd398c
BJ
119 break;
120 }
121 if (((int)q->c_cf & CROUND) == 0) {
122 bp = (struct cblock *)(q->c_cf);
123 bp--;
124 q->c_cf = bp->c_next->c_info;
125 bp->c_next = cfreelist;
126 cfreelist = bp;
48575cec
BJ
127 cfreecount += CBSIZE;
128 if (cwaiting) {
129 wakeup(&cwaiting);
130 cwaiting = 0;
131 }
11bd398c
BJ
132 }
133 }
134 splx(s);
135 return(cp-acp);
136}
137
48575cec
BJ
138#if HAVTR > 0
139/*
140 * Traverse a clist copying its contents to a buffer.
141 * q->cc and q->cf are updated with the current position
142 * in the list, but bytes are not released to the freelist.
143 */
144trq_to_b(q, cp, cc)
145register struct clist *q;
146register char *cp;
147register cc;
148{
149 register struct cblock *bp;
150 char *acp;
151
152 if (cc <= 0)
153 return(0);
154 if (q->c_cc <= 0)
155 return(0);
156
157 acp = cp;
158 cc++;
159 while (--cc) {
160 *cp++ = *q->c_cf++;
161 if (((int)q->c_cf & CROUND) == 0) {
162 bp = (struct cblock *)(q->c_cf);
163 bp--;
164 q->c_cf = bp->c_next->c_info;
165 }
166 if (--q->c_cc <= 0)
167 break;
168 }
169 return(cp-acp);
170}
171#endif
172
173
11bd398c
BJ
174/*
175 * Return count of contiguous characters
176 * in clist starting at q->c_cf.
177 * Stop counting if flag&character is non-null.
178 */
179ndqb(q, flag)
180register struct clist *q;
181{
182register cc;
183int s;
184
185 s = spl6();
186 if (q->c_cc <= 0) {
187 cc = -q->c_cc;
188 goto out;
189 }
190 cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
191 cc -= (int)q->c_cf;
192 if (q->c_cc < cc)
193 cc = q->c_cc;
194 if (flag) {
195 register char *p, *end;
196
197 p = q->c_cf;
198 end = p;
199 end += cc;
200 while (p < end) {
201 if (*p & flag) {
48575cec
BJ
202 cc = (int)p;
203 cc -= (int)q->c_cf;
11bd398c
BJ
204 break;
205 }
206 p++;
207 }
208 }
209out:
210 splx(s);
211 return(cc);
212}
213
48575cec
BJ
214
215
11bd398c 216/*
48575cec 217 * Flush cc bytes from q.
11bd398c
BJ
218 */
219ndflush(q, cc)
220register struct clist *q;
221register cc;
222{
48575cec
BJ
223register struct cblock *bp;
224char *end;
225int rem;
11bd398c
BJ
226register s;
227
11bd398c
BJ
228 s = spl6();
229 if (q->c_cc < 0) {
48575cec 230 printf("neg q flush\n");
11bd398c
BJ
231 goto out;
232 }
233 if (q->c_cc == 0) {
234 goto out;
235 }
48575cec
BJ
236 while (cc>0 && q->c_cc) {
237 bp = (struct cblock *)((int)q->c_cf & ~CROUND);
238 if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
239 end = q->c_cl;
240 } else {
241 end = (char *)((int)bp + sizeof (struct cblock));
242 }
243 rem = end - q->c_cf;
244 if (cc >= rem) {
245 cc -= rem;
246 q->c_cc -= rem;
11bd398c 247 q->c_cf = bp->c_next->c_info;
48575cec
BJ
248 bp->c_next = cfreelist;
249 cfreelist = bp;
250 cfreecount += CBSIZE;
251 if (cwaiting) {
252 wakeup(&cwaiting);
253 cwaiting = 0;
254 }
11bd398c 255 } else {
48575cec
BJ
256 q->c_cc -= cc;
257 q->c_cf += cc;
258 if (q->c_cc <= 0) {
259 bp->c_next = cfreelist;
260 cfreelist = bp;
261 cfreecount += CBSIZE;
262 if (cwaiting) {
263 wakeup(&cwaiting);
264 cwaiting = 0;
265 }
266 }
267 break;
11bd398c 268 }
48575cec
BJ
269 }
270 if (q->c_cc <= 0) {
11bd398c 271 q->c_cf = q->c_cl = NULL;
48575cec 272 q->c_cc = 0;
11bd398c
BJ
273 }
274out:
275 splx(s);
276}
b8f09f36 277
48575cec 278
11bd398c
BJ
279putc(c, p)
280register struct clist *p;
281{
282 register struct cblock *bp;
283 register char *cp;
284 register s;
285
286 s = spl6();
287 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
288 if ((bp = cfreelist) == NULL) {
289 splx(s);
290 return(-1);
291 }
292 cfreelist = bp->c_next;
48575cec 293 cfreecount -= CBSIZE;
11bd398c
BJ
294 bp->c_next = NULL;
295 p->c_cf = cp = bp->c_info;
296 } else if (((int)cp & CROUND) == 0) {
297 bp = (struct cblock *)cp - 1;
298 if ((bp->c_next = cfreelist) == NULL) {
299 splx(s);
300 return(-1);
301 }
302 bp = bp->c_next;
303 cfreelist = bp->c_next;
48575cec 304 cfreecount -= CBSIZE;
11bd398c
BJ
305 bp->c_next = NULL;
306 cp = bp->c_info;
307 }
308 *cp++ = c;
309 p->c_cc++;
310 p->c_cl = cp;
311 splx(s);
312 return(0);
313}
314
48575cec
BJ
315
316
11bd398c
BJ
317/*
318 * copy buffer to clist.
319 * return number of bytes not transfered.
320 */
321b_to_q(cp, cc, q)
322register char *cp;
323struct clist *q;
324register int cc;
325{
326 register char *cq;
327 register struct cblock *bp;
328 register s, acc;
329
330 if (cc <= 0)
331 return(0);
332 acc = cc;
48575cec
BJ
333
334
11bd398c
BJ
335 s = spl6();
336 if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
337 if ((bp = cfreelist) == NULL)
338 goto out;
339 cfreelist = bp->c_next;
48575cec 340 cfreecount -= CBSIZE;
11bd398c
BJ
341 bp->c_next = NULL;
342 q->c_cf = cq = bp->c_info;
343 }
344
345 while (cc) {
346 if (((int)cq & CROUND) == 0) {
347 bp = (struct cblock *) cq - 1;
348 if ((bp->c_next = cfreelist) == NULL)
349 goto out;
350 bp = bp->c_next;
351 cfreelist = bp->c_next;
48575cec 352 cfreecount -= CBSIZE;
11bd398c
BJ
353 bp->c_next = NULL;
354 cq = bp->c_info;
355 }
356 *cq++ = *cp++;
357 cc--;
358 }
359out:
360 q->c_cl = cq;
361 q->c_cc += acc-cc;
362 splx(s);
363 return(cc);
364}
365
48575cec
BJ
366char *
367wb_to_q(cp, cc, q)
368register char *cp;
369register struct clist *q;
370register cc;
371{
372char *f;
373register s;
374
375 s = spl6();
376 while (cc > cfreecount) {
377 cwaiting = 1;
378 sleep(&cwaiting, TTOPRI);
379 }
380 if (q->c_cc==0) {
381 b_to_q(cp, cc, q);
382 f = q->c_cf;
383 } else {
384 (void) putc(*cp++, q);
385 f = q->c_cl;
386 f--;
387 b_to_q(cp, --cc, q);
388 }
389 splx(s);
390 return(f);
391}
392
75a44ba5 393#ifdef UCBIPC
48575cec
BJ
394char *
395nb_to_q(cp, cc, q)
396register char *cp;
397register struct clist *q;
398register cc;
399{
400char *f;
401register s;
402
403 s = spl6();
404 if (cc > cfreecount) {
405 f = NULL;
406 goto out;
407 }
408 if (q->c_cc==0) {
409 b_to_q(cp, cc, q);
410 f = q->c_cf;
411 } else {
412 (void) putc(*cp++, q);
413 f = q->c_cl;
414 f--;
415 b_to_q(cp, --cc, q);
416 }
417out:
418 splx(s);
419 return(f);
420}
421#endif
422
b8f09f36
BJ
423/*
424 * Given a non-NULL pointter into the list (like c_cf which
425 * always points to a real character if non-NULL) return the pointer
426 * to the next character in the list or return NULL if no more chars.
427 *
428 * Callers must not allow getc's to happen between nextc's so that the
429 * pointer becomes invalid. Note that interrupts are NOT masked.
430 */
431char *
432nextc(p, cp)
433register struct clist *p;
434register char *cp;
435{
436
437 if (p->c_cc && ++cp != p->c_cl) {
438 if (((int)cp & CROUND) == 0)
439 return (((struct cblock *)cp)[-1].c_next->c_info);
440 return (cp);
441 }
442 return (0);
443}
444
445/*
446 * Remove the last character in the list and return it.
447 */
448unputc(p)
449register struct clist *p;
450{
451 register struct cblock *bp;
452 register int c, s;
453 struct cblock *obp;
454
455 s = spl6();
456 if (p->c_cc <= 0)
457 c = -1;
458 else {
459 c = *--p->c_cl;
460 if (--p->c_cc <= 0) {
461 bp = (struct cblock *)p->c_cl;
462 bp = (struct cblock *)((int)bp & ~CROUND);
463 p->c_cl = p->c_cf = NULL;
464 bp->c_next = cfreelist;
465 cfreelist = bp;
48575cec 466 cfreecount += CBSIZE;
b8f09f36
BJ
467 } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
468 p->c_cl = (char *)((int)p->c_cl & ~CROUND);
469 bp = (struct cblock *)p->c_cf;
470 bp = (struct cblock *)((int)bp & ~CROUND);
471 while (bp->c_next != (struct cblock *)p->c_cl)
472 bp = bp->c_next;
473 obp = bp;
474 p->c_cl = (char *)(bp + 1);
475 bp = bp->c_next;
476 bp->c_next = cfreelist;
477 cfreelist = bp;
48575cec 478 cfreecount += CBSIZE;
b8f09f36
BJ
479 obp->c_next = NULL;
480 }
481 }
482 splx(s);
483 return (c);
484}
485
486/*
487 * Put the chars in the from que
488 * on the end of the to que.
489 *
490 * SHOULD JUST USE q_to_b AND THEN b_to_q HERE.
491 */
492catq(from, to)
493struct clist *from, *to;
494{
495 register c;
496
497 while ((c = getc(from)) >= 0)
498 (void) putc(c, to);
499}
500
11bd398c
BJ
501/*
502 * integer (2-byte) get/put
503 * using clists
504 */
11bd398c
BJ
505getw(p)
506register struct clist *p;
507{
508 register int s;
509
510 if (p->c_cc <= 1)
511 return(-1);
512 s = getc(p);
513 return(s | (getc(p)<<8));
514}
48575cec
BJ
515
516#if HAVTR > 0
517trgetw(p)
518register struct clist *p;
519{
520 register int w;
521
522 if (p->c_cc <=1)
523 return(-1);
524 w = trgetc(p);
525 return(w | (trgetc(p)<<8));
526}
527#endif
11bd398c
BJ
528
529putw(c, p)
530register struct clist *p;
531{
532 register s;
533
534 s = spl6();
535 if (cfreelist==NULL) {
536 splx(s);
537 return(-1);
538 }
81263dba
BJ
539 (void) putc(c, p);
540 (void) putc(c>>8, p);
11bd398c
BJ
541 splx(s);
542 return(0);
543}