]>
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  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved. 
   8  * This file contains Original Code and/or Modifications of Original Code 
   9  * as defined in and that are subject to the Apple Public Source License 
  10  * Version 2.0 (the 'License'). You may not use this file except in 
  11  * compliance with the License. Please obtain a copy of the License at 
  12  * http://www.opensource.apple.com/apsl/ and read it before using this 
  15  * The Original Code and all software distributed under the License are 
  16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  20  * Please see the License for the specific language governing rights and 
  21  * limitations under the License. 
  23  * @APPLE_LICENSE_HEADER_END@ 
  25 /* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */ 
  27  * Copyright (c) 1993, 1994 Theo de Raadt 
  28  * All rights reserved. 
  30  * Redistribution and use in source and binary forms, with or without 
  31  * modification, are permitted provided that the following conditions 
  33  * 1. Redistributions of source code must retain the above copyright 
  34  *    notice unmodified, this list of conditions, and the following 
  36  * 2. Redistributions in binary form must reproduce the above copyright 
  37  *    notice, this list of conditions and the following disclaimer in the 
  38  *    documentation and/or other materials provided with the distribution. 
  40  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
  41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
  44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  56  * We use the NetBSD based clist system, it is much more efficient than the 
  57  * old style clist stuff used by free bsd. 
  60 #include <sys/param.h> 
  61 #include <sys/systm.h> 
  63 #include <sys/ioctl.h> 
  65 #include <sys/malloc.h> 
  67 #include <machine/spl.h> 
  70  * At compile time, choose: 
  71  * There are two ways the TTY_QUOTE bit can be stored. If QBITS is 
  72  * defined we allocate an array of bits -- 1/8th as much memory but 
  73  * setbit(), clrbit(), and isset() take more cpu. If QBITS is 
  74  * undefined, we just use an array of bytes. 
  76  * If TTY_QUOTE functionality isn't required by a line discipline, 
  77  * it can free c_cq and set it to NULL. This speeds things up, 
  78  * and also does not use any extra memory. This is useful for (say) 
  79  * a SLIP line discipline that wants a 32K ring buffer for data 
  80  * but doesn't need quoting. 
  85 #define QMEM(n)         ((((n)-1)/NBBY)+1) 
 100  * Initialize a particular clist. Ok, they are really ring buffers, 
 101  * of the specified length, with/without quoting support. 
 104 clalloc(clp
, size
, quot
) 
 110         MALLOC_ZONE(clp
->c_cs
, u_char 
*, size
, M_TTYS
, M_WAITOK
); 
 113         bzero(clp
->c_cs
, size
); 
 116                 MALLOC_ZONE(clp
->c_cq
, u_char 
*, QMEM(size
), M_TTYS
, M_WAITOK
); 
 118                         FREE_ZONE(clp
->c_cs
, size
, M_TTYS
); 
 121                 bzero(clp
->c_cs
, QMEM(size
)); 
 123                 clp
->c_cq 
= (u_char 
*)0; 
 125         clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 126         clp
->c_ce 
= clp
->c_cs 
+ size
; 
 137                 FREE_ZONE(clp
->c_cs
, clp
->c_cn
, M_TTYS
); 
 139                 FREE_ZONE(clp
->c_cq
, QMEM(clp
->c_cn
), M_TTYS
); 
 140         clp
->c_cs 
= clp
->c_cq 
= (u_char 
*)0; 
 145  * Get a character from a clist. 
 158         c 
= *clp
->c_cf 
& 0xff; 
 161                 if (isset(clp
->c_cq
, clp
->c_cf 
- clp
->c_cs
) ) 
 164                 if (*(clp
->c_cf 
- clp
->c_cs 
+ clp
->c_cq
)) 
 168         if (++clp
->c_cf 
== clp
->c_ce
) 
 169                 clp
