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