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/riscv/htif/htif_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) 2015-2016 Ruslan Bukin <br@bsdpad.com>
    3  * All rights reserved.
    4  *
    5  * Portions of this software were developed by SRI International and the
    6  * University of Cambridge Computer Laboratory under DARPA/AFRL contract
    7  * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
    8  *
    9  * Portions of this software were developed by the University of Cambridge
   10  * Computer Laboratory as part of the CTSRD Project, with support from the
   11  * UK Higher Education Innovation Fund (HEIF).
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD$");
   37 
   38 #include <sys/param.h>
   39 #include <sys/kdb.h>
   40 #include <sys/kernel.h>
   41 #include <sys/priv.h>
   42 #include <sys/systm.h>
   43 #include <sys/types.h>
   44 #include <sys/conf.h>
   45 #include <sys/cons.h>
   46 #include <sys/consio.h>
   47 #include <sys/tty.h>
   48 #include <sys/bus.h>
   49 #include <sys/module.h>
   50 
   51 #include <machine/bus.h>
   52 #include <machine/trap.h>
   53 
   54 #include "htif.h"
   55 
   56 #include <dev/ofw/openfirm.h>
   57 
   58 #include <ddb/ddb.h>
   59 
   60 extern uint64_t console_intr;
   61 
   62 static tsw_outwakeup_t riscvtty_outwakeup;
   63 
   64 static struct ttydevsw riscv_ttydevsw = {
   65         .tsw_flags      = TF_NOPREFIX,
   66         .tsw_outwakeup  = riscvtty_outwakeup,
   67 };
   68 
   69 static int                      polltime;
   70 static struct callout           riscv_callout;
   71 static struct tty               *tp = NULL;
   72 
   73 #if defined(KDB)
   74 static int                      alt_break_state;
   75 #endif
   76 
   77 static void     riscv_timeout(void *);
   78 
   79 static cn_probe_t       riscv_cnprobe;
   80 static cn_init_t        riscv_cninit;
   81 static cn_term_t        riscv_cnterm;
   82 static cn_getc_t        riscv_cngetc;
   83 static cn_putc_t        riscv_cnputc;
   84 static cn_grab_t        riscv_cngrab;
   85 static cn_ungrab_t      riscv_cnungrab;
   86 
   87 CONSOLE_DRIVER(riscv);
   88 
   89 #define MAX_BURST_LEN           1
   90 #define QUEUE_SIZE              256
   91 #define CONSOLE_DEFAULT_ID      1ul
   92 #define SPIN_IN_MACHINE_MODE    1
   93 
   94 struct queue_entry {
   95         uint64_t data;
   96         uint64_t used;
   97         struct queue_entry *next;
   98 };
   99 
  100 struct queue_entry cnqueue[QUEUE_SIZE];
  101 struct queue_entry *entry_last;
  102 struct queue_entry *entry_served;
  103 
  104 static void
  105 htif_putc(int c)
  106 {
  107         uint64_t cmd;
  108 
  109         cmd = (HTIF_CMD_WRITE << HTIF_CMD_SHIFT);
  110         cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT);
  111         cmd |= c;
  112 
  113 #ifdef SPIN_IN_MACHINE_MODE
  114         machine_command(ECALL_HTIF_LOWPUTC, cmd);
  115 #else
  116         htif_command(cmd);
  117 #endif
  118 
  119 }
  120 
  121 static uint8_t
  122 htif_getc(void)
  123 {
  124         uint64_t cmd;
  125         uint8_t res;
  126 
  127         cmd = (HTIF_CMD_READ << HTIF_CMD_SHIFT);
  128         cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT);
  129 
  130         res = htif_command(cmd);
  131 
  132         return (res);
  133 }
  134 
  135 static void
  136 riscv_putc(int c)
  137 {
  138         uint64_t counter;
  139         uint64_t *cc;
  140         uint64_t val;
  141 
  142         val = 0;
  143         counter = 0;
  144 
  145         cc = (uint64_t*)&console_intr;
  146         *cc = 0;
  147 
  148         htif_putc(c);
  149 
  150 #ifndef SPIN_IN_MACHINE_MODE
  151         /* Wait for an interrupt */
  152         __asm __volatile(
  153                 "li     %0, 1\n"        /* counter = 1 */
  154                 "slli   %0, %0, 12\n"   /* counter <<= 12 */
  155         "1:"
  156                 "addi   %0, %0, -1\n"   /* counter -= 1 */
  157                 "beqz   %0, 2f\n"       /* counter == 0 ? finish */
  158                 "ld     %1, 0(%2)\n"    /* val = *cc */
  159                 "beqz   %1, 1b\n"       /* val == 0 ? repeat */
  160         "2:"
  161                 : "=&r"(counter), "=&r"(val) : "r"(cc)
  162         );
  163 #endif
  164 }
  165 
  166 #ifdef EARLY_PRINTF
  167 early_putc_t *early_putc = riscv_putc;
  168 #endif
  169 
  170 static void
  171 cn_drvinit(void *unused)
  172 {
  173 
  174         if (riscv_consdev.cn_pri != CN_DEAD &&
  175             riscv_consdev.cn_name[0] != '\0') {
  176                 tp = tty_alloc(&riscv_ttydevsw, NULL);
  177                 tty_init_console(tp, 0);
  178                 tty_makedev(tp, NULL, "%s", "rcons");
  179 
  180                 polltime = 1;
  181 
  182                 callout_init(&riscv_callout, 1);
  183                 callout_reset(&riscv_callout, polltime, riscv_timeout, NULL);
  184         }
  185 }
  186 
  187 SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL);
  188 
  189 static void
  190 riscvtty_outwakeup(struct tty *tp)
  191 {
  192         u_char buf[MAX_BURST_LEN];
  193         int len;
  194         int i;
  195 
  196         for (;;) {
  197                 len = ttydisc_getc(tp, buf, sizeof(buf));
  198                 if (len == 0)
  199                         break;
  200 
  201                 KASSERT(len == 1, ("tty error"));
  202 
  203                 for (i = 0; i < len; i++)
  204                         riscv_putc(buf[i]);
  205         }
  206 }
  207 
  208 static void
  209 riscv_timeout(void *v)
  210 {
  211         int c;
  212 
  213         tty_lock(tp);
  214         while ((c = riscv_cngetc(NULL)) != -1)
  215                 ttydisc_rint(tp, c, 0);
  216         ttydisc_rint_done(tp);
  217         tty_unlock(tp);
  218 
  219         callout_reset(&riscv_callout, polltime, riscv_timeout, NULL);
  220 }
  221 
  222 static void
  223 riscv_cnprobe(struct consdev *cp)
  224 {
  225 
  226         cp->cn_pri = CN_NORMAL;
  227 }
  228 
  229 static void
  230 riscv_cninit(struct consdev *cp)
  231 {
  232         int i;
  233 
  234         strcpy(cp->cn_name, "rcons");
  235 
  236         for (i = 0; i < QUEUE_SIZE; i++) {
  237                 if (i == (QUEUE_SIZE - 1))
  238                         cnqueue[i].next = &cnqueue[0];
  239                 else
  240                         cnqueue[i].next = &cnqueue[i+1];
  241                 cnqueue[i].data = 0;
  242                 cnqueue[i].used = 0;
  243         }
  244 
  245         entry_last = &cnqueue[0];
  246         entry_served = &cnqueue[0];
  247 }
  248 
  249 static void
  250 riscv_cnterm(struct consdev *cp)
  251 {
  252 
  253 }
  254 
  255 static void
  256 riscv_cngrab(struct consdev *cp)
  257 {
  258 
  259 }
  260 
  261 static void
  262 riscv_cnungrab(struct consdev *cp)
  263 {
  264 
  265 }
  266 
  267 static int
  268 riscv_cngetc(struct consdev *cp)
  269 {
  270 #if defined(KDB)
  271         uint64_t devcmd;
  272         uint64_t entry;
  273         uint64_t devid;
  274 #endif
  275         uint8_t data;
  276         int ch;
  277 
  278         htif_getc();
  279 
  280 #if defined(KDB)
  281         if (kdb_active) {
  282                 entry = machine_command(ECALL_HTIF_GET_ENTRY, 0);
  283                 while (entry) {
  284                         devid = HTIF_DEV_ID(entry);
  285                         devcmd = HTIF_DEV_CMD(entry);
  286                         data = HTIF_DEV_DATA(entry);
  287 
  288                         if (devid == CONSOLE_DEFAULT_ID && devcmd == 0) {
  289                                 entry_last->data = data;
  290                                 entry_last->used = 1;
  291                                 entry_last = entry_last->next;
  292                         } else {
  293                                 printf("Lost interrupt: devid %d\n",
  294                                     devid);
  295                         }
  296 
  297                         entry = machine_command(ECALL_HTIF_GET_ENTRY, 0);
  298                 }
  299         }
  300 #endif
  301 
  302         if (entry_served->used == 1) {
  303                 data = entry_served->data;
  304                 entry_served->used = 0;
  305                 entry_served = entry_served->next;
  306                 ch = (data & 0xff);
  307                 if (ch > 0 && ch < 0xff) {
  308 #if defined(KDB)
  309                         kdb_alt_break(ch, &alt_break_state);
  310 #endif
  311                         return (ch);
  312                 }
  313         }
  314 
  315         return (-1);
  316 }
  317 
  318 static void
  319 riscv_cnputc(struct consdev *cp, int c)
  320 {
  321 
  322         riscv_putc(c);
  323 }
  324 
  325 /*
  326  * Bus interface.
  327  */
  328 
  329 struct htif_console_softc {
  330         device_t        dev;
  331         int             running;
  332         int             intr_chan;
  333         int             cmd_done;
  334         int             curtag;
  335         int             index;
  336 };
  337 
  338 static void
  339 htif_console_intr(void *arg, uint64_t entry)
  340 {
  341         struct htif_console_softc *sc;
  342         uint8_t devcmd;
  343         uint64_t data;
  344 
  345         sc = arg;
  346 
  347         devcmd = HTIF_DEV_CMD(entry);
  348         data = HTIF_DEV_DATA(entry);
  349 
  350         if (devcmd == 0) {
  351                 entry_last->data = data;
  352                 entry_last->used = 1;
  353                 entry_last = entry_last->next;
  354         }
  355 }
  356 
  357 static int
  358 htif_console_probe(device_t dev)
  359 {
  360 
  361         return (0);
  362 }
  363 
  364 static int
  365 htif_console_attach(device_t dev)
  366 {
  367         struct htif_console_softc *sc;
  368 
  369         sc = device_get_softc(dev);
  370         sc->dev = dev;
  371 
  372         sc->index = htif_get_index(dev);
  373         if (sc->index < 0)
  374                 return (EINVAL);
  375 
  376         htif_setup_intr(sc->index, htif_console_intr, sc);
  377 
  378         return (0);
  379 }
  380 
  381 static device_method_t htif_console_methods[] = {
  382         DEVMETHOD(device_probe,         htif_console_probe),
  383         DEVMETHOD(device_attach,        htif_console_attach),
  384         DEVMETHOD_END
  385 };
  386 
  387 static driver_t htif_console_driver = {
  388         "htif_console",
  389         htif_console_methods,
  390         sizeof(struct htif_console_softc)
  391 };
  392 
  393 static devclass_t htif_console_devclass;
  394 
  395 DRIVER_MODULE(htif_console, htif, htif_console_driver,
  396     htif_console_devclass, 0, 0);

Cache object: b17b71f49099aae81a6656ba760e7fc5


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