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

Cache object: 0eb0bb02bf4657946db903efb8090c7a


[ 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.