xref: /csrg-svn/sys/kern/tty_subr.c (revision 8955)
1*8955Sroot /*	tty_subr.c	4.16	82/10/31	*/
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)
1632Sbill 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 
576180Sroot #if notdef
5832Sbill /*
5932Sbill  * copy clist to buffer.
6032Sbill  * return number of bytes moved.
6132Sbill  */
6232Sbill q_to_b(q, cp, cc)
6332Sbill register struct clist *q;
6432Sbill 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 }
1134970Swnj #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)
12132Sbill register struct clist *q;
12232Sbill {
12332Sbill register cc;
12432Sbill 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)
16132Sbill register struct clist *q;
16232Sbill register cc;
16332Sbill {
1641890Swnj register struct cblock *bp;
1651890Swnj char *end;
1661890Swnj int rem;
16732Sbill register s;
16832Sbill 
1693545Swnj 	s = spl5();
17032Sbill 	if (q->c_cc < 0) {
1711890Swnj 		printf("neg q flush\n");
17232Sbill 		goto out;
17332Sbill 	}
17432Sbill 	if (q->c_cc == 0) {
17532Sbill 		goto out;
17632Sbill 	}
1771890Swnj 	while (cc>0 && q->c_cc) {
1781890Swnj 		bp = (struct cblock *)((int)q->c_cf & ~CROUND);
1791890Swnj 		if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
1801890Swnj 			end = q->c_cl;
1811890Swnj 		} else {
1821890Swnj 			end = (char *)((int)bp + sizeof (struct cblock));
1831890Swnj 		}
1841890Swnj 		rem = end - q->c_cf;
1851890Swnj 		if (cc >= rem) {
1861890Swnj 			cc -= rem;
1871890Swnj 			q->c_cc -= rem;
18832Sbill 			q->c_cf = bp->c_next->c_info;
1891890Swnj 			bp->c_next = cfreelist;
1901890Swnj 			cfreelist = bp;
1911890Swnj 			cfreecount += CBSIZE;
1921890Swnj 			if (cwaiting) {
1931890Swnj 				wakeup(&cwaiting);
1941890Swnj 				cwaiting = 0;
1951890Swnj 			}
19632Sbill 		} else {
1971890Swnj 			q->c_cc -= cc;
1981890Swnj 			q->c_cf += cc;
1991890Swnj 			if (q->c_cc <= 0) {
2001890Swnj 				bp->c_next = cfreelist;
2011890Swnj 				cfreelist = bp;
2021890Swnj 				cfreecount += CBSIZE;
2031890Swnj 				if (cwaiting) {
2041890Swnj 					wakeup(&cwaiting);
2051890Swnj 					cwaiting = 0;
2061890Swnj 				}
2071890Swnj 			}
2081890Swnj 			break;
20932Sbill 		}
2101890Swnj 	}
2111890Swnj 	if (q->c_cc <= 0) {
21232Sbill 		q->c_cf = q->c_cl = NULL;
2131890Swnj 		q->c_cc = 0;
21432Sbill 	}
21532Sbill out:
21632Sbill 	splx(s);
21732Sbill }
218172Sbill 
2191890Swnj 
22032Sbill putc(c, p)
22132Sbill register struct clist *p;
22232Sbill {
22332Sbill 	register struct cblock *bp;
22432Sbill 	register char *cp;
22532Sbill 	register s;
22632Sbill 
2273545Swnj 	s = spl5();
22832Sbill 	if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
22932Sbill 		if ((bp = cfreelist) == NULL) {
23032Sbill 			splx(s);
23132Sbill 			return(-1);
23232Sbill 		}
23332Sbill 		cfreelist = bp->c_next;
2341890Swnj 		cfreecount -= CBSIZE;
23532Sbill 		bp->c_next = NULL;
23632Sbill 		p->c_cf = cp = bp->c_info;
23732Sbill 	} else if (((int)cp & CROUND) == 0) {
23832Sbill 		bp = (struct cblock *)cp - 1;
23932Sbill 		if ((bp->c_next = cfreelist) == NULL) {
24032Sbill 			splx(s);
24132Sbill 			return(-1);
24232Sbill 		}
24332Sbill 		bp = bp->c_next;
24432Sbill 		cfreelist = bp->c_next;
2451890Swnj 		cfreecount -= CBSIZE;
24632Sbill 		bp->c_next = NULL;
24732Sbill 		cp = bp->c_info;
24832Sbill 	}
24932Sbill 	*cp++ = c;
25032Sbill 	p->c_cc++;
25132Sbill 	p->c_cl = cp;
25232Sbill 	splx(s);
25332Sbill 	return(0);
25432Sbill }
25532Sbill 
2561890Swnj 
2571890Swnj 
25832Sbill /*
25932Sbill  * copy buffer to clist.
26032Sbill  * return number of bytes not transfered.
26132Sbill  */
26232Sbill b_to_q(cp, cc, q)
26332Sbill register char *cp;
26432Sbill struct clist *q;
26532Sbill register int cc;
26632Sbill {
26732Sbill 	register char *cq;
26832Sbill 	register struct cblock *bp;
26932Sbill 	register s, acc;
27032Sbill 
27132Sbill 	if (cc <= 0)
27232Sbill 		return(0);
27332Sbill 	acc = cc;
2741890Swnj 
2751890Swnj 
2763545Swnj 	s = spl5();
27732Sbill 	if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
27832Sbill 		if ((bp = cfreelist) == NULL)
27932Sbill 			goto out;
28032Sbill 		cfreelist = bp->c_next;
2811890Swnj 		cfreecount -= CBSIZE;
28232Sbill 		bp->c_next = NULL;
28332Sbill 		q->c_cf = cq = bp->c_info;
28432Sbill 	}
28532Sbill 
28632Sbill 	while (cc) {
28732Sbill 		if (((int)cq & CROUND) == 0) {
28832Sbill 			bp = (struct cblock *) cq - 1;
28932Sbill 			if ((bp->c_next = cfreelist) == NULL)
29032Sbill 				goto out;
29132Sbill 			bp = bp->c_next;
29232Sbill 			cfreelist = bp->c_next;
2931890Swnj 			cfreecount -= CBSIZE;
29432Sbill 			bp->c_next = NULL;
29532Sbill 			cq = bp->c_info;
29632Sbill 		}
29732Sbill 		*cq++ = *cp++;
29832Sbill 		cc--;
29932Sbill 	}
30032Sbill out:
30132Sbill 	q->c_cl = cq;
30232Sbill 	q->c_cc += acc-cc;
30332Sbill 	splx(s);
30432Sbill 	return(cc);
30532Sbill }
30632Sbill 
30732Sbill /*
308172Sbill  * Given a non-NULL pointter into the list (like c_cf which
309172Sbill  * always points to a real character if non-NULL) return the pointer
310172Sbill  * to the next character in the list or return NULL if no more chars.
311172Sbill  *
312172Sbill  * Callers must not allow getc's to happen between nextc's so that the
313172Sbill  * pointer becomes invalid.  Note that interrupts are NOT masked.
314172Sbill  */
315172Sbill char *
316172Sbill nextc(p, cp)
317172Sbill register struct clist *p;
318172Sbill register char *cp;
319172Sbill {
320172Sbill 
321172Sbill 	if (p->c_cc && ++cp != p->c_cl) {
322172Sbill 		if (((int)cp & CROUND) == 0)
323172Sbill 			return (((struct cblock *)cp)[-1].c_next->c_info);
324172Sbill 		return (cp);
325172Sbill 	}
326172Sbill 	return (0);
327172Sbill }
328172Sbill 
329172Sbill /*
330172Sbill  * Remove the last character in the list and return it.
331172Sbill  */
332172Sbill unputc(p)
333172Sbill register struct clist *p;
334172Sbill {
335172Sbill 	register struct cblock *bp;
336172Sbill 	register int c, s;
337172Sbill 	struct cblock *obp;
338172Sbill 
3393545Swnj 	s = spl5();
340172Sbill 	if (p->c_cc <= 0)
341172Sbill 		c = -1;
342172Sbill 	else {
343172Sbill 		c = *--p->c_cl;
344172Sbill 		if (--p->c_cc <= 0) {
345172Sbill 			bp = (struct cblock *)p->c_cl;
346172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
347172Sbill 			p->c_cl = p->c_cf = NULL;
348172Sbill 			bp->c_next = cfreelist;
349172Sbill 			cfreelist = bp;
3501890Swnj 			cfreecount += CBSIZE;
351172Sbill 		} else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
352172Sbill 			p->c_cl = (char *)((int)p->c_cl & ~CROUND);
353172Sbill 			bp = (struct cblock *)p->c_cf;
354172Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
355172Sbill 			while (bp->c_next != (struct cblock *)p->c_cl)
356172Sbill 				bp = bp->c_next;
357172Sbill 			obp = bp;
358172Sbill 			p->c_cl = (char *)(bp + 1);
359172Sbill 			bp = bp->c_next;
360172Sbill 			bp->c_next = cfreelist;
361172Sbill 			cfreelist = bp;
3621890Swnj 			cfreecount += CBSIZE;
363172Sbill 			obp->c_next = NULL;
364172Sbill 		}
365172Sbill 	}
366172Sbill 	splx(s);
367172Sbill 	return (c);
368172Sbill }
369172Sbill 
370172Sbill /*
371172Sbill  * Put the chars in the from que
372172Sbill  * on the end of the to que.
373172Sbill  *
374172Sbill  * SHOULD JUST USE q_to_b AND THEN b_to_q HERE.
375172Sbill  */
376172Sbill catq(from, to)
377172Sbill struct clist *from, *to;
378172Sbill {
379172Sbill 	register c;
380172Sbill 
381172Sbill 	while ((c = getc(from)) >= 0)
382172Sbill 		(void) putc(c, to);
383172Sbill }
384172Sbill 
385172Sbill /*
38632Sbill  * integer (2-byte) get/put
38732Sbill  * using clists
38832Sbill  */
38932Sbill getw(p)
390*8955Sroot 	register struct clist *p;
39132Sbill {
39232Sbill 	register int s;
39332Sbill 
39432Sbill 	if (p->c_cc <= 1)
39532Sbill 		return(-1);
39632Sbill 	s = getc(p);
39732Sbill 	return(s | (getc(p)<<8));
39832Sbill }
39932Sbill 
40032Sbill putw(c, p)
401*8955Sroot 	register struct clist *p;
40232Sbill {
40332Sbill 	register s;
40432Sbill 
4053545Swnj 	s = spl5();
40632Sbill 	if (cfreelist==NULL) {
40732Sbill 		splx(s);
40832Sbill 		return(-1);
40932Sbill 	}
410130Sbill 	(void) putc(c, p);
411130Sbill 	(void) putc(c>>8, p);
41232Sbill 	splx(s);
41332Sbill 	return(0);
41432Sbill }
415