]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/tty_subr.c
xnu-792.18.15.tar.gz
[apple/xnu.git] / bsd / kern / tty_subr.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */
29/*
30 * Copyright (c) 1993, 1994 Theo de Raadt
31 * All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice unmodified, this list of conditions, and the following
38 * disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 *
55 */
56
57#ifdef NeXT
58/*
59 * We use the NetBSD based clist system, it is much more efficient than the
60 * old style clist stuff used by free bsd.
61 */
62
63#include <sys/param.h>
64#include <sys/systm.h>
1c79356b
A
65#include <sys/ioctl.h>
66#include <sys/tty.h>
67#include <sys/malloc.h>
68
69#include <machine/spl.h>
70
71/*
72 * At compile time, choose:
73 * There are two ways the TTY_QUOTE bit can be stored. If QBITS is
74 * defined we allocate an array of bits -- 1/8th as much memory but
75 * setbit(), clrbit(), and isset() take more cpu. If QBITS is
76 * undefined, we just use an array of bytes.
77 *
78 * If TTY_QUOTE functionality isn't required by a line discipline,
79 * it can free c_cq and set it to NULL. This speeds things up,
80 * and also does not use any extra memory. This is useful for (say)
81 * a SLIP line discipline that wants a 32K ring buffer for data
82 * but doesn't need quoting.
83 */
84#define QBITS
85
86#ifdef QBITS
87#define QMEM(n) ((((n)-1)/NBBY)+1)
88#else
89#define QMEM(n) (n)
90#endif
91
92
93/*
94 * Initialize clists.
95 */
96void
91447636 97cinit(void)
1c79356b
A
98{
99}
100
101/*
102 * Initialize a particular clist. Ok, they are really ring buffers,
103 * of the specified length, with/without quoting support.
104 */
105int
106clalloc(clp, size, quot)
107 struct clist *clp;
108 int size;
109 int quot;
110{
111
0b4e3aa0 112 MALLOC_ZONE(clp->c_cs, u_char *, size, M_TTYS, M_WAITOK);
1c79356b
A
113 if (!clp->c_cs)
114 return (-1);
115 bzero(clp->c_cs, size);
116
117 if(quot) {
0b4e3aa0 118 MALLOC_ZONE(clp->c_cq, u_char *, QMEM(size), M_TTYS, M_WAITOK);
1c79356b 119 if (!clp->c_cq) {
0b4e3aa0 120 FREE_ZONE(clp->c_cs, size, M_TTYS);
1c79356b
A
121 return (-1);
122 }
123 bzero(clp->c_cs, QMEM(size));
124 } else
125 clp->c_cq = (u_char *)0;
126
127 clp->c_cf = clp->c_cl = (u_char *)0;
128 clp->c_ce = clp->c_cs + size;
129 clp->c_cn = size;
130 clp->c_cc = 0;
131 return (0);
132}
133
134void
135clfree(clp)
136 struct clist *clp;
137{
138 if(clp->c_cs)
0b4e3aa0 139 FREE_ZONE(clp->c_cs, clp->c_cn, M_TTYS);
1c79356b 140 if(clp->c_cq)
0b4e3aa0 141 FREE_ZONE(clp->c_cq, QMEM(clp->c_cn), M_TTYS);
1c79356b
A
142 clp->c_cs = clp->c_cq = (u_char *)0;
143}
144
145
146/*
147 * Get a character from a clist.
148 */
149int
150getc(clp)
151 struct clist *clp;
152{
153 register int c = -1;
154 int s;
155
156 s = spltty();
157 if (clp->c_cc == 0)
158 goto out;
159
160 c = *clp->c_cf & 0xff;
161 if (clp->c_cq) {
162#ifdef QBITS
163 if (isset(clp->c_cq, clp->c_cf - clp->c_cs) )
164 c |= TTY_QUOTE;
165#else
166 if (*(clp->c_cf - clp->c_cs + clp->c_cq))
167 c |= TTY_QUOTE;
168#endif
169 }
170 if (++clp->c_cf == clp->c_ce)
171 clp->c_cf = clp->c_cs;
172 if (--clp->c_cc == 0)
173 clp->c_cf = clp->c_cl = (u_char *)0;
174out:
175 splx(s);
176 return c;
177}
178
179/*
180 * Copy clist to buffer.
181 * Return number of bytes moved.
182 */
183int
184q_to_b(clp, cp, count)
185 struct clist *clp;
186 u_char *cp;
187 int count;
188{
189 register int cc;
190 u_char *p = cp;
191 int s;
192
193 s = spltty();
194 /* optimize this while loop */
195 while (count > 0 && clp->c_cc > 0) {
196 cc = clp->c_cl - clp->c_cf;
197 if (clp->c_cf >= clp->c_cl)
198 cc = clp->c_ce - clp->c_cf;
199 if (cc > count)
200 cc = count;
201 bcopy(clp->c_cf, p, cc);
202 count -= cc;
203 p += cc;
204 clp->c_cc -= cc;
205 clp->c_cf += cc;
206 if (clp->c_cf == clp->c_ce)
207 clp->c_cf = clp->c_cs;
208 }
209 if (clp->c_cc == 0)
210 clp->c_cf = clp->c_cl = (u_char *)0;
211 splx(s);
212 return p - cp;
213}
214
215/*
216 * Return count of contiguous characters in clist.
217 * Stop counting if flag&character is non-null.
218 */
219int
220ndqb(clp, flag)
221 struct clist *clp;
222 int flag;
223{
224 int count = 0;
225 register int i;
226 register int cc;
227 int s;
228
229 s = spltty();
230 if ((cc = clp->c_cc) == 0)
231 goto out;
232
233 if (flag == 0) {
234 count = clp->c_cl - clp->c_cf;
235 if (count <= 0)
236 count = clp->c_ce - clp->c_cf;
237 goto out;
238 }
239
240 i = clp->c_cf - clp->c_cs;
241 if (flag & TTY_QUOTE) {
242 while (cc-- > 0 && !(clp->c_cs[i++] & (flag & ~TTY_QUOTE) ||
243 isset(clp->c_cq, i))) {
244 count++;
245 if (i == clp->c_cn)
246 break;
247 }
248 } else {
249 while (cc-- > 0 && !(clp->c_cs[i++] & flag)) {
250 count++;
251 if (i == clp->c_cn)
252 break;
253 }
254 }
255out:
256 splx(s);
257 return count;
258}
259
260/*
261 * Flush count bytes from clist.
262 */
263void
264ndflush(clp, count)
265 struct clist *clp;
266 int count;
267{
268 register int cc;
269 int s;
270
271 s = spltty();
272 if (count == clp->c_cc) {
273 clp->c_cc = 0;
274 clp->c_cf = clp->c_cl = (u_char *)0;
275 goto out;
276 }
277 /* optimize this while loop */
278 while (count > 0 && clp->c_cc > 0) {
279 cc = clp->c_cl - clp->c_cf;
280 if (clp->c_cf >= clp->c_cl)
281 cc = clp->c_ce - clp->c_cf;
282 if (cc > count)
283 cc = count;
284 count -= cc;
285 clp->c_cc -= cc;
286 clp->c_cf += cc;
287 if (clp->c_cf == clp->c_ce)
288 clp->c_cf = clp->c_cs;
289 }
290 if (clp->c_cc == 0)
291 clp->c_cf = clp->c_cl = (u_char *)0;
292out:
293 splx(s);
294}
295
296/*
297 * Put a character into the output queue.
298 */
299int
300putc(c, clp)
301 int c;
302 struct clist *clp;
303{
304 register int i;
305 int s;
306
307 s = spltty();
308 if (clp->c_cc == 0) {
309 if (!clp->c_cs) {
310#if DIAGNOSTIC
311 //printf("putc: required clalloc\n");
312#endif
313 if(clalloc(clp, 1024, 1)) {
314out:
315 splx(s);
316 return -1;
317 }
318 }
319 clp->c_cf = clp->c_cl = clp->c_cs;
320 }
321
322 if (clp->c_cc == clp->c_cn)
323 goto out;
324
325 *clp->c_cl = c & 0xff;
326 i = clp->c_cl - clp->c_cs;
327 if (clp->c_cq) {
328#ifdef QBITS
329 if (c & TTY_QUOTE)
330 setbit(clp->c_cq, i);
331 else
332 clrbit(clp->c_cq, i);
333#else
334 q = clp->c_cq + i;
335 *q = (c & TTY_QUOTE) ? 1 : 0;
336#endif
337 }
338 clp->c_cc++;
339 clp->c_cl++;
340 if (clp->c_cl == clp->c_ce)
341 clp->c_cl = clp->c_cs;
342 splx(s);
343 return 0;
344}
345
346#ifdef QBITS
347/*
348 * optimized version of
349 *
350 * for (i = 0; i < len; i++)
351 * clrbit(cp, off + len);
352 */
353void
91447636 354clrbits(u_char *cp, int off, int len)
1c79356b
A
355{
356 int sby, sbi, eby, ebi;
357 register int i;
358 u_char mask;
359
360 if(len==1) {
361 clrbit(cp, off);
362 return;
363 }
364
365 sby = off / NBBY;
366 sbi = off % NBBY;
367 eby = (off+len) / NBBY;
368 ebi = (off+len) % NBBY;
369 if (sby == eby) {
370 mask = ((1 << (ebi - sbi)) - 1) << sbi;
371 cp[sby] &= ~mask;
372 } else {
373 mask = (1<<sbi) - 1;
374 cp[sby++] &= mask;
375
376 mask = (1<<ebi) - 1;
377 cp[eby] &= ~mask;
378
379 for (i = sby; i < eby; i++)
380 cp[i] = 0x00;
381 }
382}
383#endif
384
385/*
386 * Copy buffer to clist.
387 * Return number of bytes not transfered.
388 */
389int
91447636 390b_to_q(const u_char *cp, int count, struct clist *clp)
1c79356b 391{
91447636
A
392 int cc;
393 const u_char *p = cp;
1c79356b
A
394 int s;
395
396 if (count <= 0)
397 return 0;
398
399 s = spltty();
400
401 if (clp->c_cc == 0) {
402 if (!clp->c_cs) {
403#if DIAGNOSTIC
404 printf("b_to_q: required clalloc\n");
405#endif
406 if(clalloc(clp, 1024, 1))
407 goto out;
408 }
409 clp->c_cf = clp->c_cl = clp->c_cs;
410 }
411
412 if (clp->c_cc == clp->c_cn)
413 goto out;
414
415 /* optimize this while loop */
416 while (count > 0 && clp->c_cc < clp->c_cn) {
417 cc = clp->c_ce - clp->c_cl;
418 if (clp->c_cf > clp->c_cl)
419 cc = clp->c_cf - clp->c_cl;
420 if (cc > count)
421 cc = count;
422 bcopy(p, clp->c_cl, cc);
423 if (clp->c_cq) {
424#ifdef QBITS
425 clrbits(clp->c_cq, clp->c_cl - clp->c_cs, cc);
426#else
427 bzero(clp->c_cl - clp->c_cs + clp->c_cq, cc);
428#endif
429 }
430 p += cc;
431 count -= cc;
432 clp->c_cc += cc;
433 clp->c_cl += cc;
434 if (clp->c_cl == clp->c_ce)
435 clp->c_cl = clp->c_cs;
436 }
437out:
438 splx(s);
439 return count;
440}
441
442static int cc;
443
444/*
445 * Given a non-NULL pointer into the clist return the pointer
446 * to the next character in the list or return NULL if no more chars.
447 *
448 * Callers must not allow getc's to happen between firstc's and getc's
449 * so that the pointer becomes invalid. Note that interrupts are NOT
450 * masked.
451 */
452u_char *
453nextc(clp, cp, c)
454 struct clist *clp;
455 register u_char *cp;
456 int *c;
457{
458
459 if (clp->c_cf == cp) {
460 /*
461 * First time initialization.
462 */
463 cc = clp->c_cc;
464 }
465 if (cc == 0 || cp == NULL)
466 return NULL;
467 if (--cc == 0)
468 return NULL;
469 if (++cp == clp->c_ce)
470 cp = clp->c_cs;
471 *c = *cp & 0xff;
472 if (clp->c_cq) {
473#ifdef QBITS
474 if (isset(clp->c_cq, cp - clp->c_cs))
475 *c |= TTY_QUOTE;
476#else
477 if (*(clp->c_cf - clp->c_cs + clp->c_cq))
478 *c |= TTY_QUOTE;
479#endif
480 }
481 return cp;
482}
483
484/*
485 * Given a non-NULL pointer into the clist return the pointer
486 * to the first character in the list or return NULL if no more chars.
487 *
488 * Callers must not allow getc's to happen between firstc's and getc's
489 * so that the pointer becomes invalid. Note that interrupts are NOT
490 * masked.
491 *
492 * *c is set to the NEXT character
493 */
494u_char *
495firstc(clp, c)
496 struct clist *clp;
497 int *c;
498{
499 register u_char *cp;
500
501 cc = clp->c_cc;
502 if (cc == 0)
503 return NULL;
504 cp = clp->c_cf;
505 *c = *cp & 0xff;
506 if(clp->c_cq) {
507#ifdef QBITS
508 if (isset(clp->c_cq, cp - clp->c_cs))
509 *c |= TTY_QUOTE;
510#else
511 if (*(cp - clp->c_cs + clp->c_cq))
512 *c |= TTY_QUOTE;
513#endif
514 }
515 return clp->c_cf;
516}
517
518/*
519 * Remove the last character in the clist and return it.
520 */
521int
522unputc(clp)
523 struct clist *clp;
524{
525 unsigned int c = -1;
526 int s;
527
528 s = spltty();
529 if (clp->c_cc == 0)
530 goto out;
531
532 if (clp->c_cl == clp->c_cs)
533 clp->c_cl = clp->c_ce - 1;
534 else
535 --clp->c_cl;
536 clp->c_cc--;
537
538 c = *clp->c_cl & 0xff;
539 if (clp->c_cq) {
540#ifdef QBITS
541 if (isset(clp->c_cq, clp->c_cl - clp->c_cs))
542 c |= TTY_QUOTE;
543#else
544 if (*(clp->c_cf - clp->c_cs + clp->c_cq))
545 c |= TTY_QUOTE;
546#endif
547 }
548 if (clp->c_cc == 0)
549 clp->c_cf = clp->c_cl = (u_char *)0;
550out:
551 splx(s);
552 return c;
553}
554
555/*
556 * Put the chars in the from queue on the end of the to queue.
557 */
558void
559catq(from, to)
560 struct clist *from, *to;
561{
562 int c;
563
564 while ((c = getc(from)) != -1)
565 putc(c, to);
566}
567
568#endif /* NeXT */