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