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.55 2008/04/28 20:24:05 martin 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.55 2008/04/28 20:24:05 martin Exp $");
   70 
   71 #include <sys/param.h>
   72 #include <sys/systm.h>
   73 #include <sys/poll.h>
   74 #include <sys/proc.h>
   75 #include <sys/tty.h>
   76 #include <sys/ttycom.h>
   77 #include <sys/conf.h>
   78 #include <sys/mutex.h>
   79 #include <sys/queue.h>
   80 
   81 static struct linesw termios_disc = {
   82         .l_name = "termios",
   83         .l_open = ttylopen,
   84         .l_close = ttylclose,
   85         .l_read = ttread,
   86         .l_write = ttwrite,
   87         .l_ioctl = ttynullioctl,
   88         .l_rint = ttyinput,
   89         .l_start = ttstart,
   90         .l_modem = ttymodem,
   91         .l_poll = ttpoll
   92 };
   93 
   94 /*
   95  * This is for the benefit of old BSD TTY compatbility, but since it is
   96  * identical to termios (except for the name), don't bother conditionalizing
   97  * it.
   98  */
   99 static struct linesw ntty_disc = {      /* old NTTYDISC */
  100         .l_name = "ntty",
  101         .l_open = ttylopen,
  102         .l_close = ttylclose,
  103         .l_read = ttread,
  104         .l_write = ttwrite,
  105         .l_ioctl = ttynullioctl,
  106         .l_rint = ttyinput,
  107         .l_start = ttstart,
  108         .l_modem = ttymodem,
  109         .l_poll = ttpoll
  110 };
  111 
  112 static LIST_HEAD(, linesw) ttyldisc_list = LIST_HEAD_INITIALIZER(ttyldisc_head);
  113 
  114 /*
  115  * Note: We don't bother refcounting termios_disc and ntty_disc; they can't
  116  * be removed from the list, and termios_disc is likely to have very many
  117  * references (could we overflow the count?).
  118  */
  119 #define TTYLDISC_ISSTATIC(disc)                                 \
  120         ((disc) == &termios_disc || (disc) == &ntty_disc)
  121 
  122 #define TTYLDISC_HOLD(disc)                                     \
  123 do {                                                            \
  124         if (! TTYLDISC_ISSTATIC(disc)) {                        \
  125                 KASSERT((disc)->l_refcnt != UINT_MAX);          \
  126                 (disc)->l_refcnt++;                             \
  127         }                                                       \
  128 } while (/*CONSTCOND*/0)
  129 
  130 #define TTYLDISC_RELE(disc)                                     \
  131 do {                                                            \
  132         if (! TTYLDISC_ISSTATIC(disc)) {                        \
  133                 KASSERT((disc)->l_refcnt != 0);                 \
  134                 (disc)->l_refcnt--;                             \
  135         }                                                       \
  136 } while (/*CONSTCOND*/0)
  137 
  138 #define TTYLDISC_ISINUSE(disc)                                  \
  139         (TTYLDISC_ISSTATIC(disc) || (disc)->l_refcnt != 0)
  140 
  141 /*
  142  * Do nothing specific version of line
  143  * discipline specific ioctl command.
  144  */
  145 /*ARGSUSED*/
  146 int
  147 ttynullioctl(struct tty *tp, u_long cmd, void *data, int flags, struct lwp *l)
  148 {
  149 
  150         return (EPASSTHROUGH);
  151 }
  152 
  153 /*
  154  * Return error to line discipline
  155  * specific poll call.
  156  */
  157 /*ARGSUSED*/
  158 int
  159 ttyerrpoll(struct tty *tp, int events, struct lwp *l)
  160 {
  161 
  162         return (POLLERR);
  163 }
  164 
  165 void
  166 ttyldisc_init(void)
  167 {
  168 
  169         if (ttyldisc_attach(&termios_disc) != 0)
  170                 panic("ttyldisc_init: termios_disc");
  171         if (ttyldisc_attach(&ntty_disc) != 0)
  172                 panic("ttyldisc_init: ntty_disc");
  173 }
  174 
  175 static struct linesw *
  176 ttyldisc_lookup_locked(const char *name)
  177 {
  178         struct linesw *disc;
  179 
  180         LIST_FOREACH(disc, &ttyldisc_list, l_list) {
  181                 if (strcmp(name, disc->l_name) == 0)
  182                         return (disc);
  183         }
  184 
  185         return (NULL);
  186 }
  187 
  188 /*
  189  * Look up a line discipline by its name.  Caller holds a reference on
  190  * the returned line discipline.
  191  */
  192 struct linesw *
  193 ttyldisc_lookup(const char *name)
  194 {
  195         struct linesw *disc;
  196 
  197         mutex_spin_enter(&tty_lock);
  198         disc = ttyldisc_lookup_locked(name);
  199         if (disc != NULL)
  200                 TTYLDISC_HOLD(disc);
  201         mutex_spin_exit(&tty_lock);
  202 
  203         return (disc);
  204 }
  205 
  206 /*
  207  * Look up a line discipline by its legacy number.  Caller holds a
  208  * reference on the returned line discipline.
  209  */
  210 struct linesw *
  211 ttyldisc_lookup_bynum(int num)
  212 {
  213         struct linesw *disc;
  214 
  215         mutex_spin_enter(&tty_lock);
  216 
  217         LIST_FOREACH(disc, &ttyldisc_list, l_list) {
  218                 if (disc->l_no == num) {
  219                         TTYLDISC_HOLD(disc);
  220                         mutex_spin_exit(&tty_lock);
  221                         return (disc);
  222                 }
  223         }
  224 
  225         mutex_spin_exit(&tty_lock);
  226         return (NULL);
  227 }
  228 
  229 /*
  230  * Release a reference on a line discipline previously added by
  231  * ttyldisc_lookup() or ttyldisc_lookup_bynum().
  232  */
  233 void
  234 ttyldisc_release(struct linesw *disc)
  235 {
  236 
  237         if (disc == NULL)
  238                 return;
  239 
  240         mutex_spin_enter(&tty_lock);
  241         TTYLDISC_RELE(disc);
  242         mutex_spin_exit(&tty_lock);
  243 }
  244 
  245 #define TTYLDISC_LEGACY_NUMBER_MIN      10
  246 #define TTYLDISC_LEGACY_NUMBER_MAX      INT_MAX
  247 
  248 static void
  249 ttyldisc_assign_legacy_number(struct linesw *disc)
  250 {
  251         static const struct {
  252                 const char *name;
  253                 int num;
  254         } table[] = {
  255                 { "termios",            TTYDISC },
  256                 { "ntty",               2 /* XXX old NTTYDISC */ },
  257                 { "tablet",             TABLDISC },
  258                 { "slip",               SLIPDISC },
  259                 { "ppp",                PPPDISC },
  260                 { "strip",              STRIPDISC },
  261                 { "hdlc",               HDLCDISC },
  262                 { NULL,                 0 }
  263         };
  264         struct linesw *ldisc;
  265         int i;
  266 
  267         for (i = 0; table[i].name != NULL; i++) {
  268                 if (strcmp(disc->l_name, table[i].name) == 0) {
  269                         disc->l_no = table[i].num;
  270                         return;
  271                 }
  272         }
  273 
  274         disc->l_no = TTYLDISC_LEGACY_NUMBER_MIN;
  275 
  276         LIST_FOREACH(ldisc, &ttyldisc_list, l_list) {
  277                 if (disc->l_no == ldisc->l_no) {
  278                         KASSERT(disc->l_no < TTYLDISC_LEGACY_NUMBER_MAX);
  279                         disc->l_no++;
  280                 }
  281         }
  282 }
  283 
  284 /*
  285  * Register a line discipline.
  286  */
  287 int
  288 ttyldisc_attach(struct linesw *disc)
  289 {
  290 
  291         KASSERT(disc->l_name != NULL);
  292         KASSERT(disc->l_open != NULL);
  293         KASSERT(disc->l_close != NULL);
  294         KASSERT(disc->l_read != NULL);
  295         KASSERT(disc->l_write != NULL);
  296         KASSERT(disc->l_ioctl != NULL);
  297         KASSERT(disc->l_rint != NULL);
  298         KASSERT(disc->l_start != NULL);
  299         KASSERT(disc->l_modem != NULL);
  300         KASSERT(disc->l_poll != NULL);
  301 
  302         /* You are not allowed to exceed TTLINEDNAMELEN */
  303         if (strlen(disc->l_name) >= TTLINEDNAMELEN)
  304                 return (ENAMETOOLONG);
  305 
  306         mutex_spin_enter(&tty_lock);
  307 
  308         if (ttyldisc_lookup_locked(disc->l_name) != NULL) {
  309                 mutex_spin_exit(&tty_lock);
  310                 return (EEXIST);
  311         }
  312 
  313         ttyldisc_assign_legacy_number(disc);
  314         LIST_INSERT_HEAD(&ttyldisc_list, disc, l_list);
  315 
  316         mutex_spin_exit(&tty_lock);
  317 
  318         return (0);
  319 }
  320 
  321 /*
  322  * Remove a line discipline.
  323  */
  324 int
  325 ttyldisc_detach(struct linesw *disc)
  326 {
  327 #ifdef DIAGNOSTIC
  328         struct linesw *ldisc = ttyldisc_lookup(disc->l_name);
  329 
  330         KASSERT(ldisc != NULL);
  331         KASSERT(ldisc == disc);
  332         ttyldisc_release(ldisc);
  333 #endif
  334 
  335         mutex_spin_enter(&tty_lock);
  336 
  337         if (TTYLDISC_ISINUSE(disc)) {
  338                 mutex_spin_exit(&tty_lock);
  339                 return (EBUSY);
  340         }
  341 
  342         LIST_REMOVE(disc, l_list);
  343 
  344         mutex_spin_exit(&tty_lock);
  345 
  346         return (0);
  347 }
  348 
  349 /*
  350  * Return the default line discipline.
  351  */
  352 struct linesw *
  353 ttyldisc_default(void)
  354 {
  355 
  356         return (&termios_disc);
  357 }

Cache object: 429ab6a4de46c4e71dc7d6b4dd4c5def


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