uart_core.c revision 285619
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 285619 2015-07-16 04:15:22Z neel $"); 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; 55119815Smarcelchar 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; 263253161Smarcel int cnt, ipend; 264119815Smarcel 265253161Smarcel if (sc->sc_leaving) 266253161Smarcel return (FILTER_STRAY); 267253161Smarcel 268253161Smarcel cnt = 0; 269253161Smarcel while (cnt < 20 && (ipend = UART_IPEND(sc)) != 0) { 270253161Smarcel cnt++; 271155971Smarcel if (ipend & SER_INT_OVERRUN) 272120146Smarcel uart_intr_overrun(sc); 273155971Smarcel if (ipend & SER_INT_BREAK) 274120146Smarcel uart_intr_break(sc); 275155971Smarcel if (ipend & SER_INT_RXREADY) 276120146Smarcel uart_intr_rxready(sc); 277155971Smarcel if (ipend & SER_INT_SIGCHG) 278120146Smarcel uart_intr_sigchg(sc); 279155971Smarcel if (ipend & SER_INT_TXIDLE) 280166901Spiso uart_intr_txidle(sc); 281157300Smarcel } 282234194Sgrehan 283234194Sgrehan if (sc->sc_polled) { 284234194Sgrehan callout_reset(&sc->sc_timer, hz / uart_poll_freq, 285234194Sgrehan (timeout_t *)uart_intr, sc); 286234194Sgrehan } 287234194Sgrehan 288253161Smarcel return ((cnt == 0) ? FILTER_STRAY : 289253161Smarcel ((cnt == 20) ? FILTER_SCHEDULE_THREAD : FILTER_HANDLED)); 290157300Smarcel} 291119815Smarcel 292157300Smarcelserdev_intr_t * 293157300Smarceluart_bus_ihand(device_t dev, int ipend) 294157300Smarcel{ 295157300Smarcel 296157300Smarcel switch (ipend) { 297157300Smarcel case SER_INT_BREAK: 298157300Smarcel return (uart_intr_break); 299157300Smarcel case SER_INT_OVERRUN: 300157300Smarcel return (uart_intr_overrun); 301157300Smarcel case SER_INT_RXREADY: 302157300Smarcel return (uart_intr_rxready); 303157300Smarcel case SER_INT_SIGCHG: 304157300Smarcel return (uart_intr_sigchg); 305157300Smarcel case SER_INT_TXIDLE: 306157300Smarcel return (uart_intr_txidle); 307157300Smarcel } 308157300Smarcel return (NULL); 309119815Smarcel} 310119815Smarcel 311119815Smarcelint 312158119Smarceluart_bus_ipend(device_t dev) 313158119Smarcel{ 314158119Smarcel struct uart_softc *sc; 315158119Smarcel 316158119Smarcel sc = device_get_softc(dev); 317158119Smarcel return (UART_IPEND(sc)); 318158119Smarcel} 319158119Smarcel 320158119Smarcelint 321157300Smarceluart_bus_sysdev(device_t dev) 322157300Smarcel{ 323157300Smarcel struct uart_softc *sc; 324157300Smarcel 325157300Smarcel sc = device_get_softc(dev); 326157300Smarcel return ((sc->sc_sysdev != NULL) ? 1 : 0); 327157300Smarcel} 328157300Smarcel 329157300Smarcelint 330120452Smarceluart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan) 331119815Smarcel{ 332119815Smarcel struct uart_softc *sc; 333119815Smarcel struct uart_devinfo *sysdev; 334119815Smarcel int error; 335119815Smarcel 336168281Smarcel sc = device_get_softc(dev); 337168281Smarcel 338119815Smarcel /* 339168281Smarcel * All uart_class references are weak. Check that the needed 340168281Smarcel * class has been compiled-in. Fail if not. 341168281Smarcel */ 342168281Smarcel if (sc->sc_class == NULL) 343168281Smarcel return (ENXIO); 344168281Smarcel 345168281Smarcel /* 346119815Smarcel * Initialize the instance. Note that the instance (=softc) does 347119815Smarcel * not necessarily match the hardware specific softc. We can't do 348119815Smarcel * anything about it now, because we may not attach to the device. 349119815Smarcel * Hardware drivers cannot use any of the class specific fields 350119815Smarcel * while probing. 351119815Smarcel */ 352119815Smarcel kobj_init((kobj_t)sc, (kobj_class_t)sc->sc_class); 353119815Smarcel sc->sc_dev = dev; 354119815Smarcel if (device_get_desc(dev) == NULL) 355168281Smarcel device_set_desc(dev, uart_getname(sc->sc_class)); 356119815Smarcel 357119815Smarcel /* 358119815Smarcel * Allocate the register resource. We assume that all UARTs have 359119815Smarcel * a single register window in either I/O port space or memory 360119815Smarcel * mapped I/O space. Any UART that needs multiple windows will 361119815Smarcel * consequently not be supported by this driver as-is. We try I/O 362119815Smarcel * port space first because that's the common case. 363119815Smarcel */ 364119815Smarcel sc->sc_rrid = rid; 365119815Smarcel sc->sc_rtype = SYS_RES_IOPORT; 366119815Smarcel sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid, 367168281Smarcel 0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE); 368119815Smarcel if (sc->sc_rres == NULL) { 369119815Smarcel sc->sc_rrid = rid; 370119815Smarcel sc->sc_rtype = SYS_RES_MEMORY; 371119815Smarcel sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, 372168281Smarcel &sc->sc_rrid, 0, ~0, uart_getrange(sc->sc_class), 373168281Smarcel RF_ACTIVE); 374119815Smarcel if (sc->sc_rres == NULL) 375119815Smarcel return (ENXIO); 376119815Smarcel } 377119815Smarcel 378119815Smarcel /* 379119815Smarcel * Fill in the bus access structure and compare this device with 380119815Smarcel * a possible console device and/or a debug port. We set the flags 381119815Smarcel * in the softc so that the hardware dependent probe can adjust 382119815Smarcel * accordingly. In general, you don't want to permanently disrupt 383119815Smarcel * console I/O. 384119815Smarcel */ 385119815Smarcel sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); 386119815Smarcel sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); 387120452Smarcel sc->sc_bas.chan = chan; 388119815Smarcel sc->sc_bas.regshft = regshft; 389119815Smarcel sc->sc_bas.rclk = (rclk == 0) ? sc->sc_class->uc_rclk : rclk; 390119815Smarcel 391119815Smarcel SLIST_FOREACH(sysdev, &uart_sysdevs, next) { 392120452Smarcel if (chan == sysdev->bas.chan && 393120452Smarcel uart_cpu_eqres(&sc->sc_bas, &sysdev->bas)) { 394119815Smarcel /* XXX check if ops matches class. */ 395119815Smarcel sc->sc_sysdev = sysdev; 396167999Smarcel sysdev->bas.rclk = sc->sc_bas.rclk; 397119815Smarcel } 398119815Smarcel } 399119815Smarcel 400119815Smarcel error = UART_PROBE(sc); 401119815Smarcel bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); 402151792Smarcel return ((error) ? error : BUS_PROBE_DEFAULT); 403119815Smarcel} 404119815Smarcel 405119815Smarcelint 406119815Smarceluart_bus_attach(device_t dev) 407119815Smarcel{ 408119815Smarcel struct uart_softc *sc, *sc0; 409119815Smarcel const char *sep; 410253161Smarcel int error, filt; 411119815Smarcel 412119815Smarcel /* 413119815Smarcel * The sc_class field defines the type of UART we're going to work 414119815Smarcel * with and thus the size of the softc. Replace the generic softc 415119815Smarcel * with one that matches the UART now that we're certain we handle 416119815Smarcel * the device. 417119815Smarcel */ 418119815Smarcel sc0 = device_get_softc(dev); 419119815Smarcel if (sc0->sc_class->size > sizeof(*sc)) { 420119815Smarcel sc = malloc(sc0->sc_class->size, M_UART, M_WAITOK|M_ZERO); 421119815Smarcel bcopy(sc0, sc, sizeof(*sc)); 422119815Smarcel device_set_softc(dev, sc); 423119815Smarcel } else 424119815Smarcel sc = sc0; 425119815Smarcel 426119815Smarcel /* 427260890Simp * Now that we know the softc for this device, connect the back 428260890Simp * pointer from the sysdev for this device, if any 429260890Simp */ 430260890Simp if (sc->sc_sysdev != NULL) 431260890Simp sc->sc_sysdev->sc = sc; 432260890Simp 433260890Simp /* 434119815Smarcel * Protect ourselves against interrupts while we're not completely 435119815Smarcel * finished attaching and initializing. We don't expect interrupts 436119815Smarcel * until after UART_ATTACH() though. 437119815Smarcel */ 438119815Smarcel sc->sc_leaving = 1; 439119815Smarcel 440157300Smarcel mtx_init(&sc->sc_hwmtx_s, "uart_hwmtx", NULL, MTX_SPIN); 441157300Smarcel if (sc->sc_hwmtx == NULL) 442157300Smarcel sc->sc_hwmtx = &sc->sc_hwmtx_s; 443120143Smarcel 444119815Smarcel /* 445119815Smarcel * Re-allocate. We expect that the softc contains the information 446119815Smarcel * collected by uart_bus_probe() intact. 447119815Smarcel */ 448119815Smarcel sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid, 449168281Smarcel 0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE); 450143025Smarius if (sc->sc_rres == NULL) { 451157300Smarcel mtx_destroy(&sc->sc_hwmtx_s); 452119815Smarcel return (ENXIO); 453143025Smarius } 454120380Snyan sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); 455120380Snyan sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); 456120380Snyan 457248963Sian /* 458248963Sian * Ensure there is room for at least three full FIFOs of data in the 459248963Sian * receive buffer (handles the case of low-level drivers with huge 460248963Sian * FIFOs), and also ensure that there is no less than the historical 461248963Sian * size of 384 bytes (handles the typical small-FIFO case). 462248963Sian */ 463248963Sian sc->sc_rxbufsz = MAX(384, sc->sc_rxfifosz * 3); 464119815Smarcel sc->sc_rxbuf = malloc(sc->sc_rxbufsz * sizeof(*sc->sc_rxbuf), 465119815Smarcel M_UART, M_WAITOK); 466119815Smarcel sc->sc_txbuf = malloc(sc->sc_txfifosz * sizeof(*sc->sc_txbuf), 467119815Smarcel M_UART, M_WAITOK); 468119815Smarcel 469119815Smarcel error = UART_ATTACH(sc); 470119815Smarcel if (error) 471119815Smarcel goto fail; 472119815Smarcel 473119815Smarcel if (sc->sc_hwiflow || sc->sc_hwoflow) { 474119815Smarcel sep = ""; 475119815Smarcel device_print_prettyname(dev); 476119815Smarcel if (sc->sc_hwiflow) { 477119815Smarcel printf("%sRTS iflow", sep); 478119815Smarcel sep = ", "; 479119815Smarcel } 480119815Smarcel if (sc->sc_hwoflow) { 481119815Smarcel printf("%sCTS oflow", sep); 482119815Smarcel sep = ", "; 483119815Smarcel } 484119815Smarcel printf("\n"); 485119815Smarcel } 486119815Smarcel 487119815Smarcel if (sc->sc_sysdev != NULL) { 488262932Simp if (sc->sc_sysdev->baudrate == 0) { 489137706Smarcel if (UART_IOCTL(sc, UART_IOCTL_BAUD, 490137706Smarcel (intptr_t)&sc->sc_sysdev->baudrate) != 0) 491137706Smarcel sc->sc_sysdev->baudrate = -1; 492137706Smarcel } 493119815Smarcel switch (sc->sc_sysdev->type) { 494119815Smarcel case UART_DEV_CONSOLE: 495119815Smarcel device_printf(dev, "console"); 496119815Smarcel break; 497119815Smarcel case UART_DEV_DBGPORT: 498119815Smarcel device_printf(dev, "debug port"); 499119815Smarcel break; 500119815Smarcel case UART_DEV_KEYBOARD: 501119815Smarcel device_printf(dev, "keyboard"); 502119815Smarcel break; 503119815Smarcel default: 504119815Smarcel device_printf(dev, "unknown system device"); 505119815Smarcel break; 506119815Smarcel } 507119815Smarcel printf(" (%d,%c,%d,%d)\n", sc->sc_sysdev->baudrate, 508119815Smarcel "noems"[sc->sc_sysdev->parity], sc->sc_sysdev->databits, 509119815Smarcel sc->sc_sysdev->stopbits); 510119815Smarcel } 511119815Smarcel 512119996Smarcel sc->sc_pps.ppscap = PPS_CAPTUREBOTH; 513119996Smarcel pps_init(&sc->sc_pps); 514119996Smarcel 515253161Smarcel sc->sc_leaving = 0; 516253161Smarcel filt = uart_intr(sc); 517253161Smarcel 518253161Smarcel /* 519253161Smarcel * Don't use interrupts if we couldn't clear any pending interrupt 520253161Smarcel * conditions. We may have broken H/W and polling is probably the 521253161Smarcel * safest thing to do. 522253161Smarcel */ 523285619Sneel if (filt != FILTER_SCHEDULE_THREAD && !uart_force_poll) { 524253161Smarcel sc->sc_irid = 0; 525253161Smarcel sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 526253161Smarcel &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE); 527253161Smarcel } 528253161Smarcel if (sc->sc_ires != NULL) { 529253161Smarcel error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY, 530253161Smarcel uart_intr, NULL, sc, &sc->sc_icookie); 531253161Smarcel sc->sc_fastintr = (error == 0) ? 1 : 0; 532253161Smarcel 533253161Smarcel if (!sc->sc_fastintr) 534253161Smarcel error = bus_setup_intr(dev, sc->sc_ires, 535253161Smarcel INTR_TYPE_TTY | INTR_MPSAFE, NULL, 536253161Smarcel (driver_intr_t *)uart_intr, sc, &sc->sc_icookie); 537253161Smarcel 538253161Smarcel if (error) { 539253161Smarcel device_printf(dev, "could not activate interrupt\n"); 540253161Smarcel bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 541253161Smarcel sc->sc_ires); 542253161Smarcel sc->sc_ires = NULL; 543253161Smarcel } 544253161Smarcel } 545253161Smarcel if (sc->sc_ires == NULL) { 546253161Smarcel /* No interrupt resource. Force polled mode. */ 547253161Smarcel sc->sc_polled = 1; 548253161Smarcel callout_init(&sc->sc_timer, 1); 549285619Sneel callout_reset(&sc->sc_timer, hz / uart_poll_freq, 550285619Sneel (timeout_t *)uart_intr, sc); 551253161Smarcel } 552253161Smarcel 553253161Smarcel if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) { 554253161Smarcel sep = ""; 555253161Smarcel device_print_prettyname(dev); 556253161Smarcel if (sc->sc_fastintr) { 557253161Smarcel printf("%sfast interrupt", sep); 558253161Smarcel sep = ", "; 559253161Smarcel } 560253161Smarcel if (sc->sc_polled) { 561254534Sian printf("%spolled mode (%dHz)", sep, uart_poll_freq); 562253161Smarcel sep = ", "; 563253161Smarcel } 564253161Smarcel printf("\n"); 565253161Smarcel } 566253161Smarcel 567119815Smarcel error = (sc->sc_sysdev != NULL && sc->sc_sysdev->attach != NULL) 568119815Smarcel ? (*sc->sc_sysdev->attach)(sc) : uart_tty_attach(sc); 569119815Smarcel if (error) 570119815Smarcel goto fail; 571119815Smarcel 572157300Smarcel if (sc->sc_sysdev != NULL) 573157300Smarcel sc->sc_sysdev->hwmtx = sc->sc_hwmtx; 574157300Smarcel 575119815Smarcel return (0); 576119815Smarcel 577119815Smarcel fail: 578119815Smarcel free(sc->sc_txbuf, M_UART); 579119815Smarcel free(sc->sc_rxbuf, M_UART); 580119815Smarcel 581119815Smarcel if (sc->sc_ires != NULL) { 582119815Smarcel bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 583119815Smarcel bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 584119815Smarcel sc->sc_ires); 585119815Smarcel } 586119815Smarcel bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); 587119815Smarcel 588157300Smarcel mtx_destroy(&sc->sc_hwmtx_s); 589143025Smarius 590119815Smarcel return (error); 591119815Smarcel} 592119815Smarcel 593119815Smarcelint 594119815Smarceluart_bus_detach(device_t dev) 595119815Smarcel{ 596119815Smarcel struct uart_softc *sc; 597119815Smarcel 598119815Smarcel sc = device_get_softc(dev); 599119815Smarcel 600119815Smarcel sc->sc_leaving = 1; 601119815Smarcel 602157300Smarcel if (sc->sc_sysdev != NULL) 603157300Smarcel sc->sc_sysdev->hwmtx = NULL; 604157300Smarcel 605119815Smarcel UART_DETACH(sc); 606119815Smarcel 607119815Smarcel if (sc->sc_sysdev != NULL && sc->sc_sysdev->detach != NULL) 608119815Smarcel (*sc->sc_sysdev->detach)(sc); 609119815Smarcel else 610119815Smarcel uart_tty_detach(sc); 611119815Smarcel 612119815Smarcel free(sc->sc_txbuf, M_UART); 613119815Smarcel free(sc->sc_rxbuf, M_UART); 614119815Smarcel 615119815Smarcel if (sc->sc_ires != NULL) { 616119815Smarcel bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 617119815Smarcel bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 618119815Smarcel sc->sc_ires); 619119815Smarcel } 620119815Smarcel bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); 621119815Smarcel 622157300Smarcel mtx_destroy(&sc->sc_hwmtx_s); 623143025Smarius 624119815Smarcel if (sc->sc_class->size > sizeof(*sc)) { 625119815Smarcel device_set_softc(dev, NULL); 626119815Smarcel free(sc, M_UART); 627119815Smarcel } else 628119815Smarcel device_set_softc(dev, NULL); 629119815Smarcel 630119815Smarcel return (0); 631119815Smarcel} 632246243Savg 633246243Savgint 634246243Savguart_bus_resume(device_t dev) 635246243Savg{ 636246243Savg struct uart_softc *sc; 637246243Savg 638246243Savg sc = device_get_softc(dev); 639246243Savg return (UART_ATTACH(sc)); 640246243Savg} 641260890Simp 642260890Simpvoid 643260890Simpuart_grab(struct uart_devinfo *di) 644260890Simp{ 645260890Simp 646260890Simp if (di->sc) 647260890Simp UART_GRAB(di->sc); 648260890Simp} 649260890Simp 650260890Simpvoid 651260890Simpuart_ungrab(struct uart_devinfo *di) 652260890Simp{ 653260890Simp 654260890Simp if (di->sc) 655260890Simp UART_UNGRAB(di->sc); 656260890Simp} 657