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_core.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) 2003 Marcel Moolenaar
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  *
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/bus.h>
   35 #include <sys/conf.h>
   36 #include <sys/cons.h>
   37 #include <sys/fcntl.h>
   38 #include <sys/interrupt.h>
   39 #include <sys/kdb.h>
   40 #include <sys/kernel.h>
   41 #include <sys/malloc.h>
   42 #include <sys/queue.h>
   43 #include <sys/reboot.h>
   44 #include <sys/sysctl.h>
   45 #include <machine/bus.h>
   46 #include <sys/rman.h>
   47 #include <machine/resource.h>
   48 #include <machine/stdarg.h>
   49 
   50 #include <dev/uart/uart.h>
   51 #include <dev/uart/uart_bus.h>
   52 #include <dev/uart/uart_cpu.h>
   53 #include <dev/uart/uart_ppstypes.h>
   54 
   55 #include "uart_if.h"
   56 
   57 const char uart_driver_name[] = "uart";
   58 
   59 SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs =
   60     SLIST_HEAD_INITIALIZER(uart_sysdevs);
   61 
   62 static MALLOC_DEFINE(M_UART, "UART", "UART driver");
   63 
   64 #ifndef UART_POLL_FREQ
   65 #define UART_POLL_FREQ          50
   66 #endif
   67 static int uart_poll_freq = UART_POLL_FREQ;
   68 SYSCTL_INT(_debug, OID_AUTO, uart_poll_freq, CTLFLAG_RDTUN, &uart_poll_freq,
   69     0, "UART poll frequency");
   70 
   71 static int uart_force_poll;
   72 SYSCTL_INT(_debug, OID_AUTO, uart_force_poll, CTLFLAG_RDTUN, &uart_force_poll,
   73     0, "Force UART polling");
   74 
   75 static inline int
   76 uart_pps_mode_valid(int pps_mode)
   77 {
   78         int opt;
   79 
   80         switch(pps_mode & UART_PPS_SIGNAL_MASK) {
   81         case UART_PPS_DISABLED:
   82         case UART_PPS_CTS:
   83         case UART_PPS_DCD:
   84                 break;
   85         default:
   86                 return (false);
   87         }
   88 
   89         opt = pps_mode & UART_PPS_OPTION_MASK;
   90         if ((opt & ~(UART_PPS_INVERT_PULSE | UART_PPS_NARROW_PULSE)) != 0)
   91                 return (false);
   92 
   93         return (true);
   94 }
   95 
   96 static void
   97 uart_pps_print_mode(struct uart_softc *sc)
   98 {
   99 
  100         device_printf(sc->sc_dev, "PPS capture mode: ");
  101         switch(sc->sc_pps_mode & UART_PPS_SIGNAL_MASK) {
  102         case UART_PPS_DISABLED:
  103                 printf("disabled");
  104                 break;
  105         case UART_PPS_CTS:
  106                 printf("CTS");
  107                 break;
  108         case UART_PPS_DCD:
  109                 printf("DCD");
  110                 break;
  111         default:
  112                 printf("invalid");
  113                 break;
  114         }
  115         if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE)
  116                 printf("-Inverted");
  117         if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE)
  118                 printf("-NarrowPulse");
  119         printf("\n");
  120 }
  121 
  122 static int
  123 uart_pps_mode_sysctl(SYSCTL_HANDLER_ARGS)
  124 {
  125         struct uart_softc *sc;
  126         int err, tmp;
  127 
  128         sc = arg1;
  129         tmp = sc->sc_pps_mode;
  130         err = sysctl_handle_int(oidp, &tmp, 0, req);
  131         if (err != 0 || req->newptr == NULL)
  132                 return (err);
  133         if (!uart_pps_mode_valid(tmp))
  134                 return (EINVAL);
  135         sc->sc_pps_mode = tmp;
  136         return(0);
  137 }
  138 
  139 static void
  140 uart_pps_process(struct uart_softc *sc, int ser_sig)
  141 {
  142         sbintime_t now;
  143         int is_assert, pps_sig;
  144 
  145         /* Which signal is configured as PPS?  Early out if none. */
  146         switch(sc->sc_pps_mode & UART_PPS_SIGNAL_MASK) {
  147         case UART_PPS_CTS:
  148                 pps_sig = SER_CTS;
  149                 break;
  150         case UART_PPS_DCD:
  151                 pps_sig = SER_DCD;
  152                 break;
  153         default:
  154                 return;
  155         }
  156 
  157         /* Early out if there is no change in the signal configured as PPS. */
  158         if ((ser_sig & SER_DELTA(pps_sig)) == 0)
  159                 return;
  160 
  161         /*
  162          * In narrow-pulse mode we need to synthesize both capture and clear
  163          * events from a single "delta occurred" indication from the uart
  164          * hardware because the pulse width is too narrow to reliably detect
  165          * both edges.  However, when the pulse width is close to our interrupt
  166          * processing latency we might intermittantly catch both edges.  To
  167          * guard against generating spurious events when that happens, we use a
  168          * separate timer to ensure at least half a second elapses before we
  169          * generate another event.
  170          */
  171         pps_capture(&sc->sc_pps);
  172         if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) {
  173                 now = getsbinuptime();
  174                 if (now > sc->sc_pps_captime + 500 * SBT_1MS) {
  175                         sc->sc_pps_captime = now;
  176                         pps_event(&sc->sc_pps, PPS_CAPTUREASSERT);
  177                         pps_event(&sc->sc_pps, PPS_CAPTURECLEAR);
  178                 }
  179         } else  {
  180                 is_assert = ser_sig & pps_sig;
  181                 if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE)
  182                         is_assert = !is_assert;
  183                 pps_event(&sc->sc_pps, is_assert ? PPS_CAPTUREASSERT :
  184                     PPS_CAPTURECLEAR);
  185         }
  186 }
  187 
  188 static void
  189 uart_pps_init(struct uart_softc *sc)
  190 {
  191         struct sysctl_ctx_list *ctx;
  192         struct sysctl_oid *tree;
  193 
  194         ctx = device_get_sysctl_ctx(sc->sc_dev);
  195         tree = device_get_sysctl_tree(sc->sc_dev);
  196 
  197         /*
  198          * The historical default for pps capture mode is either DCD or CTS,
  199          * depending on the UART_PPS_ON_CTS kernel option.  Start with that,
  200          * then try to fetch the tunable that overrides the mode for all uart
  201          * devices, then try to fetch the sysctl-tunable that overrides the mode
  202          * for one specific device.
  203          */
  204 #ifdef UART_PPS_ON_CTS
  205         sc->sc_pps_mode = UART_PPS_CTS;
  206 #else
  207         sc->sc_pps_mode = UART_PPS_DCD;
  208 #endif
  209         TUNABLE_INT_FETCH("hw.uart.pps_mode", &sc->sc_pps_mode);
  210         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "pps_mode",
  211             CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, sc, 0,
  212             uart_pps_mode_sysctl, "I", "pulse mode: 0/1/2=disabled/CTS/DCD; "
  213             "add 0x10 to invert, 0x20 for narrow pulse");
  214 
  215         if (!uart_pps_mode_valid(sc->sc_pps_mode)) {
  216                 device_printf(sc->sc_dev, 
  217                     "Invalid pps_mode 0x%02x configured; disabling PPS capture\n",
  218                     sc->sc_pps_mode);
  219                 sc->sc_pps_mode = UART_PPS_DISABLED;
  220         } else if (bootverbose) {
  221                 uart_pps_print_mode(sc);
  222         }
  223 
  224         sc->sc_pps.ppscap = PPS_CAPTUREBOTH;
  225         sc->sc_pps.driver_mtx = uart_tty_getlock(sc);
  226         sc->sc_pps.driver_abi = PPS_ABI_VERSION;
  227         pps_init_abi(&sc->sc_pps);
  228 }
  229 
  230 void
  231 uart_add_sysdev(struct uart_devinfo *di)
  232 {
  233         SLIST_INSERT_HEAD(&uart_sysdevs, di, next);
  234 }
  235 
  236 const char *
  237 uart_getname(struct uart_class *uc)
  238 {
  239         return ((uc != NULL) ? uc->name : NULL);
  240 }
  241 
  242 struct uart_ops *
  243 uart_getops(struct uart_class *uc)
  244 {
  245         return ((uc != NULL) ? uc->uc_ops : NULL);
  246 }
  247 
  248 int
  249 uart_getrange(struct uart_class *uc)
  250 {
  251         return ((uc != NULL) ? uc->uc_range : 0);
  252 }
  253 
  254 u_int
  255 uart_getregshift(struct uart_class *uc)
  256 {
  257         return ((uc != NULL) ? uc->uc_rshift : 0);
  258 }
  259 
  260 u_int
  261 uart_getregiowidth(struct uart_class *uc)
  262 {
  263         return ((uc != NULL) ? uc->uc_riowidth : 0);
  264 }
  265 
  266 /*
  267  * Schedule a soft interrupt. We do this on the 0 to !0 transition
  268  * of the TTY pending interrupt status.
  269  */
  270 void
  271 uart_sched_softih(struct uart_softc *sc, uint32_t ipend)
  272 {
  273         uint32_t new, old;
  274 
  275         do {
  276                 old = sc->sc_ttypend;
  277                 new = old | ipend;
  278         } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new));
  279 
  280         if ((old & SER_INT_MASK) == 0)
  281                 swi_sched(sc->sc_softih, 0);
  282 }
  283 
  284 /*
  285  * A break condition has been detected. We treat the break condition as
  286  * a special case that should not happen during normal operation. When
  287  * the break condition is to be passed to higher levels in the form of
  288  * a NUL character, we really want the break to be in the right place in
  289  * the input stream. The overhead to achieve that is not in relation to
  290  * the exceptional nature of the break condition, so we permit ourselves
  291  * to be sloppy.
  292  */
  293 static __inline int
  294 uart_intr_break(void *arg)
  295 {
  296         struct uart_softc *sc = arg;
  297 
  298 #if defined(KDB)
  299         if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
  300                 if (kdb_break())
  301                         return (0);
  302         }
  303 #endif
  304         if (sc->sc_opened)
  305                 uart_sched_softih(sc, SER_INT_BREAK);
  306         return (0);
  307 }
  308 
  309 /*
  310  * Handle a receiver overrun situation. We lost at least 1 byte in the
  311  * input stream and it's our job to contain the situation. We grab as
  312  * much of the data we can, but otherwise flush the receiver FIFO to
  313  * create some breathing room. The net effect is that we avoid the
  314  * overrun condition to happen for the next X characters, where X is
  315  * related to the FIFO size at the cost of losing data right away.
  316  * So, instead of having multiple overrun interrupts in close proximity
  317  * to each other and possibly pessimizing UART interrupt latency for
  318  * other UARTs in a multiport configuration, we create a longer segment
  319  * of missing characters by freeing up the FIFO.
  320  * Each overrun condition is marked in the input buffer by a token. The
  321  * token represents the loss of at least one, but possible more bytes in
  322  * the input stream.
  323  */
  324 static __inline int
  325 uart_intr_overrun(void *arg)
  326 {
  327         struct uart_softc *sc = arg;
  328 
  329         if (sc->sc_opened) {
  330                 UART_RECEIVE(sc);
  331                 if (uart_rx_put(sc, UART_STAT_OVERRUN))
  332                         sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
  333                 uart_sched_softih(sc, SER_INT_RXREADY);
  334         }
  335         sc->sc_rxoverruns++;
  336         UART_FLUSH(sc, UART_FLUSH_RECEIVER);
  337         return (0);
  338 }
  339 
  340 /*
  341  * Received data ready.
  342  */
  343 static __inline int
  344 uart_intr_rxready(void *arg)
  345 {
  346         struct uart_softc *sc = arg;
  347 #if defined(KDB)
  348         int rxp;
  349 
  350         rxp = sc->sc_rxput;
  351 #endif
  352         UART_RECEIVE(sc);
  353 #if defined(KDB)
  354         if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
  355                 while (rxp != sc->sc_rxput) {
  356                         kdb_alt_break(sc->sc_rxbuf[rxp++], &sc->sc_altbrk);
  357                         if (rxp == sc->sc_rxbufsz)
  358                                 rxp = 0;
  359                 }
  360         }
  361 #endif
  362         if (sc->sc_opened)
  363                 uart_sched_softih(sc, SER_INT_RXREADY);
  364         else
  365                 sc->sc_rxput = sc->sc_rxget;    /* Ignore received data. */
  366         return (1);
  367 }
  368 
  369 /*
  370  * Line or modem status change (OOB signalling).
  371  * We pass the signals to the software interrupt handler for further
  372  * processing. Note that we merge the delta bits, but set the state
  373  * bits. This is to avoid losing state transitions due to having more
  374  * than 1 hardware interrupt between software interrupts.
  375  */
  376 static __inline int
  377 uart_intr_sigchg(void *arg)
  378 {
  379         struct uart_softc *sc = arg;
  380         int new, old, sig;
  381 
  382         sig = UART_GETSIG(sc);
  383 
  384         /*
  385          * Time pulse counting support, invoked whenever the PPS parameters are
  386          * currently set to capture either edge of the signal.
  387          */
  388         if (sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) {
  389                 uart_pps_process(sc, sig);
  390         }
  391 
  392         /*
  393          * Keep track of signal changes, even when the device is not
  394          * opened. This allows us to inform upper layers about a
  395          * possible loss of DCD and thus the existence of a (possibly)
  396          * different connection when we have DCD back, during the time
  397          * that the device was closed.
  398          */
  399         do {
  400                 old = sc->sc_ttypend;
  401                 new = old & ~SER_MASK_STATE;
  402                 new |= sig & SER_INT_SIGMASK;
  403         } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new));
  404 
  405         if (sc->sc_opened)
  406                 uart_sched_softih(sc, SER_INT_SIGCHG);
  407         return (1);
  408 }
  409 
  410 /*
  411  * The transmitter can accept more data.
  412  */
  413 static __inline int
  414 uart_intr_txidle(void *arg)
  415 {
  416         struct uart_softc *sc = arg;
  417 
  418         if (sc->sc_txbusy) {
  419                 sc->sc_txbusy = 0;
  420                 uart_sched_softih(sc, SER_INT_TXIDLE);
  421         }
  422         return (0);
  423 }
  424 
  425 static int
  426 uart_intr(void *arg)
  427 {
  428         struct uart_softc *sc = arg;
  429         int cnt, ipend, testintr;
  430 
  431         if (sc->sc_leaving)
  432                 return (FILTER_STRAY);
  433 
  434         cnt = 0;
  435         testintr = sc->sc_testintr;
  436         while ((!testintr || cnt < 20) && (ipend = UART_IPEND(sc)) != 0) {
  437                 cnt++;
  438                 if (ipend & SER_INT_OVERRUN)
  439                         uart_intr_overrun(sc);
  440                 if (ipend & SER_INT_BREAK)
  441                         uart_intr_break(sc);
  442                 if (ipend & SER_INT_RXREADY)
  443                         uart_intr_rxready(sc);
  444                 if (ipend & SER_INT_SIGCHG)
  445                         uart_intr_sigchg(sc);
  446                 if (ipend & SER_INT_TXIDLE)
  447                         uart_intr_txidle(sc);
  448         }
  449 
  450         if (sc->sc_polled) {
  451                 callout_reset(&sc->sc_timer, hz / uart_poll_freq,
  452                     (callout_func_t *)uart_intr, sc);
  453         }
  454 
  455         return ((cnt == 0) ? FILTER_STRAY :
  456             ((testintr && cnt == 20) ? FILTER_SCHEDULE_THREAD :
  457             FILTER_HANDLED));
  458 }
  459 
  460 serdev_intr_t *
  461 uart_bus_ihand(device_t dev, int ipend)
  462 {
  463 
  464         switch (ipend) {
  465         case SER_INT_BREAK:
  466                 return (uart_intr_break);
  467         case SER_INT_OVERRUN:
  468                 return (uart_intr_overrun);
  469         case SER_INT_RXREADY:
  470                 return (uart_intr_rxready);
  471         case SER_INT_SIGCHG:
  472                 return (uart_intr_sigchg);
  473         case SER_INT_TXIDLE:
  474                 return (uart_intr_txidle);
  475         }
  476         return (NULL);
  477 }
  478 
  479 int
  480 uart_bus_ipend(device_t dev)
  481 {
  482         struct uart_softc *sc;
  483 
  484         sc = device_get_softc(dev);
  485         return (UART_IPEND(sc));
  486 }
  487 
  488 int
  489 uart_bus_sysdev(device_t dev)
  490 {
  491         struct uart_softc *sc;
  492 
  493         sc = device_get_softc(dev);
  494         return ((sc->sc_sysdev != NULL) ? 1 : 0);
  495 }
  496 
  497 int
  498 uart_bus_probe(device_t dev, int regshft, int regiowidth, int rclk, int rid, int chan, int quirks)
  499 {
  500         struct uart_softc *sc;
  501         struct uart_devinfo *sysdev;
  502         int error;
  503 
  504         sc = device_get_softc(dev);
  505 
  506         /*
  507          * All uart_class references are weak. Check that the needed
  508          * class has been compiled-in. Fail if not.
  509          */
  510         if (sc->sc_class == NULL)
  511                 return (ENXIO);
  512 
  513         /*
  514          * Initialize the instance. Note that the instance (=softc) does
  515          * not necessarily match the hardware specific softc. We can't do
  516          * anything about it now, because we may not attach to the device.
  517          * Hardware drivers cannot use any of the class specific fields
  518          * while probing.
  519          */
  520         kobj_init((kobj_t)sc, (kobj_class_t)sc->sc_class);
  521         sc->sc_dev = dev;
  522         if (device_get_desc(dev) == NULL)
  523                 device_set_desc(dev, uart_getname(sc->sc_class));
  524 
  525         /*
  526          * Allocate the register resource. We assume that all UARTs have
  527          * a single register window in either I/O port space or memory
  528          * mapped I/O space. Any UART that needs multiple windows will
  529          * consequently not be supported by this driver as-is. We try I/O
  530          * port space first because that's the common case.
  531          */
  532         sc->sc_rrid = rid;
  533         sc->sc_rtype = SYS_RES_IOPORT;
  534         sc->sc_rres = bus_alloc_resource_any(dev, sc->sc_rtype, &sc->sc_rrid,
  535             RF_ACTIVE);
  536         if (sc->sc_rres == NULL) {
  537                 sc->sc_rrid = rid;
  538                 sc->sc_rtype = SYS_RES_MEMORY;
  539                 sc->sc_rres = bus_alloc_resource_any(dev, sc->sc_rtype,
  540                     &sc->sc_rrid, RF_ACTIVE);
  541                 if (sc->sc_rres == NULL)
  542                         return (ENXIO);
  543         }
  544 
  545         /*
  546          * Fill in the bus access structure and compare this device with
  547          * a possible console device and/or a debug port. We set the flags
  548          * in the softc so that the hardware dependent probe can adjust
  549          * accordingly. In general, you don't want to permanently disrupt
  550          * console I/O.
  551          */
  552         sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
  553         sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
  554         sc->sc_bas.chan = chan;
  555         sc->sc_bas.regshft = regshft;
  556         sc->sc_bas.regiowidth = regiowidth;
  557         sc->sc_bas.rclk = (rclk == 0) ? sc->sc_class->uc_rclk : rclk;
  558         sc->sc_bas.busy_detect = !!(quirks & UART_F_BUSY_DETECT);
  559 
  560         SLIST_FOREACH(sysdev, &uart_sysdevs, next) {
  561                 if (chan == sysdev->bas.chan &&
  562                     uart_cpu_eqres(&sc->sc_bas, &sysdev->bas)) {
  563                         /* XXX check if ops matches class. */
  564                         sc->sc_sysdev = sysdev;
  565                         sysdev->bas.rclk = sc->sc_bas.rclk;
  566                 }
  567         }
  568 
  569         error = UART_PROBE(sc);
  570         bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
  571         return ((error) ? error : BUS_PROBE_DEFAULT);
  572 }
  573 
  574 int
  575 uart_bus_attach(device_t dev)
  576 {
  577         struct uart_softc *sc, *sc0;
  578         const char *sep;
  579         int error, filt;
  580 
  581         /*
  582          * The sc_class field defines the type of UART we're going to work
  583          * with and thus the size of the softc. Replace the generic softc
  584          * with one that matches the UART now that we're certain we handle
  585          * the device.
  586          */
  587         sc0 = device_get_softc(dev);
  588         if (sc0->sc_class->size > device_get_driver(dev)->size) {
  589                 sc = malloc(sc0->sc_class->size, M_UART, M_WAITOK|M_ZERO);
  590                 bcopy(sc0, sc, sizeof(*sc));
  591                 device_set_softc(dev, sc);
  592         } else
  593                 sc = sc0;
  594 
  595         /*
  596          * Now that we know the softc for this device, connect the back
  597          * pointer from the sysdev for this device, if any
  598          */
  599         if (sc->sc_sysdev != NULL)
  600                 sc->sc_sysdev->sc = sc;
  601 
  602         /*
  603          * Protect ourselves against interrupts while we're not completely
  604          * finished attaching and initializing. We don't expect interrupts
  605          * until after UART_ATTACH(), though.
  606          */
  607         sc->sc_leaving = 1;
  608 
  609         mtx_init(&sc->sc_hwmtx_s, "uart_hwmtx", NULL, MTX_SPIN);
  610         if (sc->sc_hwmtx == NULL)
  611                 sc->sc_hwmtx = &sc->sc_hwmtx_s;
  612 
  613         /*
  614          * Re-allocate. We expect that the softc contains the information
  615          * collected by uart_bus_probe() intact.
  616          */
  617         sc->sc_rres = bus_alloc_resource_any(dev, sc->sc_rtype, &sc->sc_rrid,
  618             RF_ACTIVE);
  619         if (sc->sc_rres == NULL) {
  620                 mtx_destroy(&sc->sc_hwmtx_s);
  621                 return (ENXIO);
  622         }
  623         sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
  624         sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
  625 
  626         /*
  627          * Ensure there is room for at least three full FIFOs of data in the
  628          * receive buffer (handles the case of low-level drivers with huge
  629          * FIFOs), and also ensure that there is no less than the historical
  630          * size of 384 bytes (handles the typical small-FIFO case).
  631          */
  632         sc->sc_rxbufsz = MAX(384, sc->sc_rxfifosz * 3);
  633         sc->sc_rxbuf = malloc(sc->sc_rxbufsz * sizeof(*sc->sc_rxbuf),
  634             M_UART, M_WAITOK);
  635         sc->sc_txbuf = malloc(sc->sc_txfifosz * sizeof(*sc->sc_txbuf),
  636             M_UART, M_WAITOK);
  637 
  638         error = UART_ATTACH(sc);
  639         if (error)
  640                 goto fail;
  641 
  642         if (sc->sc_hwiflow || sc->sc_hwoflow) {
  643                 sep = "";
  644                 device_print_prettyname(dev);
  645                 if (sc->sc_hwiflow) {
  646                         printf("%sRTS iflow", sep);
  647                         sep = ", ";
  648                 }
  649                 if (sc->sc_hwoflow) {
  650                         printf("%sCTS oflow", sep);
  651                         sep = ", ";
  652                 }
  653                 printf("\n");
  654         }
  655 
  656         if (sc->sc_sysdev != NULL) {
  657                 if (sc->sc_sysdev->baudrate == 0) {
  658                         if (UART_IOCTL(sc, UART_IOCTL_BAUD,
  659                             (intptr_t)&sc->sc_sysdev->baudrate) != 0)
  660                                 sc->sc_sysdev->baudrate = -1;
  661                 }
  662                 switch (sc->sc_sysdev->type) {
  663                 case UART_DEV_CONSOLE:
  664                         device_printf(dev, "console");
  665                         break;
  666                 case UART_DEV_DBGPORT:
  667                         device_printf(dev, "debug port");
  668                         break;
  669                 case UART_DEV_KEYBOARD:
  670                         device_printf(dev, "keyboard");
  671                         break;
  672                 default:
  673                         device_printf(dev, "unknown system device");
  674                         break;
  675                 }
  676                 printf(" (%d,%c,%d,%d)\n", sc->sc_sysdev->baudrate,
  677                     "noems"[sc->sc_sysdev->parity], sc->sc_sysdev->databits,
  678                     sc->sc_sysdev->stopbits);
  679         }
  680 
  681         sc->sc_leaving = 0;
  682         sc->sc_testintr = 1;
  683         filt = uart_intr(sc);
  684         sc->sc_testintr = 0;
  685 
  686         /*
  687          * Don't use interrupts if we couldn't clear any pending interrupt
  688          * conditions. We may have broken H/W and polling is probably the
  689          * safest thing to do.
  690          */
  691         if (filt != FILTER_SCHEDULE_THREAD && !uart_force_poll) {
  692                 sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
  693                     &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE);
  694         }
  695         if (sc->sc_ires != NULL) {
  696                 error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY,
  697                     uart_intr, NULL, sc, &sc->sc_icookie);
  698                 sc->sc_fastintr = (error == 0) ? 1 : 0;
  699 
  700                 if (!sc->sc_fastintr)
  701                         error = bus_setup_intr(dev, sc->sc_ires,
  702                             INTR_TYPE_TTY | INTR_MPSAFE, NULL,
  703                             (driver_intr_t *)uart_intr, sc, &sc->sc_icookie);
  704 
  705                 if (error) {
  706                         device_printf(dev, "could not activate interrupt\n");
  707                         bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
  708                             sc->sc_ires);
  709                         sc->sc_ires = NULL;
  710                 }
  711         }
  712         if (sc->sc_ires == NULL) {
  713                 /* No interrupt resource. Force polled mode. */
  714                 sc->sc_polled = 1;
  715                 callout_init(&sc->sc_timer, 1);
  716                 callout_reset(&sc->sc_timer, hz / uart_poll_freq,
  717                     (callout_func_t *)uart_intr, sc);
  718         }
  719 
  720         if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
  721                 sep = "";
  722                 device_print_prettyname(dev);
  723                 if (sc->sc_fastintr) {
  724                         printf("%sfast interrupt", sep);
  725                         sep = ", ";
  726                 }
  727                 if (sc->sc_polled) {
  728                         printf("%spolled mode (%dHz)", sep, uart_poll_freq);
  729                         sep = ", ";
  730                 }
  731                 printf("\n");
  732         }
  733 
  734         if (sc->sc_sysdev != NULL && sc->sc_sysdev->attach != NULL) {
  735                 if ((error = sc->sc_sysdev->attach(sc)) != 0)
  736                         goto fail;
  737         } else {
  738                 if ((error = uart_tty_attach(sc)) != 0)
  739                         goto fail;
  740                 uart_pps_init(sc);
  741         }
  742 
  743         if (sc->sc_sysdev != NULL)
  744                 sc->sc_sysdev->hwmtx = sc->sc_hwmtx;
  745 
  746         if (sc->sc_rxfifosz > 1)
  747                 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
  748                     SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
  749                     "rx_overruns", CTLFLAG_RD, &sc->sc_rxoverruns, 0,
  750                     "Receive overruns");
  751 
  752         return (0);
  753 
  754  fail:
  755         free(sc->sc_txbuf, M_UART);
  756         free(sc->sc_rxbuf, M_UART);
  757 
  758         if (sc->sc_ires != NULL) {
  759                 bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
  760                 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
  761                     sc->sc_ires);
  762         }
  763         bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
  764 
  765         mtx_destroy(&sc->sc_hwmtx_s);
  766 
  767         return (error);
  768 }
  769 
  770 int
  771 uart_bus_detach(device_t dev)
  772 {
  773         struct uart_softc *sc;
  774 
  775         sc = device_get_softc(dev);
  776 
  777         sc->sc_leaving = 1;
  778 
  779         if (sc->sc_sysdev != NULL)
  780                 sc->sc_sysdev->hwmtx = NULL;
  781 
  782         UART_DETACH(sc);
  783 
  784         if (sc->sc_sysdev != NULL && sc->sc_sysdev->detach != NULL)
  785                 (*sc->sc_sysdev->detach)(sc);
  786         else
  787                 uart_tty_detach(sc);
  788 
  789         free(sc->sc_txbuf, M_UART);
  790         free(sc->sc_rxbuf, M_UART);
  791 
  792         if (sc->sc_ires != NULL) {
  793                 bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
  794                 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
  795                     sc->sc_ires);
  796         }
  797         bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
  798 
  799         mtx_destroy(&sc->sc_hwmtx_s);
  800 
  801         if (sc->sc_class->size > device_get_driver(dev)->size) {
  802                 device_set_softc(dev, NULL);
  803                 free(sc, M_UART);
  804         }
  805 
  806         return (0);
  807 }
  808 
  809 int
  810 uart_bus_resume(device_t dev)
  811 {
  812         struct uart_softc *sc;
  813 
  814         sc = device_get_softc(dev);
  815         return (UART_ATTACH(sc));
  816 }
  817 
  818 void
  819 uart_grab(struct uart_devinfo *di)
  820 {
  821 
  822         if (di->sc)
  823                 UART_GRAB(di->sc);
  824 }
  825 
  826 void
  827 uart_ungrab(struct uart_devinfo *di)
  828 {
  829 
  830         if (di->sc)
  831                 UART_UNGRAB(di->sc);
  832 }

Cache object: 33bb7cea4ba177a98d6f993c5e5b56b1


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