The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/tty_conf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: tty_conf.c,v 1.52 2006/11/01 10:17:59 yamt Exp $       */
    2 
    3 /*-
    4  * Copyright (c) 2005 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*-
   40  * Copyright (c) 1982, 1986, 1991, 1993
   41  *      The Regents of the University of California.  All rights reserved.
   42  * (c) UNIX System Laboratories, Inc.
   43  * All or some portions of this file are derived from material licensed
   44  * to the University of California by American Telephone and Telegraph
   45  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   46  * the permission of UNIX System Laboratories, Inc.
   47  *
   48  * Redistribution and use in source and binary forms, with or without
   49  * modification, are permitted provided that the following conditions
   50  * are met:
   51  * 1. Redistributions of source code must retain the above copyright
   52  *    notice, this list of conditions and the following disclaimer.
   53  * 2. Redistributions in binary form must reproduce the above copyright
   54  *    notice, this list of conditions and the following disclaimer in the
   55  *    documentation and/or other materials provided with the distribution.
   56  * 3. Neither the name of the University nor the names of its contributors
   57  *    may be used to endorse or promote products derived from this software
   58  *    without specific prior written permission.
   59  *
   60  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   61  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   62  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   63  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   64  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   65  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   66  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   67  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   68  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   69  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   70  * SUCH DAMAGE.
   71  *
   72  *      @(#)tty_conf.c  8.5 (Berkeley) 1/9/95
   73  */
   74 
   75 #include <sys/cdefs.h>
   76 __KERNEL_RCSID(0, "$NetBSD: tty_conf.c,v 1.52 2006/11/01 10:17:59 yamt Exp $");
   77 
   78 #include <sys/param.h>
   79 #include <sys/systm.h>
   80 #include <sys/poll.h>
   81 #include <sys/proc.h>
   82 #include <sys/tty.h>
   83 #include <sys/ttycom.h>
   84 #include <sys/conf.h>
   85 #include <sys/once.h>
   86 #include <sys/lock.h>
   87 #include <sys/queue.h>
   88 
   89 static struct linesw termios_disc = {
   90         .l_name = "termios",
   91         .l_open = ttylopen,
   92         .l_close = ttylclose,
   93         .l_read = ttread,
   94         .l_write = ttwrite,
   95         .l_ioctl = ttynullioctl,
   96         .l_rint = ttyinput,
   97         .l_start = ttstart,
   98         .l_modem = ttymodem,
   99         .l_poll = ttpoll
  100 };
  101 
  102 /*
  103  * This is for the benefit of old BSD TTY compatbility, but since it is
  104  * identical to termios (except for the name), don't bother conditionalizing
  105  * it.
  106  */
  107 static struct linesw ntty_disc = {      /* old NTTYDISC */
  108         .l_name = "ntty",
  109         .l_open = ttylopen,
  110         .l_close = ttylclose,
  111         .l_read = ttread,
  112         .l_write = ttwrite,
  113         .l_ioctl = ttynullioctl,
  114         .l_rint = ttyinput,
  115         .l_start = ttstart,
  116         .l_modem = ttymodem,
  117         .l_poll = ttpoll
  118 };
  119 
  120 static LIST_HEAD(, linesw) ttyldisc_list = LIST_HEAD_INITIALIZER(ttyldisc_head);
  121 static struct simplelock ttyldisc_list_slock = SIMPLELOCK_INITIALIZER;
  122 
  123 /*
  124  * Note: We don't bother refcounting termios_disc and ntty_disc; they can't
  125  * be removed from the list, and termios_disc is likely to have very many
  126  * references (could we overflow the count?).
  127  */
  128 #define TTYLDISC_ISSTATIC(disc)                                 \
  129         ((disc) == &termios_disc || (disc) == &ntty_disc)
  130 
  131 #define TTYLDISC_HOLD(disc)                                     \
  132 do {                                                            \
  133         if (! TTYLDISC_ISSTATIC(disc)) {                        \
  134                 KASSERT((disc)->l_refcnt != UINT_MAX);          \
  135                 (disc)->l_refcnt++;                             \
  136         }                                                       \
  137 } while (/*CONSTCOND*/0)
  138 
  139 #define TTYLDISC_RELE(disc)                                     \
  140 do {                                                            \
  141         if (! TTYLDISC_ISSTATIC(disc)) {                        \
  142                 KASSERT((disc)->l_refcnt != 0);                 \
  143                 (disc)->l_refcnt--;                             \
  144         }                                                       \
  145 } while (/*CONSTCOND*/0)
  146 
  147 #define TTYLDISC_ISINUSE(disc)                                  \
  148         (TTYLDISC_ISSTATIC(disc) || (disc)->l_refcnt != 0)
  149 
  150 /*
  151  * Do nothing specific version of line
  152  * discipline specific ioctl command.
  153  */
  154 /*ARGSUSED*/
  155 int
  156 ttynullioctl(struct tty *tp, u_long cmd, char *data, int flags, struct lwp *l)
  157 {
  158 
  159         return (EPASSTHROUGH);
  160 }
  161 
  162 /*
  163  * Return error to line discipline
  164  * specific poll call.
  165  */
  166 /*ARGSUSED*/
  167 int
  168 ttyerrpoll(struct tty *tp, int events, struct lwp *l)
  169 {
  170 
  171         return (POLLERR);
  172 }
  173 
  174 static ONCE_DECL(ttyldisc_init_once);
  175 
  176 static int
  177 ttyldisc_init(void)
  178 {
  179 
  180         if (ttyldisc_attach(&termios_disc) != 0)
  181                 panic("ttyldisc_init: termios_disc");
  182         if (ttyldisc_attach(&ntty_disc) != 0)
  183                 panic("ttyldisc_init: ntty_disc");
  184 
  185         return 0;
  186 }
  187 
  188 static struct linesw *
  189 ttyldisc_lookup_locked(const char *name)
  190 {
  191         struct linesw *disc;
  192 
  193         LIST_FOREACH(disc, &ttyldisc_list, l_list) {
  194                 if (strcmp(name, disc->l_name) == 0)
  195                         return (disc);
  196         }
  197 
  198         return (NULL);
  199 }
  200 
  201 /*
  202  * Look up a line discipline by its name.  Caller holds a reference on
  203  * the returned line discipline.
  204  */
  205 struct linesw *
  206 ttyldisc_lookup(const char *name)
  207 {
  208         struct linesw *disc;
  209 
  210         RUN_ONCE(&ttyldisc_init_once, ttyldisc_init);
  211 
  212         simple_lock(&ttyldisc_list_slock);
  213         disc = ttyldisc_lookup_locked(name);
  214         if (disc != NULL)
  215                 TTYLDISC_HOLD(disc);
  216         simple_unlock(&ttyldisc_list_slock);
  217 
  218         return (disc);
  219 }
  220 
  221 /*
  222  * Look up a line discipline by its legacy number.  Caller holds a
  223  * reference on the returned line discipline.
  224  */
  225 struct linesw *
  226 ttyldisc_lookup_bynum(int num)
  227 {
  228         struct linesw *disc;
  229 
  230         RUN_ONCE(&ttyldisc_init_once, ttyldisc_init);
  231 
  232         simple_lock(&ttyldisc_list_slock);
  233 
  234         LIST_FOREACH(disc, &ttyldisc_list, l_list) {
  235                 if (disc->l_no == num) {
  236                         TTYLDISC_HOLD(disc);
  237                         simple_unlock(&ttyldisc_list_slock);
  238                         return (disc);
  239                 }
  240         }
  241 
  242         simple_unlock(&ttyldisc_list_slock);
  243         return (NULL);
  244 }
  245 
  246 /*
  247  * Release a reference on a line discipline previously added by
  248  * ttyldisc_lookup() or ttyldisc_lookup_bynum().
  249  */
  250 void
  251 ttyldisc_release(struct linesw *disc)
  252 {
  253 
  254         if (disc == NULL)
  255                 return;
  256 
  257         simple_lock(&ttyldisc_list_slock);
  258         TTYLDISC_RELE(disc);
  259         simple_unlock(&ttyldisc_list_slock);
  260 }
  261 
  262 #define TTYLDISC_LEGACY_NUMBER_MIN      10
  263 #define TTYLDISC_LEGACY_NUMBER_MAX      INT_MAX
  264 
  265 static void
  266 ttyldisc_assign_legacy_number(struct linesw *disc)
  267 {
  268         static const struct {
  269                 const char *name;
  270                 int num;
  271         } table[] = {
  272                 { "termios",            TTYDISC },
  273                 { "ntty",               2 /* XXX old NTTYDISC */ },
  274                 { "tablet",             TABLDISC },
  275                 { "slip",               SLIPDISC },
  276                 { "ppp",                PPPDISC },
  277                 { "strip",              STRIPDISC },
  278                 { "hdlc",               HDLCDISC },
  279                 { NULL,                 0 }
  280         };
  281         struct linesw *ldisc;
  282         int i;
  283 
  284         for (i = 0; table[i].name != NULL; i++) {
  285                 if (strcmp(disc->l_name, table[i].name) == 0) {
  286                         disc->l_no = table[i].num;
  287                         return;
  288                 }
  289         }
  290 
  291         disc->l_no = TTYLDISC_LEGACY_NUMBER_MIN;
  292 
  293         LIST_FOREACH(ldisc, &ttyldisc_list, l_list) {
  294                 if (disc->l_no == ldisc->l_no) {
  295                         KASSERT(disc->l_no < TTYLDISC_LEGACY_NUMBER_MAX);
  296                         disc->l_no++;
  297                 }
  298         }
  299 }
  300 
  301 /*
  302  * Register a line discipline.
  303  */
  304 int
  305 ttyldisc_attach(struct linesw *disc)
  306 {
  307 
  308         KASSERT(disc->l_name != NULL);
  309         KASSERT(disc->l_open != NULL);
  310         KASSERT(disc->l_close != NULL);
  311         KASSERT(disc->l_read != NULL);
  312         KASSERT(disc->l_write != NULL);
  313         KASSERT(disc->l_ioctl != NULL);
  314         KASSERT(disc->l_rint != NULL);
  315         KASSERT(disc->l_start != NULL);
  316         KASSERT(disc->l_modem != NULL);
  317         KASSERT(disc->l_poll != NULL);
  318 
  319         /* You are not allowed to exceed TTLINEDNAMELEN */
  320         if (strlen(disc->l_name) >= TTLINEDNAMELEN)
  321                 return (ENAMETOOLONG);
  322 
  323         simple_lock(&ttyldisc_list_slock);
  324 
  325         if (ttyldisc_lookup_locked(disc->l_name) != NULL) {
  326                 simple_unlock(&ttyldisc_list_slock);
  327                 return (EEXIST);
  328         }
  329 
  330         ttyldisc_assign_legacy_number(disc);
  331         LIST_INSERT_HEAD(&ttyldisc_list, disc, l_list);
  332 
  333         simple_unlock(&ttyldisc_list_slock);
  334 
  335         return (0);
  336 }
  337 
  338 /*
  339  * Remove a line discipline.
  340  */
  341 int
  342 ttyldisc_detach(struct linesw *disc)
  343 {
  344 #ifdef DIAGNOSTIC
  345         struct linesw *ldisc = ttyldisc_lookup(disc->l_name);
  346 
  347         KASSERT(ldisc != NULL);
  348         KASSERT(ldisc == disc);
  349         ttyldisc_release(ldisc);
  350 #endif
  351 
  352         simple_lock(&ttyldisc_list_slock);
  353 
  354         if (TTYLDISC_ISINUSE(disc)) {
  355                 simple_unlock(&ttyldisc_list_slock);
  356                 return (EBUSY);
  357         }
  358 
  359         LIST_REMOVE(disc, l_list);
  360 
  361         simple_unlock(&ttyldisc_list_slock);
  362 
  363         return (0);
  364 }
  365 
  366 /*
  367  * Return the default line discipline.
  368  */
  369 struct linesw *
  370 ttyldisc_default(void)
  371 {
  372 
  373         return (&termios_disc);
  374 }

Cache object: 5437651d43abe4dd09f671dd932903f4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.