xref: /csrg-svn/sys/kern/tty_subr.c (revision 12754)
1*12754Ssam /*	tty_subr.c	4.20	83/05/27	*/
21892Swnj 
332Sbill #include "../h/param.h"
432Sbill #include "../h/systm.h"
532Sbill #include "../h/conf.h"
632Sbill #include "../h/buf.h"
71890Swnj #include "../h/tty.h"
82745Swnj #include "../h/clist.h"
932Sbill 
101890Swnj char	cwaiting;
111890Swnj 
1232Sbill /*
1332Sbill  * Character list get/put
1432Sbill  */
1532Sbill getc(p)
16*12754Ssam 	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 
57*12754Ssam #ifdef notdef
5832Sbill /*
5932Sbill  * copy clist to buffer.
6032Sbill  * return number of bytes moved.
6132Sbill  */
6232Sbill q_to_b(q, cp, cc)
639761Ssam 	register struct clist *q;
649761Ssam 	register char *cp;
6532Sbill {
6632Sbill 	register struct cblock *bp;
6732Sbill 	register int s;
6832Sbill 	char *acp;
6932Sbill 
7032Sbill 	if (cc <= 0)
7132Sbill 		return(0);
723545Swnj 	s = spl5();
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 	cc++;
8132Sbill 
8232Sbill 	while (--cc) {
8332Sbill 		*cp++ = *q->c_cf++;
8432Sbill 		if (--q->c_cc <= 0) {
8532Sbill 			bp = (struct cblock *)(q->c_cf-1);
8632Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
8732Sbill 			q->c_cf = q->c_cl = NULL;
8832Sbill 			bp->c_next = cfreelist;
8932Sbill 			cfreelist = bp;
901890Swnj 			cfreecount += CBSIZE;
911890Swnj 			if (cwaiting) {
921890Swnj 				wakeup(&cwaiting);
931890Swnj 				cwaiting = 0;
941890Swnj 			}
9532Sbill 			break;
9632Sbill 		}
9732Sbill 		if (((int)q->c_cf & CROUND) == 0) {
9832Sbill 			bp = (struct cblock *)(q->c_cf);
9932Sbill 			bp--;
10032Sbill 			q->c_cf = bp->c_next->c_info;
10132Sbill 			bp->c_next = cfreelist;
10232Sbill 			cfreelist = bp;
1031890Swnj 			cfreecount += CBSIZE;
1041890Swnj 			if (cwaiting) {
1051890Swnj 				wakeup(&cwaiting);
1061890Swnj 				cwaiting = 0;
1071890Swnj 			}
10832Sbill 		}
10932Sbill 	}
11032Sbill 	splx(s);
11132Sbill 	return(cp-acp);
11232Sbill }
113*12754Ssam #endif
11432Sbill 
11532Sbill /*
11632Sbill  * Return count of contiguous characters
11732Sbill  * in clist starting at q->c_cf.
11832Sbill  * Stop counting if flag&character is non-null.
11932Sbill  */
12032Sbill ndqb(q, flag)
1219761Ssam 	register struct clist *q;
12232Sbill {
1239761Ssam 	register cc;
1249761Ssam 	int s;
12532Sbill 
1263545Swnj 	s = spl5();
12732Sbill 	if (q->c_cc <= 0) {
12832Sbill 		cc = -q->c_cc;
12932Sbill 		goto out;
13032Sbill 	}
13132Sbill 	cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
13232Sbill 	cc -= (int)q->c_cf;
13332Sbill 	if (q->c_cc < cc)
13432Sbill 		cc = q->c_cc;
13532Sbill 	if (flag) {
13632Sbill 		register char *p, *end;
13732Sbill 
13832Sbill 		p = q->c_cf;
13932Sbill 		end = p;
14032Sbill 		end += cc;
14132Sbill 		while (p < end) {
14232Sbill 			if (*p & flag) {
1431890Swnj 				cc = (int)p;
1441890Swnj 				cc -= (int)q->c_cf;
14532Sbill 				break;
14632Sbill 			}
14732Sbill 			p++;
14832Sbill 		}
14932Sbill 	}
15032Sbill out:
15132Sbill 	splx(s);
15232Sbill 	return(cc);
15332Sbill }
15432Sbill 
1551890Swnj 
1561890Swnj 
15732Sbill /*
1581890Swnj  * Flush cc bytes from q.
15932Sbill  */
16032Sbill ndflush(q, cc)
161*12754Ssam 	register struct clist *q;
162*12754Ssam 	register cc;
16332Sbill {
164*12754Ssam 	register struct cblock *bp;
165*12754Ssam 	char *end;
166*12754Ssam 	int rem, s;
16732Sbill 
1683545Swnj 	s = spl5();
16910749Seric 	if (q->c_cc <= 0) {
17032Sbill 		goto out;
17132Sbill 	}
1721890Swnj 	while (cc>0 && q->c_cc) {
1731890Swnj 		bp = (struct cblock *)((int)q->c_cf & ~CROUND);
1741890Swnj 		if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
1751890Swnj 			end = q->c_cl;
1761890Swnj 		} else {
1771890Swnj 			end = (char *)((int)bp + sizeof (struct cblock));
1781890Swnj 		}
1791890Swnj 		rem = end - q->c_cf;
1801890Swnj 		if (cc >= rem) {
1811890Swnj 			cc -= rem;
1821890Swnj 			q->c_cc -= rem;
18332Sbill 			q->c_cf = bp->c_next->c_info;
1841890Swnj 			bp->c_next = cfreelist;
1851890Swnj 			cfreelist = bp;
1861890Swnj 			cfreecount += CBSIZE;
1871890Swnj 			if (cwaiting) {
1881890Swnj 				wakeup(&cwaiting);
1891890Swnj 				cwaiting = 0;
1901890Swnj 			}
19132Sbill 		} else {
1921890Swnj 			q->c_cc -= cc;
1931890Swnj 			q->c_cf += cc;
1941890Swnj 			if (q->c_cc <= 0) {
1951890Swnj 				bp->c_next = cfreelist;
1961890Swnj 				cfreelist = bp;
1971890Swnj 				cfreecount += CBSIZE;
1981890Swnj 				if (cwaiting) {
1991890Swnj 					wakeup(&cwaiting);
2001890Swnj 					cwaiting = 0;
2011890Swnj 				}
2021890Swnj 			}
2031890Swnj 			break;
20432Sbill 		}
2051890Swnj 	}
2061890Swnj 	if (q->c_cc <= 0) {
20732Sbill 		q->c_cf = q->c_cl = NULL;
2081890Swnj 		q->c_cc = 0;
20932Sbill 	}
21032Sbill out:
21132Sbill 	splx(s);
21232Sbill }
213172Sbill 
2141890Swnj 
21532Sbill putc(c, p)
216*12754Ssam 	register struct clist *p;
21732Sbill {
21832Sbill 	register struct cblock *bp;
21932Sbill 	register char *cp;
22032Sbill 	register s;
22132Sbill 
2223545Swnj 	s = spl5();
22332Sbill 	if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
22432Sbill 		if ((bp = cfreelist) == NULL) {
22532Sbill 			splx(s);
22632Sbill 			return(-1);
22732Sbill 		}
22832Sbill 		cfreelist = bp->c_next;
2291890Swnj 		cfreecount -= CBSIZE;
23032Sbill 		bp->c_next = NULL;
23132Sbill 		p->c_cf = cp = bp->c_info;
23232Sbill 	} else if (((int)cp & CROUND) == 0) {
23332Sbill 		bp = (struct cblock *)cp - 1;
23432Sbill 		if ((bp->c_next = cfreelist) == NULL) {
23532Sbill 			splx(s);
23632Sbill 			return(-1);
23732Sbill 		}
23832Sbill 		bp = bp->c_next;
23932Sbill 		cfreelist = bp->c_next;
2401890Swnj 		cfreecount -= CBSIZE;
24132Sbill 		bp->c_next = NULL;
24232Sbill 		cp = bp->c_info;
24332Sbill 	}
24432Sbill 	*cp++ = c;
24532Sbill 	p->c_cc++;
24632Sbill 	p->c_cl = cp;
24732Sbill 	splx(s);
24832Sbill 	return(0);
24932Sbill }
25032Sbill 
2511890Swnj 
2521890Swnj 
25332Sbill /*
25432Sbill  * copy buffer to clist.
25532Sbill  * return number of bytes not transfered.
25632Sbill  */
25732Sbill b_to_q(cp, cc, q)
258*12754Ssam 	register char *cp;
259*12754Ssam 	struct clist *q;
260*12754Ssam 	register int cc;
26132Sbill {
26232Sbill 	register char *cq;
26332Sbill 	register struct cblock *bp;
26432Sbill 	register s, acc;
26532Sbill 
26632Sbill 	if (cc <= 0)
26732Sbill 		return(0);
26832Sbill 	acc = cc;
2691890Swnj 
2701890Swnj 
2713545Swnj 	s = spl5();
27232Sbill 	if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
27332Sbill 		if ((bp = cfreelist) == NULL)
27432Sbill 			goto out;
27532Sbill 		cfreelist = bp->c_next;
2761890Swnj 		cfreecount -= CBSIZE;
27732Sbill 		bp->c_next = NULL;
27832Sbill 		q->c_cf = cq = bp->c_info;
27932Sbill 	}
28032Sbill 
28132Sbill 	while (cc) {
28232Sbill 		if (((int)cq & CROUND) == 0) {
28332Sbill 			bp = (struct cblock *) cq - 1;
28432Sbill 			if ((bp->c_next = cfreelist) == NULL)
28532Sbill 				goto out;
28632Sbill 			bp = bp->c_next;
28732Sbill 			cfreelist = bp->c_next;
2881890Swnj 			cfreecount -= CBSIZE;
28932Sbill 			bp->c_next = NULL;
29032Sbill 			cq = bp->c_info;
29132Sbill 		}
29232Sbill 		*cq++ = *cp++;
29332Sbill 		cc--;
29432Sbill 	}
29532Sbill out:
29632Sbill 	q->c_cl = cq;
29732Sbill 	q->c_cc += acc-cc;
29832Sbill 	splx(s);
29932Sbill 	return(cc);
30032Sbill }
30132Sbill 
30232Sbill /*
303172Sbill  * Given a non-NULL pointter into the list (like c_cf which
304172Sbill  * always points to a real character if non-NULL) return the pointer
305172Sbill  * to the next character in the list or return NULL if no more chars.
306172Sbill  *
307172Sbill  * Callers must not allow getc's to happen between nextc's so that the
308172Sbill  * pointer becomes invalid.  Note that interrupts are NOT masked.
309172Sbill  */
310172Sbill char *
311172Sbill nextc(p, cp)
312*12754Ssam 	register struct clist *p;
313*12754Ssam 	register char *cp;
314172Sbill {
315172Sbill 
316172Sbill 	if (p->c_cc && ++cp != p->c_cl) {
317172Sbill 		if (((int)cp & CROUND) == 0)
318172Sbill 			return (((struct cblock *)cp)[-1].c_next->c_info);
319172Sbill 		return (cp);
320172Sbill 	}
321172Sbill 	return (0);
322172Sbill }
323172Sbill 
324172Sbill /*
325172Sbill  * Remove the last character in the list and return it.
326172Sbill  */
327172Sbill unputc(p)
328*12754Ssam 	register struct clist *p;
329172Sbill {
330172Sbill 	register struct cblock *bp;
331172Sbill 	register int c, s;
332172Sbill 	struct cblock *obp;
333172Sbill 
3343545Swnj 	s = spl5();
335172Sbill 	if (p->c_cc <= 0)
336172Sbill 		c = -1;
337172Sbill 	else {
338172Sbill 		c = *--p->c_cl;
339172Sbill 		if (--p->c_cc <= 0) {
340172Sbill 			bp = (struct cblock *)p->c_cl;
341172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
342172Sbill 			p->c_cl = p->c_cf = NULL;
343172Sbill 			bp->c_next = cfreelist;
344172Sbill 			cfreelist = bp;
3451890Swnj 			cfreecount += CBSIZE;
346172Sbill 		} else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
347172Sbill 			p->c_cl = (char *)((int)p->c_cl & ~CROUND);
348172Sbill 			bp = (struct cblock *)p->c_cf;
349172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
350172Sbill 			while (bp->c_next != (struct cblock *)p->c_cl)
351172Sbill 				bp = bp->c_next;
352172Sbill 			obp = bp;
353172Sbill 			p->c_cl = (char *)(bp + 1);
354172Sbill 			bp = bp->c_next;
355172Sbill 			bp->c_next = cfreelist;
356172Sbill 			cfreelist = bp;
3571890Swnj 			cfreecount += CBSIZE;
358172Sbill 			obp->c_next = NULL;
359172Sbill 		}
360172Sbill 	}
361172Sbill 	splx(s);
362172Sbill 	return (c);
363172Sbill }
364172Sbill 
365172Sbill /*
366172Sbill  * Put the chars in the from que
367172Sbill  * on the end of the to que.
368172Sbill  *
369172Sbill  * SHOULD JUST USE q_to_b AND THEN b_to_q HERE.
370172Sbill  */
371172Sbill catq(from, to)
372*12754Ssam 	struct clist *from, *to;
373172Sbill {
374172Sbill 	register c;
375172Sbill 
376172Sbill 	while ((c = getc(from)) >= 0)
377172Sbill 		(void) putc(c, to);
378172Sbill }
379172Sbill 
380172Sbill /*
3819761Ssam  * Integer (short) get/put
38232Sbill  * using clists
38332Sbill  */
3849761Ssam typedef	short word_t;
3859761Ssam union chword {
3869761Ssam 	word_t	word;
3879761Ssam 	struct {
3889761Ssam 		char	Ch[sizeof (word_t)];
3899761Ssam 	} Cha;
3909761Ssam #define	ch	Cha.Ch
3919761Ssam };
3929761Ssam 
39332Sbill getw(p)
3948955Sroot 	register struct clist *p;
39532Sbill {
3969761Ssam 	register int i;
3979761Ssam 	union chword x;
39832Sbill 
3999761Ssam 	if (p->c_cc < sizeof (word_t))
4009761Ssam 		return (-1);
4019761Ssam 	for (i = 0; i < sizeof (word_t); i++)
4029761Ssam 		x.ch[i] = getc(p);
4039761Ssam 	return (x.word);
40432Sbill }
40532Sbill 
40632Sbill putw(c, p)
4078955Sroot 	register struct clist *p;
40832Sbill {
40932Sbill 	register s;
4109761Ssam 	register int i;
4119761Ssam 	union chword x;
41232Sbill 
4133545Swnj 	s = spl5();
41432Sbill 	if (cfreelist==NULL) {
41532Sbill 		splx(s);
41632Sbill 		return(-1);
41732Sbill 	}
4189761Ssam 	x.word = c;
4199761Ssam 	for (i = 0; i < sizeof (word_t); i++)
4209761Ssam 		(void) putc(x.ch[i], p);
42132Sbill 	splx(s);
4229761Ssam 	return (0);
42332Sbill }
424