xref: /csrg-svn/sys/kern/tty_subr.c (revision 2745)
1*2745Swnj /*	tty_subr.c	4.7	02/26/81	*/
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"
8*2745Swnj #include "../h/clist.h"
932Sbill 
101890Swnj char	cwaiting;
111890Swnj 
1232Sbill /*
1332Sbill  * Character list get/put
1432Sbill  */
1532Sbill getc(p)
1632Sbill register struct clist *p;
1732Sbill {
1832Sbill 	register struct cblock *bp;
1932Sbill 	register int c, s;
2032Sbill 
2132Sbill 	s = spl6();
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 
571890Swnj #if HAVTR > 0
581890Swnj trgetc(p)
591890Swnj register struct clist *p;
601890Swnj {
611890Swnj 	register struct cblock *bp;
621890Swnj 	register int c, s;
631890Swnj 
641890Swnj 	if (p->c_cc <= 0) {
651890Swnj 		c = -1;
661890Swnj 		p->c_cc = 0;
671890Swnj 		p->c_cf = NULL;
681890Swnj 	} else {
691890Swnj 		c = *p->c_cf++ & 0377;
701890Swnj 		if (--p->c_cc<=0) {
711890Swnj 			p->c_cf = NULL;
721890Swnj 		} else if (((int)p->c_cf & CROUND) == 0) {
731890Swnj 			bp = (struct cblock *)(p->c_cf);
741890Swnj 			bp--;
751890Swnj 			p->c_cf = bp->c_next->c_info;
761890Swnj 		}
771890Swnj 	}
781890Swnj 	return(c);
791890Swnj }
801890Swnj #endif
811890Swnj 
8232Sbill /*
8332Sbill  * copy clist to buffer.
8432Sbill  * return number of bytes moved.
8532Sbill  */
8632Sbill q_to_b(q, cp, cc)
8732Sbill register struct clist *q;
8832Sbill register char *cp;
8932Sbill {
9032Sbill 	register struct cblock *bp;
9132Sbill 	register int s;
9232Sbill 	char *acp;
9332Sbill 
9432Sbill 	if (cc <= 0)
9532Sbill 		return(0);
9632Sbill 	s = spl6();
9732Sbill 	if (q->c_cc <= 0) {
9832Sbill 		q->c_cc = 0;
9932Sbill 		q->c_cf = q->c_cl = NULL;
1001890Swnj 		splx(s);
10132Sbill 		return(0);
10232Sbill 	}
10332Sbill 	acp = cp;
10432Sbill 	cc++;
10532Sbill 
10632Sbill 	while (--cc) {
10732Sbill 		*cp++ = *q->c_cf++;
10832Sbill 		if (--q->c_cc <= 0) {
10932Sbill 			bp = (struct cblock *)(q->c_cf-1);
11032Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
11132Sbill 			q->c_cf = q->c_cl = NULL;
11232Sbill 			bp->c_next = cfreelist;
11332Sbill 			cfreelist = bp;
1141890Swnj 			cfreecount += CBSIZE;
1151890Swnj 			if (cwaiting) {
1161890Swnj 				wakeup(&cwaiting);
1171890Swnj 				cwaiting = 0;
1181890Swnj 			}
11932Sbill 			break;
12032Sbill 		}
12132Sbill 		if (((int)q->c_cf & CROUND) == 0) {
12232Sbill 			bp = (struct cblock *)(q->c_cf);
12332Sbill 			bp--;
12432Sbill 			q->c_cf = bp->c_next->c_info;
12532Sbill 			bp->c_next = cfreelist;
12632Sbill 			cfreelist = bp;
1271890Swnj 			cfreecount += CBSIZE;
1281890Swnj 			if (cwaiting) {
1291890Swnj 				wakeup(&cwaiting);
1301890Swnj 				cwaiting = 0;
1311890Swnj 			}
13232Sbill 		}
13332Sbill 	}
13432Sbill 	splx(s);
13532Sbill 	return(cp-acp);
13632Sbill }
13732Sbill 
1381890Swnj #if HAVTR > 0
13932Sbill /*
1401890Swnj  * Traverse a clist copying its contents to a buffer.
1411890Swnj  * q->cc and q->cf are updated with the current position
1421890Swnj  * in the list, but bytes are not released to the freelist.
1431890Swnj  */
1441890Swnj trq_to_b(q, cp, cc)
1451890Swnj register struct clist *q;
1461890Swnj register char *cp;
1471890Swnj register cc;
1481890Swnj {
1491890Swnj 	register struct cblock *bp;
1501890Swnj 	char *acp;
1511890Swnj 
1521890Swnj 	if (cc <= 0)
1531890Swnj 		return(0);
1541890Swnj 	if (q->c_cc <= 0)
1551890Swnj 		return(0);
1561890Swnj 
1571890Swnj 	acp = cp;
1581890Swnj 	cc++;
1591890Swnj 	while (--cc) {
1601890Swnj 		*cp++ = *q->c_cf++;
1611890Swnj 		if (((int)q->c_cf & CROUND) == 0) {
1621890Swnj 			bp = (struct cblock *)(q->c_cf);
1631890Swnj 			bp--;
1641890Swnj 			q->c_cf = bp->c_next->c_info;
1651890Swnj 		}
1661890Swnj 		if (--q->c_cc <= 0)
1671890Swnj 			break;
1681890Swnj 	}
1691890Swnj 	return(cp-acp);
1701890Swnj }
1711890Swnj #endif
1721890Swnj 
1731890Swnj 
1741890Swnj /*
17532Sbill  * Return count of contiguous characters
17632Sbill  * in clist starting at q->c_cf.
17732Sbill  * Stop counting if flag&character is non-null.
17832Sbill  */
17932Sbill ndqb(q, flag)
18032Sbill register struct clist *q;
18132Sbill {
18232Sbill register cc;
18332Sbill int s;
18432Sbill 
18532Sbill 	s = spl6();
18632Sbill 	if (q->c_cc <= 0) {
18732Sbill 		cc = -q->c_cc;
18832Sbill 		goto out;
18932Sbill 	}
19032Sbill 	cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
19132Sbill 	cc -= (int)q->c_cf;
19232Sbill 	if (q->c_cc < cc)
19332Sbill 		cc = q->c_cc;
19432Sbill 	if (flag) {
19532Sbill 		register char *p, *end;
19632Sbill 
19732Sbill 		p = q->c_cf;
19832Sbill 		end = p;
19932Sbill 		end += cc;
20032Sbill 		while (p < end) {
20132Sbill 			if (*p & flag) {
2021890Swnj 				cc = (int)p;
2031890Swnj 				cc -= (int)q->c_cf;
20432Sbill 				break;
20532Sbill 			}
20632Sbill 			p++;
20732Sbill 		}
20832Sbill 	}
20932Sbill out:
21032Sbill 	splx(s);
21132Sbill 	return(cc);
21232Sbill }
21332Sbill 
2141890Swnj 
2151890Swnj 
21632Sbill /*
2171890Swnj  * Flush cc bytes from q.
21832Sbill  */
21932Sbill ndflush(q, cc)
22032Sbill register struct clist *q;
22132Sbill register cc;
22232Sbill {
2231890Swnj register struct cblock *bp;
2241890Swnj char *end;
2251890Swnj int rem;
22632Sbill register s;
22732Sbill 
22832Sbill 	s = spl6();
22932Sbill 	if (q->c_cc < 0) {
2301890Swnj 		printf("neg q flush\n");
23132Sbill 		goto out;
23232Sbill 	}
23332Sbill 	if (q->c_cc == 0) {
23432Sbill 		goto out;
23532Sbill 	}
2361890Swnj 	while (cc>0 && q->c_cc) {
2371890Swnj 		bp = (struct cblock *)((int)q->c_cf & ~CROUND);
2381890Swnj 		if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
2391890Swnj 			end = q->c_cl;
2401890Swnj 		} else {
2411890Swnj 			end = (char *)((int)bp + sizeof (struct cblock));
2421890Swnj 		}
2431890Swnj 		rem = end - q->c_cf;
2441890Swnj 		if (cc >= rem) {
2451890Swnj 			cc -= rem;
2461890Swnj 			q->c_cc -= rem;
24732Sbill 			q->c_cf = bp->c_next->c_info;
2481890Swnj 			bp->c_next = cfreelist;
2491890Swnj 			cfreelist = bp;
2501890Swnj 			cfreecount += CBSIZE;
2511890Swnj 			if (cwaiting) {
2521890Swnj 				wakeup(&cwaiting);
2531890Swnj 				cwaiting = 0;
2541890Swnj 			}
25532Sbill 		} else {
2561890Swnj 			q->c_cc -= cc;
2571890Swnj 			q->c_cf += cc;
2581890Swnj 			if (q->c_cc <= 0) {
2591890Swnj 				bp->c_next = cfreelist;
2601890Swnj 				cfreelist = bp;
2611890Swnj 				cfreecount += CBSIZE;
2621890Swnj 				if (cwaiting) {
2631890Swnj 					wakeup(&cwaiting);
2641890Swnj 					cwaiting = 0;
2651890Swnj 				}
2661890Swnj 			}
2671890Swnj 			break;
26832Sbill 		}
2691890Swnj 	}
2701890Swnj 	if (q->c_cc <= 0) {
27132Sbill 		q->c_cf = q->c_cl = NULL;
2721890Swnj 		q->c_cc = 0;
27332Sbill 	}
27432Sbill out:
27532Sbill 	splx(s);
27632Sbill }
277172Sbill 
2781890Swnj 
27932Sbill putc(c, p)
28032Sbill register struct clist *p;
28132Sbill {
28232Sbill 	register struct cblock *bp;
28332Sbill 	register char *cp;
28432Sbill 	register s;
28532Sbill 
28632Sbill 	s = spl6();
28732Sbill 	if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
28832Sbill 		if ((bp = cfreelist) == NULL) {
28932Sbill 			splx(s);
29032Sbill 			return(-1);
29132Sbill 		}
29232Sbill 		cfreelist = bp->c_next;
2931890Swnj 		cfreecount -= CBSIZE;
29432Sbill 		bp->c_next = NULL;
29532Sbill 		p->c_cf = cp = bp->c_info;
29632Sbill 	} else if (((int)cp & CROUND) == 0) {
29732Sbill 		bp = (struct cblock *)cp - 1;
29832Sbill 		if ((bp->c_next = cfreelist) == NULL) {
29932Sbill 			splx(s);
30032Sbill 			return(-1);
30132Sbill 		}
30232Sbill 		bp = bp->c_next;
30332Sbill 		cfreelist = bp->c_next;
3041890Swnj 		cfreecount -= CBSIZE;
30532Sbill 		bp->c_next = NULL;
30632Sbill 		cp = bp->c_info;
30732Sbill 	}
30832Sbill 	*cp++ = c;
30932Sbill 	p->c_cc++;
31032Sbill 	p->c_cl = cp;
31132Sbill 	splx(s);
31232Sbill 	return(0);
31332Sbill }
31432Sbill 
3151890Swnj 
3161890Swnj 
31732Sbill /*
31832Sbill  * copy buffer to clist.
31932Sbill  * return number of bytes not transfered.
32032Sbill  */
32132Sbill b_to_q(cp, cc, q)
32232Sbill register char *cp;
32332Sbill struct clist *q;
32432Sbill register int cc;
32532Sbill {
32632Sbill 	register char *cq;
32732Sbill 	register struct cblock *bp;
32832Sbill 	register s, acc;
32932Sbill 
33032Sbill 	if (cc <= 0)
33132Sbill 		return(0);
33232Sbill 	acc = cc;
3331890Swnj 
3341890Swnj 
33532Sbill 	s = spl6();
33632Sbill 	if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
33732Sbill 		if ((bp = cfreelist) == NULL)
33832Sbill 			goto out;
33932Sbill 		cfreelist = bp->c_next;
3401890Swnj 		cfreecount -= CBSIZE;
34132Sbill 		bp->c_next = NULL;
34232Sbill 		q->c_cf = cq = bp->c_info;
34332Sbill 	}
34432Sbill 
34532Sbill 	while (cc) {
34632Sbill 		if (((int)cq & CROUND) == 0) {
34732Sbill 			bp = (struct cblock *) cq - 1;
34832Sbill 			if ((bp->c_next = cfreelist) == NULL)
34932Sbill 				goto out;
35032Sbill 			bp = bp->c_next;
35132Sbill 			cfreelist = bp->c_next;
3521890Swnj 			cfreecount -= CBSIZE;
35332Sbill 			bp->c_next = NULL;
35432Sbill 			cq = bp->c_info;
35532Sbill 		}
35632Sbill 		*cq++ = *cp++;
35732Sbill 		cc--;
35832Sbill 	}
35932Sbill out:
36032Sbill 	q->c_cl = cq;
36132Sbill 	q->c_cc += acc-cc;
36232Sbill 	splx(s);
36332Sbill 	return(cc);
36432Sbill }
36532Sbill 
3661890Swnj char *
3671890Swnj wb_to_q(cp, cc, q)
3681890Swnj register char *cp;
3691890Swnj register struct clist *q;
3701890Swnj register cc;
3711890Swnj {
3721890Swnj char *f;
3731890Swnj register s;
3741890Swnj 
3751890Swnj 	s = spl6();
3761890Swnj 	while (cc > cfreecount) {
3771890Swnj 		cwaiting = 1;
3781890Swnj 		sleep(&cwaiting, TTOPRI);
3791890Swnj 	}
3801890Swnj 	if (q->c_cc==0) {
3811890Swnj 		b_to_q(cp, cc, q);
3821890Swnj 		f = q->c_cf;
3831890Swnj 	} else {
3841890Swnj 		(void) putc(*cp++, q);
3851890Swnj 		f = q->c_cl;
3861890Swnj 		f--;
3871890Swnj 		b_to_q(cp, --cc, q);
3881890Swnj 	}
3891890Swnj 	splx(s);
3901890Swnj 	return(f);
3911890Swnj }
3921890Swnj 
3932329Swnj #ifdef UCBIPC
3941890Swnj char *
3951890Swnj nb_to_q(cp, cc, q)
3961890Swnj register char *cp;
3971890Swnj register struct clist *q;
3981890Swnj register cc;
3991890Swnj {
4001890Swnj char *f;
4011890Swnj register s;
4021890Swnj 
4031890Swnj 	s = spl6();
4041890Swnj 	if (cc > cfreecount) {
4051890Swnj 		f = NULL;
4061890Swnj 		goto out;
4071890Swnj 	}
4081890Swnj 	if (q->c_cc==0) {
4091890Swnj 		b_to_q(cp, cc, q);
4101890Swnj 		f = q->c_cf;
4111890Swnj 	} else {
4121890Swnj 		(void) putc(*cp++, q);
4131890Swnj 		f = q->c_cl;
4141890Swnj 		f--;
4151890Swnj 		b_to_q(cp, --cc, q);
4161890Swnj 	}
4171890Swnj out:
4181890Swnj 	splx(s);
4191890Swnj 	return(f);
4201890Swnj }
4211890Swnj #endif
4221890Swnj 
42332Sbill /*
424172Sbill  * Given a non-NULL pointter into the list (like c_cf which
425172Sbill  * always points to a real character if non-NULL) return the pointer
426172Sbill  * to the next character in the list or return NULL if no more chars.
427172Sbill  *
428172Sbill  * Callers must not allow getc's to happen between nextc's so that the
429172Sbill  * pointer becomes invalid.  Note that interrupts are NOT masked.
430172Sbill  */
431172Sbill char *
432172Sbill nextc(p, cp)
433172Sbill register struct clist *p;
434172Sbill register char *cp;
435172Sbill {
436172Sbill 
437172Sbill 	if (p->c_cc && ++cp != p->c_cl) {
438172Sbill 		if (((int)cp & CROUND) == 0)
439172Sbill 			return (((struct cblock *)cp)[-1].c_next->c_info);
440172Sbill 		return (cp);
441172Sbill 	}
442172Sbill 	return (0);
443172Sbill }
444172Sbill 
445172Sbill /*
446172Sbill  * Remove the last character in the list and return it.
447172Sbill  */
448172Sbill unputc(p)
449172Sbill register struct clist *p;
450172Sbill {
451172Sbill 	register struct cblock *bp;
452172Sbill 	register int c, s;
453172Sbill 	struct cblock *obp;
454172Sbill 
455172Sbill 	s = spl6();
456172Sbill 	if (p->c_cc <= 0)
457172Sbill 		c = -1;
458172Sbill 	else {
459172Sbill 		c = *--p->c_cl;
460172Sbill 		if (--p->c_cc <= 0) {
461172Sbill 			bp = (struct cblock *)p->c_cl;
462172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
463172Sbill 			p->c_cl = p->c_cf = NULL;
464172Sbill 			bp->c_next = cfreelist;
465172Sbill 			cfreelist = bp;
4661890Swnj 			cfreecount += CBSIZE;
467172Sbill 		} else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
468172Sbill 			p->c_cl = (char *)((int)p->c_cl & ~CROUND);
469172Sbill 			bp = (struct cblock *)p->c_cf;
470172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
471172Sbill 			while (bp->c_next != (struct cblock *)p->c_cl)
472172Sbill 				bp = bp->c_next;
473172Sbill 			obp = bp;
474172Sbill 			p->c_cl = (char *)(bp + 1);
475172Sbill 			bp = bp->c_next;
476172Sbill 			bp->c_next = cfreelist;
477172Sbill 			cfreelist = bp;
4781890Swnj 			cfreecount += CBSIZE;
479172Sbill 			obp->c_next = NULL;
480172Sbill 		}
481172Sbill 	}
482172Sbill 	splx(s);
483172Sbill 	return (c);
484172Sbill }
485172Sbill 
486172Sbill /*
487172Sbill  * Put the chars in the from que
488172Sbill  * on the end of the to que.
489172Sbill  *
490172Sbill  * SHOULD JUST USE q_to_b AND THEN b_to_q HERE.
491172Sbill  */
492172Sbill catq(from, to)
493172Sbill struct clist *from, *to;
494172Sbill {
495172Sbill 	register c;
496172Sbill 
497172Sbill 	while ((c = getc(from)) >= 0)
498172Sbill 		(void) putc(c, to);
499172Sbill }
500172Sbill 
501172Sbill /*
50232Sbill  * integer (2-byte) get/put
50332Sbill  * using clists
50432Sbill  */
50532Sbill getw(p)
50632Sbill register struct clist *p;
50732Sbill {
50832Sbill 	register int s;
50932Sbill 
51032Sbill 	if (p->c_cc <= 1)
51132Sbill 		return(-1);
51232Sbill 	s = getc(p);
51332Sbill 	return(s | (getc(p)<<8));
51432Sbill }
51532Sbill 
5161890Swnj #if HAVTR > 0
5171890Swnj trgetw(p)
5181890Swnj register struct clist *p;
5191890Swnj {
5201890Swnj 	register int w;
5211890Swnj 
5221890Swnj 	if (p->c_cc <=1)
5231890Swnj 		return(-1);
5241890Swnj 	w = trgetc(p);
5251890Swnj 	return(w | (trgetc(p)<<8));
5261890Swnj }
5271890Swnj #endif
5281890Swnj 
52932Sbill putw(c, p)
53032Sbill register struct clist *p;
53132Sbill {
53232Sbill 	register s;
53332Sbill 
53432Sbill 	s = spl6();
53532Sbill 	if (cfreelist==NULL) {
53632Sbill 		splx(s);
53732Sbill 		return(-1);
53832Sbill 	}
539130Sbill 	(void) putc(c, p);
540130Sbill 	(void) putc(c>>8, p);
54132Sbill 	splx(s);
54232Sbill 	return(0);
54332Sbill }
544