xref: /original-bsd/sys/kern/tty_subr.c (revision 6c57d260)
1 /*	tty_subr.c	4.11	81/04/17	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/conf.h"
6 #include "../h/buf.h"
7 #include "../h/tty.h"
8 #include "../h/clist.h"
9 
10 char	cwaiting;
11 
12 /*
13  * Character list get/put
14  */
15 getc(p)
16 register struct clist *p;
17 {
18 	register struct cblock *bp;
19 	register int c, s;
20 
21 	s = spl5();
22 	if (p->c_cc <= 0) {
23 		c = -1;
24 		p->c_cc = 0;
25 		p->c_cf = p->c_cl = NULL;
26 	} else {
27 		c = *p->c_cf++ & 0377;
28 		if (--p->c_cc<=0) {
29 			bp = (struct cblock *)(p->c_cf-1);
30 			bp = (struct cblock *) ((int)bp & ~CROUND);
31 			p->c_cf = NULL;
32 			p->c_cl = NULL;
33 			bp->c_next = cfreelist;
34 			cfreelist = bp;
35 			cfreecount += CBSIZE;
36 			if (cwaiting) {
37 				wakeup(&cwaiting);
38 				cwaiting = 0;
39 			}
40 		} else if (((int)p->c_cf & CROUND) == 0){
41 			bp = (struct cblock *)(p->c_cf);
42 			bp--;
43 			p->c_cf = bp->c_next->c_info;
44 			bp->c_next = cfreelist;
45 			cfreelist = bp;
46 			cfreecount += CBSIZE;
47 			if (cwaiting) {
48 				wakeup(&cwaiting);
49 				cwaiting = 0;
50 			}
51 		}
52 	}
53 	splx(s);
54 	return(c);
55 }
56 
57 /*
58  * copy clist to buffer.
59  * return number of bytes moved.
60  */
61 q_to_b(q, cp, cc)
62 register struct clist *q;
63 register char *cp;
64 {
65 	register struct cblock *bp;
66 	register int s;
67 	char *acp;
68 
69 	if (cc <= 0)
70 		return(0);
71 	s = spl5();
72 	if (q->c_cc <= 0) {
73 		q->c_cc = 0;
74 		q->c_cf = q->c_cl = NULL;
75 		splx(s);
76 		return(0);
77 	}
78 	acp = cp;
79 	cc++;
80 
81 	while (--cc) {
82 		*cp++ = *q->c_cf++;
83 		if (--q->c_cc <= 0) {
84 			bp = (struct cblock *)(q->c_cf-1);
85 			bp = (struct cblock *)((int)bp & ~CROUND);
86 			q->c_cf = q->c_cl = NULL;
87 			bp->c_next = cfreelist;
88 			cfreelist = bp;
89 			cfreecount += CBSIZE;
90 			if (cwaiting) {
91 				wakeup(&cwaiting);
92 				cwaiting = 0;
93 			}
94 			break;
95 		}
96 		if (((int)q->c_cf & CROUND) == 0) {
97 			bp = (struct cblock *)(q->c_cf);
98 			bp--;
99 			q->c_cf = bp->c_next->c_info;
100 			bp->c_next = cfreelist;
101 			cfreelist = bp;
102 			cfreecount += CBSIZE;
103 			if (cwaiting) {
104 				wakeup(&cwaiting);
105 				cwaiting = 0;
106 			}
107 		}
108 	}
109 	splx(s);
110 	return(cp-acp);
111 }
112 
113 /*
114  * Return count of contiguous characters
115  * in clist starting at q->c_cf.
116  * Stop counting if flag&character is non-null.
117  */
118 ndqb(q, flag)
119 register struct clist *q;
120 {
121 register cc;
122 int s;
123 
124 	s = spl5();
125 	if (q->c_cc <= 0) {
126 		cc = -q->c_cc;
127 		goto out;
128 	}
129 	cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
130 	cc -= (int)q->c_cf;
131 	if (q->c_cc < cc)
132 		cc = q->c_cc;
133 	if (flag) {
134 		register char *p, *end;
135 
136 		p = q->c_cf;
137 		end = p;
138 		end += cc;
139 		while (p < end) {
140 			if (*p & flag) {
141 				cc = (int)p;
142 				cc -= (int)q->c_cf;
143 				break;
144 			}
145 			p++;
146 		}
147 	}
148 out:
149 	splx(s);
150 	return(cc);
151 }
152 
153 
154 
155 /*
156  * Flush cc bytes from q.
157  */
158 ndflush(q, cc)
159 register struct clist *q;
160 register cc;
161 {
162 register struct cblock *bp;
163 char *end;
164 int rem;
165 register s;
166 
167 	s = spl5();
168 	if (q->c_cc < 0) {
169 		printf("neg q flush\n");
170 		goto out;
171 	}
172 	if (q->c_cc == 0) {
173 		goto out;
174 	}
175 	while (cc>0 && q->c_cc) {
176 		bp = (struct cblock *)((int)q->c_cf & ~CROUND);
177 		if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
178 			end = q->c_cl;
179 		} else {
180 			end = (char *)((int)bp + sizeof (struct cblock));
181 		}
182 		rem = end - q->c_cf;
183 		if (cc >= rem) {
184 			cc -= rem;
185 			q->c_cc -= rem;
186 			q->c_cf = bp->c_next->c_info;
187 			bp->c_next = cfreelist;
188 			cfreelist = bp;
189 			cfreecount += CBSIZE;
190 			if (cwaiting) {
191 				wakeup(&cwaiting);
192 				cwaiting = 0;
193 			}
194 		} else {
195 			q->c_cc -= cc;
196 			q->c_cf += cc;
197 			if (q->c_cc <= 0) {
198 				bp->c_next = cfreelist;
199 				cfreelist = bp;
200 				cfreecount += CBSIZE;
201 				if (cwaiting) {
202 					wakeup(&cwaiting);
203 					cwaiting = 0;
204 				}
205 			}
206 			break;
207 		}
208 	}
209 	if (q->c_cc <= 0) {
210 		q->c_cf = q->c_cl = NULL;
211 		q->c_cc = 0;
212 	}
213 out:
214 	splx(s);
215 }
216 
217 
218 putc(c, p)
219 register struct clist *p;
220 {
221 	register struct cblock *bp;
222 	register char *cp;
223 	register s;
224 
225 	s = spl5();
226 	if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
227 		if ((bp = cfreelist) == NULL) {
228 			splx(s);
229 			return(-1);
230 		}
231 		cfreelist = bp->c_next;
232 		cfreecount -= CBSIZE;
233 		bp->c_next = NULL;
234 		p->c_cf = cp = bp->c_info;
235 	} else if (((int)cp & CROUND) == 0) {
236 		bp = (struct cblock *)cp - 1;
237 		if ((bp->c_next = cfreelist) == NULL) {
238 			splx(s);
239 			return(-1);
240 		}
241 		bp = bp->c_next;
242 		cfreelist = bp->c_next;
243 		cfreecount -= CBSIZE;
244 		bp->c_next = NULL;
245 		cp = bp->c_info;
246 	}
247 	*cp++ = c;
248 	p->c_cc++;
249 	p->c_cl = cp;
250 	splx(s);
251 	return(0);
252 }
253 
254 
255 
256 /*
257  * copy buffer to clist.
258  * return number of bytes not transfered.
259  */
260 b_to_q(cp, cc, q)
261 register char *cp;
262 struct clist *q;
263 register int cc;
264 {
265 	register char *cq;
266 	register struct cblock *bp;
267 	register s, acc;
268 
269 	if (cc <= 0)
270 		return(0);
271 	acc = cc;
272 
273 
274 	s = spl5();
275 	if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
276 		if ((bp = cfreelist) == NULL)
277 			goto out;
278 		cfreelist = bp->c_next;
279 		cfreecount -= CBSIZE;
280 		bp->c_next = NULL;
281 		q->c_cf = cq = bp->c_info;
282 	}
283 
284 	while (cc) {
285 		if (((int)cq & CROUND) == 0) {
286 			bp = (struct cblock *) cq - 1;
287 			if ((bp->c_next = cfreelist) == NULL)
288 				goto out;
289 			bp = bp->c_next;
290 			cfreelist = bp->c_next;
291 			cfreecount -= CBSIZE;
292 			bp->c_next = NULL;
293 			cq = bp->c_info;
294 		}
295 		*cq++ = *cp++;
296 		cc--;
297 	}
298 out:
299 	q->c_cl = cq;
300 	q->c_cc += acc-cc;
301 	splx(s);
302 	return(cc);
303 }
304 
305 /*
306  * Given a non-NULL pointter into the list (like c_cf which
307  * always points to a real character if non-NULL) return the pointer
308  * to the next character in the list or return NULL if no more chars.
309  *
310  * Callers must not allow getc's to happen between nextc's so that the
311  * pointer becomes invalid.  Note that interrupts are NOT masked.
312  */
313 char *
314 nextc(p, cp)
315 register struct clist *p;
316 register char *cp;
317 {
318 
319 	if (p->c_cc && ++cp != p->c_cl) {
320 		if (((int)cp & CROUND) == 0)
321 			return (((struct cblock *)cp)[-1].c_next->c_info);
322 		return (cp);
323 	}
324 	return (0);
325 }
326 
327 /*
328  * Remove the last character in the list and return it.
329  */
330 unputc(p)
331 register struct clist *p;
332 {
333 	register struct cblock *bp;
334 	register int c, s;
335 	struct cblock *obp;
336 
337 	s = spl5();
338 	if (p->c_cc <= 0)
339 		c = -1;
340 	else {
341 		c = *--p->c_cl;
342 		if (--p->c_cc <= 0) {
343 			bp = (struct cblock *)p->c_cl;
344 			bp = (struct cblock *)((int)bp & ~CROUND);
345 			p->c_cl = p->c_cf = NULL;
346 			bp->c_next = cfreelist;
347 			cfreelist = bp;
348 			cfreecount += CBSIZE;
349 		} else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
350 			p->c_cl = (char *)((int)p->c_cl & ~CROUND);
351 			bp = (struct cblock *)p->c_cf;
352 			bp = (struct cblock *)((int)bp & ~CROUND);
353 			while (bp->c_next != (struct cblock *)p->c_cl)
354 				bp = bp->c_next;
355 			obp = bp;
356 			p->c_cl = (char *)(bp + 1);
357 			bp = bp->c_next;
358 			bp->c_next = cfreelist;
359 			cfreelist = bp;
360 			cfreecount += CBSIZE;
361 			obp->c_next = NULL;
362 		}
363 	}
364 	splx(s);
365 	return (c);
366 }
367 
368 /*
369  * Put the chars in the from que
370  * on the end of the to que.
371  *
372  * SHOULD JUST USE q_to_b AND THEN b_to_q HERE.
373  */
374 catq(from, to)
375 struct clist *from, *to;
376 {
377 	register c;
378 
379 	while ((c = getc(from)) >= 0)
380 		(void) putc(c, to);
381 }
382 
383 /*
384  * integer (2-byte) get/put
385  * using clists
386  */
387 #ifdef unneeded
388 getw(p)
389 register struct clist *p;
390 {
391 	register int s;
392 
393 	if (p->c_cc <= 1)
394 		return(-1);
395 	s = getc(p);
396 	return(s | (getc(p)<<8));
397 }
398 #endif
399 
400 putw(c, p)
401 register struct clist *p;
402 {
403 	register s;
404 
405 	s = spl5();
406 	if (cfreelist==NULL) {
407 		splx(s);
408 		return(-1);
409 	}
410 	(void) putc(c, p);
411 	(void) putc(c>>8, p);
412 	splx(s);
413 	return(0);
414 }
415