VOID=>void
[unix-history] / usr / src / sys / kern / tty_subr.c
CommitLineData
81263dba 1/* tty_subr.c 3.2 %H% */
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];
15struct cblock *cfreelist;
16
17/*
18 * Character list get/put
19 */
20getc(p)
21register struct clist *p;
22{
23 register struct cblock *bp;
24 register int c, s;
25
26 s = spl6();
27 if (p->c_cc <= 0) {
28 c = -1;
29 p->c_cc = 0;
30 p->c_cf = p->c_cl = NULL;
31 } else {
32 c = *p->c_cf++ & 0377;
33 if (--p->c_cc<=0) {
34 bp = (struct cblock *)(p->c_cf-1);
35 bp = (struct cblock *) ((int)bp & ~CROUND);
36 p->c_cf = NULL;
37 p->c_cl = NULL;
38 bp->c_next = cfreelist;
39 cfreelist = bp;
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 }
47 }
48 splx(s);
49 return(c);
50}
51
52/*
53 * copy clist to buffer.
54 * return number of bytes moved.
55 */
56q_to_b(q, cp, cc)
57register struct clist *q;
58register char *cp;
59{
60 register struct cblock *bp;
61 register int s;
62 char *acp;
63
64 if (cc <= 0)
65 return(0);
66 s = spl6();
67 if (q->c_cc <= 0) {
68 q->c_cc = 0;
69 q->c_cf = q->c_cl = NULL;
70 return(0);
71 }
72 acp = cp;
73 cc++;
74
75 while (--cc) {
76 *cp++ = *q->c_cf++;
77 if (--q->c_cc <= 0) {
78 bp = (struct cblock *)(q->c_cf-1);
79 bp = (struct cblock *)((int)bp & ~CROUND);
80 q->c_cf = q->c_cl = NULL;
81 bp->c_next = cfreelist;
82 cfreelist = bp;
83 break;
84 }
85 if (((int)q->c_cf & CROUND) == 0) {
86 bp = (struct cblock *)(q->c_cf);
87 bp--;
88 q->c_cf = bp->c_next->c_info;
89 bp->c_next = cfreelist;
90 cfreelist = bp;
91 }
92 }
93 splx(s);
94 return(cp-acp);
95}
96
97
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
137
138
139/*
140 * Update clist to show that cc characters
141 * were removed. It is assumed that cc < CBSIZE.
142 */
143ndflush(q, cc)
144register struct clist *q;
145register cc;
146{
147register s;
148
149 if (cc == 0)
150 return;
151 s = spl6();
152 if (q->c_cc < 0) {
153 if (q->c_cf != NULL) {
154 q->c_cc += cc;
155 q->c_cf += cc;
156 goto out;
157 }
158 q->c_cc = 0;
159 goto out;
160 }
161 if (q->c_cc == 0) {
162 goto out;
163 }
164 q->c_cc -= cc;
165 q->c_cf += cc;
166 if (((int)q->c_cf & CROUND) == 0) {
167 register struct cblock *bp;
168
169 bp = (struct cblock *)(q->c_cf) -1;
170 if (bp->c_next) {
171 q->c_cf = bp->c_next->c_info;
172 } else {
173 q->c_cf = q->c_cl = NULL;
174 }
175 bp->c_next = cfreelist;
176 cfreelist = bp;
177 } else
178 if (q->c_cc == 0) {
179 register struct cblock *bp;
180 q->c_cf = (char *)((int)q->c_cf & ~CROUND);
181 bp = (struct cblock *)(q->c_cf);
182 bp->c_next = cfreelist;
183 cfreelist = bp;
184 q->c_cf = q->c_cl = NULL;
185 }
186out:
187 splx(s);
188}
189putc(c, p)
190register struct clist *p;
191{
192 register struct cblock *bp;
193 register char *cp;
194 register s;
195
196 s = spl6();
197 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
198 if ((bp = cfreelist) == NULL) {
199 splx(s);
200 return(-1);
201 }
202 cfreelist = bp->c_next;
203 bp->c_next = NULL;
204 p->c_cf = cp = bp->c_info;
205 } else if (((int)cp & CROUND) == 0) {
206 bp = (struct cblock *)cp - 1;
207 if ((bp->c_next = cfreelist) == NULL) {
208 splx(s);
209 return(-1);
210 }
211 bp = bp->c_next;
212 cfreelist = bp->c_next;
213 bp->c_next = NULL;
214 cp = bp->c_info;
215 }
216 *cp++ = c;
217 p->c_cc++;
218 p->c_cl = cp;
219 splx(s);
220 return(0);
221}
222
223
224
225/*
226 * copy buffer to clist.
227 * return number of bytes not transfered.
228 */
229b_to_q(cp, cc, q)
230register char *cp;
231struct clist *q;
232register int cc;
233{
234 register char *cq;
235 register struct cblock *bp;
236 register s, acc;
237
238 if (cc <= 0)
239 return(0);
240 acc = cc;
241 s = spl6();
242 if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
243 if ((bp = cfreelist) == NULL)
244 goto out;
245 cfreelist = bp->c_next;
246 bp->c_next = NULL;
247 q->c_cf = cq = bp->c_info;
248 }
249
250 while (cc) {
251 if (((int)cq & CROUND) == 0) {
252 bp = (struct cblock *) cq - 1;
253 if ((bp->c_next = cfreelist) == NULL)
254 goto out;
255 bp = bp->c_next;
256 cfreelist = bp->c_next;
257 bp->c_next = NULL;
258 cq = bp->c_info;
259 }
260 *cq++ = *cp++;
261 cc--;
262 }
263out:
264 q->c_cl = cq;
265 q->c_cc += acc-cc;
266 splx(s);
267 return(cc);
268}
269
270/*
271 * Initialize clist by freeing all character blocks, then count
272 * number of character devices. (Once-only routine)
273 */
274cinit()
275{
276 register int ccp;
277 register struct cblock *cp;
278 register struct cdevsw *cdp;
279
280 ccp = (int)cfree;
281 ccp = (ccp+CROUND) & ~CROUND;
282 for(cp=(struct cblock *)ccp; cp <= &cfree[NCLIST-1]; cp++) {
283 cp->c_next = cfreelist;
284 cfreelist = cp;
285 }
286 ccp = 0;
287 for(cdp = cdevsw; cdp->d_open; cdp++)
288 ccp++;
289 nchrdev = ccp;
290}
291
292/*
293 * integer (2-byte) get/put
294 * using clists
295 */
296/*
297getw(p)
298register struct clist *p;
299{
300 register int s;
301
302 if (p->c_cc <= 1)
303 return(-1);
304 s = getc(p);
305 return(s | (getc(p)<<8));
306}
307*/
308
309putw(c, p)
310register struct clist *p;
311{
312 register s;
313
314 s = spl6();
315 if (cfreelist==NULL) {
316 splx(s);
317 return(-1);
318 }
81263dba
BJ
319 (void) putc(c, p);
320 (void) putc(c>>8, p);
11bd398c
BJ
321 splx(s);
322 return(0);
323}