xref: /csrg-svn/sys/kern/tty_subr.c (revision 32)
1*32Sbill /*	tty_subr.c	3.1	10/14/12	*/
2*32Sbill 
3*32Sbill #include "../h/param.h"
4*32Sbill #include "../h/tty.h"
5*32Sbill #include "../h/systm.h"
6*32Sbill #include "../h/conf.h"
7*32Sbill #include "../h/buf.h"
8*32Sbill 
9*32Sbill struct cblock {
10*32Sbill 	struct cblock *c_next;
11*32Sbill 	char	c_info[CBSIZE];
12*32Sbill };
13*32Sbill 
14*32Sbill struct	cblock	cfree[NCLIST];
15*32Sbill struct	cblock	*cfreelist;
16*32Sbill 
17*32Sbill /*
18*32Sbill  * Character list get/put
19*32Sbill  */
20*32Sbill getc(p)
21*32Sbill register struct clist *p;
22*32Sbill {
23*32Sbill 	register struct cblock *bp;
24*32Sbill 	register int c, s;
25*32Sbill 
26*32Sbill 	s = spl6();
27*32Sbill 	if (p->c_cc <= 0) {
28*32Sbill 		c = -1;
29*32Sbill 		p->c_cc = 0;
30*32Sbill 		p->c_cf = p->c_cl = NULL;
31*32Sbill 	} else {
32*32Sbill 		c = *p->c_cf++ & 0377;
33*32Sbill 		if (--p->c_cc<=0) {
34*32Sbill 			bp = (struct cblock *)(p->c_cf-1);
35*32Sbill 			bp = (struct cblock *) ((int)bp & ~CROUND);
36*32Sbill 			p->c_cf = NULL;
37*32Sbill 			p->c_cl = NULL;
38*32Sbill 			bp->c_next = cfreelist;
39*32Sbill 			cfreelist = bp;
40*32Sbill 		} else if (((int)p->c_cf & CROUND) == 0){
41*32Sbill 			bp = (struct cblock *)(p->c_cf);
42*32Sbill 			bp--;
43*32Sbill 			p->c_cf = bp->c_next->c_info;
44*32Sbill 			bp->c_next = cfreelist;
45*32Sbill 			cfreelist = bp;
46*32Sbill 		}
47*32Sbill 	}
48*32Sbill 	splx(s);
49*32Sbill 	return(c);
50*32Sbill }
51*32Sbill 
52*32Sbill /*
53*32Sbill  * copy clist to buffer.
54*32Sbill  * return number of bytes moved.
55*32Sbill  */
56*32Sbill q_to_b(q, cp, cc)
57*32Sbill register struct clist *q;
58*32Sbill register char *cp;
59*32Sbill {
60*32Sbill 	register struct cblock *bp;
61*32Sbill 	register int s;
62*32Sbill 	char *acp;
63*32Sbill 
64*32Sbill 	if (cc <= 0)
65*32Sbill 		return(0);
66*32Sbill 	s = spl6();
67*32Sbill 	if (q->c_cc <= 0) {
68*32Sbill 		q->c_cc = 0;
69*32Sbill 		q->c_cf = q->c_cl = NULL;
70*32Sbill 		return(0);
71*32Sbill 	}
72*32Sbill 	acp = cp;
73*32Sbill 	cc++;
74*32Sbill 
75*32Sbill 	while (--cc) {
76*32Sbill 		*cp++ = *q->c_cf++;
77*32Sbill 		if (--q->c_cc <= 0) {
78*32Sbill 			bp = (struct cblock *)(q->c_cf-1);
79*32Sbill 			bp = (struct cblock *)((int)bp & ~CROUND);
80*32Sbill 			q->c_cf = q->c_cl = NULL;
81*32Sbill 			bp->c_next = cfreelist;
82*32Sbill 			cfreelist = bp;
83*32Sbill 			break;
84*32Sbill 		}
85*32Sbill 		if (((int)q->c_cf & CROUND) == 0) {
86*32Sbill 			bp = (struct cblock *)(q->c_cf);
87*32Sbill 			bp--;
88*32Sbill 			q->c_cf = bp->c_next->c_info;
89*32Sbill 			bp->c_next = cfreelist;
90*32Sbill 			cfreelist = bp;
91*32Sbill 		}
92*32Sbill 	}
93*32Sbill 	splx(s);
94*32Sbill 	return(cp-acp);
95*32Sbill }
96*32Sbill 
97*32Sbill 
98*32Sbill /*
99*32Sbill  * Return count of contiguous characters
100*32Sbill  * in clist starting at q->c_cf.
101*32Sbill  * Stop counting if flag&character is non-null.
102*32Sbill  */
103*32Sbill ndqb(q, flag)
104*32Sbill register struct clist *q;
105*32Sbill {
106*32Sbill register cc;
107*32Sbill int s;
108*32Sbill 
109*32Sbill 	s = spl6();
110*32Sbill 	if (q->c_cc <= 0) {
111*32Sbill 		cc = -q->c_cc;
112*32Sbill 		goto out;
113*32Sbill 	}
114*32Sbill 	cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
115*32Sbill 	cc -= (int)q->c_cf;
116*32Sbill 	if (q->c_cc < cc)
117*32Sbill 		cc = q->c_cc;
118*32Sbill 	if (flag) {
119*32Sbill 		register char *p, *end;
120*32Sbill 
121*32Sbill 		p = q->c_cf;
122*32Sbill 		end = p;
123*32Sbill 		end += cc;
124*32Sbill 		while (p < end) {
125*32Sbill 			if (*p & flag) {
126*32Sbill 				cc = (int)p - (int)q->c_cf;
127*32Sbill 				break;
128*32Sbill 			}
129*32Sbill 			p++;
130*32Sbill 		}
131*32Sbill 	}
132*32Sbill out:
133*32Sbill 	splx(s);
134*32Sbill 	return(cc);
135*32Sbill }
136*32Sbill 
137*32Sbill 
138*32Sbill 
139*32Sbill /*
140*32Sbill  * Update clist to show that cc characters
141*32Sbill  * were removed.  It is assumed that cc < CBSIZE.
142*32Sbill  */
143*32Sbill ndflush(q, cc)
144*32Sbill register struct clist *q;
145*32Sbill register cc;
146*32Sbill {
147*32Sbill register s;
148*32Sbill 
149*32Sbill 	if (cc == 0)
150*32Sbill 		return;
151*32Sbill 	s = spl6();
152*32Sbill 	if (q->c_cc < 0) {
153*32Sbill 		if (q->c_cf != NULL) {
154*32Sbill 			q->c_cc += cc;
155*32Sbill 			q->c_cf += cc;
156*32Sbill 			goto out;
157*32Sbill 		}
158*32Sbill 		q->c_cc = 0;
159*32Sbill 		goto out;
160*32Sbill 	}
161*32Sbill 	if (q->c_cc == 0) {
162*32Sbill 		goto out;
163*32Sbill 	}
164*32Sbill 	q->c_cc -= cc;
165*32Sbill 	q->c_cf += cc;
166*32Sbill 	if (((int)q->c_cf & CROUND) == 0) {
167*32Sbill 		register struct cblock *bp;
168*32Sbill 
169*32Sbill 		bp = (struct cblock *)(q->c_cf) -1;
170*32Sbill 		if (bp->c_next) {
171*32Sbill 			q->c_cf = bp->c_next->c_info;
172*32Sbill 		} else {
173*32Sbill 			q->c_cf = q->c_cl = NULL;
174*32Sbill 		}
175*32Sbill 		bp->c_next = cfreelist;
176*32Sbill 		cfreelist = bp;
177*32Sbill 	} else
178*32Sbill 	if (q->c_cc == 0) {
179*32Sbill 		register struct cblock *bp;
180*32Sbill 		q->c_cf = (char *)((int)q->c_cf & ~CROUND);
181*32Sbill 		bp = (struct cblock *)(q->c_cf);
182*32Sbill 		bp->c_next = cfreelist;
183*32Sbill 		cfreelist = bp;
184*32Sbill 		q->c_cf = q->c_cl = NULL;
185*32Sbill 	}
186*32Sbill out:
187*32Sbill 	splx(s);
188*32Sbill }
189*32Sbill putc(c, p)
190*32Sbill register struct clist *p;
191*32Sbill {
192*32Sbill 	register struct cblock *bp;
193*32Sbill 	register char *cp;
194*32Sbill 	register s;
195*32Sbill 
196*32Sbill 	s = spl6();
197*32Sbill 	if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
198*32Sbill 		if ((bp = cfreelist) == NULL) {
199*32Sbill 			splx(s);
200*32Sbill 			return(-1);
201*32Sbill 		}
202*32Sbill 		cfreelist = bp->c_next;
203*32Sbill 		bp->c_next = NULL;
204*32Sbill 		p->c_cf = cp = bp->c_info;
205*32Sbill 	} else if (((int)cp & CROUND) == 0) {
206*32Sbill 		bp = (struct cblock *)cp - 1;
207*32Sbill 		if ((bp->c_next = cfreelist) == NULL) {
208*32Sbill 			splx(s);
209*32Sbill 			return(-1);
210*32Sbill 		}
211*32Sbill 		bp = bp->c_next;
212*32Sbill 		cfreelist = bp->c_next;
213*32Sbill 		bp->c_next = NULL;
214*32Sbill 		cp = bp->c_info;
215*32Sbill 	}
216*32Sbill 	*cp++ = c;
217*32Sbill 	p->c_cc++;
218*32Sbill 	p->c_cl = cp;
219*32Sbill 	splx(s);
220*32Sbill 	return(0);
221*32Sbill }
222*32Sbill 
223*32Sbill 
224*32Sbill 
225*32Sbill /*
226*32Sbill  * copy buffer to clist.
227*32Sbill  * return number of bytes not transfered.
228*32Sbill  */
229*32Sbill b_to_q(cp, cc, q)
230*32Sbill register char *cp;
231*32Sbill struct clist *q;
232*32Sbill register int cc;
233*32Sbill {
234*32Sbill 	register char *cq;
235*32Sbill 	register struct cblock *bp;
236*32Sbill 	register s, acc;
237*32Sbill 
238*32Sbill 	if (cc <= 0)
239*32Sbill 		return(0);
240*32Sbill 	acc = cc;
241*32Sbill 	s = spl6();
242*32Sbill 	if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
243*32Sbill 		if ((bp = cfreelist) == NULL)
244*32Sbill 			goto out;
245*32Sbill 		cfreelist = bp->c_next;
246*32Sbill 		bp->c_next = NULL;
247*32Sbill 		q->c_cf = cq = bp->c_info;
248*32Sbill 	}
249*32Sbill 
250*32Sbill 	while (cc) {
251*32Sbill 		if (((int)cq & CROUND) == 0) {
252*32Sbill 			bp = (struct cblock *) cq - 1;
253*32Sbill 			if ((bp->c_next = cfreelist) == NULL)
254*32Sbill 				goto out;
255*32Sbill 			bp = bp->c_next;
256*32Sbill 			cfreelist = bp->c_next;
257*32Sbill 			bp->c_next = NULL;
258*32Sbill 			cq = bp->c_info;
259*32Sbill 		}
260*32Sbill 		*cq++ = *cp++;
261*32Sbill 		cc--;
262*32Sbill 	}
263*32Sbill out:
264*32Sbill 	q->c_cl = cq;
265*32Sbill 	q->c_cc += acc-cc;
266*32Sbill 	splx(s);
267*32Sbill 	return(cc);
268*32Sbill }
269*32Sbill 
270*32Sbill /*
271*32Sbill  * Initialize clist by freeing all character blocks, then count
272*32Sbill  * number of character devices. (Once-only routine)
273*32Sbill  */
274*32Sbill cinit()
275*32Sbill {
276*32Sbill 	register int ccp;
277*32Sbill 	register struct cblock *cp;
278*32Sbill 	register struct cdevsw *cdp;
279*32Sbill 
280*32Sbill 	ccp = (int)cfree;
281*32Sbill 	ccp = (ccp+CROUND) & ~CROUND;
282*32Sbill 	for(cp=(struct cblock *)ccp; cp <= &cfree[NCLIST-1]; cp++) {
283*32Sbill 		cp->c_next = cfreelist;
284*32Sbill 		cfreelist = cp;
285*32Sbill 	}
286*32Sbill 	ccp = 0;
287*32Sbill 	for(cdp = cdevsw; cdp->d_open; cdp++)
288*32Sbill 		ccp++;
289*32Sbill 	nchrdev = ccp;
290*32Sbill }
291*32Sbill 
292*32Sbill /*
293*32Sbill  * integer (2-byte) get/put
294*32Sbill  * using clists
295*32Sbill  */
296*32Sbill /*
297*32Sbill getw(p)
298*32Sbill register struct clist *p;
299*32Sbill {
300*32Sbill 	register int s;
301*32Sbill 
302*32Sbill 	if (p->c_cc <= 1)
303*32Sbill 		return(-1);
304*32Sbill 	s = getc(p);
305*32Sbill 	return(s | (getc(p)<<8));
306*32Sbill }
307*32Sbill */
308*32Sbill 
309*32Sbill putw(c, p)
310*32Sbill register struct clist *p;
311*32Sbill {
312*32Sbill 	register s;
313*32Sbill 
314*32Sbill 	s = spl6();
315*32Sbill 	if (cfreelist==NULL) {
316*32Sbill 		splx(s);
317*32Sbill 		return(-1);
318*32Sbill 	}
319*32Sbill 	VOID putc(c, p);
320*32Sbill 	VOID putc(c>>8, p);
321*32Sbill 	splx(s);
322*32Sbill 	return(0);
323*32Sbill }
324