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/uart/uart_subr.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) 2004 Marcel Moolenaar
    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  *
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 
   34 #include <machine/bus.h>
   35 #include <machine/vmparam.h>
   36 
   37 #include <dev/uart/uart.h>
   38 #include <dev/uart/uart_cpu.h>
   39 
   40 #define UART_TAG_BR     0
   41 #define UART_TAG_CH     1
   42 #define UART_TAG_DB     2
   43 #define UART_TAG_DT     3
   44 #define UART_TAG_IO     4
   45 #define UART_TAG_MM     5
   46 #define UART_TAG_PA     6
   47 #define UART_TAG_RS     7
   48 #define UART_TAG_SB     8
   49 #define UART_TAG_XO     9
   50 
   51 static bus_addr_t
   52 uart_parse_addr(__const char **p)
   53 {
   54         return (strtoul(*p, (char**)(uintptr_t)p, 0));
   55 }
   56 
   57 static long
   58 uart_parse_long(__const char **p)
   59 {
   60         return (strtol(*p, (char**)(uintptr_t)p, 0));
   61 }
   62 
   63 static int
   64 uart_parse_parity(__const char **p)
   65 {
   66         if (!strncmp(*p, "even", 4)) {
   67                 *p += 4;
   68                 return UART_PARITY_EVEN;
   69         }
   70         if (!strncmp(*p, "mark", 4)) {
   71                 *p += 4;
   72                 return UART_PARITY_MARK;
   73         }
   74         if (!strncmp(*p, "none", 4)) {
   75                 *p += 4;
   76                 return UART_PARITY_NONE;
   77         }
   78         if (!strncmp(*p, "odd", 3)) {
   79                 *p += 3;
   80                 return UART_PARITY_ODD;
   81         }
   82         if (!strncmp(*p, "space", 5)) {
   83                 *p += 5;
   84                 return UART_PARITY_SPACE;
   85         }
   86         return (-1);
   87 }
   88 
   89 static int
   90 uart_parse_tag(__const char **p)
   91 {
   92         int tag;
   93 
   94         if ((*p)[0] == 'b' && (*p)[1] == 'r') {
   95                 tag = UART_TAG_BR;
   96                 goto out;
   97         }
   98         if ((*p)[0] == 'c' && (*p)[1] == 'h') {
   99                 tag = UART_TAG_CH;
  100                 goto out;
  101         }
  102         if ((*p)[0] == 'd' && (*p)[1] == 'b') {
  103                 tag = UART_TAG_DB;
  104                 goto out;
  105         }
  106         if ((*p)[0] == 'd' && (*p)[1] == 't') {
  107                 tag = UART_TAG_DT;
  108                 goto out;
  109         }
  110         if ((*p)[0] == 'i' && (*p)[1] == 'o') {
  111                 tag = UART_TAG_IO;
  112                 goto out;
  113         }
  114         if ((*p)[0] == 'm' && (*p)[1] == 'm') {
  115                 tag = UART_TAG_MM;
  116                 goto out;
  117         }
  118         if ((*p)[0] == 'p' && (*p)[1] == 'a') {
  119                 tag = UART_TAG_PA;
  120                 goto out;
  121         }
  122         if ((*p)[0] == 'r' && (*p)[1] == 's') {
  123                 tag = UART_TAG_RS;
  124                 goto out;
  125         }
  126         if ((*p)[0] == 's' && (*p)[1] == 'b') {
  127                 tag = UART_TAG_SB;
  128                 goto out;
  129         }
  130         if ((*p)[0] == 'x' && (*p)[1] == 'o') {
  131                 tag = UART_TAG_XO;
  132                 goto out;
  133         }
  134         return (-1);
  135 
  136 out:
  137         *p += 2;
  138         if ((*p)[0] != ':')
  139                 return (-1);
  140         (*p)++;
  141         return (tag);
  142 }
  143 
  144 /*
  145  * Parse a device specification. The specification is a list of attributes
  146  * seperated by commas. Each attribute is a tag-value pair with the tag and
  147  * value seperated by a colon. Supported tags are:
  148  *
  149  *      br = Baudrate
  150  *      ch = Channel
  151  *      db = Data bits
  152  *      dt = Device type
  153  *      io = I/O port address
  154  *      mm = Memory mapped I/O address
  155  *      pa = Parity
  156  *      rs = Register shift
  157  *      sb = Stopbits
  158  *      xo = Device clock (xtal oscillator)
  159  *
  160  * The io and mm tags are mutually exclusive.
  161  */
  162 
  163 int
  164 uart_getenv(int devtype, struct uart_devinfo *di)
  165 {
  166         __const char *spec;
  167         bus_addr_t addr = ~0U;
  168 
  169         /*
  170          * Check the environment variables "hw.uart.console" and
  171          * "hw.uart.dbgport". These variables, when present, specify
  172          * which UART port is to be used as serial console or debug
  173          * port (resp).
  174          */
  175         if (devtype == UART_DEV_CONSOLE)
  176                 spec = getenv("hw.uart.console");
  177         else if (devtype == UART_DEV_DBGPORT)
  178                 spec = getenv("hw.uart.dbgport");
  179         else
  180                 spec = NULL;
  181         if (spec == NULL)
  182                 return (ENXIO);
  183 
  184         /* Set defaults. */
  185         di->ops = uart_ns8250_ops;
  186         di->bas.chan = 0;
  187         di->bas.regshft = 0;
  188         di->bas.rclk = 0;
  189         di->baudrate = 0;
  190         di->databits = 8;
  191         di->stopbits = 1;
  192         di->parity = UART_PARITY_NONE;
  193 
  194         /* Parse the attributes. */
  195         while (1) {
  196                 switch (uart_parse_tag(&spec)) {
  197                 case UART_TAG_BR:
  198                         di->baudrate = uart_parse_long(&spec);
  199                         break;
  200                 case UART_TAG_CH:
  201                         di->bas.chan = uart_parse_long(&spec);
  202                         break;
  203                 case UART_TAG_DB:
  204                         di->databits = uart_parse_long(&spec);
  205                         break;
  206                 case UART_TAG_DT:
  207                         return (EINVAL);        /* XXX not yet implemented. */
  208                         break;
  209                 case UART_TAG_IO:
  210                         di->bas.bst = uart_bus_space_io;
  211                         addr = uart_parse_addr(&spec);
  212                         break;
  213                 case UART_TAG_MM:
  214                         di->bas.bst = uart_bus_space_mem;
  215                         addr = uart_parse_addr(&spec);
  216                         break;
  217                 case UART_TAG_PA:
  218                         di->parity = uart_parse_parity(&spec);
  219                         break;
  220                 case UART_TAG_RS:
  221                         di->bas.regshft = uart_parse_long(&spec);
  222                         break;
  223                 case UART_TAG_SB:
  224                         di->stopbits = uart_parse_long(&spec);
  225                         break;
  226                 case UART_TAG_XO:
  227                         di->bas.rclk = uart_parse_long(&spec);
  228                         break;
  229                 default:
  230                         return (EINVAL);
  231                 }
  232                 if (*spec == '\0')
  233                         break;
  234                 if (*spec != ',')
  235                         return (EINVAL);
  236                 spec++;
  237         }
  238 
  239         /*
  240          * If we still have an invalid address, the specification must be
  241          * missing an I/O port or memory address. We don't like that.
  242          */
  243         if (addr == ~0U)
  244                 return (EINVAL);
  245 
  246         /*
  247          * Accept only the well-known baudrates. Any invalid baudrate
  248          * is silently replaced with a 0-valued baudrate. The 0 baudrate
  249          * has special meaning. It means that we're not supposed to
  250          * program the baudrate and simply communicate with whatever
  251          * speed the hardware is currently programmed for.
  252          */
  253         if (di->baudrate >= 19200) {
  254                 if (di->baudrate % 19200)
  255                         di->baudrate = 0;
  256         } else if (di->baudrate >= 1200) {
  257                 if (di->baudrate % 1200)
  258                         di->baudrate = 0;
  259         } else if (di->baudrate > 0) {
  260                 if (di->baudrate % 75)
  261                         di->baudrate = 0;
  262         } else
  263                 di->baudrate = 0;
  264 
  265         /* XXX the size of the mapping depends on the UART class. */
  266         if (bus_space_map(di->bas.bst, addr, 8, 0, &di->bas.bsh) != 0)
  267                 return (EINVAL);
  268         return (0);
  269 }

Cache object: cf1e4c3e9bac3ce45e1d670d743acba2


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