uart_core.c revision 285843
1139749Simp/*- 2119815Smarcel * Copyright (c) 2003 Marcel Moolenaar 3119815Smarcel * All rights reserved. 4119815Smarcel * 5119815Smarcel * Redistribution and use in source and binary forms, with or without 6119815Smarcel * modification, are permitted provided that the following conditions 7119815Smarcel * are met: 8119815Smarcel * 9119815Smarcel * 1. Redistributions of source code must retain the above copyright 10119815Smarcel * notice, this list of conditions and the following disclaimer. 11119815Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12119815Smarcel * notice, this list of conditions and the following disclaimer in the 13119815Smarcel * documentation and/or other materials provided with the distribution. 14119815Smarcel * 15119815Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16119815Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17119815Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18119815Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19119815Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20119815Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21119815Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22119815Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23119815Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24119815Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25119815Smarcel */ 26119815Smarcel 27119815Smarcel#include <sys/cdefs.h> 28119815Smarcel__FBSDID("$FreeBSD: head/sys/dev/uart/uart_core.c 285843 2015-07-24 17:01:16Z marius $"); 29119815Smarcel 30119815Smarcel#include <sys/param.h> 31119815Smarcel#include <sys/systm.h> 32119815Smarcel#include <sys/bus.h> 33119815Smarcel#include <sys/conf.h> 34119815Smarcel#include <sys/cons.h> 35119815Smarcel#include <sys/fcntl.h> 36119815Smarcel#include <sys/interrupt.h> 37131921Smarcel#include <sys/kdb.h> 38119815Smarcel#include <sys/kernel.h> 39119815Smarcel#include <sys/malloc.h> 40119815Smarcel#include <sys/queue.h> 41119815Smarcel#include <sys/reboot.h> 42285619Sneel#include <sys/sysctl.h> 43119815Smarcel#include <machine/bus.h> 44119815Smarcel#include <sys/rman.h> 45119815Smarcel#include <machine/resource.h> 46119815Smarcel#include <machine/stdarg.h> 47119815Smarcel 48119815Smarcel#include <dev/uart/uart.h> 49119815Smarcel#include <dev/uart/uart_bus.h> 50119815Smarcel#include <dev/uart/uart_cpu.h> 51119815Smarcel 52119815Smarcel#include "uart_if.h" 53119815Smarcel 54119815Smarceldevclass_t uart_devclass; 55285843Smariusconst char uart_driver_name[] = "uart"; 56119815Smarcel 57119815SmarcelSLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs = 58119815Smarcel SLIST_HEAD_INITIALIZER(uart_sysdevs); 59119815Smarcel 60227293Sedstatic MALLOC_DEFINE(M_UART, "UART", "UART driver"); 61119815Smarcel 62234194Sgrehan#ifndef UART_POLL_FREQ 63234194Sgrehan#define UART_POLL_FREQ 50 64234194Sgrehan#endif 65234194Sgrehanstatic int uart_poll_freq = UART_POLL_FREQ; 66285619SneelSYSCTL_INT(_debug, OID_AUTO, uart_poll_freq, CTLFLAG_RDTUN, &uart_poll_freq, 67285619Sneel 0, "UART poll frequency"); 68234194Sgrehan 69285619Sneelstatic int uart_force_poll; 70285619SneelSYSCTL_INT(_debug, OID_AUTO, uart_force_poll, CTLFLAG_RDTUN, &uart_force_poll, 71285619Sneel 0, "Force UART polling"); 72285619Sneel 73119815Smarcelvoid 74119815Smarceluart_add_sysdev(struct uart_devinfo *di) 75119815Smarcel{ 76119815Smarcel SLIST_INSERT_HEAD(&uart_sysdevs, di, next); 77119815Smarcel} 78119815Smarcel 79168281Smarcelconst char * 80168281Smarceluart_getname(struct uart_class *uc) 81168281Smarcel{ 82168281Smarcel return ((uc != NULL) ? uc->name : NULL); 83168281Smarcel} 84168281Smarcel 85168281Smarcelstruct uart_ops * 86168281Smarceluart_getops(struct uart_class *uc) 87168281Smarcel{ 88168281Smarcel return ((uc != NULL) ? uc->uc_ops : NULL); 89168281Smarcel} 90168281Smarcel 91168281Smarcelint 92168281Smarceluart_getrange(struct uart_class *uc) 93168281Smarcel{ 94168281Smarcel return ((uc != NULL) ? uc->uc_range : 0); 95168281Smarcel} 96168281Smarcel 97281438Sandrewu_int 98281438Sandrewuart_getregshift(struct uart_class *uc) 99281438Sandrew{ 100281438Sandrew return ((uc != NULL) ? uc->uc_rshift : 0); 101281438Sandrew} 102281438Sandrew 103119815Smarcel/* 104157300Smarcel * Schedule a soft interrupt. We do this on the 0 to !0 transition 105157300Smarcel * of the TTY pending interrupt status. 106157300Smarcel */ 107197721Smarcelvoid 108157300Smarceluart_sched_softih(struct uart_softc *sc, uint32_t ipend) 109157300Smarcel{ 110157300Smarcel uint32_t new, old; 111157300Smarcel 112157300Smarcel do { 113157300Smarcel old = sc->sc_ttypend; 114157300Smarcel new = old | ipend; 115157300Smarcel } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new)); 116157300Smarcel 117157300Smarcel if ((old & SER_INT_MASK) == 0) 118157300Smarcel swi_sched(sc->sc_softih, 0); 119157300Smarcel} 120157300Smarcel 121157300Smarcel/* 122119815Smarcel * A break condition has been detected. We treat the break condition as 123119815Smarcel * a special case that should not happen during normal operation. When 124119815Smarcel * the break condition is to be passed to higher levels in the form of 125119815Smarcel * a NUL character, we really want the break to be in the right place in 126119815Smarcel * the input stream. The overhead to achieve that is not in relation to 127119815Smarcel * the exceptional nature of the break condition, so we permit ourselves 128119815Smarcel * to be sloppy. 129119815Smarcel */ 130157300Smarcelstatic __inline int 131157300Smarceluart_intr_break(void *arg) 132119815Smarcel{ 133157300Smarcel struct uart_softc *sc = arg; 134119815Smarcel 135225203Srwatson#if defined(KDB) 136119815Smarcel if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { 137225203Srwatson if (kdb_break()) 138225203Srwatson return (0); 139119815Smarcel } 140119815Smarcel#endif 141119815Smarcel if (sc->sc_opened) 142157300Smarcel uart_sched_softih(sc, SER_INT_BREAK); 143157300Smarcel return (0); 144119815Smarcel} 145119815Smarcel 146119815Smarcel/* 147119815Smarcel * Handle a receiver overrun situation. We lost at least 1 byte in the 148119815Smarcel * input stream and it's our job to contain the situation. We grab as 149119815Smarcel * much of the data we can, but otherwise flush the receiver FIFO to 150119815Smarcel * create some breathing room. The net effect is that we avoid the 151119815Smarcel * overrun condition to happen for the next X characters, where X is 152250576Seadler * related to the FIFO size at the cost of losing data right away. 153119815Smarcel * So, instead of having multiple overrun interrupts in close proximity 154119815Smarcel * to each other and possibly pessimizing UART interrupt latency for 155119815Smarcel * other UARTs in a multiport configuration, we create a longer segment 156119815Smarcel * of missing characters by freeing up the FIFO. 157119815Smarcel * Each overrun condition is marked in the input buffer by a token. The 158119815Smarcel * token represents the loss of at least one, but possible more bytes in 159119815Smarcel * the input stream. 160119815Smarcel */ 161157300Smarcelstatic __inline int 162157300Smarceluart_intr_overrun(void *arg) 163119815Smarcel{ 164157300Smarcel struct uart_softc *sc = arg; 165119815Smarcel 166119815Smarcel if (sc->sc_opened) { 167119815Smarcel UART_RECEIVE(sc); 168119815Smarcel if (uart_rx_put(sc, UART_STAT_OVERRUN)) 169119815Smarcel sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; 170157300Smarcel uart_sched_softih(sc, SER_INT_RXREADY); 171119815Smarcel } 172119815Smarcel UART_FLUSH(sc, UART_FLUSH_RECEIVER); 173157300Smarcel return (0); 174119815Smarcel} 175119815Smarcel 176119815Smarcel/* 177119815Smarcel * Received data ready. 178119815Smarcel */ 179157300Smarcelstatic __inline int 180157300Smarceluart_intr_rxready(void *arg) 181119815Smarcel{ 182157300Smarcel struct uart_softc *sc = arg; 183119815Smarcel int rxp; 184119815Smarcel 185119815Smarcel rxp = sc->sc_rxput; 186119815Smarcel UART_RECEIVE(sc); 187225203Srwatson#if defined(KDB) 188119815Smarcel if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { 189119815Smarcel while (rxp != sc->sc_rxput) { 190225203Srwatson kdb_alt_break(sc->sc_rxbuf[rxp++], &sc->sc_altbrk); 191119815Smarcel if (rxp == sc->sc_rxbufsz) 192119815Smarcel rxp = 0; 193119815Smarcel } 194119815Smarcel } 195119815Smarcel#endif 196119815Smarcel if (sc->sc_opened) 197157300Smarcel uart_sched_softih(sc, SER_INT_RXREADY); 198119815Smarcel else 199119815Smarcel sc->sc_rxput = sc->sc_rxget; /* Ignore received data. */ 200157300Smarcel return (1); 201119815Smarcel} 202119815Smarcel 203119815Smarcel/* 204119815Smarcel * Line or modem status change (OOB signalling). 205119815Smarcel * We pass the signals to the software interrupt handler for further 206119815Smarcel * processing. Note that we merge the delta bits, but set the state 207250576Seadler * bits. This is to avoid losing state transitions due to having more 208119815Smarcel * than 1 hardware interrupt between software interrupts. 209119815Smarcel */ 210157300Smarcelstatic __inline int 211157300Smarceluart_intr_sigchg(void *arg) 212119815Smarcel{ 213157300Smarcel struct uart_softc *sc = arg; 214119815Smarcel int new, old, sig; 215119815Smarcel 216119815Smarcel sig = UART_GETSIG(sc); 217119996Smarcel 218119996Smarcel if (sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) { 219119996Smarcel if (sig & UART_SIG_DPPS) { 220119996Smarcel pps_capture(&sc->sc_pps); 221119996Smarcel pps_event(&sc->sc_pps, (sig & UART_SIG_PPS) ? 222119996Smarcel PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); 223119996Smarcel } 224119996Smarcel } 225119996Smarcel 226157300Smarcel /* 227157300Smarcel * Keep track of signal changes, even when the device is not 228157300Smarcel * opened. This allows us to inform upper layers about a 229157300Smarcel * possible loss of DCD and thus the existence of a (possibly) 230157300Smarcel * different connection when we have DCD back, during the time 231157300Smarcel * that the device was closed. 232157300Smarcel */ 233119815Smarcel do { 234119815Smarcel old = sc->sc_ttypend; 235155973Smarcel new = old & ~SER_MASK_STATE; 236155971Smarcel new |= sig & SER_INT_SIGMASK; 237119815Smarcel } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new)); 238157300Smarcel 239157300Smarcel if (sc->sc_opened) 240157300Smarcel uart_sched_softih(sc, SER_INT_SIGCHG); 241157300Smarcel return (1); 242119815Smarcel} 243119815Smarcel 244119815Smarcel/* 245119815Smarcel * The transmitter can accept more data. 246119815Smarcel */ 247157300Smarcelstatic __inline int 248157300Smarceluart_intr_txidle(void *arg) 249119815Smarcel{ 250157300Smarcel struct uart_softc *sc = arg; 251157300Smarcel 252119815Smarcel if (sc->sc_txbusy) { 253119815Smarcel sc->sc_txbusy = 0; 254157300Smarcel uart_sched_softih(sc, SER_INT_TXIDLE); 255119815Smarcel } 256157300Smarcel return (0); 257119815Smarcel} 258119815Smarcel 259166901Spisostatic int 260119815Smarceluart_intr(void *arg) 261119815Smarcel{ 262119815Smarcel struct uart_softc *sc = arg; 263285843Smarius int cnt, ipend, testintr; 264119815Smarcel 265253161Smarcel if (sc->sc_leaving) 266253161Smarcel return (FILTER_STRAY); 267253161Smarcel 268253161Smarcel cnt = 0; 269285843Smarius testintr = sc->sc_testintr; 270285843Smarius while ((!testintr || cnt < 20) && (ipend = UART_IPEND(sc)) != 0) { 271253161Smarcel cnt++; 272155971Smarcel if (ipend & SER_INT_OVERRUN) 273120146Smarcel uart_intr_overrun(sc); 274155971Smarcel if (ipend & SER_INT_BREAK) 275120146Smarcel uart_intr_break(sc); 276155971Smarcel if (ipend & SER_INT_RXREADY) 277120146Smarcel uart_intr_rxready(sc); 278155971Smarcel if (ipend & SER_INT_SIGCHG) 279120146Smarcel uart_intr_sigchg(sc); 280155971Smarcel if (ipend & SER_INT_TXIDLE) 281285843Smarius uart_intr_txidle(sc); 282157300Smarcel } 283234194Sgrehan 284234194Sgrehan if (sc->sc_polled) { 285234194Sgrehan callout_reset(&sc->sc_timer, hz / uart_poll_freq, 286234194Sgrehan (timeout_t *)uart_intr, sc); 287234194Sgrehan } 288234194Sgrehan 289253161Smarcel return ((cnt == 0) ? FILTER_STRAY : 290285843Smarius ((testintr && cnt == 20) ? FILTER_SCHEDULE_THREAD : 291285843Smarius FILTER_HANDLED)); 292157300Smarcel} 293119815Smarcel 294157300Smarcelserdev_intr_t * 295157300Smarceluart_bus_ihand(device_t dev, int ipend) 296157300Smarcel{ 297157300Smarcel 298157300Smarcel switch (ipend) { 299157300Smarcel case SER_INT_BREAK: 300157300Smarcel return (uart_intr_break); 301157300Smarcel case SER_INT_OVERRUN: 302157300Smarcel return (uart_intr_overrun); 303157300Smarcel case SER_INT_RXREADY: 304157300Smarcel return (uart_intr_rxready); 305157300Smarcel case SER_INT_SIGCHG: 306157300Smarcel return (uart_intr_sigchg); 307157300Smarcel case SER_INT_TXIDLE: 308157300Smarcel return (uart_intr_txidle); 309157300Smarcel } 310157300Smarcel return (NULL); 311119815Smarcel} 312119815Smarcel 313119815Smarcelint 314158119Smarceluart_bus_ipend(device_t dev) 315158119Smarcel{ 316158119Smarcel struct uart_softc *sc; 317158119Smarcel 318158119Smarcel sc = device_get_softc(dev); 319158119Smarcel return (UART_IPEND(sc)); 320158119Smarcel} 321158119Smarcel 322158119Smarcelint 323157300Smarceluart_bus_sysdev(device_t dev) 324157300Smarcel{ 325157300Smarcel struct uart_softc *sc; 326157300Smarcel 327157300Smarcel sc = device_get_softc(dev); 328157300Smarcel return ((sc->sc_sysdev != NULL) ? 1 : 0); 329157300Smarcel} 330157300Smarcel 331157300Smarcelint 332120452Smarceluart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan) 333119815Smarcel{ 334119815Smarcel struct uart_softc *sc; 335119815Smarcel struct uart_devinfo *sysdev; 336119815Smarcel int error; 337119815Smarcel 338168281Smarcel sc = device_get_softc(dev); 339168281Smarcel 340119815Smarcel /* 341168281Smarcel * All uart_class references are weak. Check that the needed 342168281Smarcel * class has been compiled-in. Fail if not. 343168281Smarcel */ 344168281Smarcel if (sc->sc_class == NULL) 345168281Smarcel return (ENXIO); 346168281Smarcel 347168281Smarcel /* 348119815Smarcel * Initialize the instance. Note that the instance (=softc) does 349119815Smarcel * not necessarily match the hardware specific softc. We can't do 350119815Smarcel * anything about it now, because we may not attach to the device. 351119815Smarcel * Hardware drivers cannot use any of the class specific fields 352119815Smarcel * while probing. 353119815Smarcel */ 354119815Smarcel kobj_init((kobj_t)sc, (kobj_class_t)sc->sc_class); 355119815Smarcel sc->sc_dev = dev; 356119815Smarcel if (device_get_desc(dev) == NULL) 357168281Smarcel device_set_desc(dev, uart_getname(sc->sc_class)); 358119815Smarcel 359119815Smarcel /* 360119815Smarcel * Allocate the register resource. We assume that all UARTs have 361119815Smarcel * a single register window in either I/O port space or memory 362119815Smarcel * mapped I/O space. Any UART that needs multiple windows will 363119815Smarcel * consequently not be supported by this driver as-is. We try I/O 364119815Smarcel * port space first because that's the common case. 365119815Smarcel */ 366119815Smarcel sc->sc_rrid = rid; 367119815Smarcel sc->sc_rtype = SYS_RES_IOPORT; 368119815Smarcel sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid, 369168281Smarcel 0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE); 370119815Smarcel if (sc->sc_rres == NULL) { 371119815Smarcel sc->sc_rrid = rid; 372119815Smarcel sc->sc_rtype = SYS_RES_MEMORY; 373119815Smarcel sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, 374168281Smarcel &sc->sc_rrid, 0, ~0, uart_getrange(sc->sc_class), 375168281Smarcel RF_ACTIVE); 376119815Smarcel if (sc->sc_rres == NULL) 377119815Smarcel return (ENXIO); 378119815Smarcel } 379119815Smarcel 380119815Smarcel /* 381119815Smarcel * Fill in the bus access structure and compare this device with 382119815Smarcel * a possible console device and/or a debug port. We set the flags 383119815Smarcel * in the softc so that the hardware dependent probe can adjust 384119815Smarcel * accordingly. In general, you don't want to permanently disrupt 385119815Smarcel * console I/O. 386119815Smarcel */ 387119815Smarcel sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); 388119815Smarcel sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); 389120452Smarcel sc->sc_bas.chan = chan; 390119815Smarcel sc->sc_bas.regshft = regshft; 391119815Smarcel sc->sc_bas.rclk = (rclk == 0) ? sc->sc_class->uc_rclk : rclk; 392119815Smarcel 393119815Smarcel SLIST_FOREACH(sysdev, &uart_sysdevs, next) { 394120452Smarcel if (chan == sysdev->bas.chan && 395120452Smarcel uart_cpu_eqres(&sc->sc_bas, &sysdev->bas)) { 396119815Smarcel /* XXX check if ops matches class. */ 397119815Smarcel sc->sc_sysdev = sysdev; 398167999Smarcel sysdev->bas.rclk = sc->sc_bas.rclk; 399119815Smarcel } 400119815Smarcel } 401119815Smarcel 402119815Smarcel error = UART_PROBE(sc); 403119815Smarcel bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); 404151792Smarcel return ((error) ? error : BUS_PROBE_DEFAULT); 405119815Smarcel} 406119815Smarcel 407119815Smarcelint 408119815Smarceluart_bus_attach(device_t dev) 409119815Smarcel{ 410119815Smarcel struct uart_softc *sc, *sc0; 411119815Smarcel const char *sep; 412253161Smarcel int error, filt; 413119815Smarcel 414119815Smarcel /* 415119815Smarcel * The sc_class field defines the type of UART we're going to work 416119815Smarcel * with and thus the size of the softc. Replace the generic softc 417119815Smarcel * with one that matches the UART now that we're certain we handle 418119815Smarcel * the device. 419119815Smarcel */ 420119815Smarcel sc0 = device_get_softc(dev); 421119815Smarcel if (sc0->sc_class->size > sizeof(*sc)) { 422119815Smarcel sc = malloc(sc0->sc_class->size, M_UART, M_WAITOK|M_ZERO); 423119815Smarcel bcopy(sc0, sc, sizeof(*sc)); 424119815Smarcel device_set_softc(dev, sc); 425119815Smarcel } else 426119815Smarcel sc = sc0; 427119815Smarcel 428119815Smarcel /* 429260890Simp * Now that we know the softc for this device, connect the back 430260890Simp * pointer from the sysdev for this device, if any 431260890Simp */ 432260890Simp if (sc->sc_sysdev != NULL) 433260890Simp sc->sc_sysdev->sc = sc; 434260890Simp 435260890Simp /* 436119815Smarcel * Protect ourselves against interrupts while we're not completely 437119815Smarcel * finished attaching and initializing. We don't expect interrupts 438285843Smarius * until after UART_ATTACH(), though. 439119815Smarcel */ 440119815Smarcel sc->sc_leaving = 1; 441119815Smarcel 442157300Smarcel mtx_init(&sc->sc_hwmtx_s, "uart_hwmtx", NULL, MTX_SPIN); 443157300Smarcel if (sc->sc_hwmtx == NULL) 444157300Smarcel sc->sc_hwmtx = &sc->sc_hwmtx_s; 445120143Smarcel 446119815Smarcel /* 447119815Smarcel * Re-allocate. We expect that the softc contains the information 448119815Smarcel * collected by uart_bus_probe() intact. 449119815Smarcel */ 450119815Smarcel sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid, 451168281Smarcel 0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE); 452143025Smarius if (sc->sc_rres == NULL) { 453157300Smarcel mtx_destroy(&sc->sc_hwmtx_s); 454119815Smarcel return (ENXIO); 455143025Smarius } 456120380Snyan sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); 457120380Snyan sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); 458120380Snyan 459248963Sian /* 460248963Sian * Ensure there is room for at least three full FIFOs of data in the 461248963Sian * receive buffer (handles the case of low-level drivers with huge 462248963Sian * FIFOs), and also ensure that there is no less than the historical 463248963Sian * size of 384 bytes (handles the typical small-FIFO case). 464248963Sian */ 465248963Sian sc->sc_rxbufsz = MAX(384, sc->sc_rxfifosz * 3); 466119815Smarcel sc->sc_rxbuf = malloc(sc->sc_rxbufsz * sizeof(*sc->sc_rxbuf), 467119815Smarcel M_UART, M_WAITOK); 468119815Smarcel sc->sc_txbuf = malloc(sc->sc_txfifosz * sizeof(*sc->sc_txbuf), 469119815Smarcel M_UART, M_WAITOK); 470119815Smarcel 471119815Smarcel error = UART_ATTACH(sc); 472119815Smarcel if (error) 473119815Smarcel goto fail; 474119815Smarcel 475119815Smarcel if (sc->sc_hwiflow || sc->sc_hwoflow) { 476119815Smarcel sep = ""; 477119815Smarcel device_print_prettyname(dev); 478119815Smarcel if (sc->sc_hwiflow) { 479119815Smarcel printf("%sRTS iflow", sep); 480119815Smarcel sep = ", "; 481119815Smarcel } 482119815Smarcel if (sc->sc_hwoflow) { 483119815Smarcel printf("%sCTS oflow", sep); 484119815Smarcel sep = ", "; 485119815Smarcel } 486119815Smarcel printf("\n"); 487119815Smarcel } 488119815Smarcel 489119815Smarcel if (sc->sc_sysdev != NULL) { 490262932Simp if (sc->sc_sysdev->baudrate == 0) { 491137706Smarcel if (UART_IOCTL(sc, UART_IOCTL_BAUD, 492137706Smarcel (intptr_t)&sc->sc_sysdev->baudrate) != 0) 493137706Smarcel sc->sc_sysdev->baudrate = -1; 494137706Smarcel } 495119815Smarcel switch (sc->sc_sysdev->type) { 496119815Smarcel case UART_DEV_CONSOLE: 497119815Smarcel device_printf(dev, "console"); 498119815Smarcel break; 499119815Smarcel case UART_DEV_DBGPORT: 500119815Smarcel device_printf(dev, "debug port"); 501119815Smarcel break; 502119815Smarcel case UART_DEV_KEYBOARD: 503119815Smarcel device_printf(dev, "keyboard"); 504119815Smarcel break; 505119815Smarcel default: 506119815Smarcel device_printf(dev, "unknown system device"); 507119815Smarcel break; 508119815Smarcel } 509119815Smarcel printf(" (%d,%c,%d,%d)\n", sc->sc_sysdev->baudrate, 510119815Smarcel "noems"[sc->sc_sysdev->parity], sc->sc_sysdev->databits, 511119815Smarcel sc->sc_sysdev->stopbits); 512119815Smarcel } 513119815Smarcel 514119996Smarcel sc->sc_pps.ppscap = PPS_CAPTUREBOTH; 515119996Smarcel pps_init(&sc->sc_pps); 516119996Smarcel 517253161Smarcel sc->sc_leaving = 0; 518285843Smarius sc->sc_testintr = 1; 519253161Smarcel filt = uart_intr(sc); 520285843Smarius sc->sc_testintr = 0; 521253161Smarcel 522253161Smarcel /* 523253161Smarcel * Don't use interrupts if we couldn't clear any pending interrupt 524253161Smarcel * conditions. We may have broken H/W and polling is probably the 525253161Smarcel * safest thing to do. 526253161Smarcel */ 527285619Sneel if (filt != FILTER_SCHEDULE_THREAD && !uart_force_poll) { 528253161Smarcel sc->sc_irid = 0; 529253161Smarcel sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 530253161Smarcel &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE); 531253161Smarcel } 532253161Smarcel if (sc->sc_ires != NULL) { 533253161Smarcel error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY, 534253161Smarcel uart_intr, NULL, sc, &sc->sc_icookie); 535253161Smarcel sc->sc_fastintr = (error == 0) ? 1 : 0; 536253161Smarcel 537253161Smarcel if (!sc->sc_fastintr) 538253161Smarcel error = bus_setup_intr(dev, sc->sc_ires, 539253161Smarcel INTR_TYPE_TTY | INTR_MPSAFE, NULL, 540253161Smarcel (driver_intr_t *)uart_intr, sc, &sc->sc_icookie); 541253161Smarcel 542253161Smarcel if (error) { 543253161Smarcel device_printf(dev, "could not activate interrupt\n"); 544253161Smarcel bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 545253161Smarcel sc->sc_ires); 546253161Smarcel sc->sc_ires = NULL; 547253161Smarcel } 548253161Smarcel } 549253161Smarcel if (sc->sc_ires == NULL) { 550253161Smarcel /* No interrupt resource. Force polled mode. */ 551253161Smarcel sc->sc_polled = 1; 552253161Smarcel callout_init(&sc->sc_timer, 1); 553285619Sneel callout_reset(&sc->sc_timer, hz / uart_poll_freq, 554285619Sneel (timeout_t *)uart_intr, sc); 555253161Smarcel } 556253161Smarcel 557253161Smarcel if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) { 558253161Smarcel sep = ""; 559253161Smarcel device_print_prettyname(dev); 560253161Smarcel if (sc->sc_fastintr) { 561253161Smarcel printf("%sfast interrupt", sep); 562253161Smarcel sep = ", "; 563253161Smarcel } 564253161Smarcel if (sc->sc_polled) { 565254534Sian printf("%spolled mode (%dHz)", sep, uart_poll_freq); 566253161Smarcel sep = ", "; 567253161Smarcel } 568253161Smarcel printf("\n"); 569253161Smarcel } 570253161Smarcel 571119815Smarcel error = (sc->sc_sysdev != NULL && sc->sc_sysdev->attach != NULL) 572119815Smarcel ? (*sc->sc_sysdev->attach)(sc) : uart_tty_attach(sc); 573119815Smarcel if (error) 574119815Smarcel goto fail; 575119815Smarcel 576157300Smarcel if (sc->sc_sysdev != NULL) 577157300Smarcel sc->sc_sysdev->hwmtx = sc->sc_hwmtx; 578157300Smarcel 579119815Smarcel return (0); 580119815Smarcel 581119815Smarcel fail: 582119815Smarcel free(sc->sc_txbuf, M_UART); 583119815Smarcel free(sc->sc_rxbuf, M_UART); 584119815Smarcel 585119815Smarcel if (sc->sc_ires != NULL) { 586119815Smarcel bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 587119815Smarcel bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 588119815Smarcel sc->sc_ires); 589119815Smarcel } 590119815Smarcel bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); 591119815Smarcel 592157300Smarcel mtx_destroy(&sc->sc_hwmtx_s); 593143025Smarius 594119815Smarcel return (error); 595119815Smarcel} 596119815Smarcel 597119815Smarcelint 598119815Smarceluart_bus_detach(device_t dev) 599119815Smarcel{ 600119815Smarcel struct uart_softc *sc; 601119815Smarcel 602119815Smarcel sc = device_get_softc(dev); 603119815Smarcel 604119815Smarcel sc->sc_leaving = 1; 605119815Smarcel 606157300Smarcel if (sc->sc_sysdev != NULL) 607157300Smarcel sc->sc_sysdev->hwmtx = NULL; 608157300Smarcel 609119815Smarcel UART_DETACH(sc); 610119815Smarcel 611119815Smarcel if (sc->sc_sysdev != NULL && sc->sc_sysdev->detach != NULL) 612119815Smarcel (*sc->sc_sysdev->detach)(sc); 613119815Smarcel else 614119815Smarcel uart_tty_detach(sc); 615119815Smarcel 616119815Smarcel free(sc->sc_txbuf, M_UART); 617119815Smarcel free(sc->sc_rxbuf, M_UART); 618119815Smarcel 619119815Smarcel if (sc->sc_ires != NULL) { 620119815Smarcel bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 621119815Smarcel bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 622119815Smarcel sc->sc_ires); 623119815Smarcel } 624119815Smarcel bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); 625119815Smarcel 626157300Smarcel mtx_destroy(&sc->sc_hwmtx_s); 627143025Smarius 628119815Smarcel if (sc->sc_class->size > sizeof(*sc)) { 629119815Smarcel device_set_softc(dev, NULL); 630119815Smarcel free(sc, M_UART); 631119815Smarcel } else 632119815Smarcel device_set_softc(dev, NULL); 633119815Smarcel 634119815Smarcel return (0); 635119815Smarcel} 636246243Savg 637246243Savgint 638246243Savguart_bus_resume(device_t dev) 639246243Savg{ 640246243Savg struct uart_softc *sc; 641246243Savg 642246243Savg sc = device_get_softc(dev); 643246243Savg return (UART_ATTACH(sc)); 644246243Savg} 645260890Simp 646260890Simpvoid 647260890Simpuart_grab(struct uart_devinfo *di) 648260890Simp{ 649260890Simp 650260890Simp if (di->sc) 651260890Simp UART_GRAB(di->sc); 652260890Simp} 653260890Simp 654260890Simpvoid 655260890Simpuart_ungrab(struct uart_devinfo *di) 656260890Simp{ 657260890Simp 658260890Simp if (di->sc) 659260890Simp UART_UNGRAB(di->sc); 660260890Simp} 661