]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/tty_subr.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1993, 1994 Theo de Raadt
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice unmodified, this list of conditions, and the following
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
37 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * We use the NetBSD based clist system, it is much more efficient than the
54 * old style clist stuff used by free bsd.
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/ioctl.h>
61 #include <sys/malloc.h>
63 #include <machine/spl.h>
66 * At compile time, choose:
67 * There are two ways the TTY_QUOTE bit can be stored. If QBITS is
68 * defined we allocate an array of bits -- 1/8th as much memory but
69 * setbit(), clrbit(), and isset() take more cpu. If QBITS is
70 * undefined, we just use an array of bytes.
72 * If TTY_QUOTE functionality isn't required by a line discipline,
73 * it can free c_cq and set it to NULL. This speeds things up,
74 * and also does not use any extra memory. This is useful for (say)
75 * a SLIP line discipline that wants a 32K ring buffer for data
76 * but doesn't need quoting.
81 #define QMEM(n) ((((n)-1)/NBBY)+1)
96 * Initialize a particular clist. Ok, they are really ring buffers,
97 * of the specified length, with/without quoting support.
100 clalloc(clp
, size
, quot
)
106 MALLOC_ZONE(clp
->c_cs
, u_char
*, size
, M_TTYS
, M_WAITOK
);
109 bzero(clp
->c_cs
, size
);
112 MALLOC_ZONE(clp
->c_cq
, u_char
*, QMEM(size
), M_TTYS
, M_WAITOK
);
114 FREE_ZONE(clp
->c_cs
, size
, M_TTYS
);
117 bzero(clp
->c_cs
, QMEM(size
));
119 clp
->c_cq
= (u_char
*)0;
121 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
122 clp
->c_ce
= clp
->c_cs
+ size
;
133 FREE_ZONE(clp
->c_cs
, clp
->c_cn
, M_TTYS
);
135 FREE_ZONE(clp
->c_cq
, QMEM(clp
->c_cn
), M_TTYS
);
136 clp
->c_cs
= clp
->c_cq
= (u_char
*)0;
141 * Get a character from a clist.
154 c
= *clp
->c_cf
& 0xff;
157 if (isset(clp
->c_cq
, clp
->c_cf
- clp
->c_cs
) )
160 if (*(clp
->c_cf
- clp
->c_cs
+ clp
->c_cq
))
164 if (++clp
->c_cf
== clp
->c_ce
)
165 clp
->c_cf
= clp
->c_cs
;
166 if (--clp
->c_cc
== 0)
167 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
174 * Copy clist to buffer.
175 * Return number of bytes moved.
178 q_to_b(clp
, cp
, count
)
188 /* optimize this while loop */
189 while (count
> 0 && clp
->c_cc
> 0) {
190 cc
= clp
->c_cl
- clp
->c_cf
;
191 if (clp
->c_cf
>= clp
->c_cl
)
192 cc
= clp
->c_ce
- clp
->c_cf
;
195 bcopy(clp
->c_cf
, p
, cc
);
200 if (clp
->c_cf
== clp
->c_ce
)
201 clp
->c_cf
= clp
->c_cs
;
204 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
210 * Return count of contiguous characters in clist.
211 * Stop counting if flag&character is non-null.
224 if ((cc
= clp
->c_cc
) == 0)
228 count
= clp
->c_cl
- clp
->c_cf
;
230 count
= clp
->c_ce
- clp
->c_cf
;
234 i
= clp
->c_cf
- clp
->c_cs
;
235 if (flag
& TTY_QUOTE
) {
236 while (cc
-- > 0 && !(clp
->c_cs
[i
++] & (flag
& ~TTY_QUOTE
) ||
237 isset(clp
->c_cq
, i
))) {
243 while (cc
-- > 0 && !(clp
->c_cs
[i
++] & flag
)) {
255 * Flush count bytes from clist.
266 if (count
== clp
->c_cc
) {
268 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
271 /* optimize this while loop */
272 while (count
> 0 && clp
->c_cc
> 0) {
273 cc
= clp
->c_cl
- clp
->c_cf
;
274 if (clp
->c_cf
>= clp
->c_cl
)
275 cc
= clp
->c_ce
- clp
->c_cf
;
281 if (clp
->c_cf
== clp
->c_ce
)
282 clp
->c_cf
= clp
->c_cs
;
285 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
291 * Put a character into the output queue.
302 if (clp
->c_cc
== 0) {
305 //printf("putc: required clalloc\n");
307 if(clalloc(clp
, 1024, 1)) {
313 clp
->c_cf
= clp
->c_cl
= clp
->c_cs
;
316 if (clp
->c_cc
== clp
->c_cn
)
319 *clp
->c_cl
= c
& 0xff;
320 i
= clp
->c_cl
- clp
->c_cs
;
324 setbit(clp
->c_cq
, i
);
326 clrbit(clp
->c_cq
, i
);
329 *q
= (c
& TTY_QUOTE
) ? 1 : 0;
334 if (clp
->c_cl
== clp
->c_ce
)
335 clp
->c_cl
= clp
->c_cs
;
342 * optimized version of
344 * for (i = 0; i < len; i++)
345 * clrbit(cp, off + len);
348 clrbits(u_char
*cp
, int off
, int len
)
350 int sby
, sbi
, eby
, ebi
;
361 eby
= (off
+len
) / NBBY
;
362 ebi
= (off
+len
) % NBBY
;
364 mask
= ((1 << (ebi
- sbi
)) - 1) << sbi
;
373 for (i
= sby
; i
< eby
; i
++)
380 * Copy buffer to clist.
381 * Return number of bytes not transfered.
384 b_to_q(const u_char
*cp
, int count
, struct clist
*clp
)
387 const u_char
*p
= cp
;
395 if (clp
->c_cc
== 0) {
398 printf("b_to_q: required clalloc\n");
400 if(clalloc(clp
, 1024, 1))
403 clp
->c_cf
= clp
->c_cl
= clp
->c_cs
;
406 if (clp
->c_cc
== clp
->c_cn
)
409 /* optimize this while loop */
410 while (count
> 0 && clp
->c_cc
< clp
->c_cn
) {
411 cc
= clp
->c_ce
- clp
->c_cl
;
412 if (clp
->c_cf
> clp
->c_cl
)
413 cc
= clp
->c_cf
- clp
->c_cl
;
416 bcopy(p
, clp
->c_cl
, cc
);
419 clrbits(clp
->c_cq
, clp
->c_cl
- clp
->c_cs
, cc
);
421 bzero(clp
->c_cl
- clp
->c_cs
+ clp
->c_cq
, cc
);
428 if (clp
->c_cl
== clp
->c_ce
)
429 clp
->c_cl
= clp
->c_cs
;
439 * Given a non-NULL pointer into the clist return the pointer
440 * to the next character in the list or return NULL if no more chars.
442 * Callers must not allow getc's to happen between firstc's and getc's
443 * so that the pointer becomes invalid. Note that interrupts are NOT
453 if (clp
->c_cf
== cp
) {
455 * First time initialization.
459 if (cc
== 0 || cp
== NULL
)
463 if (++cp
== clp
->c_ce
)
468 if (isset(clp
->c_cq
, cp
- clp
->c_cs
))
471 if (*(clp
->c_cf
- clp
->c_cs
+ clp
->c_cq
))
479 * Given a non-NULL pointer into the clist return the pointer
480 * to the first character in the list or return NULL if no more chars.
482 * Callers must not allow getc's to happen between firstc's and getc's
483 * so that the pointer becomes invalid. Note that interrupts are NOT
486 * *c is set to the NEXT character
502 if (isset(clp
->c_cq
, cp
- clp
->c_cs
))
505 if (*(cp
- clp
->c_cs
+ clp
->c_cq
))
513 * Remove the last character in the clist and return it.
526 if (clp
->c_cl
== clp
->c_cs
)
527 clp
->c_cl
= clp
->c_ce
- 1;
532 c
= *clp
->c_cl
& 0xff;
535 if (isset(clp
->c_cq
, clp
->c_cl
- clp
->c_cs
))
538 if (*(clp
->c_cf
- clp
->c_cs
+ clp
->c_cq
))
543 clp
->c_cf
= clp
->c_cl
= (u_char
*)0;
550 * Put the chars in the from queue on the end of the to queue.
554 struct clist
*from
, *to
;
558 while ((c
= getc(from
)) != -1)