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 114 struct ttyfd tty; 115 bool thre_int_pending; /* THRE interrupt pending */ 116 117 void *arg; 118 uart_intr_func_t intr_assert; 119 uart_intr_func_t intr_deassert; 120 }; 121 122 static void uart_drain(int fd, enum ev_type ev, void *arg); 123 124 static void 125 ttyclose(void) 126 { 127 128 tcsetattr(STDIN_FILENO, TCSANOW, &tio_stdio_orig); 129 } 130 131 static void 132 ttyopen(struct ttyfd *tf) 133 { 134 135 tcgetattr(tf->fd, &tf->tio_orig); 136 137 tf->tio_new = tf->tio_orig; 138 cfmakeraw(&tf->tio_new); 139 tf->tio_new.c_cflag |= CLOCAL; 140 tcsetattr(tf->fd, TCSANOW, &tf->tio_new); 141 142 if (tf->fd == STDIN_FILENO) { 143 tio_stdio_orig = tf->tio_orig; 144 atexit(ttyclose); 145 } 146 } 147 148 static bool 149 tty_char_available(struct ttyfd *tf) 150 { 151 fd_set rfds; 152 struct timeval tv; 153 154 FD_ZERO(&rfds); 155 FD_SET(tf->fd, &rfds); 156 tv.tv_sec = 0; 157 tv.tv_usec = 0; 158 if (select(tf->fd + 1, &rfds, NULL, NULL, &tv) > 0 ) { 159 return (true); 160 } else { 161 return (false); 162 } 163 } 164 165 static int 166 ttyread(struct ttyfd *tf) 167 { 168 char rb; 169 170 if (tty_char_available(tf)) { 171 read(tf->fd, &rb, 1); 172 return (rb & 0xff); 173 } else { 174 return (-1); 175 } 176 } 177 178 static void 179 ttywrite(struct ttyfd *tf, unsigned char wb) 180 { 181 182 (void)write(tf->fd, &wb, 1); 183 } 184 185 static void 186 fifo_reset(struct fifo *fifo, int size) 187 { 188 189 bzero(fifo, sizeof(struct fifo)); 190 fifo->size = size; 191 } 192 193 static int 194 fifo_putchar(struct fifo *fifo, uint8_t ch) 195 { 196 197 if (fifo->num < fifo->size) { 198 fifo->buf[fifo->windex] = ch; 199 fifo->windex = (fifo->windex + 1) % fifo->size; 200 fifo->num++; 201 return (0); 202 } else 203 return (-1); 204 } 205 206 static int 207 fifo_getchar(struct fifo *fifo) 208 { 209 int c; 210 211 if (fifo->num > 0) { 212 c = fifo->buf[fifo->rindex]; 213 fifo->rindex = (fifo->rindex + 1) % fifo->size; 214 fifo->num--; 215 return (c); 216 } else 217 return (-1); 218 } 219 220 static int 221 fifo_numchars(struct fifo *fifo) 222 { 223 224 return (fifo->num); 225 } 226 227 static int 228 fifo_available(struct fifo *fifo) 229 { 230 231 return (fifo->num < fifo->size); 232 } 233 234 static void 235 uart_opentty(struct uart_softc *sc) 236 { 237 struct mevent *mev; 238 239 ttyopen(&sc->tty); 240 mev = mevent_add(sc->tty.fd, EVF_READ, uart_drain, sc); 241 assert(mev); 242 } 243 244 /* 245 * The IIR returns a prioritized interrupt reason: 246 * - receive data available 247 * - transmit holding register empty 248 * - modem status change 249 * 250 * Return an interrupt reason if one is available. 251 */ 252 static int 253 uart_intr_reason(struct uart_softc *sc) 254 { 255 256 if ((sc->lsr & LSR_OE) != 0 && (sc->ier & IER_ERLS) != 0) 257 return (IIR_RLS); 258 else if (fifo_numchars(&sc->rxfifo) > 0 && (sc->ier & IER_ERXRDY) != 0) 259 return (IIR_RXTOUT); 260 else if (sc->thre_int_pending && (sc->ier & IER_ETXRDY) != 0) 261 return (IIR_TXRDY); 262 else if ((sc->msr & MSR_DELTA_MASK) != 0 && (sc->ier & IER_EMSC) != 0) 263 return (IIR_MLSC); 264 else 265 return (IIR_NOPEND); 266 } 267 268 static void 269 uart_reset(struct uart_softc *sc) 270 { 271 uint16_t divisor; 272 273 divisor = DEFAULT_RCLK / DEFAULT_BAUD / 16; 274 sc->dll = divisor; 275 sc->dlh = divisor >> 16; 276 277 fifo_reset(&sc->rxfifo, 1); /* no fifo until enabled by software */ 278 } 279 280 /* 281 * Toggle the COM port's intr pin depending on whether or not we have an 282 * interrupt condition to report to the processor. 283 */ 284 static void 285 uart_toggle_intr(struct uart_softc *sc) 286 { 287 uint8_t intr_reason; 288 289 intr_reason = uart_intr_reason(sc); 290 291 if (intr_reason == IIR_NOPEND) 292 (*sc->intr_deassert)(sc->arg); 293 else 294 (*sc->intr_assert)(sc->arg); 295 } 296 297 static void 298 uart_drain(int fd, enum ev_type ev, void *arg) 299 { 300 struct uart_softc *sc; 301 int ch; 302 303 sc = arg; 304 305 assert(fd == sc->tty.fd); 306 assert(ev == EVF_READ); 307 308 /* 309 * This routine is called in the context of the mevent thread 310 * to take out the softc lock to protect against concurrent 311 * access from a vCPU i/o exit 312 */ 313 pthread_mutex_lock(&sc->mtx); 314 315 if ((sc->mcr & MCR_LOOPBACK) != 0) { 316 (void) ttyread(&sc->tty); 317 } else { 318 while (fifo_available(&sc->rxfifo) && 319 ((ch = ttyread(&sc->tty)) != -1)) { 320 fifo_putchar(&sc->rxfifo, ch); 321 } 322 uart_toggle_intr(sc); 323 } 324 325 pthread_mutex_unlock(&sc->mtx); 326 } 327 328 void 329 uart_write(struct uart_softc *sc, int offset, uint8_t value) 330 { 331 int fifosz; 332 uint8_t msr; 333 334 pthread_mutex_lock(&sc->mtx); 335 336 /* 337 * Take care of the special case DLAB accesses first 338 */ 339 if ((sc->lcr & LCR_DLAB) != 0) { 340 if (offset == REG_DLL) { 341 sc->dll = value; 342 goto done; 343 } 344 345 if (offset == REG_DLH) { 346 sc->dlh = value; 347 goto done; 348 } 349 } 350 351 switch (offset) { 352 case REG_DATA: 353 if (sc->mcr & MCR_LOOPBACK) { 354 if (fifo_putchar(&sc->rxfifo, value) != 0) 355 sc->lsr |= LSR_OE; 356 } else if (sc->tty.opened) { 357 ttywrite(&sc->tty, value); 358 } /* else drop on floor */ 359 sc->thre_int_pending = true; 360 break; 361 case REG_IER: 362 /* 363 * Apply mask so that bits 4-7 are 0 364 * Also enables bits 0-3 only if they're 1 365 */ 366 sc->ier = value & 0x0F; 367 break; 368 case REG_FCR: 369 /* 370 * When moving from FIFO and 16450 mode and vice versa, 371 * the FIFO contents are reset. 372 */ 373 if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) { 374 fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1; 375 fifo_reset(&sc->rxfifo, fifosz); 376 } 377 378 /* 379 * The FCR_ENABLE bit must be '1' for the programming 380 * of other FCR bits to be effective. 381 */ 382 if ((value & FCR_ENABLE) == 0) { 383 sc->fcr = 0; 384 } else { 385 if ((value & FCR_RCV_RST) != 0) 386 fifo_reset(&sc->rxfifo, FIFOSZ); 387 388 sc->fcr = value & 389 (FCR_ENABLE | FCR_DMA | FCR_RX_MASK); 390 } 391 break; 392 case REG_LCR: 393 sc->lcr = value; 394 break; 395 case REG_MCR: 396 /* Apply mask so that bits 5-7 are 0 */ 397 sc->mcr = value & 0x1F; 398 399 msr = 0; 400 if (sc->mcr & MCR_LOOPBACK) { 401 /* 402 * In the loopback mode certain bits from the 403 * MCR are reflected back into MSR 404 */ 405 if (sc->mcr & MCR_RTS) 406 msr |= MSR_CTS; 407 if (sc->mcr & MCR_DTR) 408 msr |= MSR_DSR; 409 if (sc->mcr & MCR_OUT1) 410 msr |= MSR_RI; 411 if (sc->mcr & MCR_OUT2) 412 msr |= MSR_DCD; 413 } 414 415 /* 416 * Detect if there has been any change between the 417 * previous and the new value of MSR. If there is 418 * then assert the appropriate MSR delta bit. 419 */ 420 if ((msr & MSR_CTS) ^ (sc->msr & MSR_CTS)) 421 sc->msr |= MSR_DCTS; 422 if ((msr & MSR_DSR) ^ (sc->msr & MSR_DSR)) 423 sc->msr |= MSR_DDSR; 424 if ((msr & MSR_DCD) ^ (sc->msr & MSR_DCD)) 425 sc->msr |= MSR_DDCD; 426 if ((sc->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0) 427 sc->msr |= MSR_TERI; 428 429 /* 430 * Update the value of MSR while retaining the delta 431 * bits. 432 */ 433 sc->msr &= MSR_DELTA_MASK; 434 sc->msr |= msr; 435 break; 436 case REG_LSR: 437 /* 438 * Line status register is not meant to be written to 439 * during normal operation. 440 */ 441 break; 442 case REG_MSR: 443 /* 444 * As far as I can tell MSR is a read-only register. 445 */ 446 break; 447 case REG_SCR: 448 sc->scr = value; 449 break; 450 default: 451 break; 452 } 453 454 done: 455 uart_toggle_intr(sc); 456 pthread_mutex_unlock(&sc->mtx); 457 } 458 459 uint8_t 460 uart_read(struct uart_softc *sc, int offset) 461 { 462 uint8_t iir, intr_reason, reg; 463 464 pthread_mutex_lock(&sc->mtx); 465 466 /* 467 * Take care of the special case DLAB accesses first 468 */ 469 if ((sc->lcr & LCR_DLAB) != 0) { 470 if (offset == REG_DLL) { 471 reg = sc->dll; 472 goto done; 473 } 474 475 if (offset == REG_DLH) { 476 reg = sc->dlh; 477 goto done; 478 } 479 } 480 481 switch (offset) { 482 case REG_DATA: 483 reg = fifo_getchar(&sc->rxfifo); 484 break; 485 case REG_IER: 486 reg = sc->ier; 487 break; 488 case REG_IIR: 489 iir = (sc->fcr & FCR_ENABLE) ? IIR_FIFO_MASK : 0; 490 491 intr_reason = uart_intr_reason(sc); 492 493 /* 494 * Deal with side effects of reading the IIR register 495 */ 496 if (intr_reason == IIR_TXRDY) 497 sc->thre_int_pending = false; 498 499 iir |= intr_reason; 500 501 reg = iir; 502 break; 503 case REG_LCR: 504 reg = sc->lcr; 505 break; 506 case REG_MCR: 507 reg = sc->mcr; 508 break; 509 case REG_LSR: 510 /* Transmitter is always ready for more data */ 511 sc->lsr |= LSR_TEMT | LSR_THRE; 512 513 /* Check for new receive data */ 514 if (fifo_numchars(&sc->rxfifo) > 0) 515 sc->lsr |= LSR_RXRDY; 516 else 517 sc->lsr &= ~LSR_RXRDY; 518 519 reg = sc->lsr; 520 521 /* The LSR_OE bit is cleared on LSR read */ 522 sc->lsr &= ~LSR_OE; 523 break; 524 case REG_MSR: 525 /* 526 * MSR delta bits are cleared on read 527 */ 528 reg = sc->msr; 529 sc->msr &= ~MSR_DELTA_MASK; 530 break; 531 case REG_SCR: 532 reg = sc->scr; 533 break; 534 default: 535 reg = 0xFF; 536 break; 537 } 538 539 done: 540 uart_toggle_intr(sc); 541 pthread_mutex_unlock(&sc->mtx); 542 543 return (reg); 544 } 545 546 int 547 uart_legacy_alloc(int which, int *baseaddr, int *irq) 548 { 549 550 if (which < 0 || which >= UART_NLDEVS || uart_lres[which].inuse) 551 return (-1); 552 553 uart_lres[which].inuse = true; 554 *baseaddr = uart_lres[which].baseaddr; 555 *irq = uart_lres[which].irq; 556 557 return (0); 558 } 559 560 struct uart_softc * 561 uart_init(uart_intr_func_t intr_assert, uart_intr_func_t intr_deassert, 562 void *arg) 563 { 564 struct uart_softc *sc; 565 566 sc = malloc(sizeof(struct uart_softc)); 567 bzero(sc, sizeof(struct uart_softc)); 568 569 sc->arg = arg; 570 sc->intr_assert = intr_assert; 571 sc->intr_deassert = intr_deassert; 572 573 pthread_mutex_init(&sc->mtx, NULL); 574 575 uart_reset(sc); 576 577 return (sc); 578 } 579 580 static int 581 uart_tty_backend(struct uart_softc *sc, const char *opts) 582 { 583 int fd; 584 int retval; 585 586 retval = -1; 587 588 fd = open(opts, O_RDWR); 589 if (fd > 0 && isatty(fd)) { 590 sc->tty.fd = fd; 591 sc->tty.opened = true; 592 retval = 0; 593 } 594 595 return (retval); 596 } 597 598 int 599 uart_set_backend(struct uart_softc *sc, const char *opts) 600 { 601 int retval; 602 603 retval = -1; 604 605 if (opts == NULL) 606 return (0); 607 608 if (strcmp("stdio", opts) == 0) { 609 if (!uart_stdio) { 610 sc->tty.fd = STDIN_FILENO; 611 sc->tty.opened = true; 612 uart_stdio = true; 613 retval = 0; 614 } 615 } else if (uart_tty_backend(sc, opts) == 0) { 616 retval = 0; 617 } 618 619 if (retval == 0) 620 uart_opentty(sc); 621 622 return (retval); 623 } 624