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