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/gxemul/cons/gxemul_cons.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2011-2012 Robert N. M. Watson
    5  * All rights reserved.
    6  *
    7  * This software was developed by SRI International and the University of
    8  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
    9  * ("CTSRD"), as part of the DARPA CRASH research programme.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include <sys/param.h>
   37 #include <sys/cons.h>
   38 #include <sys/endian.h>
   39 #include <sys/kdb.h>
   40 #include <sys/systm.h>
   41 #include <sys/kernel.h>
   42 #include <sys/reboot.h>
   43 #include <sys/tty.h>
   44 
   45 #include <ddb/ddb.h>
   46 
   47 #include <machine/cpuregs.h>
   48 
   49 #define GC_LOCK_INIT()          mtx_init(&gc_lock, "gc_lock", NULL, MTX_SPIN)
   50 
   51 #define GC_LOCK() do {                                                  \
   52         if (!kdb_active)                                                \
   53                 mtx_lock_spin(&gc_lock);                                \
   54 } while (0)
   55 
   56 #define GC_LOCK_ASSERT() do {                                           \
   57         if (!kdb_active)                                                \
   58                 mtx_assert(&gc_lock, MA_OWNED);                         \
   59 } while (0)
   60 
   61 #define GC_UNLOCK() do {                                                \
   62         if (!kdb_active)                                                \
   63                 mtx_unlock_spin(&gc_lock);                              \
   64 } while (0)
   65 
   66 
   67 static struct mtx       gc_lock;
   68 
   69 /*
   70  * Low-level console driver functions.
   71  */
   72 static cn_probe_t       gxemul_cons_cnprobe;
   73 static cn_init_t        gxemul_cons_cninit;
   74 static cn_term_t        gxemul_cons_cnterm;
   75 static cn_getc_t        gxemul_cons_cngetc;
   76 static cn_putc_t        gxemul_cons_cnputc;
   77 static cn_grab_t        gxemul_cons_cngrab;
   78 static cn_ungrab_t      gxemul_cons_cnungrab;
   79 
   80 /*
   81  * TTY-level fields.
   82  */
   83 static tsw_outwakeup_t  gxemul_cons_outwakeup;
   84 
   85 static struct ttydevsw gxemul_cons_ttydevsw = {
   86         .tsw_flags      = TF_NOPREFIX,
   87         .tsw_outwakeup  = gxemul_cons_outwakeup,
   88 };
   89 
   90 static struct callout   gxemul_cons_callout;
   91 static u_int            gxemul_cons_polltime = 10;
   92 #ifdef KDB
   93 static int              gxemul_cons_alt_break_state;
   94 #endif
   95 
   96 static void             gxemul_cons_timeout(void *);
   97 
   98 /*
   99  * I/O routines lifted from Deimos.
  100  *
  101  * XXXRW: Should be using FreeBSD's bus routines here, but they are not
  102  * available until later in the boot.
  103  */
  104 
  105 static inline vm_offset_t
  106 mips_phys_to_uncached(vm_paddr_t phys)            
  107 {
  108 
  109         return (MIPS_PHYS_TO_DIRECT_UNCACHED(phys));
  110 }
  111 
  112 static inline uint8_t
  113 mips_ioread_uint8(vm_offset_t vaddr)
  114 {
  115         uint8_t v;
  116 
  117         __asm__ __volatile__ ("lbu %0, 0(%1)" : "=r" (v) : "r" (vaddr));
  118         return (v);
  119 }
  120 
  121 static inline void
  122 mips_iowrite_uint8(vm_offset_t vaddr, uint8_t v)
  123 {
  124 
  125         __asm__ __volatile__ ("sb %0, 0(%1)" : : "r" (v), "r" (vaddr));
  126 }
  127 
  128 /*
  129  * gxemul-specific constants.
  130  */
  131 #define GXEMUL_CONS_BASE        0x10000000      /* gxemul console device. */
  132 
  133 /*
  134  * Routines for interacting with the gxemul test console.  Programming details
  135  * are a result of manually inspecting the source code for gxemul's
  136  * dev_cons.cc and dev_cons.h.
  137  *
  138  * Offsets of I/O channels relative to the base.
  139  */
  140 #define GXEMUL_PUTGETCHAR_OFF           0x00000000
  141 #define GXEMUL_CONS_HALT                0x00000010
  142 
  143 /*
  144  * One-byte buffer as we can't check whether the console is readable without
  145  * actually reading from it.
  146  */
  147 static char     buffer_data;
  148 static int      buffer_valid;
  149 
  150 /*
  151  * Low-level read and write routines.
  152  */
  153 static inline uint8_t
  154 gxemul_cons_data_read(void)
  155 {
  156 
  157         return (mips_ioread_uint8(mips_phys_to_uncached(GXEMUL_CONS_BASE +
  158             GXEMUL_PUTGETCHAR_OFF)));
  159 }
  160 
  161 static inline void
  162 gxemul_cons_data_write(uint8_t v)
  163 {
  164 
  165         mips_iowrite_uint8(mips_phys_to_uncached(GXEMUL_CONS_BASE +
  166             GXEMUL_PUTGETCHAR_OFF), v);
  167 }
  168 
  169 static int
  170 gxemul_cons_writable(void)
  171 {
  172 
  173         return (1);
  174 }
  175 
  176 static int
  177 gxemul_cons_readable(void)
  178 {
  179         uint32_t v;
  180 
  181         GC_LOCK_ASSERT();
  182 
  183         if (buffer_valid)
  184                 return (1);
  185         v = gxemul_cons_data_read();
  186         if (v != 0) {
  187                 buffer_valid = 1;
  188                 buffer_data = v;
  189                 return (1);
  190         }
  191         return (0);
  192 }
  193 
  194 static void
  195 gxemul_cons_write(char ch)
  196 {
  197 
  198         GC_LOCK_ASSERT();
  199 
  200         while (!gxemul_cons_writable());
  201         gxemul_cons_data_write(ch);
  202 }
  203 
  204 static char
  205 gxemul_cons_read(void)
  206 {
  207 
  208         GC_LOCK_ASSERT();
  209 
  210         while (!gxemul_cons_readable());
  211         buffer_valid = 0;
  212         return (buffer_data);
  213 }
  214 
  215 /*
  216  * Implementation of a FreeBSD low-level, polled console driver.
  217  */
  218 static void
  219 gxemul_cons_cnprobe(struct consdev *cp)
  220 {
  221 
  222         sprintf(cp->cn_name, "ttyu0");
  223         cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL;
  224 }
  225 
  226 static void
  227 gxemul_cons_cninit(struct consdev *cp)
  228 {
  229 
  230         GC_LOCK_INIT();
  231 }
  232 
  233 static void
  234 gxemul_cons_cnterm(struct consdev *cp)
  235 {
  236 
  237 }
  238 
  239 static int
  240 gxemul_cons_cngetc(struct consdev *cp)
  241 {
  242         int ret;
  243 
  244         GC_LOCK();
  245         ret = gxemul_cons_read();
  246         GC_UNLOCK();
  247         return (ret);
  248 }
  249 
  250 static void
  251 gxemul_cons_cnputc(struct consdev *cp, int c)
  252 {
  253 
  254         GC_LOCK();
  255         gxemul_cons_write(c);
  256         GC_UNLOCK();
  257 }
  258 
  259 static void
  260 gxemul_cons_cngrab(struct consdev *cp)
  261 {
  262 
  263 }
  264 
  265 static void
  266 gxemul_cons_cnungrab(struct consdev *cp)
  267 {
  268 
  269 }
  270 
  271 CONSOLE_DRIVER(gxemul_cons);
  272 
  273 /*
  274  * TTY-level functions for gxemul_cons.
  275  */
  276 static void
  277 gxemul_cons_ttyinit(void *unused)
  278 {
  279         struct tty *tp;
  280 
  281         tp = tty_alloc(&gxemul_cons_ttydevsw, NULL);
  282         tty_init_console(tp, 0);
  283         tty_makedev(tp, NULL, "%s", "ttyu0");
  284         callout_init(&gxemul_cons_callout, 1);
  285         callout_reset(&gxemul_cons_callout, gxemul_cons_polltime,
  286             gxemul_cons_timeout, tp);
  287 
  288 }
  289 SYSINIT(gxemul_cons_ttyinit, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE,
  290     gxemul_cons_ttyinit, NULL);
  291 
  292 static void
  293 gxemul_cons_outwakeup(struct tty *tp)
  294 {
  295         int len;
  296         u_char ch;
  297 
  298         /*
  299          * XXXRW: Would be nice not to do blocking writes to the console here,
  300          * rescheduling on our timer tick if work remains to be done..
  301          */
  302         for (;;) {
  303                 len = ttydisc_getc(tp, &ch, sizeof(ch));
  304                 if (len == 0)
  305                         break;
  306                 GC_LOCK();
  307                 gxemul_cons_write(ch);
  308                 GC_UNLOCK();
  309         }
  310 }
  311 
  312 static void
  313 gxemul_cons_timeout(void *v)
  314 {
  315         struct tty *tp;
  316         int c;
  317 
  318         tp = v;
  319         tty_lock(tp);
  320         GC_LOCK();
  321         while (gxemul_cons_readable()) {
  322                 c = gxemul_cons_read();
  323                 GC_UNLOCK();
  324 #ifdef KDB
  325                 kdb_alt_break(c, &gxemul_cons_alt_break_state);
  326 #endif
  327                 ttydisc_rint(tp, c, 0);
  328                 GC_LOCK();
  329         }
  330         GC_UNLOCK();
  331         ttydisc_rint_done(tp);
  332         tty_unlock(tp);
  333         callout_reset(&gxemul_cons_callout, gxemul_cons_polltime,
  334             gxemul_cons_timeout, tp);
  335 }

Cache object: fd86f71b7c54f3c6c5ae0e1906fde8ad


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