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