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