xref: /csrg-svn/sys/kern/tty_subr.c (revision 17368)
1*17368Ssam /*	tty_subr.c	6.6	84/11/15	*/
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 
213545Swnj 	s = spl5();
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;
6732Sbill 	char *acp;
6832Sbill 
6932Sbill 	if (cc <= 0)
7032Sbill 		return(0);
713545Swnj 	s = spl5();
7232Sbill 	if (q->c_cc <= 0) {
7332Sbill 		q->c_cc = 0;
7432Sbill 		q->c_cf = q->c_cl = NULL;
751890Swnj 		splx(s);
7632Sbill 		return(0);
7732Sbill 	}
7832Sbill 	acp = cp;
7932Sbill 	cc++;
8032Sbill 
8132Sbill 	while (--cc) {
8232Sbill 		*cp++ = *q->c_cf++;
8332Sbill 		if (--q->c_cc <= 0) {
8432Sbill 			bp = (struct cblock *)(q->c_cf-1);
8532Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
8632Sbill 			q->c_cf = q->c_cl = NULL;
8732Sbill 			bp->c_next = cfreelist;
8832Sbill 			cfreelist = bp;
891890Swnj 			cfreecount += CBSIZE;
901890Swnj 			if (cwaiting) {
911890Swnj 				wakeup(&cwaiting);
921890Swnj 				cwaiting = 0;
931890Swnj 			}
9432Sbill 			break;
9532Sbill 		}
9632Sbill 		if (((int)q->c_cf & CROUND) == 0) {
9732Sbill 			bp = (struct cblock *)(q->c_cf);
9832Sbill 			bp--;
9932Sbill 			q->c_cf = bp->c_next->c_info;
10032Sbill 			bp->c_next = cfreelist;
10132Sbill 			cfreelist = bp;
1021890Swnj 			cfreecount += CBSIZE;
1031890Swnj 			if (cwaiting) {
1041890Swnj 				wakeup(&cwaiting);
1051890Swnj 				cwaiting = 0;
1061890Swnj 			}
10732Sbill 		}
10832Sbill 	}
10932Sbill 	splx(s);
11032Sbill 	return(cp-acp);
11132Sbill }
11232Sbill 
11332Sbill /*
11432Sbill  * Return count of contiguous characters
11532Sbill  * in clist starting at q->c_cf.
11632Sbill  * Stop counting if flag&character is non-null.
11732Sbill  */
11832Sbill ndqb(q, flag)
1199761Ssam 	register struct clist *q;
12032Sbill {
1219761Ssam 	register cc;
1229761Ssam 	int s;
12332Sbill 
1243545Swnj 	s = spl5();
12532Sbill 	if (q->c_cc <= 0) {
12632Sbill 		cc = -q->c_cc;
12732Sbill 		goto out;
12832Sbill 	}
12932Sbill 	cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
13032Sbill 	cc -= (int)q->c_cf;
13132Sbill 	if (q->c_cc < cc)
13232Sbill 		cc = q->c_cc;
13332Sbill 	if (flag) {
13432Sbill 		register char *p, *end;
13532Sbill 
13632Sbill 		p = q->c_cf;
13732Sbill 		end = p;
13832Sbill 		end += cc;
13932Sbill 		while (p < end) {
14032Sbill 			if (*p & flag) {
1411890Swnj 				cc = (int)p;
1421890Swnj 				cc -= (int)q->c_cf;
14332Sbill 				break;
14432Sbill 			}
14532Sbill 			p++;
14632Sbill 		}
14732Sbill 	}
14832Sbill out:
14932Sbill 	splx(s);
15032Sbill 	return(cc);
15132Sbill }
15232Sbill 
1531890Swnj 
1541890Swnj 
15532Sbill /*
1561890Swnj  * Flush cc bytes from q.
15732Sbill  */
15832Sbill ndflush(q, cc)
15912754Ssam 	register struct clist *q;
16012754Ssam 	register cc;
16132Sbill {
16212754Ssam 	register struct cblock *bp;
16312754Ssam 	char *end;
16412754Ssam 	int rem, s;
16532Sbill 
1663545Swnj 	s = spl5();
16710749Seric 	if (q->c_cc <= 0) {
16832Sbill 		goto out;
16932Sbill 	}
1701890Swnj 	while (cc>0 && q->c_cc) {
1711890Swnj 		bp = (struct cblock *)((int)q->c_cf & ~CROUND);
1721890Swnj 		if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
1731890Swnj 			end = q->c_cl;
1741890Swnj 		} else {
1751890Swnj 			end = (char *)((int)bp + sizeof (struct cblock));
1761890Swnj 		}
1771890Swnj 		rem = end - q->c_cf;
1781890Swnj 		if (cc >= rem) {
1791890Swnj 			cc -= rem;
1801890Swnj 			q->c_cc -= rem;
18132Sbill 			q->c_cf = bp->c_next->c_info;
1821890Swnj 			bp->c_next = cfreelist;
1831890Swnj 			cfreelist = bp;
1841890Swnj 			cfreecount += CBSIZE;
1851890Swnj 			if (cwaiting) {
1861890Swnj 				wakeup(&cwaiting);
1871890Swnj 				cwaiting = 0;
1881890Swnj 			}
18932Sbill 		} else {
1901890Swnj 			q->c_cc -= cc;
1911890Swnj 			q->c_cf += cc;
1921890Swnj 			if (q->c_cc <= 0) {
1931890Swnj 				bp->c_next = cfreelist;
1941890Swnj 				cfreelist = bp;
1951890Swnj 				cfreecount += CBSIZE;
1961890Swnj 				if (cwaiting) {
1971890Swnj 					wakeup(&cwaiting);
1981890Swnj 					cwaiting = 0;
1991890Swnj 				}
2001890Swnj 			}
2011890Swnj 			break;
20232Sbill 		}
2031890Swnj 	}
2041890Swnj 	if (q->c_cc <= 0) {
20532Sbill 		q->c_cf = q->c_cl = NULL;
2061890Swnj 		q->c_cc = 0;
20732Sbill 	}
20832Sbill out:
20932Sbill 	splx(s);
21032Sbill }
211172Sbill 
2121890Swnj 
21332Sbill putc(c, p)
21412754Ssam 	register struct clist *p;
21532Sbill {
21632Sbill 	register struct cblock *bp;
21732Sbill 	register char *cp;
21832Sbill 	register s;
21932Sbill 
2203545Swnj 	s = spl5();
22132Sbill 	if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
22232Sbill 		if ((bp = cfreelist) == NULL) {
22332Sbill 			splx(s);
22432Sbill 			return(-1);
22532Sbill 		}
22632Sbill 		cfreelist = bp->c_next;
2271890Swnj 		cfreecount -= CBSIZE;
22832Sbill 		bp->c_next = NULL;
22932Sbill 		p->c_cf = cp = bp->c_info;
23032Sbill 	} else if (((int)cp & CROUND) == 0) {
23132Sbill 		bp = (struct cblock *)cp - 1;
23232Sbill 		if ((bp->c_next = cfreelist) == NULL) {
23332Sbill 			splx(s);
23432Sbill 			return(-1);
23532Sbill 		}
23632Sbill 		bp = bp->c_next;
23732Sbill 		cfreelist = bp->c_next;
2381890Swnj 		cfreecount -= CBSIZE;
23932Sbill 		bp->c_next = NULL;
24032Sbill 		cp = bp->c_info;
24132Sbill 	}
24232Sbill 	*cp++ = c;
24332Sbill 	p->c_cc++;
24432Sbill 	p->c_cl = cp;
24532Sbill 	splx(s);
24632Sbill 	return(0);
24732Sbill }
24832Sbill 
2491890Swnj 
2501890Swnj 
25132Sbill /*
25232Sbill  * copy buffer to clist.
25332Sbill  * return number of bytes not transfered.
25432Sbill  */
25532Sbill b_to_q(cp, cc, q)
25612754Ssam 	register char *cp;
25712754Ssam 	struct clist *q;
25812754Ssam 	register int cc;
25932Sbill {
26032Sbill 	register char *cq;
26132Sbill 	register struct cblock *bp;
26232Sbill 	register s, acc;
26332Sbill 
26432Sbill 	if (cc <= 0)
265*17368Ssam 		return (0);
26617366Stef 	while (cc > 0) {
26717366Stef 		s = spl6();
26817366Stef 		if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
26917366Stef 			if ((bp = cfreelist) == NULL) {
27017366Stef 				splx(s);
27117366Stef 				break;
27217366Stef 			}
27317366Stef 			q->c_cf = cq = bp->c_info;
27417366Stef 			goto middle;
27517366Stef 		}
27632Sbill 		if (((int)cq & CROUND) == 0) {
277*17368Ssam 			bp = &((struct cblock *)cq)[-1];
27817366Stef 			if ((bp->c_next = cfreelist) == NULL) {
27917366Stef 				splx(s);
28017366Stef 				break;
28117366Stef 			}
28232Sbill 			bp = bp->c_next;
28317366Stef 			cq = bp->c_info;
284*17368Ssam 	middle:
28532Sbill 			cfreelist = bp->c_next;
2861890Swnj 			cfreecount -= CBSIZE;
28732Sbill 			bp->c_next = NULL;
288*17368Ssam 			acc = MIN(cc, CBSIZE);
289*17368Ssam 		} else {
290*17368Ssam 			acc = (char *)((int)&cq[CBSIZE] &~ CROUND) - cq;
291*17368Ssam 			if (acc > cc)
292*17368Ssam 				acc = cc;
29332Sbill 		}
294*17368Ssam 		bcopy((caddr_t)cp, cq, acc);
29517366Stef 		q->c_cl = &cq[acc];
29617366Stef 		q->c_cc += acc;
29717366Stef 		splx(s);
29817366Stef 		cp += acc;
29917366Stef 		cc -= acc;
30032Sbill 	}
301*17368Ssam 	return (cc);
30232Sbill }
30332Sbill 
30432Sbill /*
305172Sbill  * Given a non-NULL pointter into the list (like c_cf which
306172Sbill  * always points to a real character if non-NULL) return the pointer
307172Sbill  * to the next character in the list or return NULL if no more chars.
308172Sbill  *
309172Sbill  * Callers must not allow getc's to happen between nextc's so that the
310172Sbill  * pointer becomes invalid.  Note that interrupts are NOT masked.
311172Sbill  */
312172Sbill char *
313172Sbill nextc(p, cp)
31412754Ssam 	register struct clist *p;
31512754Ssam 	register char *cp;
316172Sbill {
317172Sbill 
318172Sbill 	if (p->c_cc && ++cp != p->c_cl) {
319172Sbill 		if (((int)cp & CROUND) == 0)
320172Sbill 			return (((struct cblock *)cp)[-1].c_next->c_info);
321172Sbill 		return (cp);
322172Sbill 	}
323172Sbill 	return (0);
324172Sbill }
325172Sbill 
326172Sbill /*
327172Sbill  * Remove the last character in the list and return it.
328172Sbill  */
329172Sbill unputc(p)
33012754Ssam 	register struct clist *p;
331172Sbill {
332172Sbill 	register struct cblock *bp;
333172Sbill 	register int c, s;
334172Sbill 	struct cblock *obp;
335172Sbill 
3363545Swnj 	s = spl5();
337172Sbill 	if (p->c_cc <= 0)
338172Sbill 		c = -1;
339172Sbill 	else {
340172Sbill 		c = *--p->c_cl;
341172Sbill 		if (--p->c_cc <= 0) {
342172Sbill 			bp = (struct cblock *)p->c_cl;
343172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
344172Sbill 			p->c_cl = p->c_cf = NULL;
345172Sbill 			bp->c_next = cfreelist;
346172Sbill 			cfreelist = bp;
3471890Swnj 			cfreecount += CBSIZE;
348172Sbill 		} else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
349172Sbill 			p->c_cl = (char *)((int)p->c_cl & ~CROUND);
350172Sbill 			bp = (struct cblock *)p->c_cf;
351172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
352172Sbill 			while (bp->c_next != (struct cblock *)p->c_cl)
353172Sbill 				bp = bp->c_next;
354172Sbill 			obp = bp;
355172Sbill 			p->c_cl = (char *)(bp + 1);
356172Sbill 			bp = bp->c_next;
357172Sbill 			bp->c_next = cfreelist;
358172Sbill 			cfreelist = bp;
3591890Swnj 			cfreecount += CBSIZE;
360172Sbill 			obp->c_next = NULL;
361172Sbill 		}
362172Sbill 	}
363172Sbill 	splx(s);
364172Sbill 	return (c);
365172Sbill }
366172Sbill 
367172Sbill /*
368172Sbill  * Put the chars in the from que
369172Sbill  * on the end of the to que.
370172Sbill  *
371172Sbill  * SHOULD JUST USE q_to_b AND THEN b_to_q HERE.
372172Sbill  */
373172Sbill catq(from, to)
37412754Ssam 	struct clist *from, *to;
375172Sbill {
376172Sbill 	register c;
377172Sbill 
378172Sbill 	while ((c = getc(from)) >= 0)
379172Sbill 		(void) putc(c, to);
380172Sbill }
381172Sbill 
382172Sbill /*
3839761Ssam  * Integer (short) get/put
38432Sbill  * using clists
38532Sbill  */
3869761Ssam typedef	short word_t;
3879761Ssam union chword {
3889761Ssam 	word_t	word;
3899761Ssam 	struct {
3909761Ssam 		char	Ch[sizeof (word_t)];
3919761Ssam 	} Cha;
3929761Ssam #define	ch	Cha.Ch
3939761Ssam };
3949761Ssam 
39532Sbill getw(p)
3968955Sroot 	register struct clist *p;
39732Sbill {
3989761Ssam 	register int i;
3999761Ssam 	union chword x;
40032Sbill 
4019761Ssam 	if (p->c_cc < sizeof (word_t))
4029761Ssam 		return (-1);
4039761Ssam 	for (i = 0; i < sizeof (word_t); i++)
4049761Ssam 		x.ch[i] = getc(p);
4059761Ssam 	return (x.word);
40632Sbill }
40732Sbill 
40832Sbill putw(c, p)
4098955Sroot 	register struct clist *p;
41032Sbill {
41132Sbill 	register s;
4129761Ssam 	register int i;
4139761Ssam 	union chword x;
41432Sbill 
4153545Swnj 	s = spl5();
41632Sbill 	if (cfreelist==NULL) {
41732Sbill 		splx(s);
41832Sbill 		return(-1);
41932Sbill 	}
4209761Ssam 	x.word = c;
4219761Ssam 	for (i = 0; i < sizeof (word_t); i++)
4229761Ssam 		(void) putc(x.ch[i], p);
42332Sbill 	splx(s);
4249761Ssam 	return (0);
42532Sbill }
426