xref: /csrg-svn/sys/kern/tty_subr.c (revision 130)
1*130Sbill /*	tty_subr.c	3.2	10/14/12	*/
232Sbill 
332Sbill #include "../h/param.h"
432Sbill #include "../h/tty.h"
532Sbill #include "../h/systm.h"
632Sbill #include "../h/conf.h"
732Sbill #include "../h/buf.h"
832Sbill 
932Sbill struct cblock {
1032Sbill 	struct cblock *c_next;
1132Sbill 	char	c_info[CBSIZE];
1232Sbill };
1332Sbill 
1432Sbill struct	cblock	cfree[NCLIST];
1532Sbill struct	cblock	*cfreelist;
1632Sbill 
1732Sbill /*
1832Sbill  * Character list get/put
1932Sbill  */
2032Sbill getc(p)
2132Sbill register struct clist *p;
2232Sbill {
2332Sbill 	register struct cblock *bp;
2432Sbill 	register int c, s;
2532Sbill 
2632Sbill 	s = spl6();
2732Sbill 	if (p->c_cc <= 0) {
2832Sbill 		c = -1;
2932Sbill 		p->c_cc = 0;
3032Sbill 		p->c_cf = p->c_cl = NULL;
3132Sbill 	} else {
3232Sbill 		c = *p->c_cf++ & 0377;
3332Sbill 		if (--p->c_cc<=0) {
3432Sbill 			bp = (struct cblock *)(p->c_cf-1);
3532Sbill 			bp = (struct cblock *) ((int)bp & ~CROUND);
3632Sbill 			p->c_cf = NULL;
3732Sbill 			p->c_cl = NULL;
3832Sbill 			bp->c_next = cfreelist;
3932Sbill 			cfreelist = bp;
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;
4632Sbill 		}
4732Sbill 	}
4832Sbill 	splx(s);
4932Sbill 	return(c);
5032Sbill }
5132Sbill 
5232Sbill /*
5332Sbill  * copy clist to buffer.
5432Sbill  * return number of bytes moved.
5532Sbill  */
5632Sbill q_to_b(q, cp, cc)
5732Sbill register struct clist *q;
5832Sbill register char *cp;
5932Sbill {
6032Sbill 	register struct cblock *bp;
6132Sbill 	register int s;
6232Sbill 	char *acp;
6332Sbill 
6432Sbill 	if (cc <= 0)
6532Sbill 		return(0);
6632Sbill 	s = spl6();
6732Sbill 	if (q->c_cc <= 0) {
6832Sbill 		q->c_cc = 0;
6932Sbill 		q->c_cf = q->c_cl = NULL;
7032Sbill 		return(0);
7132Sbill 	}
7232Sbill 	acp = cp;
7332Sbill 	cc++;
7432Sbill 
7532Sbill 	while (--cc) {
7632Sbill 		*cp++ = *q->c_cf++;
7732Sbill 		if (--q->c_cc <= 0) {
7832Sbill 			bp = (struct cblock *)(q->c_cf-1);
7932Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
8032Sbill 			q->c_cf = q->c_cl = NULL;
8132Sbill 			bp->c_next = cfreelist;
8232Sbill 			cfreelist = bp;
8332Sbill 			break;
8432Sbill 		}
8532Sbill 		if (((int)q->c_cf & CROUND) == 0) {
8632Sbill 			bp = (struct cblock *)(q->c_cf);
8732Sbill 			bp--;
8832Sbill 			q->c_cf = bp->c_next->c_info;
8932Sbill 			bp->c_next = cfreelist;
9032Sbill 			cfreelist = bp;
9132Sbill 		}
9232Sbill 	}
9332Sbill 	splx(s);
9432Sbill 	return(cp-acp);
9532Sbill }
9632Sbill 
9732Sbill 
9832Sbill /*
9932Sbill  * Return count of contiguous characters
10032Sbill  * in clist starting at q->c_cf.
10132Sbill  * Stop counting if flag&character is non-null.
10232Sbill  */
10332Sbill ndqb(q, flag)
10432Sbill register struct clist *q;
10532Sbill {
10632Sbill register cc;
10732Sbill int s;
10832Sbill 
10932Sbill 	s = spl6();
11032Sbill 	if (q->c_cc <= 0) {
11132Sbill 		cc = -q->c_cc;
11232Sbill 		goto out;
11332Sbill 	}
11432Sbill 	cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
11532Sbill 	cc -= (int)q->c_cf;
11632Sbill 	if (q->c_cc < cc)
11732Sbill 		cc = q->c_cc;
11832Sbill 	if (flag) {
11932Sbill 		register char *p, *end;
12032Sbill 
12132Sbill 		p = q->c_cf;
12232Sbill 		end = p;
12332Sbill 		end += cc;
12432Sbill 		while (p < end) {
12532Sbill 			if (*p & flag) {
12632Sbill 				cc = (int)p - (int)q->c_cf;
12732Sbill 				break;
12832Sbill 			}
12932Sbill 			p++;
13032Sbill 		}
13132Sbill 	}
13232Sbill out:
13332Sbill 	splx(s);
13432Sbill 	return(cc);
13532Sbill }
13632Sbill 
13732Sbill 
13832Sbill 
13932Sbill /*
14032Sbill  * Update clist to show that cc characters
14132Sbill  * were removed.  It is assumed that cc < CBSIZE.
14232Sbill  */
14332Sbill ndflush(q, cc)
14432Sbill register struct clist *q;
14532Sbill register cc;
14632Sbill {
14732Sbill register s;
14832Sbill 
14932Sbill 	if (cc == 0)
15032Sbill 		return;
15132Sbill 	s = spl6();
15232Sbill 	if (q->c_cc < 0) {
15332Sbill 		if (q->c_cf != NULL) {
15432Sbill 			q->c_cc += cc;
15532Sbill 			q->c_cf += cc;
15632Sbill 			goto out;
15732Sbill 		}
15832Sbill 		q->c_cc = 0;
15932Sbill 		goto out;
16032Sbill 	}
16132Sbill 	if (q->c_cc == 0) {
16232Sbill 		goto out;
16332Sbill 	}
16432Sbill 	q->c_cc -= cc;
16532Sbill 	q->c_cf += cc;
16632Sbill 	if (((int)q->c_cf & CROUND) == 0) {
16732Sbill 		register struct cblock *bp;
16832Sbill 
16932Sbill 		bp = (struct cblock *)(q->c_cf) -1;
17032Sbill 		if (bp->c_next) {
17132Sbill 			q->c_cf = bp->c_next->c_info;
17232Sbill 		} else {
17332Sbill 			q->c_cf = q->c_cl = NULL;
17432Sbill 		}
17532Sbill 		bp->c_next = cfreelist;
17632Sbill 		cfreelist = bp;
17732Sbill 	} else
17832Sbill 	if (q->c_cc == 0) {
17932Sbill 		register struct cblock *bp;
18032Sbill 		q->c_cf = (char *)((int)q->c_cf & ~CROUND);
18132Sbill 		bp = (struct cblock *)(q->c_cf);
18232Sbill 		bp->c_next = cfreelist;
18332Sbill 		cfreelist = bp;
18432Sbill 		q->c_cf = q->c_cl = NULL;
18532Sbill 	}
18632Sbill out:
18732Sbill 	splx(s);
18832Sbill }
18932Sbill putc(c, p)
19032Sbill register struct clist *p;
19132Sbill {
19232Sbill 	register struct cblock *bp;
19332Sbill 	register char *cp;
19432Sbill 	register s;
19532Sbill 
19632Sbill 	s = spl6();
19732Sbill 	if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
19832Sbill 		if ((bp = cfreelist) == NULL) {
19932Sbill 			splx(s);
20032Sbill 			return(-1);
20132Sbill 		}
20232Sbill 		cfreelist = bp->c_next;
20332Sbill 		bp->c_next = NULL;
20432Sbill 		p->c_cf = cp = bp->c_info;
20532Sbill 	} else if (((int)cp & CROUND) == 0) {
20632Sbill 		bp = (struct cblock *)cp - 1;
20732Sbill 		if ((bp->c_next = cfreelist) == NULL) {
20832Sbill 			splx(s);
20932Sbill 			return(-1);
21032Sbill 		}
21132Sbill 		bp = bp->c_next;
21232Sbill 		cfreelist = bp->c_next;
21332Sbill 		bp->c_next = NULL;
21432Sbill 		cp = bp->c_info;
21532Sbill 	}
21632Sbill 	*cp++ = c;
21732Sbill 	p->c_cc++;
21832Sbill 	p->c_cl = cp;
21932Sbill 	splx(s);
22032Sbill 	return(0);
22132Sbill }
22232Sbill 
22332Sbill 
22432Sbill 
22532Sbill /*
22632Sbill  * copy buffer to clist.
22732Sbill  * return number of bytes not transfered.
22832Sbill  */
22932Sbill b_to_q(cp, cc, q)
23032Sbill register char *cp;
23132Sbill struct clist *q;
23232Sbill register int cc;
23332Sbill {
23432Sbill 	register char *cq;
23532Sbill 	register struct cblock *bp;
23632Sbill 	register s, acc;
23732Sbill 
23832Sbill 	if (cc <= 0)
23932Sbill 		return(0);
24032Sbill 	acc = cc;
24132Sbill 	s = spl6();
24232Sbill 	if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
24332Sbill 		if ((bp = cfreelist) == NULL)
24432Sbill 			goto out;
24532Sbill 		cfreelist = bp->c_next;
24632Sbill 		bp->c_next = NULL;
24732Sbill 		q->c_cf = cq = bp->c_info;
24832Sbill 	}
24932Sbill 
25032Sbill 	while (cc) {
25132Sbill 		if (((int)cq & CROUND) == 0) {
25232Sbill 			bp = (struct cblock *) cq - 1;
25332Sbill 			if ((bp->c_next = cfreelist) == NULL)
25432Sbill 				goto out;
25532Sbill 			bp = bp->c_next;
25632Sbill 			cfreelist = bp->c_next;
25732Sbill 			bp->c_next = NULL;
25832Sbill 			cq = bp->c_info;
25932Sbill 		}
26032Sbill 		*cq++ = *cp++;
26132Sbill 		cc--;
26232Sbill 	}
26332Sbill out:
26432Sbill 	q->c_cl = cq;
26532Sbill 	q->c_cc += acc-cc;
26632Sbill 	splx(s);
26732Sbill 	return(cc);
26832Sbill }
26932Sbill 
27032Sbill /*
27132Sbill  * Initialize clist by freeing all character blocks, then count
27232Sbill  * number of character devices. (Once-only routine)
27332Sbill  */
27432Sbill cinit()
27532Sbill {
27632Sbill 	register int ccp;
27732Sbill 	register struct cblock *cp;
27832Sbill 	register struct cdevsw *cdp;
27932Sbill 
28032Sbill 	ccp = (int)cfree;
28132Sbill 	ccp = (ccp+CROUND) & ~CROUND;
28232Sbill 	for(cp=(struct cblock *)ccp; cp <= &cfree[NCLIST-1]; cp++) {
28332Sbill 		cp->c_next = cfreelist;
28432Sbill 		cfreelist = cp;
28532Sbill 	}
28632Sbill 	ccp = 0;
28732Sbill 	for(cdp = cdevsw; cdp->d_open; cdp++)
28832Sbill 		ccp++;
28932Sbill 	nchrdev = ccp;
29032Sbill }
29132Sbill 
29232Sbill /*
29332Sbill  * integer (2-byte) get/put
29432Sbill  * using clists
29532Sbill  */
29632Sbill /*
29732Sbill getw(p)
29832Sbill register struct clist *p;
29932Sbill {
30032Sbill 	register int s;
30132Sbill 
30232Sbill 	if (p->c_cc <= 1)
30332Sbill 		return(-1);
30432Sbill 	s = getc(p);
30532Sbill 	return(s | (getc(p)<<8));
30632Sbill }
30732Sbill */
30832Sbill 
30932Sbill putw(c, p)
31032Sbill register struct clist *p;
31132Sbill {
31232Sbill 	register s;
31332Sbill 
31432Sbill 	s = spl6();
31532Sbill 	if (cfreelist==NULL) {
31632Sbill 		splx(s);
31732Sbill 		return(-1);
31832Sbill 	}
319*130Sbill 	(void) putc(c, p);
320*130Sbill 	(void) putc(c>>8, p);
32132Sbill 	splx(s);
32232Sbill 	return(0);
32332Sbill }
324