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