1 /*- 2 * Copyright (c) 2012 NetApp, Inc. 3 * Copyright (c) 2013 Neel Natu <neel@freebsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/types.h> 34 #include <dev/ic/ns16550.h> 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <assert.h> 39 #include <fcntl.h> 40 #include <termios.h> 41 #include <unistd.h> 42 #include <stdbool.h> 43 #include <string.h> 44 #include <pthread.h> 45 46 #include "mevent.h" 47 #include "uart_emul.h" 48 49 #define COM1_BASE 0x3F8 50 #define COM1_IRQ 4 51 #define COM2_BASE 0x2F8 52 #define COM2_IRQ 3 53 54 #define DEFAULT_RCLK 1843200 55 #define DEFAULT_BAUD 9600 56 57 #define FCR_RX_MASK 0xC0 58 59 #define MCR_OUT1 0x04 60 #define MCR_OUT2 0x08 61 62 #define MSR_DELTA_MASK 0x0f 63 64 #ifndef REG_SCR 65 #define REG_SCR com_scr 66 #endif 67 68 #define FIFOSZ 16 69 70 static bool uart_stdio; /* stdio in use for i/o */ 71 static struct termios tio_stdio_orig; 72 73 static struct { 74 int baseaddr; 75 int irq; 76 bool inuse; 77 } uart_lres[] = { 78 { COM1_BASE, COM1_IRQ, false}, 79 { COM2_BASE, COM2_IRQ, false}, 80 }; 81 82 #define UART_NLDEVS (sizeof(uart_lres) / sizeof(uart_lres[0])) 83 84 struct fifo { 85 uint8_t buf[FIFOSZ]; 86 int rindex; /* index to read from */ 87 int windex; /* index to write to */ 88 int num; /* number of characters in the fifo */ 89 int size; /* size of the fifo */ 90 }; 91 92 struct ttyfd { 93 bool opened; 94 int fd; /* tty device file descriptor */ 95 struct termios tio_orig, tio_new; /* I/O Terminals */ 96 }; 97 98 struct uart_softc { 99 pthread_mutex_t mtx; /* protects all softc elements */ 100 uint8_t data; /* Data register (R/W) */ 101 uint8_t ier; /* Interrupt enable register (R/W) */ 102 uint8_t lcr; /* Line control register (R/W) */ 103 uint8_t mcr; /* Modem control register (R/W) */ 104 uint8_t lsr; /* Line status register (R/W) */ 105 uint8_t msr; /* Modem status register (R/W) */ 106 uint8_t fcr; /* FIFO control register (W) */ 107 uint8_t scr; /* Scratch register (R/W) */ 108 109 uint8_t dll; /* Baudrate divisor latch LSB */ 110 uint8_t dlh; /* Baudrate divisor latch MSB */ 111 112 struct fifo rxfifo; 113 struct mevent *mev; 114 115 struct ttyfd tty; 116 bool thre_int_pending; /* THRE interrupt pending */ 117 118 void *arg; 119 uart_intr_func_t intr_assert; 120 uart_intr_func_t intr_deassert; 121 }; 122 123 static void uart_drain(int fd, enum ev_type ev, void *arg); 124 125 static void 126 ttyclose(void) 127 { 128 129 tcsetattr(STDIN_FILENO, TCSANOW, &tio_stdio_orig); 130 } 131 132 static void 133 ttyopen(struct ttyfd *tf) 134 { 135 136 tcgetattr(tf->fd, &tf->tio_orig); 137 138 tf->tio_new = tf->tio_orig; 139 cfmakeraw(&tf->tio_new); 140 tf->tio_new.c_cflag |= CLOCAL; 141 tcsetattr(tf->fd, TCSANOW, &tf->tio_new); 142 143 if (tf->fd == STDIN_FILENO) { 144 tio_stdio_orig = tf->tio_orig; 145 atexit(ttyclose); 146 } 147 } 148 149 static int 150 ttyread(struct ttyfd *tf) 151 { 152 unsigned char rb; 153 154 if (read(tf->fd, &rb, 1) == 1) 155 return (rb); 156 else 157 return (-1); 158 } 159 160 static void 161 ttywrite(struct ttyfd *tf, unsigned char wb) 162 { 163 164 (void)write(tf->fd, &wb, 1); 165 } 166 167 static void 168 rxfifo_reset(struct uart_softc *sc, int size) 169 { 170 char flushbuf[32]; 171 struct fifo *fifo; 172 ssize_t nread; 173 int error; 174 175 fifo = &sc->rxfifo; 176 bzero(fifo, sizeof(struct fifo)); 177 fifo->size = size; 178 179 if (sc->tty.opened) { 180 /* 181 * Flush any unread input from the tty buffer. 182 */ 183 while (1) { 184 nread = read(sc->tty.fd, flushbuf, sizeof(flushbuf)); 185 if (nread != sizeof(flushbuf)) 186 break; 187 } 188 189 /* 190 * Enable mevent to trigger when new characters are available 191 * on the tty fd. 192 */ 193 error = mevent_enable(sc->mev); 194 assert(error == 0); 195 } 196 } 197 198 static int 199 rxfifo_available(struct uart_softc *sc) 200 { 201 struct fifo *fifo; 202 203 fifo = &sc->rxfifo; 204 return (fifo->num < fifo->size); 205 } 206 207 static int 208 rxfifo_putchar(struct uart_softc *sc, uint8_t ch) 209 { 210 struct fifo *fifo; 211 int error; 212 213 fifo = &sc->rxfifo; 214 215 if (fifo->num < fifo->size) { 216 fifo->buf[fifo->windex] = ch; 217 fifo->windex = (fifo->windex + 1) % fifo->size; 218 fifo->num++; 219 if (!rxfifo_available(sc)) { 220 if (sc->tty.opened) { 221 /* 222 * Disable mevent callback if the FIFO is full. 223 */ 224 error = mevent_disable(sc->mev); 225 assert(error == 0); 226 } 227 } 228 return (0); 229 } else 230 return (-1); 231 } 232 233 static int 234 rxfifo_getchar(struct uart_softc *sc) 235 { 236 struct fifo *fifo; 237 int c, error, wasfull; 238 239 wasfull = 0; 240 fifo = &sc->rxfifo; 241 if (fifo->num > 0) { 242 if (!rxfifo_available(sc)) 243 wasfull = 1; 244 c = fifo->buf[fifo->rindex]; 245 fifo->rindex = (fifo->rindex + 1) % fifo->size; 246 fifo->num--; 247 if (wasfull) { 248 if (sc->tty.opened) { 249 error = mevent_enable(sc->mev); 250 assert(error == 0); 251 } 252 } 253 return (c); 254 } else 255 return (-1); 256 } 257 258 static int 259 rxfifo_numchars(struct uart_softc *sc) 260 { 261 struct fifo *fifo = &sc->rxfifo; 262 263 return (fifo->num); 264 } 265 266 static void 267 uart_opentty(struct uart_softc *sc) 268 { 269 270 ttyopen(&sc->tty); 271 sc->mev = mevent_add(sc->tty.fd, EVF_READ, uart_drain, sc); 272 assert(sc->mev != NULL); 273 } 274 275 static uint8_t 276 modem_status(uint8_t mcr) 277 { 278 uint8_t msr; 279 280 if (mcr & MCR_LOOPBACK) { 281 /* 282 * In the loopback mode certain bits from the MCR are 283 * reflected back into MSR. 284 */ 285 msr = 0; 286 if (mcr & MCR_RTS) 287 msr |= MSR_CTS; 288 if (mcr & MCR_DTR) 289 msr |= MSR_DSR; 290 if (mcr & MCR_OUT1) 291 msr |= MSR_RI; 292 if (mcr & MCR_OUT2) 293 msr |= MSR_DCD; 294 } else { 295 /* 296 * Always assert DCD and DSR so tty open doesn't block 297 * even if CLOCAL is turned off. 298 */ 299 msr = MSR_DCD | MSR_DSR; 300 } 301 assert((msr & MSR_DELTA_MASK) == 0); 302 303 return (msr); 304 } 305 306 /* 307 * The IIR returns a prioritized interrupt reason: 308 * - receive data available 309 * - transmit holding register empty 310 * - modem status change 311 * 312 * Return an interrupt reason if one is available. 313 */ 314 static int 315 uart_intr_reason(struct uart_softc *sc) 316 { 317 318 if ((sc->lsr & LSR_OE) != 0 && (sc->ier & IER_ERLS) != 0) 319 return (IIR_RLS); 320 else if (rxfifo_numchars(sc) > 0 && (sc->ier & IER_ERXRDY) != 0) 321 return (IIR_RXTOUT); 322 else if (sc->thre_int_pending && (sc->ier & IER_ETXRDY) != 0) 323 return (IIR_TXRDY); 324 else if ((sc->msr & MSR_DELTA_MASK) != 0 && (sc->ier & IER_EMSC) != 0) 325 return (IIR_MLSC); 326 else 327 return (IIR_NOPEND); 328 } 329 330 static void 331 uart_reset(struct uart_softc *sc) 332 { 333 uint16_t divisor; 334 335 divisor = DEFAULT_RCLK / DEFAULT_BAUD / 16; 336 sc->dll = divisor; 337 sc->dlh = divisor >> 16; 338 sc->msr = modem_status(sc->mcr); 339 340 rxfifo_reset(sc, 1); /* no fifo until enabled by software */ 341 } 342 343 /* 344 * Toggle the COM port's intr pin depending on whether or not we have an 345 * interrupt condition to report to the processor. 346 */ 347 static void 348 uart_toggle_intr(struct uart_softc *sc) 349 { 350 uint8_t intr_reason; 351 352 intr_reason = uart_intr_reason(sc); 353 354 if (intr_reason == IIR_NOPEND) 355 (*sc->intr_deassert)(sc->arg); 356 else 357 (*sc->intr_assert)(sc->arg); 358 } 359 360 static void 361 uart_drain(int fd, enum ev_type ev, void *arg) 362 { 363 struct uart_softc *sc; 364 int ch; 365 366 sc = arg; 367 368 assert(fd == sc->tty.fd); 369 assert(ev == EVF_READ); 370 371 /* 372 * This routine is called in the context of the mevent thread 373 * to take out the softc lock to protect against concurrent 374 * access from a vCPU i/o exit 375 */ 376 pthread_mutex_lock(&sc->mtx); 377 378 if ((sc->mcr & MCR_LOOPBACK) != 0) { 379 (void) ttyread(&sc->tty); 380 } else { 381 while (rxfifo_available(sc) && 382 ((ch = ttyread(&sc->tty)) != -1)) { 383 rxfifo_putchar(sc, ch); 384 } 385 uart_toggle_intr(sc); 386 } 387 388 pthread_mutex_unlock(&sc->mtx); 389 } 390 391 void 392 uart_write(struct uart_softc *sc, int offset, uint8_t value) 393 { 394 int fifosz; 395 uint8_t msr; 396 397 pthread_mutex_lock(&sc->mtx); 398 399 /* 400 * Take care of the special case DLAB accesses first 401 */ 402 if ((sc->lcr & LCR_DLAB) != 0) { 403 if (offset == REG_DLL) { 404 sc->dll = value; 405 goto done; 406 } 407 408 if (offset == REG_DLH) { 409 sc->dlh = value; 410 goto done; 411 } 412 } 413 414 switch (offset) { 415 case REG_DATA: 416 if (sc->mcr & MCR_LOOPBACK) { 417 if (rxfifo_putchar(sc, value) != 0) 418 sc->lsr |= LSR_OE; 419 } else if (sc->tty.opened) { 420 ttywrite(&sc->tty, value); 421 } /* else drop on floor */ 422 sc->thre_int_pending = true; 423 break; 424 case REG_IER: 425 /* 426 * Apply mask so that bits 4-7 are 0 427 * Also enables bits 0-3 only if they're 1 428 */ 429 sc->ier = value & 0x0F; 430 break; 431 case REG_FCR: 432 /* 433 * When moving from FIFO and 16450 mode and vice versa, 434 * the FIFO contents are reset. 435 */ 436 if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) { 437 fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1; 438 rxfifo_reset(sc, fifosz); 439 } 440 441 /* 442 * The FCR_ENABLE bit must be '1' for the programming 443 * of other FCR bits to be effective. 444 */ 445 if ((value & FCR_ENABLE) == 0) { 446 sc->fcr = 0; 447 } else { 448 if ((value & FCR_RCV_RST) != 0) 449 rxfifo_reset(sc, FIFOSZ); 450 451 sc->fcr = value & 452 (FCR_ENABLE | FCR_DMA | FCR_RX_MASK); 453 } 454 break; 455 case REG_LCR: 456 sc->lcr = value; 457 break; 458 case REG_MCR: 459 /* Apply mask so that bits 5-7 are 0 */ 460 sc->mcr = value & 0x1F; 461 msr = modem_status(sc->mcr); 462 463 /* 464 * Detect if there has been any change between the 465 * previous and the new value of MSR. If there is 466 * then assert the appropriate MSR delta bit. 467 */ 468 if ((msr & MSR_CTS) ^ (sc->msr & MSR_CTS)) 469 sc->msr |= MSR_DCTS; 470 if ((msr & MSR_DSR) ^ (sc->msr & MSR_DSR)) 471 sc->msr |= MSR_DDSR; 472 if ((msr & MSR_DCD) ^ (sc->msr & MSR_DCD)) 473 sc->msr |= MSR_DDCD; 474 if ((sc->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0) 475 sc->msr |= MSR_TERI; 476 477 /* 478 * Update the value of MSR while retaining the delta 479 * bits. 480 */ 481 sc->msr &= MSR_DELTA_MASK; 482 sc->msr |= msr; 483 break; 484 case REG_LSR: 485 /* 486 * Line status register is not meant to be written to 487 * during normal operation. 488 */ 489 break; 490 case REG_MSR: 491 /* 492 * As far as I can tell MSR is a read-only register. 493 */ 494 break; 495 case REG_SCR: 496 sc->scr = value; 497 break; 498 default: 499 break; 500 } 501 502 done: 503 uart_toggle_intr(sc); 504 pthread_mutex_unlock(&sc->mtx); 505 } 506 507 uint8_t 508 uart_read(struct uart_softc *sc, int offset) 509 { 510 uint8_t iir, intr_reason, reg; 511 512 pthread_mutex_lock(&sc->mtx); 513 514 /* 515 * Take care of the special case DLAB accesses first 516 */ 517 if ((sc->lcr & LCR_DLAB) != 0) { 518 if (offset == REG_DLL) { 519 reg = sc->dll; 520 goto done; 521 } 522 523 if (offset == REG_DLH) { 524 reg = sc->dlh; 525 goto done; 526 } 527 } 528 529 switch (offset) { 530 case REG_DATA: 531 reg = rxfifo_getchar(sc); 532 break; 533 case REG_IER: 534 reg = sc->ier; 535 break; 536 case REG_IIR: 537 iir = (sc->fcr & FCR_ENABLE) ? IIR_FIFO_MASK : 0; 538 539 intr_reason = uart_intr_reason(sc); 540 541 /* 542 * Deal with side effects of reading the IIR register 543 */ 544 if (intr_reason == IIR_TXRDY) 545 sc->thre_int_pending = false; 546 547 iir |= intr_reason; 548 549 reg = iir; 550 break; 551 case REG_LCR: 552 reg = sc->lcr; 553 break; 554 case REG_MCR: 555 reg = sc->mcr; 556 break; 557 case REG_LSR: 558 /* Transmitter is always ready for more data */ 559 sc->lsr |= LSR_TEMT | LSR_THRE; 560 561 /* Check for new receive data */ 562 if (rxfifo_numchars(sc) > 0) 563 sc->lsr |= LSR_RXRDY; 564 else 565 sc->lsr &= ~LSR_RXRDY; 566 567 reg = sc->lsr; 568 569 /* The LSR_OE bit is cleared on LSR read */ 570 sc->lsr &= ~LSR_OE; 571 break; 572 case REG_MSR: 573 /* 574 * MSR delta bits are cleared on read 575 */ 576 reg = sc->msr; 577 sc->msr &= ~MSR_DELTA_MASK; 578 break; 579 case REG_SCR: 580 reg = sc->scr; 581 break; 582 default: 583 reg = 0xFF; 584 break; 585 } 586 587 done: 588 uart_toggle_intr(sc); 589 pthread_mutex_unlock(&sc->mtx); 590 591 return (reg); 592 } 593 594 int 595 uart_legacy_alloc(int which, int *baseaddr, int *irq) 596 { 597 598 if (which < 0 || which >= UART_NLDEVS || uart_lres[which].inuse) 599 return (-1); 600 601 uart_lres[which].inuse = true; 602 *baseaddr = uart_lres[which].baseaddr; 603 *irq = uart_lres[which].irq; 604 605 return (0); 606 } 607 608 struct uart_softc * 609 uart_init(uart_intr_func_t intr_assert, uart_intr_func_t intr_deassert, 610 void *arg) 611 { 612 struct uart_softc *sc; 613 614 sc = calloc(1, sizeof(struct uart_softc)); 615 616 sc->arg = arg; 617 sc->intr_assert = intr_assert; 618 sc->intr_deassert = intr_deassert; 619 620 pthread_mutex_init(&sc->mtx, NULL); 621 622 uart_reset(sc); 623 624 return (sc); 625 } 626 627 static int 628 uart_tty_backend(struct uart_softc *sc, const char *opts) 629 { 630 int fd; 631 int retval; 632 633 retval = -1; 634 635 fd = open(opts, O_RDWR | O_NONBLOCK); 636 if (fd > 0 && isatty(fd)) { 637 sc->tty.fd = fd; 638 sc->tty.opened = true; 639 retval = 0; 640 } 641 642 return (retval); 643 } 644 645 int 646 uart_set_backend(struct uart_softc *sc, const char *opts) 647 { 648 int retval; 649 650 retval = -1; 651 652 if (opts == NULL) 653 return (0); 654 655 if (strcmp("stdio", opts) == 0) { 656 if (!uart_stdio) { 657 sc->tty.fd = STDIN_FILENO; 658 sc->tty.opened = true; 659 uart_stdio = true; 660 retval = 0; 661 } 662 } else if (uart_tty_backend(sc, opts) == 0) { 663 retval = 0; 664 } 665 666 /* Make the backend file descriptor non-blocking */ 667 if (retval == 0) 668 retval = fcntl(sc->tty.fd, F_SETFL, O_NONBLOCK); 669 670 if (retval == 0) 671 uart_opentty(sc); 672 673 return (retval); 674 } 675