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$"); 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> 42119815Smarcel#include <machine/bus.h> 43119815Smarcel#include <sys/rman.h> 44119815Smarcel#include <machine/resource.h> 45119815Smarcel#include <machine/stdarg.h> 46119815Smarcel 47119815Smarcel#include <dev/uart/uart.h> 48119815Smarcel#include <dev/uart/uart_bus.h> 49119815Smarcel#include <dev/uart/uart_cpu.h> 50119815Smarcel 51119815Smarcel#include "uart_if.h" 52119815Smarcel 53119815Smarceldevclass_t uart_devclass; 54119815Smarcelchar uart_driver_name[] = "uart"; 55119815Smarcel 56119815SmarcelSLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs = 57119815Smarcel SLIST_HEAD_INITIALIZER(uart_sysdevs); 58119815Smarcel 59249132Smavstatic MALLOC_DEFINE(M_UART, "UART", "UART driver"); 60119815Smarcel 61119815Smarcelvoid 62119815Smarceluart_add_sysdev(struct uart_devinfo *di) 63119815Smarcel{ 64119815Smarcel SLIST_INSERT_HEAD(&uart_sysdevs, di, next); 65119815Smarcel} 66119815Smarcel 67168281Smarcelconst char * 68168281Smarceluart_getname(struct uart_class *uc) 69168281Smarcel{ 70168281Smarcel return ((uc != NULL) ? uc->name : NULL); 71168281Smarcel} 72168281Smarcel 73168281Smarcelstruct uart_ops * 74168281Smarceluart_getops(struct uart_class *uc) 75168281Smarcel{ 76168281Smarcel return ((uc != NULL) ? uc->uc_ops : NULL); 77168281Smarcel} 78168281Smarcel 79168281Smarcelint 80168281Smarceluart_getrange(struct uart_class *uc) 81168281Smarcel{ 82168281Smarcel return ((uc != NULL) ? uc->uc_range : 0); 83168281Smarcel} 84168281Smarcel 85119815Smarcel/* 86157300Smarcel * Schedule a soft interrupt. We do this on the 0 to !0 transition 87157300Smarcel * of the TTY pending interrupt status. 88157300Smarcel */ 89197721Smarcelvoid 90157300Smarceluart_sched_softih(struct uart_softc *sc, uint32_t ipend) 91157300Smarcel{ 92157300Smarcel uint32_t new, old; 93157300Smarcel 94157300Smarcel do { 95157300Smarcel old = sc->sc_ttypend; 96157300Smarcel new = old | ipend; 97157300Smarcel } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new)); 98157300Smarcel 99157300Smarcel if ((old & SER_INT_MASK) == 0) 100157300Smarcel swi_sched(sc->sc_softih, 0); 101157300Smarcel} 102157300Smarcel 103157300Smarcel/* 104119815Smarcel * A break condition has been detected. We treat the break condition as 105119815Smarcel * a special case that should not happen during normal operation. When 106119815Smarcel * the break condition is to be passed to higher levels in the form of 107119815Smarcel * a NUL character, we really want the break to be in the right place in 108119815Smarcel * the input stream. The overhead to achieve that is not in relation to 109119815Smarcel * the exceptional nature of the break condition, so we permit ourselves 110119815Smarcel * to be sloppy. 111119815Smarcel */ 112157300Smarcelstatic __inline int 113157300Smarceluart_intr_break(void *arg) 114119815Smarcel{ 115157300Smarcel struct uart_softc *sc = arg; 116119815Smarcel 117225203Srwatson#if defined(KDB) 118119815Smarcel if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { 119225203Srwatson if (kdb_break()) 120225203Srwatson return (0); 121119815Smarcel } 122119815Smarcel#endif 123119815Smarcel if (sc->sc_opened) 124157300Smarcel uart_sched_softih(sc, SER_INT_BREAK); 125157300Smarcel return (0); 126119815Smarcel} 127119815Smarcel 128119815Smarcel/* 129119815Smarcel * Handle a receiver overrun situation. We lost at least 1 byte in the 130119815Smarcel * input stream and it's our job to contain the situation. We grab as 131119815Smarcel * much of the data we can, but otherwise flush the receiver FIFO to 132119815Smarcel * create some breathing room. The net effect is that we avoid the 133119815Smarcel * overrun condition to happen for the next X characters, where X is 134258218Smav * related to the FIFO size at the cost of losing data right away. 135119815Smarcel * So, instead of having multiple overrun interrupts in close proximity 136119815Smarcel * to each other and possibly pessimizing UART interrupt latency for 137119815Smarcel * other UARTs in a multiport configuration, we create a longer segment 138119815Smarcel * of missing characters by freeing up the FIFO. 139119815Smarcel * Each overrun condition is marked in the input buffer by a token. The 140119815Smarcel * token represents the loss of at least one, but possible more bytes in 141119815Smarcel * the input stream. 142119815Smarcel */ 143157300Smarcelstatic __inline int 144157300Smarceluart_intr_overrun(void *arg) 145119815Smarcel{ 146157300Smarcel struct uart_softc *sc = arg; 147119815Smarcel 148119815Smarcel if (sc->sc_opened) { 149119815Smarcel UART_RECEIVE(sc); 150119815Smarcel if (uart_rx_put(sc, UART_STAT_OVERRUN)) 151119815Smarcel sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; 152157300Smarcel uart_sched_softih(sc, SER_INT_RXREADY); 153119815Smarcel } 154119815Smarcel UART_FLUSH(sc, UART_FLUSH_RECEIVER); 155157300Smarcel return (0); 156119815Smarcel} 157119815Smarcel 158119815Smarcel/* 159119815Smarcel * Received data ready. 160119815Smarcel */ 161157300Smarcelstatic __inline int 162157300Smarceluart_intr_rxready(void *arg) 163119815Smarcel{ 164157300Smarcel struct uart_softc *sc = arg; 165119815Smarcel int rxp; 166119815Smarcel 167119815Smarcel rxp = sc->sc_rxput; 168119815Smarcel UART_RECEIVE(sc); 169225203Srwatson#if defined(KDB) 170119815Smarcel if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { 171119815Smarcel while (rxp != sc->sc_rxput) { 172225203Srwatson kdb_alt_break(sc->sc_rxbuf[rxp++], &sc->sc_altbrk); 173119815Smarcel if (rxp == sc->sc_rxbufsz) 174119815Smarcel rxp = 0; 175119815Smarcel } 176119815Smarcel } 177119815Smarcel#endif 178119815Smarcel if (sc->sc_opened) 179157300Smarcel uart_sched_softih(sc, SER_INT_RXREADY); 180119815Smarcel else 181119815Smarcel sc->sc_rxput = sc->sc_rxget; /* Ignore received data. */ 182157300Smarcel return (1); 183119815Smarcel} 184119815Smarcel 185119815Smarcel/* 186119815Smarcel * Line or modem status change (OOB signalling). 187119815Smarcel * We pass the signals to the software interrupt handler for further 188119815Smarcel * processing. Note that we merge the delta bits, but set the state 189258218Smav * bits. This is to avoid losing state transitions due to having more 190119815Smarcel * than 1 hardware interrupt between software interrupts. 191119815Smarcel */ 192157300Smarcelstatic __inline int 193157300Smarceluart_intr_sigchg(void *arg) 194119815Smarcel{ 195157300Smarcel struct uart_softc *sc = arg; 196119815Smarcel int new, old, sig; 197119815Smarcel 198119815Smarcel sig = UART_GETSIG(sc); 199119996Smarcel 200119996Smarcel if (sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) { 201119996Smarcel if (sig & UART_SIG_DPPS) { 202119996Smarcel pps_capture(&sc->sc_pps); 203119996Smarcel pps_event(&sc->sc_pps, (sig & UART_SIG_PPS) ? 204119996Smarcel PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); 205119996Smarcel } 206119996Smarcel } 207119996Smarcel 208157300Smarcel /* 209157300Smarcel * Keep track of signal changes, even when the device is not 210157300Smarcel * opened. This allows us to inform upper layers about a 211157300Smarcel * possible loss of DCD and thus the existence of a (possibly) 212157300Smarcel * different connection when we have DCD back, during the time 213157300Smarcel * that the device was closed. 214157300Smarcel */ 215119815Smarcel do { 216119815Smarcel old = sc->sc_ttypend; 217155973Smarcel new = old & ~SER_MASK_STATE; 218155971Smarcel new |= sig & SER_INT_SIGMASK; 219119815Smarcel } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new)); 220157300Smarcel 221157300Smarcel if (sc->sc_opened) 222157300Smarcel uart_sched_softih(sc, SER_INT_SIGCHG); 223157300Smarcel return (1); 224119815Smarcel} 225119815Smarcel 226119815Smarcel/* 227119815Smarcel * The transmitter can accept more data. 228119815Smarcel */ 229157300Smarcelstatic __inline int 230157300Smarceluart_intr_txidle(void *arg) 231119815Smarcel{ 232157300Smarcel struct uart_softc *sc = arg; 233157300Smarcel 234119815Smarcel if (sc->sc_txbusy) { 235119815Smarcel sc->sc_txbusy = 0; 236157300Smarcel uart_sched_softih(sc, SER_INT_TXIDLE); 237119815Smarcel } 238157300Smarcel return (0); 239119815Smarcel} 240119815Smarcel 241166901Spisostatic int 242119815Smarceluart_intr(void *arg) 243119815Smarcel{ 244119815Smarcel struct uart_softc *sc = arg; 245166901Spiso int flag = 0, ipend; 246119815Smarcel 247157300Smarcel while (!sc->sc_leaving && (ipend = UART_IPEND(sc)) != 0) { 248166901Spiso flag = 1; 249155971Smarcel if (ipend & SER_INT_OVERRUN) 250120146Smarcel uart_intr_overrun(sc); 251155971Smarcel if (ipend & SER_INT_BREAK) 252120146Smarcel uart_intr_break(sc); 253155971Smarcel if (ipend & SER_INT_RXREADY) 254120146Smarcel uart_intr_rxready(sc); 255155971Smarcel if (ipend & SER_INT_SIGCHG) 256120146Smarcel uart_intr_sigchg(sc); 257155971Smarcel if (ipend & SER_INT_TXIDLE) 258166901Spiso uart_intr_txidle(sc); 259157300Smarcel } 260166901Spiso return((flag)?FILTER_HANDLED:FILTER_STRAY); 261157300Smarcel} 262119815Smarcel 263157300Smarcelserdev_intr_t * 264157300Smarceluart_bus_ihand(device_t dev, int ipend) 265157300Smarcel{ 266157300Smarcel 267157300Smarcel switch (ipend) { 268157300Smarcel case SER_INT_BREAK: 269157300Smarcel return (uart_intr_break); 270157300Smarcel case SER_INT_OVERRUN: 271157300Smarcel return (uart_intr_overrun); 272157300Smarcel case SER_INT_RXREADY: 273157300Smarcel return (uart_intr_rxready); 274157300Smarcel case SER_INT_SIGCHG: 275157300Smarcel return (uart_intr_sigchg); 276157300Smarcel case SER_INT_TXIDLE: 277157300Smarcel return (uart_intr_txidle); 278157300Smarcel } 279157300Smarcel return (NULL); 280119815Smarcel} 281119815Smarcel 282119815Smarcelint 283158119Smarceluart_bus_ipend(device_t dev) 284158119Smarcel{ 285158119Smarcel struct uart_softc *sc; 286158119Smarcel 287158119Smarcel sc = device_get_softc(dev); 288158119Smarcel return (UART_IPEND(sc)); 289158119Smarcel} 290158119Smarcel 291158119Smarcelint 292157300Smarceluart_bus_sysdev(device_t dev) 293157300Smarcel{ 294157300Smarcel struct uart_softc *sc; 295157300Smarcel 296157300Smarcel sc = device_get_softc(dev); 297157300Smarcel return ((sc->sc_sysdev != NULL) ? 1 : 0); 298157300Smarcel} 299157300Smarcel 300157300Smarcelint 301120452Smarceluart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan) 302119815Smarcel{ 303119815Smarcel struct uart_softc *sc; 304119815Smarcel struct uart_devinfo *sysdev; 305119815Smarcel int error; 306119815Smarcel 307168281Smarcel sc = device_get_softc(dev); 308168281Smarcel 309119815Smarcel /* 310168281Smarcel * All uart_class references are weak. Check that the needed 311168281Smarcel * class has been compiled-in. Fail if not. 312168281Smarcel */ 313168281Smarcel if (sc->sc_class == NULL) 314168281Smarcel return (ENXIO); 315168281Smarcel 316168281Smarcel /* 317119815Smarcel * Initialize the instance. Note that the instance (=softc) does 318119815Smarcel * not necessarily match the hardware specific softc. We can't do 319119815Smarcel * anything about it now, because we may not attach to the device. 320119815Smarcel * Hardware drivers cannot use any of the class specific fields 321119815Smarcel * while probing. 322119815Smarcel */ 323119815Smarcel kobj_init((kobj_t)sc, (kobj_class_t)sc->sc_class); 324119815Smarcel sc->sc_dev = dev; 325119815Smarcel if (device_get_desc(dev) == NULL) 326168281Smarcel device_set_desc(dev, uart_getname(sc->sc_class)); 327119815Smarcel 328119815Smarcel /* 329119815Smarcel * Allocate the register resource. We assume that all UARTs have 330119815Smarcel * a single register window in either I/O port space or memory 331119815Smarcel * mapped I/O space. Any UART that needs multiple windows will 332119815Smarcel * consequently not be supported by this driver as-is. We try I/O 333119815Smarcel * port space first because that's the common case. 334119815Smarcel */ 335119815Smarcel sc->sc_rrid = rid; 336119815Smarcel sc->sc_rtype = SYS_RES_IOPORT; 337119815Smarcel sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid, 338168281Smarcel 0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE); 339119815Smarcel if (sc->sc_rres == NULL) { 340119815Smarcel sc->sc_rrid = rid; 341119815Smarcel sc->sc_rtype = SYS_RES_MEMORY; 342119815Smarcel sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, 343168281Smarcel &sc->sc_rrid, 0, ~0, uart_getrange(sc->sc_class), 344168281Smarcel RF_ACTIVE); 345119815Smarcel if (sc->sc_rres == NULL) 346119815Smarcel return (ENXIO); 347119815Smarcel } 348119815Smarcel 349119815Smarcel /* 350119815Smarcel * Fill in the bus access structure and compare this device with 351119815Smarcel * a possible console device and/or a debug port. We set the flags 352119815Smarcel * in the softc so that the hardware dependent probe can adjust 353119815Smarcel * accordingly. In general, you don't want to permanently disrupt 354119815Smarcel * console I/O. 355119815Smarcel */ 356119815Smarcel sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); 357119815Smarcel sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); 358120452Smarcel sc->sc_bas.chan = chan; 359119815Smarcel sc->sc_bas.regshft = regshft; 360119815Smarcel sc->sc_bas.rclk = (rclk == 0) ? sc->sc_class->uc_rclk : rclk; 361119815Smarcel 362119815Smarcel SLIST_FOREACH(sysdev, &uart_sysdevs, next) { 363120452Smarcel if (chan == sysdev->bas.chan && 364120452Smarcel uart_cpu_eqres(&sc->sc_bas, &sysdev->bas)) { 365119815Smarcel /* XXX check if ops matches class. */ 366119815Smarcel sc->sc_sysdev = sysdev; 367167999Smarcel sysdev->bas.rclk = sc->sc_bas.rclk; 368119815Smarcel } 369119815Smarcel } 370119815Smarcel 371119815Smarcel error = UART_PROBE(sc); 372119815Smarcel bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); 373151792Smarcel return ((error) ? error : BUS_PROBE_DEFAULT); 374119815Smarcel} 375119815Smarcel 376119815Smarcelint 377119815Smarceluart_bus_attach(device_t dev) 378119815Smarcel{ 379119815Smarcel struct uart_softc *sc, *sc0; 380119815Smarcel const char *sep; 381119815Smarcel int error; 382119815Smarcel 383119815Smarcel /* 384119815Smarcel * The sc_class field defines the type of UART we're going to work 385119815Smarcel * with and thus the size of the softc. Replace the generic softc 386119815Smarcel * with one that matches the UART now that we're certain we handle 387119815Smarcel * the device. 388119815Smarcel */ 389119815Smarcel sc0 = device_get_softc(dev); 390119815Smarcel if (sc0->sc_class->size > sizeof(*sc)) { 391119815Smarcel sc = malloc(sc0->sc_class->size, M_UART, M_WAITOK|M_ZERO); 392119815Smarcel bcopy(sc0, sc, sizeof(*sc)); 393119815Smarcel device_set_softc(dev, sc); 394119815Smarcel } else 395119815Smarcel sc = sc0; 396119815Smarcel 397119815Smarcel /* 398119815Smarcel * Protect ourselves against interrupts while we're not completely 399119815Smarcel * finished attaching and initializing. We don't expect interrupts 400119815Smarcel * until after UART_ATTACH() though. 401119815Smarcel */ 402119815Smarcel sc->sc_leaving = 1; 403119815Smarcel 404157300Smarcel mtx_init(&sc->sc_hwmtx_s, "uart_hwmtx", NULL, MTX_SPIN); 405157300Smarcel if (sc->sc_hwmtx == NULL) 406157300Smarcel sc->sc_hwmtx = &sc->sc_hwmtx_s; 407120143Smarcel 408119815Smarcel /* 409119815Smarcel * Re-allocate. We expect that the softc contains the information 410119815Smarcel * collected by uart_bus_probe() intact. 411119815Smarcel */ 412119815Smarcel sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid, 413168281Smarcel 0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE); 414143025Smarius if (sc->sc_rres == NULL) { 415157300Smarcel mtx_destroy(&sc->sc_hwmtx_s); 416119815Smarcel return (ENXIO); 417143025Smarius } 418120380Snyan sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); 419120380Snyan sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); 420120380Snyan 421119815Smarcel sc->sc_irid = 0; 422127135Snjl sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, 423143025Smarius RF_ACTIVE | RF_SHAREABLE); 424119815Smarcel if (sc->sc_ires != NULL) { 425155921Sjhb error = bus_setup_intr(dev, 426166901Spiso sc->sc_ires, INTR_TYPE_TTY, 427166901Spiso uart_intr, NULL, sc, &sc->sc_icookie); 428119815Smarcel if (error) 429155921Sjhb error = bus_setup_intr(dev, 430128909Smarcel sc->sc_ires, INTR_TYPE_TTY | INTR_MPSAFE, 431166901Spiso NULL, (driver_intr_t *)uart_intr, sc, &sc->sc_icookie); 432119815Smarcel else 433119815Smarcel sc->sc_fastintr = 1; 434119815Smarcel 435119815Smarcel if (error) { 436119815Smarcel device_printf(dev, "could not activate interrupt\n"); 437119815Smarcel bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 438119815Smarcel sc->sc_ires); 439119815Smarcel sc->sc_ires = NULL; 440119815Smarcel } 441119815Smarcel } 442119815Smarcel if (sc->sc_ires == NULL) { 443119815Smarcel /* XXX no interrupt resource. Force polled mode. */ 444119815Smarcel sc->sc_polled = 1; 445119815Smarcel } 446119815Smarcel 447181905Sed sc->sc_rxbufsz = 384; 448119815Smarcel sc->sc_rxbuf = malloc(sc->sc_rxbufsz * sizeof(*sc->sc_rxbuf), 449119815Smarcel M_UART, M_WAITOK); 450119815Smarcel sc->sc_txbuf = malloc(sc->sc_txfifosz * sizeof(*sc->sc_txbuf), 451119815Smarcel M_UART, M_WAITOK); 452119815Smarcel 453119815Smarcel error = UART_ATTACH(sc); 454119815Smarcel if (error) 455119815Smarcel goto fail; 456119815Smarcel 457119815Smarcel if (sc->sc_hwiflow || sc->sc_hwoflow) { 458119815Smarcel sep = ""; 459119815Smarcel device_print_prettyname(dev); 460119815Smarcel if (sc->sc_hwiflow) { 461119815Smarcel printf("%sRTS iflow", sep); 462119815Smarcel sep = ", "; 463119815Smarcel } 464119815Smarcel if (sc->sc_hwoflow) { 465119815Smarcel printf("%sCTS oflow", sep); 466119815Smarcel sep = ", "; 467119815Smarcel } 468119815Smarcel printf("\n"); 469119815Smarcel } 470119815Smarcel 471119815Smarcel if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) { 472119815Smarcel sep = ""; 473119815Smarcel device_print_prettyname(dev); 474119815Smarcel if (sc->sc_fastintr) { 475119815Smarcel printf("%sfast interrupt", sep); 476119815Smarcel sep = ", "; 477119815Smarcel } 478119815Smarcel if (sc->sc_polled) { 479119815Smarcel printf("%spolled mode", sep); 480119815Smarcel sep = ", "; 481119815Smarcel } 482119815Smarcel printf("\n"); 483119815Smarcel } 484119815Smarcel 485119815Smarcel if (sc->sc_sysdev != NULL) { 486137706Smarcel if (sc->sc_sysdev->baudrate == 0) { 487137706Smarcel if (UART_IOCTL(sc, UART_IOCTL_BAUD, 488137706Smarcel (intptr_t)&sc->sc_sysdev->baudrate) != 0) 489137706Smarcel sc->sc_sysdev->baudrate = -1; 490137706Smarcel } 491119815Smarcel switch (sc->sc_sysdev->type) { 492119815Smarcel case UART_DEV_CONSOLE: 493119815Smarcel device_printf(dev, "console"); 494119815Smarcel break; 495119815Smarcel case UART_DEV_DBGPORT: 496119815Smarcel device_printf(dev, "debug port"); 497119815Smarcel break; 498119815Smarcel case UART_DEV_KEYBOARD: 499119815Smarcel device_printf(dev, "keyboard"); 500119815Smarcel break; 501119815Smarcel default: 502119815Smarcel device_printf(dev, "unknown system device"); 503119815Smarcel break; 504119815Smarcel } 505119815Smarcel printf(" (%d,%c,%d,%d)\n", sc->sc_sysdev->baudrate, 506119815Smarcel "noems"[sc->sc_sysdev->parity], sc->sc_sysdev->databits, 507119815Smarcel sc->sc_sysdev->stopbits); 508119815Smarcel } 509119815Smarcel 510119996Smarcel sc->sc_pps.ppscap = PPS_CAPTUREBOTH; 511119996Smarcel pps_init(&sc->sc_pps); 512119996Smarcel 513119815Smarcel error = (sc->sc_sysdev != NULL && sc->sc_sysdev->attach != NULL) 514119815Smarcel ? (*sc->sc_sysdev->attach)(sc) : uart_tty_attach(sc); 515119815Smarcel if (error) 516119815Smarcel goto fail; 517119815Smarcel 518157300Smarcel if (sc->sc_sysdev != NULL) 519157300Smarcel sc->sc_sysdev->hwmtx = sc->sc_hwmtx; 520157300Smarcel 521119815Smarcel sc->sc_leaving = 0; 522119815Smarcel uart_intr(sc); 523119815Smarcel return (0); 524119815Smarcel 525119815Smarcel fail: 526119815Smarcel free(sc->sc_txbuf, M_UART); 527119815Smarcel free(sc->sc_rxbuf, M_UART); 528119815Smarcel 529119815Smarcel if (sc->sc_ires != NULL) { 530119815Smarcel bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 531119815Smarcel bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 532119815Smarcel sc->sc_ires); 533119815Smarcel } 534119815Smarcel bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); 535119815Smarcel 536157300Smarcel mtx_destroy(&sc->sc_hwmtx_s); 537143025Smarius 538119815Smarcel return (error); 539119815Smarcel} 540119815Smarcel 541119815Smarcelint 542119815Smarceluart_bus_detach(device_t dev) 543119815Smarcel{ 544119815Smarcel struct uart_softc *sc; 545119815Smarcel 546119815Smarcel sc = device_get_softc(dev); 547119815Smarcel 548119815Smarcel sc->sc_leaving = 1; 549119815Smarcel 550157300Smarcel if (sc->sc_sysdev != NULL) 551157300Smarcel sc->sc_sysdev->hwmtx = NULL; 552157300Smarcel 553119815Smarcel UART_DETACH(sc); 554119815Smarcel 555119815Smarcel if (sc->sc_sysdev != NULL && sc->sc_sysdev->detach != NULL) 556119815Smarcel (*sc->sc_sysdev->detach)(sc); 557119815Smarcel else 558119815Smarcel uart_tty_detach(sc); 559119815Smarcel 560119815Smarcel free(sc->sc_txbuf, M_UART); 561119815Smarcel free(sc->sc_rxbuf, M_UART); 562119815Smarcel 563119815Smarcel if (sc->sc_ires != NULL) { 564119815Smarcel bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); 565119815Smarcel bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, 566119815Smarcel sc->sc_ires); 567119815Smarcel } 568119815Smarcel bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); 569119815Smarcel 570157300Smarcel mtx_destroy(&sc->sc_hwmtx_s); 571143025Smarius 572119815Smarcel if (sc->sc_class->size > sizeof(*sc)) { 573119815Smarcel device_set_softc(dev, NULL); 574119815Smarcel free(sc, M_UART); 575119815Smarcel } else 576119815Smarcel device_set_softc(dev, NULL); 577119815Smarcel 578119815Smarcel return (0); 579119815Smarcel} 580247887Savg 581247887Savgint 582247887Savguart_bus_resume(device_t dev) 583247887Savg{ 584247887Savg struct uart_softc *sc; 585247887Savg 586247887Savg sc = device_get_softc(dev); 587247887Savg return (UART_ATTACH(sc)); 588247887Savg} 589