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/dev/ofw/ofw_console.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 /*-
    2  * Copyright (C) 2001 Benno Rice.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
   15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   17  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24  */
   25 
   26 #include <sys/cdefs.h>
   27 __FBSDID("$FreeBSD: src/sys/dev/ofw/ofw_console.c,v 1.28.2.1 2005/01/30 00:59:56 imp Exp $");
   28 
   29 #include "opt_comconsole.h"
   30 #include "opt_ofw.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/kdb.h>
   34 #include <sys/kernel.h>
   35 #include <sys/systm.h>
   36 #include <sys/types.h>
   37 #include <sys/conf.h>
   38 #include <sys/cons.h>
   39 #include <sys/consio.h>
   40 #include <sys/tty.h>
   41 
   42 #include <dev/ofw/openfirm.h>
   43 
   44 #include <ddb/ddb.h>
   45 
   46 #ifndef OFWCONS_POLL_HZ
   47 #define OFWCONS_POLL_HZ 4       /* 50-100 works best on Ultra2 */
   48 #endif
   49 #define OFBURSTLEN      128     /* max number of bytes to write in one chunk */
   50 
   51 static d_open_t         ofw_dev_open;
   52 static d_close_t        ofw_dev_close;
   53 
   54 static struct cdevsw ofw_cdevsw = {
   55         .d_version =    D_VERSION,
   56         .d_open =       ofw_dev_open,
   57         .d_close =      ofw_dev_close,
   58         .d_name =       "ofw",
   59         .d_flags =      D_TTY | D_NEEDGIANT,
   60 };
   61 
   62 static struct tty               *ofw_tp = NULL;
   63 static int                      polltime;
   64 static struct callout_handle    ofw_timeouthandle
   65     = CALLOUT_HANDLE_INITIALIZER(&ofw_timeouthandle);
   66 
   67 #if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
   68 static int                      alt_break_state;
   69 #endif
   70 
   71 static void     ofw_tty_start(struct tty *);
   72 static int      ofw_tty_param(struct tty *, struct termios *);
   73 static void     ofw_tty_stop(struct tty *, int);
   74 static void     ofw_timeout(void *);
   75 
   76 static cn_probe_t       ofw_cons_probe;
   77 static cn_init_t        ofw_cons_init;
   78 static cn_getc_t        ofw_cons_getc;
   79 static cn_checkc_t      ofw_cons_checkc;
   80 static cn_putc_t        ofw_cons_putc;
   81 
   82 CONS_DRIVER(ofw, ofw_cons_probe, ofw_cons_init, NULL, ofw_cons_getc,
   83     ofw_cons_checkc, ofw_cons_putc, NULL);
   84 
   85 static void
   86 cn_drvinit(void *unused)
   87 {
   88         phandle_t options;
   89         char output[32];
   90         struct cdev *dev;
   91 
   92         if (ofw_consdev.cn_pri != CN_DEAD &&
   93             ofw_consdev.cn_name[0] != '\0') {
   94                 if ((options = OF_finddevice("/options")) == -1 ||
   95                     OF_getprop(options, "output-device", output,
   96                     sizeof(output)) == -1)
   97                         return;
   98                 dev = make_dev(&ofw_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "%s",
   99                     output);
  100                 make_dev_alias(dev, "ofwcons");
  101         }
  102 }
  103 
  104 SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL)
  105 
  106 static int      stdin;
  107 static int      stdout;
  108 
  109 static int
  110 ofw_dev_open(struct cdev *dev, int flag, int mode, struct thread *td)
  111 {
  112         struct  tty *tp;
  113         int     unit;
  114         int     error, setuptimeout;
  115 
  116         error = 0;
  117         setuptimeout = 0;
  118         unit = minor(dev);
  119 
  120         tp = ofw_tp = dev->si_tty = ttymalloc(ofw_tp);
  121 
  122         tp->t_oproc = ofw_tty_start;
  123         tp->t_param = ofw_tty_param;
  124         tp->t_stop = ofw_tty_stop;
  125         tp->t_dev = dev;
  126 
  127         if ((tp->t_state & TS_ISOPEN) == 0) {
  128                 tp->t_state |= TS_CARR_ON;
  129                 ttychars(tp);
  130                 tp->t_iflag = TTYDEF_IFLAG;
  131                 tp->t_oflag = TTYDEF_OFLAG;
  132                 tp->t_cflag = TTYDEF_CFLAG | CLOCAL;
  133                 tp->t_lflag = TTYDEF_LFLAG;
  134                 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  135                 ttsetwater(tp);
  136 
  137                 setuptimeout = 1;
  138         } else if ((tp->t_state & TS_XCLUDE) && suser(td)) {
  139                 return (EBUSY);
  140         }
  141 
  142         error = ttyld_open(tp, dev);
  143 
  144         if (error == 0 && setuptimeout) {
  145                 polltime = hz / OFWCONS_POLL_HZ;
  146                 if (polltime < 1) {
  147                         polltime = 1;
  148                 }
  149 
  150                 ofw_timeouthandle = timeout(ofw_timeout, tp, polltime);
  151         }
  152 
  153         return (error);
  154 }
  155 
  156 static int
  157 ofw_dev_close(struct cdev *dev, int flag, int mode, struct thread *td)
  158 {
  159         int     unit;
  160         struct  tty *tp;
  161 
  162         unit = minor(dev);
  163         tp = ofw_tp;
  164 
  165         if (unit != 0) {
  166                 return (ENXIO);
  167         }
  168 
  169         /* XXX Should be replaced with callout_stop(9) */
  170         untimeout(ofw_timeout, tp, ofw_timeouthandle);
  171         ttyld_close(tp, flag);
  172         tty_close(tp);
  173 
  174         return (0);
  175 }
  176 
  177 
  178 static int
  179 ofw_tty_param(struct tty *tp, struct termios *t)
  180 {
  181 
  182         return (0);
  183 }
  184 
  185 static void
  186 ofw_tty_start(struct tty *tp)
  187 {
  188         struct clist *cl;
  189         int len;
  190         u_char buf[OFBURSTLEN];
  191 
  192 
  193         if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
  194                 return;
  195 
  196         tp->t_state |= TS_BUSY;
  197         cl = &tp->t_outq;
  198         len = q_to_b(cl, buf, OFBURSTLEN);
  199         OF_write(stdout, buf, len);
  200         tp->t_state &= ~TS_BUSY;
  201 
  202         ttwwakeup(tp);
  203 }
  204 
  205 static void
  206 ofw_tty_stop(struct tty *tp, int flag)
  207 {
  208 
  209         if (tp->t_state & TS_BUSY) {
  210                 if ((tp->t_state & TS_TTSTOP) == 0) {
  211                         tp->t_state |= TS_FLUSH;
  212                 }
  213         }
  214 }
  215 
  216 static void
  217 ofw_timeout(void *v)
  218 {
  219         struct  tty *tp;
  220         int     c;
  221 
  222         tp = (struct tty *)v;
  223 
  224         while ((c = ofw_cons_checkc(NULL)) != -1) {
  225                 if (tp->t_state & TS_ISOPEN) {
  226                         ttyld_rint(tp, c);
  227                 }
  228         }
  229 
  230         ofw_timeouthandle = timeout(ofw_timeout, tp, polltime);
  231 }
  232 
  233 static void
  234 ofw_cons_probe(struct consdev *cp)
  235 {
  236         int chosen;
  237 
  238         if ((chosen = OF_finddevice("/chosen")) == -1) {
  239                 cp->cn_pri = CN_DEAD;
  240                 return;
  241         }
  242 
  243         if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1) {
  244                 cp->cn_pri = CN_DEAD;
  245                 return;
  246         }
  247 
  248         if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) {
  249                 cp->cn_pri = CN_DEAD;
  250                 return;
  251         }
  252 
  253         cp->cn_pri = CN_LOW;
  254 }
  255 
  256 static void
  257 ofw_cons_init(struct consdev *cp)
  258 {
  259 
  260         /* XXX: This is the alias, but that should be good enough */
  261         sprintf(cp->cn_name, "ofwcons");
  262         cp->cn_tp = ofw_tp;
  263 }
  264 
  265 static int
  266 ofw_cons_getc(struct consdev *cp)
  267 {
  268         unsigned char ch;
  269         int l;
  270 
  271         ch = '\0';
  272 
  273         while ((l = OF_read(stdin, &ch, 1)) != 1) {
  274                 if (l != -2 && l != 0) {
  275                         return (-1);
  276                 }
  277         }
  278 
  279 #if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
  280         if (kdb_alt_break(ch, &alt_break_state))
  281                 kdb_enter("Break sequence on console");
  282 #endif
  283 
  284         return (ch);
  285 }
  286 
  287 static int
  288 ofw_cons_checkc(struct consdev *cp)
  289 {
  290         unsigned char ch;
  291 
  292         if (OF_read(stdin, &ch, 1) > 0) {
  293 #if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
  294                 if (kdb_alt_break(ch, &alt_break_state))
  295                         kdb_enter("Break sequence on console");
  296 #endif
  297                 return (ch);
  298         }
  299 
  300         return (-1);
  301 }
  302 
  303 static void
  304 ofw_cons_putc(struct consdev *cp, int c)
  305 {
  306         char cbuf;
  307 
  308         if (c == '\n') {
  309                 cbuf = '\r';
  310                 OF_write(stdout, &cbuf, 1);
  311         }
  312 
  313         cbuf = c;
  314         OF_write(stdout, &cbuf, 1);
  315 }

Cache object: 2b0086dd95ab114eae7162ab0b1aca3b


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