xref: /csrg-svn/sys/kern/tty_subr.c (revision 17576)
1*17576Sbloom /*	tty_subr.c	6.8	84/12/21	*/
21892Swnj 
317097Sbloom #include "param.h"
417097Sbloom #include "systm.h"
517097Sbloom #include "conf.h"
617097Sbloom #include "buf.h"
7*17576Sbloom #include "ioctl.h"
817097Sbloom #include "tty.h"
917097Sbloom #include "clist.h"
1032Sbill 
111890Swnj char	cwaiting;
121890Swnj 
1332Sbill /*
1432Sbill  * Character list get/put
1532Sbill  */
1632Sbill getc(p)
1712754Ssam 	register struct clist *p;
1832Sbill {
1932Sbill 	register struct cblock *bp;
2032Sbill 	register int c, s;
2132Sbill 
2217542Skarels 	s = spltty();
2332Sbill 	if (p->c_cc <= 0) {
2432Sbill 		c = -1;
2532Sbill 		p->c_cc = 0;
2632Sbill 		p->c_cf = p->c_cl = NULL;
2732Sbill 	} else {
2832Sbill 		c = *p->c_cf++ & 0377;
2932Sbill 		if (--p->c_cc<=0) {
3032Sbill 			bp = (struct cblock *)(p->c_cf-1);
3132Sbill 			bp = (struct cblock *) ((int)bp & ~CROUND);
3232Sbill 			p->c_cf = NULL;
3332Sbill 			p->c_cl = NULL;
3432Sbill 			bp->c_next = cfreelist;
3532Sbill 			cfreelist = bp;
361890Swnj 			cfreecount += CBSIZE;
371890Swnj 			if (cwaiting) {
381890Swnj 				wakeup(&cwaiting);
391890Swnj 				cwaiting = 0;
401890Swnj 			}
4132Sbill 		} else if (((int)p->c_cf & CROUND) == 0){
4232Sbill 			bp = (struct cblock *)(p->c_cf);
4332Sbill 			bp--;
4432Sbill 			p->c_cf = bp->c_next->c_info;
4532Sbill 			bp->c_next = cfreelist;
4632Sbill 			cfreelist = bp;
471890Swnj 			cfreecount += CBSIZE;
481890Swnj 			if (cwaiting) {
491890Swnj 				wakeup(&cwaiting);
501890Swnj 				cwaiting = 0;
511890Swnj 			}
5232Sbill 		}
5332Sbill 	}
5432Sbill 	splx(s);
5532Sbill 	return(c);
5632Sbill }
5732Sbill 
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;
6817542Skarels 	register nc;
6932Sbill 	char *acp;
7032Sbill 
7132Sbill 	if (cc <= 0)
7232Sbill 		return(0);
7317542Skarels 	s = spltty();
7432Sbill 	if (q->c_cc <= 0) {
7532Sbill 		q->c_cc = 0;
7632Sbill 		q->c_cf = q->c_cl = NULL;
771890Swnj 		splx(s);
7832Sbill 		return(0);
7932Sbill 	}
8032Sbill 	acp = cp;
8132Sbill 
8217542Skarels 	while (cc) {
8317542Skarels 		nc = sizeof(struct cblock) - ((int)q->c_cf & CROUND);
8417542Skarels 		nc = MIN(nc, cc);
8517542Skarels 		nc = MIN(nc, q->c_cc);
8617542Skarels 		(void) bcopy(q->c_cf, cp, (unsigned)nc);
8717542Skarels 		q->c_cf += nc;
8817542Skarels 		q->c_cc -= nc;
8917542Skarels 		cc -= nc;
9017542Skarels 		cp += nc;
9117542Skarels 		if (q->c_cc <= 0) {
9217542Skarels 			bp = (struct cblock *)(q->c_cf - 1);
9332Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
9432Sbill 			q->c_cf = q->c_cl = NULL;
9532Sbill 			bp->c_next = cfreelist;
9632Sbill 			cfreelist = bp;
971890Swnj 			cfreecount += CBSIZE;
981890Swnj 			if (cwaiting) {
991890Swnj 				wakeup(&cwaiting);
1001890Swnj 				cwaiting = 0;
1011890Swnj 			}
10232Sbill 			break;
10332Sbill 		}
10432Sbill 		if (((int)q->c_cf & CROUND) == 0) {
10532Sbill 			bp = (struct cblock *)(q->c_cf);
10632Sbill 			bp--;
10732Sbill 			q->c_cf = bp->c_next->c_info;
10832Sbill 			bp->c_next = cfreelist;
10932Sbill 			cfreelist = bp;
1101890Swnj 			cfreecount += CBSIZE;
1111890Swnj 			if (cwaiting) {
1121890Swnj 				wakeup(&cwaiting);
1131890Swnj 				cwaiting = 0;
1141890Swnj 			}
11532Sbill 		}
11632Sbill 	}
11732Sbill 	splx(s);
11832Sbill 	return(cp-acp);
11932Sbill }
12032Sbill 
12132Sbill /*
12232Sbill  * Return count of contiguous characters
12332Sbill  * in clist starting at q->c_cf.
12432Sbill  * Stop counting if flag&character is non-null.
12532Sbill  */
12632Sbill ndqb(q, flag)
1279761Ssam 	register struct clist *q;
12832Sbill {
1299761Ssam 	register cc;
1309761Ssam 	int s;
13132Sbill 
13217542Skarels 	s = spltty();
13332Sbill 	if (q->c_cc <= 0) {
13432Sbill 		cc = -q->c_cc;
13532Sbill 		goto out;
13632Sbill 	}
13732Sbill 	cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
13832Sbill 	cc -= (int)q->c_cf;
13932Sbill 	if (q->c_cc < cc)
14032Sbill 		cc = q->c_cc;
14132Sbill 	if (flag) {
14232Sbill 		register char *p, *end;
14332Sbill 
14432Sbill 		p = q->c_cf;
14532Sbill 		end = p;
14632Sbill 		end += cc;
14732Sbill 		while (p < end) {
14832Sbill 			if (*p & flag) {
1491890Swnj 				cc = (int)p;
1501890Swnj 				cc -= (int)q->c_cf;
15132Sbill 				break;
15232Sbill 			}
15332Sbill 			p++;
15432Sbill 		}
15532Sbill 	}
15632Sbill out:
15732Sbill 	splx(s);
15832Sbill 	return(cc);
15932Sbill }
16032Sbill 
1611890Swnj 
1621890Swnj 
16332Sbill /*
1641890Swnj  * Flush cc bytes from q.
16532Sbill  */
16632Sbill ndflush(q, cc)
16712754Ssam 	register struct clist *q;
16812754Ssam 	register cc;
16932Sbill {
17012754Ssam 	register struct cblock *bp;
17112754Ssam 	char *end;
17212754Ssam 	int rem, s;
17332Sbill 
17417542Skarels 	s = spltty();
17510749Seric 	if (q->c_cc <= 0) {
17632Sbill 		goto out;
17732Sbill 	}
1781890Swnj 	while (cc>0 && q->c_cc) {
1791890Swnj 		bp = (struct cblock *)((int)q->c_cf & ~CROUND);
1801890Swnj 		if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
1811890Swnj 			end = q->c_cl;
1821890Swnj 		} else {
1831890Swnj 			end = (char *)((int)bp + sizeof (struct cblock));
1841890Swnj 		}
1851890Swnj 		rem = end - q->c_cf;
1861890Swnj 		if (cc >= rem) {
1871890Swnj 			cc -= rem;
1881890Swnj 			q->c_cc -= rem;
18932Sbill 			q->c_cf = bp->c_next->c_info;
1901890Swnj 			bp->c_next = cfreelist;
1911890Swnj 			cfreelist = bp;
1921890Swnj 			cfreecount += CBSIZE;
1931890Swnj 			if (cwaiting) {
1941890Swnj 				wakeup(&cwaiting);
1951890Swnj 				cwaiting = 0;
1961890Swnj 			}
19732Sbill 		} else {
1981890Swnj 			q->c_cc -= cc;
1991890Swnj 			q->c_cf += cc;
2001890Swnj 			if (q->c_cc <= 0) {
2011890Swnj 				bp->c_next = cfreelist;
2021890Swnj 				cfreelist = bp;
2031890Swnj 				cfreecount += CBSIZE;
2041890Swnj 				if (cwaiting) {
2051890Swnj 					wakeup(&cwaiting);
2061890Swnj 					cwaiting = 0;
2071890Swnj 				}
2081890Swnj 			}
2091890Swnj 			break;
21032Sbill 		}
2111890Swnj 	}
2121890Swnj 	if (q->c_cc <= 0) {
21332Sbill 		q->c_cf = q->c_cl = NULL;
2141890Swnj 		q->c_cc = 0;
21532Sbill 	}
21632Sbill out:
21732Sbill 	splx(s);
21832Sbill }
219172Sbill 
2201890Swnj 
22132Sbill putc(c, p)
22212754Ssam 	register struct clist *p;
22332Sbill {
22432Sbill 	register struct cblock *bp;
22532Sbill 	register char *cp;
22632Sbill 	register s;
22732Sbill 
22817542Skarels 	s = spltty();
22932Sbill 	if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
23032Sbill 		if ((bp = cfreelist) == NULL) {
23132Sbill 			splx(s);
23232Sbill 			return(-1);
23332Sbill 		}
23432Sbill 		cfreelist = bp->c_next;
2351890Swnj 		cfreecount -= CBSIZE;
23632Sbill 		bp->c_next = NULL;
23732Sbill 		p->c_cf = cp = bp->c_info;
23832Sbill 	} else if (((int)cp & CROUND) == 0) {
23932Sbill 		bp = (struct cblock *)cp - 1;
24032Sbill 		if ((bp->c_next = cfreelist) == NULL) {
24132Sbill 			splx(s);
24232Sbill 			return(-1);
24332Sbill 		}
24432Sbill 		bp = bp->c_next;
24532Sbill 		cfreelist = bp->c_next;
2461890Swnj 		cfreecount -= CBSIZE;
24732Sbill 		bp->c_next = NULL;
24832Sbill 		cp = bp->c_info;
24932Sbill 	}
25032Sbill 	*cp++ = c;
25132Sbill 	p->c_cc++;
25232Sbill 	p->c_cl = cp;
25332Sbill 	splx(s);
25432Sbill 	return(0);
25532Sbill }
25632Sbill 
2571890Swnj 
2581890Swnj 
25932Sbill /*
26032Sbill  * copy buffer to clist.
26132Sbill  * return number of bytes not transfered.
26232Sbill  */
26332Sbill b_to_q(cp, cc, q)
26412754Ssam 	register char *cp;
26512754Ssam 	struct clist *q;
26612754Ssam 	register int cc;
26732Sbill {
26832Sbill 	register char *cq;
26932Sbill 	register struct cblock *bp;
27017542Skarels 	register s, nc;
27117542Skarels 	int acc;
27232Sbill 
27332Sbill 	if (cc <= 0)
27417542Skarels 		return(0);
27517542Skarels 	acc = cc;
27617542Skarels 	s = spltty();
27717542Skarels 	if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
27817542Skarels 		if ((bp = cfreelist) == NULL)
27917542Skarels 			goto out;
28017542Skarels 		cfreelist = bp->c_next;
28117542Skarels 		cfreecount -= CBSIZE;
28217542Skarels 		bp->c_next = NULL;
28317542Skarels 		q->c_cf = cq = bp->c_info;
28417542Skarels 	}
28517542Skarels 
28617542Skarels 	while (cc) {
28732Sbill 		if (((int)cq & CROUND) == 0) {
28817542Skarels 			bp = (struct cblock *) cq - 1;
28917542Skarels 			if ((bp->c_next = cfreelist) == NULL)
29017542Skarels 				goto out;
29132Sbill 			bp = bp->c_next;
29232Sbill 			cfreelist = bp->c_next;
2931890Swnj 			cfreecount -= CBSIZE;
29432Sbill 			bp->c_next = NULL;
29517542Skarels 			cq = bp->c_info;
29632Sbill 		}
29717542Skarels 		nc = MIN(cc, sizeof(struct cblock) - ((int)cq & CROUND));
29817542Skarels 		(void) bcopy(cp, cq, (unsigned)nc);
29917542Skarels 		cp += nc;
30017542Skarels 		cq += nc;
30117542Skarels 		cc -= nc;
30232Sbill 	}
30317542Skarels out:
30417542Skarels 	q->c_cl = cq;
30517542Skarels 	q->c_cc += acc - cc;
30617542Skarels 	splx(s);
30717368Ssam 	return (cc);
30832Sbill }
30932Sbill 
31032Sbill /*
311172Sbill  * Given a non-NULL pointter into the list (like c_cf which
312172Sbill  * always points to a real character if non-NULL) return the pointer
313172Sbill  * to the next character in the list or return NULL if no more chars.
314172Sbill  *
315172Sbill  * Callers must not allow getc's to happen between nextc's so that the
316172Sbill  * pointer becomes invalid.  Note that interrupts are NOT masked.
317172Sbill  */
318172Sbill char *
319172Sbill nextc(p, cp)
32012754Ssam 	register struct clist *p;
32112754Ssam 	register char *cp;
322172Sbill {
323172Sbill 
324172Sbill 	if (p->c_cc && ++cp != p->c_cl) {
325172Sbill 		if (((int)cp & CROUND) == 0)
326172Sbill 			return (((struct cblock *)cp)[-1].c_next->c_info);
327172Sbill 		return (cp);
328172Sbill 	}
329172Sbill 	return (0);
330172Sbill }
331172Sbill 
332172Sbill /*
333172Sbill  * Remove the last character in the list and return it.
334172Sbill  */
335172Sbill unputc(p)
33612754Ssam 	register struct clist *p;
337172Sbill {
338172Sbill 	register struct cblock *bp;
339172Sbill 	register int c, s;
340172Sbill 	struct cblock *obp;
341172Sbill 
34217542Skarels 	s = spltty();
343172Sbill 	if (p->c_cc <= 0)
344172Sbill 		c = -1;
345172Sbill 	else {
346172Sbill 		c = *--p->c_cl;
347172Sbill 		if (--p->c_cc <= 0) {
348172Sbill 			bp = (struct cblock *)p->c_cl;
349172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
350172Sbill 			p->c_cl = p->c_cf = NULL;
351172Sbill 			bp->c_next = cfreelist;
352172Sbill 			cfreelist = bp;
3531890Swnj 			cfreecount += CBSIZE;
354172Sbill 		} else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
355172Sbill 			p->c_cl = (char *)((int)p->c_cl & ~CROUND);
356172Sbill 			bp = (struct cblock *)p->c_cf;
357172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
358172Sbill 			while (bp->c_next != (struct cblock *)p->c_cl)
359172Sbill 				bp = bp->c_next;
360172Sbill 			obp = bp;
361172Sbill 			p->c_cl = (char *)(bp + 1);
362172Sbill 			bp = bp->c_next;
363172Sbill 			bp->c_next = cfreelist;
364172Sbill 			cfreelist = bp;
3651890Swnj 			cfreecount += CBSIZE;
366172Sbill 			obp->c_next = NULL;
367172Sbill 		}
368172Sbill 	}
369172Sbill 	splx(s);
370172Sbill 	return (c);
371172Sbill }
372172Sbill 
373172Sbill /*
374172Sbill  * Put the chars in the from que
375172Sbill  * on the end of the to que.
376172Sbill  */
377172Sbill catq(from, to)
37812754Ssam 	struct clist *from, *to;
379172Sbill {
38017542Skarels 	char bbuf[CBSIZE*4];
38117542Skarels 	register s, c;
382172Sbill 
38317542Skarels 	s = spltty();
38417542Skarels 	if (to->c_cc == 0) {
38517542Skarels 		*to = *from;
38617542Skarels 		from->c_cc = 0;
38717542Skarels 		from->c_cf = NULL;
38817542Skarels 		from->c_cl = NULL;
38917542Skarels 		splx(s);
39017542Skarels 		return;
39117542Skarels 	}
39217542Skarels 	splx(s);
39317542Skarels 	while (from->c_cc > 0) {
39417542Skarels 		c = q_to_b(from, bbuf, sizeof bbuf);
39517542Skarels 		(void) b_to_q(bbuf, c, to);
39617542Skarels 	}
397172Sbill }
398172Sbill 
39917542Skarels #ifdef unneeded
400172Sbill /*
4019761Ssam  * Integer (short) get/put
40232Sbill  * using clists
40332Sbill  */
40417542Skarels typedef	u_short word_t;
4059761Ssam 
40632Sbill getw(p)
4078955Sroot 	register struct clist *p;
40832Sbill {
40917542Skarels 	register int s, c;
41017542Skarels 	register struct cblock *bp;
41132Sbill 
41217542Skarels 	if (p->c_cc <= 1)
41317542Skarels 		return(-1);
41417542Skarels 	if (p->c_cc & 01) {
41517542Skarels 		c = getc(p);
41617542Skarels 		return(c | (getc(p)<<8));
41717542Skarels 	}
41817542Skarels 	s = spltty();
41917542Skarels 	c = *((word_t *)p->c_cf);
42017542Skarels 	p->c_cf += sizeof(word_t);
42117542Skarels 	p->c_cc -= sizeof(word_t);
42217542Skarels 	if (p->c_cc <= 0) {
42317542Skarels 		bp = (struct cblock *)(p->c_cf-1);
42417542Skarels 		bp = (struct cblock *) ((int)bp & ~CROUND);
42517542Skarels 		p->c_cf = NULL;
42617542Skarels 		p->c_cl = NULL;
42717542Skarels 		bp->c_next = cfreelist;
42817542Skarels 		cfreelist = bp;
42917542Skarels 		cfreecount += CBSIZE;
43017542Skarels 		if (cwaiting) {
43117542Skarels 			wakeup(&cwaiting);
43217542Skarels 			cwaiting = 0;
43317542Skarels 		}
43417542Skarels 	} else if (((int)p->c_cf & CROUND) == 0) {
43517542Skarels 		bp = (struct cblock *)(p->c_cf);
43617542Skarels 		bp--;
43717542Skarels 		p->c_cf = bp->c_next->c_info;
43817542Skarels 		bp->c_next = cfreelist;
43917542Skarels 		cfreelist = bp;
44017542Skarels 		cfreecount += CBSIZE;
44117542Skarels 		if (cwaiting) {
44217542Skarels 			wakeup(&cwaiting);
44317542Skarels 			cwaiting = 0;
44417542Skarels 		}
44517542Skarels 	}
44617542Skarels 	splx(s);
44717542Skarels 	return (c);
44832Sbill }
44932Sbill 
45032Sbill putw(c, p)
4518955Sroot 	register struct clist *p;
45217542Skarels 	word_t c;
45332Sbill {
45432Sbill 	register s;
45517542Skarels 	register struct cblock *bp;
45617542Skarels 	register char *cp;
45732Sbill 
45817542Skarels 	s = spltty();
45932Sbill 	if (cfreelist==NULL) {
46032Sbill 		splx(s);
46132Sbill 		return(-1);
46232Sbill 	}
46317542Skarels 	if (p->c_cc & 01) {
46417542Skarels 		(void) putc(c, p);
46517542Skarels 		(void) putc(c>>8, p);
46617542Skarels 	} else {
46717542Skarels 		if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
46817542Skarels 			if ((bp = cfreelist) == NULL) {
46917542Skarels 				splx(s);
47017542Skarels 				return (-1);
47117542Skarels 			}
47217542Skarels 			cfreelist = bp->c_next;
47317542Skarels 			cfreecount -= CBSIZE;
47417542Skarels 			bp->c_next = NULL;
47517542Skarels 			p->c_cf = cp = bp->c_info;
47617542Skarels 		} else if (((int)cp & CROUND) == 0) {
47717542Skarels 			bp = (struct cblock *)cp - 1;
47817542Skarels 			if ((bp->c_next = cfreelist) == NULL) {
47917542Skarels 				splx(s);
48017542Skarels 				return (-1);
48117542Skarels 			}
48217542Skarels 			bp = bp->c_next;
48317542Skarels 			cfreelist = bp->c_next;
48417542Skarels 			cfreecount -= CBSIZE;
48517542Skarels 			bp->c_next = NULL;
48617542Skarels 			cp = bp->c_info;
48717542Skarels 		}
48817542Skarels 		*(word_t *)cp = c;
48917542Skarels 		p->c_cl = cp + sizeof(word_t);
49017542Skarels 		p->c_cc += sizeof(word_t);
49117542Skarels 	}
49232Sbill 	splx(s);
4939761Ssam 	return (0);
49432Sbill }
49517542Skarels #endif unneeded
496