generalize uba code to handle Q bus more gracefully
[unix-history] / usr / src / sys / kern / tty_subr.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
0880b18e 6 * @(#)tty_subr.c 7.1 (Berkeley) %G%
da7c5cc6 7 */
8f6119af 8
94368568
JB
9#include "param.h"
10#include "systm.h"
94368568 11#include "buf.h"
3358b36b 12#include "ioctl.h"
94368568
JB
13#include "tty.h"
14#include "clist.h"
11bd398c 15
48575cec 16char cwaiting;
11bd398c
BJ
17
18/*
19 * Character list get/put
20 */
21getc(p)
88a7a62a 22 register struct clist *p;
11bd398c
BJ
23{
24 register struct cblock *bp;
25 register int c, s;
26
a8170d5d 27 s = spltty();
11bd398c
BJ
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);
01b0e233 36 bp = (struct cblock *)((int)bp & ~CROUND);
11bd398c
BJ
37 p->c_cf = NULL;
38 p->c_cl = NULL;
39 bp->c_next = cfreelist;
40 cfreelist = bp;
48575cec
BJ
41 cfreecount += CBSIZE;
42 if (cwaiting) {
43 wakeup(&cwaiting);
44 cwaiting = 0;
45 }
11bd398c
BJ
46 } else if (((int)p->c_cf & CROUND) == 0){
47 bp = (struct cblock *)(p->c_cf);
48 bp--;
49 p->c_cf = bp->c_next->c_info;
50 bp->c_next = cfreelist;
51 cfreelist = bp;
48575cec
BJ
52 cfreecount += CBSIZE;
53 if (cwaiting) {
54 wakeup(&cwaiting);
55 cwaiting = 0;
56 }
11bd398c
BJ
57 }
58 }
59 splx(s);
01b0e233 60 return (c);
11bd398c
BJ
61}
62
63/*
64 * copy clist to buffer.
65 * return number of bytes moved.
66 */
67q_to_b(q, cp, cc)
961945a8
SL
68 register struct clist *q;
69 register char *cp;
11bd398c
BJ
70{
71 register struct cblock *bp;
72 register int s;
a8170d5d 73 register nc;
11bd398c
BJ
74 char *acp;
75
76 if (cc <= 0)
01b0e233 77 return (0);
a8170d5d 78 s = spltty();
11bd398c
BJ
79 if (q->c_cc <= 0) {
80 q->c_cc = 0;
81 q->c_cf = q->c_cl = NULL;
48575cec 82 splx(s);
01b0e233 83 return (0);
11bd398c
BJ
84 }
85 acp = cp;
11bd398c 86
a8170d5d 87 while (cc) {
01b0e233 88 nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND);
a8170d5d
MK
89 nc = MIN(nc, cc);
90 nc = MIN(nc, q->c_cc);
91 (void) bcopy(q->c_cf, cp, (unsigned)nc);
92 q->c_cf += nc;
93 q->c_cc -= nc;
94 cc -= nc;
95 cp += nc;
96 if (q->c_cc <= 0) {
97 bp = (struct cblock *)(q->c_cf - 1);
11bd398c
BJ
98 bp = (struct cblock *)((int)bp & ~CROUND);
99 q->c_cf = q->c_cl = NULL;
100 bp->c_next = cfreelist;
101 cfreelist = bp;
48575cec
BJ
102 cfreecount += CBSIZE;
103 if (cwaiting) {
104 wakeup(&cwaiting);
105 cwaiting = 0;
106 }
11bd398c
BJ
107 break;
108 }
109 if (((int)q->c_cf & CROUND) == 0) {
110 bp = (struct cblock *)(q->c_cf);
111 bp--;
112 q->c_cf = bp->c_next->c_info;
113 bp->c_next = cfreelist;
114 cfreelist = bp;
48575cec
BJ
115 cfreecount += CBSIZE;
116 if (cwaiting) {
117 wakeup(&cwaiting);
118 cwaiting = 0;
119 }
11bd398c
BJ
120 }
121 }
122 splx(s);
01b0e233 123 return (cp-acp);
11bd398c
BJ
124}
125
11bd398c
BJ
126/*
127 * Return count of contiguous characters
128 * in clist starting at q->c_cf.
129 * Stop counting if flag&character is non-null.
130 */
131ndqb(q, flag)
961945a8 132 register struct clist *q;
11bd398c 133{
961945a8
SL
134 register cc;
135 int s;
11bd398c 136
a8170d5d 137 s = spltty();
11bd398c
BJ
138 if (q->c_cc <= 0) {
139 cc = -q->c_cc;
140 goto out;
141 }
142 cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
143 cc -= (int)q->c_cf;
144 if (q->c_cc < cc)
145 cc = q->c_cc;
146 if (flag) {
147 register char *p, *end;
148
149 p = q->c_cf;
150 end = p;
151 end += cc;
152 while (p < end) {
153 if (*p & flag) {
48575cec
BJ
154 cc = (int)p;
155 cc -= (int)q->c_cf;
11bd398c
BJ
156 break;
157 }
158 p++;
159 }
160 }
161out:
162 splx(s);
01b0e233 163 return (cc);
11bd398c
BJ
164}
165
11bd398c 166/*
48575cec 167 * Flush cc bytes from q.
11bd398c
BJ
168 */
169ndflush(q, cc)
88a7a62a
SL
170 register struct clist *q;
171 register cc;
11bd398c 172{
88a7a62a
SL
173 register struct cblock *bp;
174 char *end;
175 int rem, s;
11bd398c 176
a8170d5d 177 s = spltty();
01b0e233 178 if (q->c_cc <= 0)
11bd398c 179 goto out;
48575cec
BJ
180 while (cc>0 && q->c_cc) {
181 bp = (struct cblock *)((int)q->c_cf & ~CROUND);
182 if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
183 end = q->c_cl;
184 } else {
185 end = (char *)((int)bp + sizeof (struct cblock));
186 }
187 rem = end - q->c_cf;
188 if (cc >= rem) {
189 cc -= rem;
190 q->c_cc -= rem;
11bd398c 191 q->c_cf = bp->c_next->c_info;
48575cec
BJ
192 bp->c_next = cfreelist;
193 cfreelist = bp;
194 cfreecount += CBSIZE;
195 if (cwaiting) {
196 wakeup(&cwaiting);
197 cwaiting = 0;
198 }
11bd398c 199 } else {
48575cec
BJ
200 q->c_cc -= cc;
201 q->c_cf += cc;
202 if (q->c_cc <= 0) {
203 bp->c_next = cfreelist;
204 cfreelist = bp;
205 cfreecount += CBSIZE;
206 if (cwaiting) {
207 wakeup(&cwaiting);
208 cwaiting = 0;
209 }
210 }
211 break;
11bd398c 212 }
48575cec
BJ
213 }
214 if (q->c_cc <= 0) {
11bd398c 215 q->c_cf = q->c_cl = NULL;
48575cec 216 q->c_cc = 0;
11bd398c
BJ
217 }
218out:
219 splx(s);
220}
b8f09f36 221
48575cec 222
11bd398c 223putc(c, p)
88a7a62a 224 register struct clist *p;
11bd398c
BJ
225{
226 register struct cblock *bp;
227 register char *cp;
228 register s;
229
a8170d5d 230 s = spltty();
11bd398c
BJ
231 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
232 if ((bp = cfreelist) == NULL) {
233 splx(s);
01b0e233 234 return (-1);
11bd398c
BJ
235 }
236 cfreelist = bp->c_next;
48575cec 237 cfreecount -= CBSIZE;
11bd398c
BJ
238 bp->c_next = NULL;
239 p->c_cf = cp = bp->c_info;
240 } else if (((int)cp & CROUND) == 0) {
241 bp = (struct cblock *)cp - 1;
242 if ((bp->c_next = cfreelist) == NULL) {
243 splx(s);
01b0e233 244 return (-1);
11bd398c
BJ
245 }
246 bp = bp->c_next;
247 cfreelist = bp->c_next;
48575cec 248 cfreecount -= CBSIZE;
11bd398c
BJ
249 bp->c_next = NULL;
250 cp = bp->c_info;
251 }
252 *cp++ = c;
253 p->c_cc++;
254 p->c_cl = cp;
255 splx(s);
01b0e233 256 return (0);
11bd398c
BJ
257}
258
11bd398c
BJ
259/*
260 * copy buffer to clist.
261 * return number of bytes not transfered.
262 */
263b_to_q(cp, cc, q)
88a7a62a
SL
264 register char *cp;
265 struct clist *q;
266 register int cc;
11bd398c
BJ
267{
268 register char *cq;
269 register struct cblock *bp;
a8170d5d
MK
270 register s, nc;
271 int acc;
11bd398c
BJ
272
273 if (cc <= 0)
01b0e233 274 return (0);
a8170d5d
MK
275 acc = cc;
276 s = spltty();
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) {
11bd398c 287 if (((int)cq & CROUND) == 0) {
01b0e233 288 bp = (struct cblock *)cq - 1;
a8170d5d
MK
289 if ((bp->c_next = cfreelist) == NULL)
290 goto out;
11bd398c
BJ
291 bp = bp->c_next;
292 cfreelist = bp->c_next;
48575cec 293 cfreecount -= CBSIZE;
11bd398c 294 bp->c_next = NULL;
a8170d5d 295 cq = bp->c_info;
11bd398c 296 }
01b0e233 297 nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND));
a8170d5d
MK
298 (void) bcopy(cp, cq, (unsigned)nc);
299 cp += nc;
300 cq += nc;
301 cc -= nc;
11bd398c 302 }
a8170d5d
MK
303out:
304 q->c_cl = cq;
305 q->c_cc += acc - cc;
306 splx(s);
42cc3b3d 307 return (cc);
11bd398c
BJ
308}
309
b8f09f36
BJ
310/*
311 * Given a non-NULL pointter into the list (like c_cf which
312 * always points to a real character if non-NULL) return the pointer
313 * to the next character in the list or return NULL if no more chars.
314 *
315 * Callers must not allow getc's to happen between nextc's so that the
316 * pointer becomes invalid. Note that interrupts are NOT masked.
317 */
318char *
319nextc(p, cp)
88a7a62a
SL
320 register struct clist *p;
321 register char *cp;
b8f09f36
BJ
322{
323
324 if (p->c_cc && ++cp != p->c_cl) {
325 if (((int)cp & CROUND) == 0)
326 return (((struct cblock *)cp)[-1].c_next->c_info);
327 return (cp);
328 }
329 return (0);
330}
331
332/*
333 * Remove the last character in the list and return it.
334 */
335unputc(p)
88a7a62a 336 register struct clist *p;
b8f09f36
BJ
337{
338 register struct cblock *bp;
339 register int c, s;
340 struct cblock *obp;
341
a8170d5d 342 s = spltty();
b8f09f36
BJ
343 if (p->c_cc <= 0)
344 c = -1;
345 else {
346 c = *--p->c_cl;
347 if (--p->c_cc <= 0) {
348 bp = (struct cblock *)p->c_cl;
349 bp = (struct cblock *)((int)bp & ~CROUND);
350 p->c_cl = p->c_cf = NULL;
351 bp->c_next = cfreelist;
352 cfreelist = bp;
48575cec 353 cfreecount += CBSIZE;
b8f09f36
BJ
354 } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
355 p->c_cl = (char *)((int)p->c_cl & ~CROUND);
356 bp = (struct cblock *)p->c_cf;
357 bp = (struct cblock *)((int)bp & ~CROUND);
358 while (bp->c_next != (struct cblock *)p->c_cl)
359 bp = bp->c_next;
360 obp = bp;
361 p->c_cl = (char *)(bp + 1);
362 bp = bp->c_next;
363 bp->c_next = cfreelist;
364 cfreelist = bp;
48575cec 365 cfreecount += CBSIZE;
b8f09f36
BJ
366 obp->c_next = NULL;
367 }
368 }
369 splx(s);
370 return (c);
371}
372
373/*
374 * Put the chars in the from que
375 * on the end of the to que.
b8f09f36
BJ
376 */
377catq(from, to)
88a7a62a 378 struct clist *from, *to;
b8f09f36 379{
a8170d5d
MK
380 char bbuf[CBSIZE*4];
381 register s, c;
382
383 s = spltty();
384 if (to->c_cc == 0) {
385 *to = *from;
386 from->c_cc = 0;
387 from->c_cf = NULL;
388 from->c_cl = NULL;
389 splx(s);
390 return;
391 }
392 splx(s);
393 while (from->c_cc > 0) {
394 c = q_to_b(from, bbuf, sizeof bbuf);
395 (void) b_to_q(bbuf, c, to);
396 }
b8f09f36
BJ
397}
398
a8170d5d 399#ifdef unneeded
11bd398c 400/*
01b0e233
MK
401 * Integer (short) get/put using clists.
402 * Note dependency on byte order.
11bd398c 403 */
a8170d5d 404typedef u_short word_t;
961945a8 405
11bd398c 406getw(p)
d0b37068 407 register struct clist *p;
11bd398c 408{
a8170d5d
MK
409 register int s, c;
410 register struct cblock *bp;
411
412 if (p->c_cc <= 1)
413 return(-1);
414 if (p->c_cc & 01) {
415 c = getc(p);
01b0e233
MK
416#if defined(vax)
417 return (c | (getc(p)<<8));
418#else
419 return (getc(p) | (c<<8));
420#endif
a8170d5d
MK
421 }
422 s = spltty();
01b0e233 423#if defined(vax)
a8170d5d 424 c = *((word_t *)p->c_cf);
01b0e233
MK
425#else
426 c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0];
427#endif
428 p->c_cf += sizeof (word_t);
429 p->c_cc -= sizeof (word_t);
a8170d5d
MK
430 if (p->c_cc <= 0) {
431 bp = (struct cblock *)(p->c_cf-1);
01b0e233 432 bp = (struct cblock *)((int)bp & ~CROUND);
a8170d5d
MK
433 p->c_cf = NULL;
434 p->c_cl = NULL;
435 bp->c_next = cfreelist;
436 cfreelist = bp;
437 cfreecount += CBSIZE;
438 if (cwaiting) {
439 wakeup(&cwaiting);
440 cwaiting = 0;
441 }
442 } else if (((int)p->c_cf & CROUND) == 0) {
443 bp = (struct cblock *)(p->c_cf);
444 bp--;
445 p->c_cf = bp->c_next->c_info;
446 bp->c_next = cfreelist;
447 cfreelist = bp;
448 cfreecount += CBSIZE;
449 if (cwaiting) {
450 wakeup(&cwaiting);
451 cwaiting = 0;
452 }
453 }
454 splx(s);
455 return (c);
11bd398c 456}
48575cec 457
11bd398c 458putw(c, p)
d0b37068 459 register struct clist *p;
a8170d5d 460 word_t c;
11bd398c
BJ
461{
462 register s;
a8170d5d
MK
463 register struct cblock *bp;
464 register char *cp;
11bd398c 465
a8170d5d 466 s = spltty();
11bd398c
BJ
467 if (cfreelist==NULL) {
468 splx(s);
469 return(-1);
470 }
a8170d5d 471 if (p->c_cc & 01) {
01b0e233 472#if defined(vax)
a8170d5d
MK
473 (void) putc(c, p);
474 (void) putc(c>>8, p);
01b0e233
MK
475#else
476 (void) putc(c>>8, p);
477 (void) putc(c, p);
478#endif
a8170d5d
MK
479 } else {
480 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
481 if ((bp = cfreelist) == NULL) {
482 splx(s);
483 return (-1);
484 }
485 cfreelist = bp->c_next;
486 cfreecount -= CBSIZE;
487 bp->c_next = NULL;
488 p->c_cf = cp = bp->c_info;
489 } else if (((int)cp & CROUND) == 0) {
490 bp = (struct cblock *)cp - 1;
491 if ((bp->c_next = cfreelist) == NULL) {
492 splx(s);
493 return (-1);
494 }
495 bp = bp->c_next;
496 cfreelist = bp->c_next;
497 cfreecount -= CBSIZE;
498 bp->c_next = NULL;
499 cp = bp->c_info;
500 }
01b0e233 501#if defined(vax)
a8170d5d 502 *(word_t *)cp = c;
01b0e233
MK
503#else
504 ((u_char *)cp)[0] = c>>8;
505 ((u_char *)cp)[1] = c;
506#endif
507 p->c_cl = cp + sizeof (word_t);
508 p->c_cc += sizeof (word_t);
a8170d5d 509 }
11bd398c 510 splx(s);
961945a8 511 return (0);
11bd398c 512}
a8170d5d 513#endif unneeded