->c_cf 
= clp
->c_cs
; 
 170         if (--clp
->c_cc 
== 0) 
 171                 clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 178  * Copy clist to buffer. 
 179  * Return number of bytes moved. 
 182 q_to_b(clp
, cp
, count
) 
 192         /* optimize this while loop */ 
 193         while (count 
> 0 && clp
->c_cc 
> 0) { 
 194                 cc 
= clp
->c_cl 
- clp
->c_cf
; 
 195                 if (clp
->c_cf 
>= clp
->c_cl
) 
 196                         cc 
= clp
->c_ce 
- clp
->c_cf
; 
 199                 bcopy(clp
->c_cf
, p
, cc
); 
 204                 if (clp
->c_cf 
== clp
->c_ce
) 
 205                         clp
->c_cf 
= clp
->c_cs
; 
 208                 clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 214  * Return count of contiguous characters in clist. 
 215  * Stop counting if flag&character is non-null. 
 228         if ((cc 
= clp
->c_cc
) == 0) 
 232                 count 
= clp
->c_cl 
- clp
->c_cf
; 
 234                         count 
= clp
->c_ce 
- clp
->c_cf
; 
 238         i 
= clp
->c_cf 
- clp
->c_cs
; 
 239         if (flag 
& TTY_QUOTE
) { 
 240                 while (cc
-- > 0 && !(clp
->c_cs
[i
++] & (flag 
& ~TTY_QUOTE
) || 
 241                     isset(clp
->c_cq
, i
))) { 
 247                 while (cc
-- > 0 && !(clp
->c_cs
[i
++] & flag
)) { 
 259  * Flush count bytes from clist. 
 270         if (count 
== clp
->c_cc
) { 
 272                 clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 275         /* optimize this while loop */ 
 276         while (count 
> 0 && clp
->c_cc 
> 0) { 
 277                 cc 
= clp
->c_cl 
- clp
->c_cf
; 
 278                 if (clp
->c_cf 
>= clp
->c_cl
) 
 279                         cc 
= clp
->c_ce 
- clp
->c_cf
; 
 285                 if (clp
->c_cf 
== clp
->c_ce
) 
 286                         clp
->c_cf 
= clp
->c_cs
; 
 289                 clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 295  * Put a character into the output queue. 
 306         if (clp
->c_cc 
== 0) { 
 309                         //printf("putc: required clalloc\n"); 
 311                         if(clalloc(clp
, 1024, 1)) { 
 317                 clp
->c_cf 
= clp
->c_cl 
= clp
->c_cs
; 
 320         if (clp
->c_cc 
== clp
->c_cn
) 
 323         *clp
->c_cl 
= c 
& 0xff; 
 324         i 
= clp
->c_cl 
- clp
->c_cs
; 
 328                         setbit(clp
->c_cq
, i
);  
 330                         clrbit(clp
->c_cq
, i
); 
 333                 *q 
= (c 
& TTY_QUOTE
) ? 1 : 0; 
 338         if (clp
->c_cl 
== clp
->c_ce
) 
 339                 clp
->c_cl 
= clp
->c_cs
; 
 346  * optimized version of 
 348  * for (i = 0; i < len; i++) 
 349  *      clrbit(cp, off + len); 
 352 clrbits(cp
, off
, len
) 
 357         int sby
, sbi
, eby
, ebi
; 
 368         eby 
= (off
+len
) / NBBY
; 
 369         ebi 
= (off
+len
) % NBBY
; 
 371                 mask 
= ((1 << (ebi 
- sbi
)) - 1) << sbi
; 
 380                 for (i 
= sby
; i 
< eby
; i
++) 
 387  * Copy buffer to clist. 
 388  * Return number of bytes not transfered. 
 391 b_to_q(cp
, count
, clp
) 
 397         register u_char 
*p 
= cp
; 
 405         if (clp
->c_cc 
== 0) { 
 408                         printf("b_to_q: required clalloc\n"); 
 410                         if(clalloc(clp
, 1024, 1)) 
 413                 clp
->c_cf 
= clp
->c_cl 
= clp
->c_cs
; 
 416         if (clp
->c_cc 
== clp
->c_cn
) 
 419         /* optimize this while loop */ 
 420         while (count 
> 0 && clp
->c_cc 
< clp
->c_cn
) { 
 421                 cc 
= clp
->c_ce 
- clp
->c_cl
; 
 422                 if (clp
->c_cf 
> clp
->c_cl
) 
 423                         cc 
= clp
->c_cf 
- clp
->c_cl
; 
 426                 bcopy(p
, clp
->c_cl
, cc
); 
 429                         clrbits(clp
->c_cq
, clp
->c_cl 
- clp
->c_cs
, cc
); 
 431                         bzero(clp
->c_cl 
- clp
->c_cs 
+ clp
->c_cq
, cc
); 
 438                 if (clp
->c_cl 
== clp
->c_ce
) 
 439                         clp
->c_cl 
= clp
->c_cs
; 
 449  * Given a non-NULL pointer into the clist return the pointer 
 450  * to the next character in the list or return NULL if no more chars. 
 452  * Callers must not allow getc's to happen between firstc's and getc's 
 453  * so that the pointer becomes invalid.  Note that interrupts are NOT 
 463         if (clp
->c_cf 
== cp
) { 
 465                  * First time initialization. 
 469         if (cc 
== 0 || cp 
== NULL
) 
 473         if (++cp 
== clp
->c_ce
) 
 478                 if (isset(clp
->c_cq
, cp 
- clp
->c_cs
)) 
 481                 if (*(clp
->c_cf 
- clp
->c_cs 
+ clp
->c_cq
)) 
 489  * Given a non-NULL pointer into the clist return the pointer 
 490  * to the first character in the list or return NULL if no more chars. 
 492  * Callers must not allow getc's to happen between firstc's and getc's 
 493  * so that the pointer becomes invalid.  Note that interrupts are NOT 
 496  * *c is set to the NEXT character 
 512                 if (isset(clp
->c_cq
, cp 
- clp
->c_cs
)) 
 515                 if (*(cp 
- clp
->c_cs 
+ clp
->c_cq
)) 
 523  * Remove the last character in the clist and return it. 
 536         if (clp
->c_cl 
== clp
->c_cs
) 
 537                 clp
->c_cl 
= clp
->c_ce 
- 1; 
 542         c 
= *clp
->c_cl 
& 0xff; 
 545                 if (isset(clp
->c_cq
, clp
->c_cl 
- clp
->c_cs
)) 
 548                 if (*(clp
->c_cf 
- clp
->c_cs 
+ clp
->c_cq
)) 
 553                 clp
->c_cf 
= clp
->c_cl 
= (u_char 
*)0; 
 560  * Put the chars in the from queue on the end of the to queue. 
 564         struct clist 
*from
, *to
; 
 568         while ((c 
= getc(from
)) != -1)