xref: /csrg-svn/sys/kern/tty_subr.c (revision 17542)
1*17542Skarels /*	tty_subr.c	6.7	84/12/20	*/
21892Swnj 
317097Sbloom #include "param.h"
417097Sbloom #include "systm.h"
517097Sbloom #include "conf.h"
617097Sbloom #include "buf.h"
717097Sbloom #include "tty.h"
817097Sbloom #include "clist.h"
932Sbill 
101890Swnj char	cwaiting;
111890Swnj 
1232Sbill /*
1332Sbill  * Character list get/put
1432Sbill  */
1532Sbill getc(p)
1612754Ssam 	register struct clist *p;
1732Sbill {
1832Sbill 	register struct cblock *bp;
1932Sbill 	register int c, s;
2032Sbill 
21*17542Skarels 	s = spltty();
2232Sbill 	if (p->c_cc <= 0) {
2332Sbill 		c = -1;
2432Sbill 		p->c_cc = 0;
2532Sbill 		p->c_cf = p->c_cl = NULL;
2632Sbill 	} else {
2732Sbill 		c = *p->c_cf++ & 0377;
2832Sbill 		if (--p->c_cc<=0) {
2932Sbill 			bp = (struct cblock *)(p->c_cf-1);
3032Sbill 			bp = (struct cblock *) ((int)bp & ~CROUND);
3132Sbill 			p->c_cf = NULL;
3232Sbill 			p->c_cl = NULL;
3332Sbill 			bp->c_next = cfreelist;
3432Sbill 			cfreelist = bp;
351890Swnj 			cfreecount += CBSIZE;
361890Swnj 			if (cwaiting) {
371890Swnj 				wakeup(&cwaiting);
381890Swnj 				cwaiting = 0;
391890Swnj 			}
4032Sbill 		} else if (((int)p->c_cf & CROUND) == 0){
4132Sbill 			bp = (struct cblock *)(p->c_cf);
4232Sbill 			bp--;
4332Sbill 			p->c_cf = bp->c_next->c_info;
4432Sbill 			bp->c_next = cfreelist;
4532Sbill 			cfreelist = bp;
461890Swnj 			cfreecount += CBSIZE;
471890Swnj 			if (cwaiting) {
481890Swnj 				wakeup(&cwaiting);
491890Swnj 				cwaiting = 0;
501890Swnj 			}
5132Sbill 		}
5232Sbill 	}
5332Sbill 	splx(s);
5432Sbill 	return(c);
5532Sbill }
5632Sbill 
5732Sbill /*
5832Sbill  * copy clist to buffer.
5932Sbill  * return number of bytes moved.
6032Sbill  */
6132Sbill q_to_b(q, cp, cc)
629761Ssam 	register struct clist *q;
639761Ssam 	register char *cp;
6432Sbill {
6532Sbill 	register struct cblock *bp;
6632Sbill 	register int s;
67*17542Skarels 	register nc;
6832Sbill 	char *acp;
6932Sbill 
7032Sbill 	if (cc <= 0)
7132Sbill 		return(0);
72*17542Skarels 	s = spltty();
7332Sbill 	if (q->c_cc <= 0) {
7432Sbill 		q->c_cc = 0;
7532Sbill 		q->c_cf = q->c_cl = NULL;
761890Swnj 		splx(s);
7732Sbill 		return(0);
7832Sbill 	}
7932Sbill 	acp = cp;
8032Sbill 
81*17542Skarels 	while (cc) {
82*17542Skarels 		nc = sizeof(struct cblock) - ((int)q->c_cf & CROUND);
83*17542Skarels 		nc = MIN(nc, cc);
84*17542Skarels 		nc = MIN(nc, q->c_cc);
85*17542Skarels 		(void) bcopy(q->c_cf, cp, (unsigned)nc);
86*17542Skarels 		q->c_cf += nc;
87*17542Skarels 		q->c_cc -= nc;
88*17542Skarels 		cc -= nc;
89*17542Skarels 		cp += nc;
90*17542Skarels 		if (q->c_cc <= 0) {
91*17542Skarels 			bp = (struct cblock *)(q->c_cf - 1);
9232Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
9332Sbill 			q->c_cf = q->c_cl = NULL;
9432Sbill 			bp->c_next = cfreelist;
9532Sbill 			cfreelist = bp;
961890Swnj 			cfreecount += CBSIZE;
971890Swnj 			if (cwaiting) {
981890Swnj 				wakeup(&cwaiting);
991890Swnj 				cwaiting = 0;
1001890Swnj 			}
10132Sbill 			break;
10232Sbill 		}
10332Sbill 		if (((int)q->c_cf & CROUND) == 0) {
10432Sbill 			bp = (struct cblock *)(q->c_cf);
10532Sbill 			bp--;
10632Sbill 			q->c_cf = bp->c_next->c_info;
10732Sbill 			bp->c_next = cfreelist;
10832Sbill 			cfreelist = bp;
1091890Swnj 			cfreecount += CBSIZE;
1101890Swnj 			if (cwaiting) {
1111890Swnj 				wakeup(&cwaiting);
1121890Swnj 				cwaiting = 0;
1131890Swnj 			}
11432Sbill 		}
11532Sbill 	}
11632Sbill 	splx(s);
11732Sbill 	return(cp-acp);
11832Sbill }
11932Sbill 
12032Sbill /*
12132Sbill  * Return count of contiguous characters
12232Sbill  * in clist starting at q->c_cf.
12332Sbill  * Stop counting if flag&character is non-null.
12432Sbill  */
12532Sbill ndqb(q, flag)
1269761Ssam 	register struct clist *q;
12732Sbill {
1289761Ssam 	register cc;
1299761Ssam 	int s;
13032Sbill 
131*17542Skarels 	s = spltty();
13232Sbill 	if (q->c_cc <= 0) {
13332Sbill 		cc = -q->c_cc;
13432Sbill 		goto out;
13532Sbill 	}
13632Sbill 	cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
13732Sbill 	cc -= (int)q->c_cf;
13832Sbill 	if (q->c_cc < cc)
13932Sbill 		cc = q->c_cc;
14032Sbill 	if (flag) {
14132Sbill 		register char *p, *end;
14232Sbill 
14332Sbill 		p = q->c_cf;
14432Sbill 		end = p;
14532Sbill 		end += cc;
14632Sbill 		while (p < end) {
14732Sbill 			if (*p & flag) {
1481890Swnj 				cc = (int)p;
1491890Swnj 				cc -= (int)q->c_cf;
15032Sbill 				break;
15132Sbill 			}
15232Sbill 			p++;
15332Sbill 		}
15432Sbill 	}
15532Sbill out:
15632Sbill 	splx(s);
15732Sbill 	return(cc);
15832Sbill }
15932Sbill 
1601890Swnj 
1611890Swnj 
16232Sbill /*
1631890Swnj  * Flush cc bytes from q.
16432Sbill  */
16532Sbill ndflush(q, cc)
16612754Ssam 	register struct clist *q;
16712754Ssam 	register cc;
16832Sbill {
16912754Ssam 	register struct cblock *bp;
17012754Ssam 	char *end;
17112754Ssam 	int rem, s;
17232Sbill 
173*17542Skarels 	s = spltty();
17410749Seric 	if (q->c_cc <= 0) {
17532Sbill 		goto out;
17632Sbill 	}
1771890Swnj 	while (cc>0 && q->c_cc) {
1781890Swnj 		bp = (struct cblock *)((int)q->c_cf & ~CROUND);
1791890Swnj 		if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
1801890Swnj 			end = q->c_cl;
1811890Swnj 		} else {
1821890Swnj 			end = (char *)((int)bp + sizeof (struct cblock));
1831890Swnj 		}
1841890Swnj 		rem = end - q->c_cf;
1851890Swnj 		if (cc >= rem) {
1861890Swnj 			cc -= rem;
1871890Swnj 			q->c_cc -= rem;
18832Sbill 			q->c_cf = bp->c_next->c_info;
1891890Swnj 			bp->c_next = cfreelist;
1901890Swnj 			cfreelist = bp;
1911890Swnj 			cfreecount += CBSIZE;
1921890Swnj 			if (cwaiting) {
1931890Swnj 				wakeup(&cwaiting);
1941890Swnj 				cwaiting = 0;
1951890Swnj 			}
19632Sbill 		} else {
1971890Swnj 			q->c_cc -= cc;
1981890Swnj 			q->c_cf += cc;
1991890Swnj 			if (q->c_cc <= 0) {
2001890Swnj 				bp->c_next = cfreelist;
2011890Swnj 				cfreelist = bp;
2021890Swnj 				cfreecount += CBSIZE;
2031890Swnj 				if (cwaiting) {
2041890Swnj 					wakeup(&cwaiting);
2051890Swnj 					cwaiting = 0;
2061890Swnj 				}
2071890Swnj 			}
2081890Swnj 			break;
20932Sbill 		}
2101890Swnj 	}
2111890Swnj 	if (q->c_cc <= 0) {
21232Sbill 		q->c_cf = q->c_cl = NULL;
2131890Swnj 		q->c_cc = 0;
21432Sbill 	}
21532Sbill out:
21632Sbill 	splx(s);
21732Sbill }
218172Sbill 
2191890Swnj 
22032Sbill putc(c, p)
22112754Ssam 	register struct clist *p;
22232Sbill {
22332Sbill 	register struct cblock *bp;
22432Sbill 	register char *cp;
22532Sbill 	register s;
22632Sbill 
227*17542Skarels 	s = spltty();
22832Sbill 	if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
22932Sbill 		if ((bp = cfreelist) == NULL) {
23032Sbill 			splx(s);
23132Sbill 			return(-1);
23232Sbill 		}
23332Sbill 		cfreelist = bp->c_next;
2341890Swnj 		cfreecount -= CBSIZE;
23532Sbill 		bp->c_next = NULL;
23632Sbill 		p->c_cf = cp = bp->c_info;
23732Sbill 	} else if (((int)cp & CROUND) == 0) {
23832Sbill 		bp = (struct cblock *)cp - 1;
23932Sbill 		if ((bp->c_next = cfreelist) == NULL) {
24032Sbill 			splx(s);
24132Sbill 			return(-1);
24232Sbill 		}
24332Sbill 		bp = bp->c_next;
24432Sbill 		cfreelist = bp->c_next;
2451890Swnj 		cfreecount -= CBSIZE;
24632Sbill 		bp->c_next = NULL;
24732Sbill 		cp = bp->c_info;
24832Sbill 	}
24932Sbill 	*cp++ = c;
25032Sbill 	p->c_cc++;
25132Sbill 	p->c_cl = cp;
25232Sbill 	splx(s);
25332Sbill 	return(0);
25432Sbill }
25532Sbill 
2561890Swnj 
2571890Swnj 
25832Sbill /*
25932Sbill  * copy buffer to clist.
26032Sbill  * return number of bytes not transfered.
26132Sbill  */
26232Sbill b_to_q(cp, cc, q)
26312754Ssam 	register char *cp;
26412754Ssam 	struct clist *q;
26512754Ssam 	register int cc;
26632Sbill {
26732Sbill 	register char *cq;
26832Sbill 	register struct cblock *bp;
269*17542Skarels 	register s, nc;
270*17542Skarels 	int acc;
27132Sbill 
27232Sbill 	if (cc <= 0)
273*17542Skarels 		return(0);
274*17542Skarels 	acc = cc;
275*17542Skarels 	s = spltty();
276*17542Skarels 	if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
277*17542Skarels 		if ((bp = cfreelist) == NULL)
278*17542Skarels 			goto out;
279*17542Skarels 		cfreelist = bp->c_next;
280*17542Skarels 		cfreecount -= CBSIZE;
281*17542Skarels 		bp->c_next = NULL;
282*17542Skarels 		q->c_cf = cq = bp->c_info;
283*17542Skarels 	}
284*17542Skarels 
285*17542Skarels 	while (cc) {
28632Sbill 		if (((int)cq & CROUND) == 0) {
287*17542Skarels 			bp = (struct cblock *) cq - 1;
288*17542Skarels 			if ((bp->c_next = cfreelist) == NULL)
289*17542Skarels 				goto out;
29032Sbill 			bp = bp->c_next;
29132Sbill 			cfreelist = bp->c_next;
2921890Swnj 			cfreecount -= CBSIZE;
29332Sbill 			bp->c_next = NULL;
294*17542Skarels 			cq = bp->c_info;
29532Sbill 		}
296*17542Skarels 		nc = MIN(cc, sizeof(struct cblock) - ((int)cq & CROUND));
297*17542Skarels 		(void) bcopy(cp, cq, (unsigned)nc);
298*17542Skarels 		cp += nc;
299*17542Skarels 		cq += nc;
300*17542Skarels 		cc -= nc;
30132Sbill 	}
302*17542Skarels out:
303*17542Skarels 	q->c_cl = cq;
304*17542Skarels 	q->c_cc += acc - cc;
305*17542Skarels 	splx(s);
30617368Ssam 	return (cc);
30732Sbill }
30832Sbill 
30932Sbill /*
310172Sbill  * Given a non-NULL pointter into the list (like c_cf which
311172Sbill  * always points to a real character if non-NULL) return the pointer
312172Sbill  * to the next character in the list or return NULL if no more chars.
313172Sbill  *
314172Sbill  * Callers must not allow getc's to happen between nextc's so that the
315172Sbill  * pointer becomes invalid.  Note that interrupts are NOT masked.
316172Sbill  */
317172Sbill char *
318172Sbill nextc(p, cp)
31912754Ssam 	register struct clist *p;
32012754Ssam 	register char *cp;
321172Sbill {
322172Sbill 
323172Sbill 	if (p->c_cc && ++cp != p->c_cl) {
324172Sbill 		if (((int)cp & CROUND) == 0)
325172Sbill 			return (((struct cblock *)cp)[-1].c_next->c_info);
326172Sbill 		return (cp);
327172Sbill 	}
328172Sbill 	return (0);
329172Sbill }
330172Sbill 
331172Sbill /*
332172Sbill  * Remove the last character in the list and return it.
333172Sbill  */
334172Sbill unputc(p)
33512754Ssam 	register struct clist *p;
336172Sbill {
337172Sbill 	register struct cblock *bp;
338172Sbill 	register int c, s;
339172Sbill 	struct cblock *obp;
340172Sbill 
341*17542Skarels 	s = spltty();
342172Sbill 	if (p->c_cc <= 0)
343172Sbill 		c = -1;
344172Sbill 	else {
345172Sbill 		c = *--p->c_cl;
346172Sbill 		if (--p->c_cc <= 0) {
347172Sbill 			bp = (struct cblock *)p->c_cl;
348172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
349172Sbill 			p->c_cl = p->c_cf = NULL;
350172Sbill 			bp->c_next = cfreelist;
351172Sbill 			cfreelist = bp;
3521890Swnj 			cfreecount += CBSIZE;
353172Sbill 		} else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
354172Sbill 			p->c_cl = (char *)((int)p->c_cl & ~CROUND);
355172Sbill 			bp = (struct cblock *)p->c_cf;
356172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
357172Sbill 			while (bp->c_next != (struct cblock *)p->c_cl)
358172Sbill 				bp = bp->c_next;
359172Sbill 			obp = bp;
360172Sbill 			p->c_cl = (char *)(bp + 1);
361172Sbill 			bp = bp->c_next;
362172Sbill 			bp->c_next = cfreelist;
363172Sbill 			cfreelist = bp;
3641890Swnj 			cfreecount += CBSIZE;
365172Sbill 			obp->c_next = NULL;
366172Sbill 		}
367172Sbill 	}
368172Sbill 	splx(s);
369172Sbill 	return (c);
370172Sbill }
371172Sbill 
372172Sbill /*
373172Sbill  * Put the chars in the from que
374172Sbill  * on the end of the to que.
375172Sbill  */
376172Sbill catq(from, to)
37712754Ssam 	struct clist *from, *to;
378172Sbill {
379*17542Skarels 	char bbuf[CBSIZE*4];
380*17542Skarels 	register s, c;
381172Sbill 
382*17542Skarels 	s = spltty();
383*17542Skarels 	if (to->c_cc == 0) {
384*17542Skarels 		*to = *from;
385*17542Skarels 		from->c_cc = 0;
386*17542Skarels 		from->c_cf = NULL;
387*17542Skarels 		from->c_cl = NULL;
388*17542Skarels 		splx(s);
389*17542Skarels 		return;
390*17542Skarels 	}
391*17542Skarels 	splx(s);
392*17542Skarels 	while (from->c_cc > 0) {
393*17542Skarels 		c = q_to_b(from, bbuf, sizeof bbuf);
394*17542Skarels 		(void) b_to_q(bbuf, c, to);
395*17542Skarels 	}
396172Sbill }
397172Sbill 
398*17542Skarels #ifdef unneeded
399172Sbill /*
4009761Ssam  * Integer (short) get/put
40132Sbill  * using clists
40232Sbill  */
403*17542Skarels typedef	u_short word_t;
4049761Ssam 
40532Sbill getw(p)
4068955Sroot 	register struct clist *p;
40732Sbill {
408*17542Skarels 	register int s, c;
409*17542Skarels 	register struct cblock *bp;
41032Sbill 
411*17542Skarels 	if (p->c_cc <= 1)
412*17542Skarels 		return(-1);
413*17542Skarels 	if (p->c_cc & 01) {
414*17542Skarels 		c = getc(p);
415*17542Skarels 		return(c | (getc(p)<<8));
416*17542Skarels 	}
417*17542Skarels 	s = spltty();
418*17542Skarels 	c = *((word_t *)p->c_cf);
419*17542Skarels 	p->c_cf += sizeof(word_t);
420*17542Skarels 	p->c_cc -= sizeof(word_t);
421*17542Skarels 	if (p->c_cc <= 0) {
422*17542Skarels 		bp = (struct cblock *)(p->c_cf-1);
423*17542Skarels 		bp = (struct cblock *) ((int)bp & ~CROUND);
424*17542Skarels 		p->c_cf = NULL;
425*17542Skarels 		p->c_cl = NULL;
426*17542Skarels 		bp->c_next = cfreelist;
427*17542Skarels 		cfreelist = bp;
428*17542Skarels 		cfreecount += CBSIZE;
429*17542Skarels 		if (cwaiting) {
430*17542Skarels 			wakeup(&cwaiting);
431*17542Skarels 			cwaiting = 0;
432*17542Skarels 		}
433*17542Skarels 	} else if (((int)p->c_cf & CROUND) == 0) {
434*17542Skarels 		bp = (struct cblock *)(p->c_cf);
435*17542Skarels 		bp--;
436*17542Skarels 		p->c_cf = bp->c_next->c_info;
437*17542Skarels 		bp->c_next = cfreelist;
438*17542Skarels 		cfreelist = bp;
439*17542Skarels 		cfreecount += CBSIZE;
440*17542Skarels 		if (cwaiting) {
441*17542Skarels 			wakeup(&cwaiting);
442*17542Skarels 			cwaiting = 0;
443*17542Skarels 		}
444*17542Skarels 	}
445*17542Skarels 	splx(s);
446*17542Skarels 	return (c);
44732Sbill }
44832Sbill 
44932Sbill putw(c, p)
4508955Sroot 	register struct clist *p;
451*17542Skarels 	word_t c;
45232Sbill {
45332Sbill 	register s;
454*17542Skarels 	register struct cblock *bp;
455*17542Skarels 	register char *cp;
45632Sbill 
457*17542Skarels 	s = spltty();
45832Sbill 	if (cfreelist==NULL) {
45932Sbill 		splx(s);
46032Sbill 		return(-1);
46132Sbill 	}
462*17542Skarels 	if (p->c_cc & 01) {
463*17542Skarels 		(void) putc(c, p);
464*17542Skarels 		(void) putc(c>>8, p);
465*17542Skarels 	} else {
466*17542Skarels 		if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
467*17542Skarels 			if ((bp = cfreelist) == NULL) {
468*17542Skarels 				splx(s);
469*17542Skarels 				return (-1);
470*17542Skarels 			}
471*17542Skarels 			cfreelist = bp->c_next;
472*17542Skarels 			cfreecount -= CBSIZE;
473*17542Skarels 			bp->c_next = NULL;
474*17542Skarels 			p->c_cf = cp = bp->c_info;
475*17542Skarels 		} else if (((int)cp & CROUND) == 0) {
476*17542Skarels 			bp = (struct cblock *)cp - 1;
477*17542Skarels 			if ((bp->c_next = cfreelist) == NULL) {
478*17542Skarels 				splx(s);
479*17542Skarels 				return (-1);
480*17542Skarels 			}
481*17542Skarels 			bp = bp->c_next;
482*17542Skarels 			cfreelist = bp->c_next;
483*17542Skarels 			cfreecount -= CBSIZE;
484*17542Skarels 			bp->c_next = NULL;
485*17542Skarels 			cp = bp->c_info;
486*17542Skarels 		}
487*17542Skarels 		*(word_t *)cp = c;
488*17542Skarels 		p->c_cl = cp + sizeof(word_t);
489*17542Skarels 		p->c_cc += sizeof(word_t);
490*17542Skarels 	}
49132Sbill 	splx(s);
4929761Ssam 	return (0);
49332Sbill }
494*17542Skarels #endif unneeded
495