1 /*- 2 * Copyright (c) 2012 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/types.h> 33 #include <sys/select.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 "bhyverun.h" 46 #include "pci_emul.h" 47 #include "mevent.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 /* 71 * Pick a PCI vid/did of a chip with a single uart at 72 * BAR0, that most versions of FreeBSD can understand: 73 * Siig CyberSerial 1-port. 74 */ 75 #define COM_VENDOR 0x131f 76 #define COM_DEV 0x2000 77 78 static int pci_uart_stdio; /* stdio in use for i/o */ 79 80 static int pci_uart_nldevs; /* number of legacy devices - 2 max */ 81 82 static struct { 83 uint64_t baddr; 84 int vector; 85 } pci_uart_lres[] = { 86 { COM1_BASE, COM1_IRQ}, 87 { COM2_BASE, COM2_IRQ}, 88 { 0, 0 } 89 }; 90 91 struct fifo { 92 uint8_t buf[FIFOSZ]; 93 int rindex; /* index to read from */ 94 int windex; /* index to write to */ 95 int num; /* number of characters in the fifo */ 96 int size; /* size of the fifo */ 97 }; 98 99 struct pci_uart_softc { 100 struct pci_devinst *pi; 101 pthread_mutex_t mtx; /* protects all softc elements */ 102 uint8_t data; /* Data register (R/W) */ 103 uint8_t ier; /* Interrupt enable register (R/W) */ 104 uint8_t lcr; /* Line control register (R/W) */ 105 uint8_t mcr; /* Modem control register (R/W) */ 106 uint8_t lsr; /* Line status register (R/W) */ 107 uint8_t msr; /* Modem status register (R/W) */ 108 uint8_t fcr; /* FIFO control register (W) */ 109 uint8_t scr; /* Scratch register (R/W) */ 110 111 uint8_t dll; /* Baudrate divisor latch LSB */ 112 uint8_t dlh; /* Baudrate divisor latch MSB */ 113 114 struct fifo rxfifo; 115 116 int opened; 117 int stdio; 118 bool thre_int_pending; /* THRE interrupt pending */ 119 }; 120 121 static void pci_uart_drain(int fd, enum ev_type ev, void *arg); 122 123 static struct termios tio_orig, tio_new; /* I/O Terminals */ 124 125 static void 126 ttyclose(void) 127 { 128 tcsetattr(STDIN_FILENO, TCSANOW, &tio_orig); 129 } 130 131 static void 132 ttyopen(void) 133 { 134 tcgetattr(STDIN_FILENO, &tio_orig); 135 136 cfmakeraw(&tio_new); 137 tcsetattr(STDIN_FILENO, TCSANOW, &tio_new); 138 139 atexit(ttyclose); 140 } 141 142 static bool 143 tty_char_available(void) 144 { 145 fd_set rfds; 146 struct timeval tv; 147 148 FD_ZERO(&rfds); 149 FD_SET(STDIN_FILENO, &rfds); 150 tv.tv_sec = 0; 151 tv.tv_usec = 0; 152 if (select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) > 0 ) { 153 return (true); 154 } else { 155 return (false); 156 } 157 } 158 159 static int 160 ttyread(void) 161 { 162 char rb; 163 164 if (tty_char_available()) { 165 read(STDIN_FILENO, &rb, 1); 166 return (rb & 0xff); 167 } else { 168 return (-1); 169 } 170 } 171 172 static void 173 ttywrite(unsigned char wb) 174 { 175 (void) write(STDIN_FILENO, &wb, 1); 176 } 177 178 static void 179 fifo_reset(struct fifo *fifo, int size) 180 { 181 bzero(fifo, sizeof(struct fifo)); 182 fifo->size = size; 183 } 184 185 static int 186 fifo_putchar(struct fifo *fifo, uint8_t ch) 187 { 188 189 if (fifo->num < fifo->size) { 190 fifo->buf[fifo->windex] = ch; 191 fifo->windex = (fifo->windex + 1) % fifo->size; 192 fifo->num++; 193 return (0); 194 } else 195 return (-1); 196 } 197 198 static int 199 fifo_getchar(struct fifo *fifo) 200 { 201 int c; 202 203 if (fifo->num > 0) { 204 c = fifo->buf[fifo->rindex]; 205 fifo->rindex = (fifo->rindex + 1) % fifo->size; 206 fifo->num--; 207 return (c); 208 } else 209 return (-1); 210 } 211 212 static int 213 fifo_numchars(struct fifo *fifo) 214 { 215 216 return (fifo->num); 217 } 218 219 static int 220 fifo_available(struct fifo *fifo) 221 { 222 223 return (fifo->num < fifo->size); 224 } 225 226 static void 227 pci_uart_opentty(struct pci_uart_softc *sc) 228 { 229 struct mevent *mev; 230 231 assert(sc->opened == 0); 232 assert(sc->stdio); 233 234 ttyopen(); 235 mev = mevent_add(STDIN_FILENO, EVF_READ, pci_uart_drain, sc); 236 assert(mev); 237 } 238 239 static void 240 pci_uart_legacy_res(uint64_t *bar, int *ivec) 241 { 242 if (pci_uart_lres[pci_uart_nldevs].baddr != 0) { 243 *bar = pci_uart_lres[pci_uart_nldevs].baddr; 244 *ivec = pci_uart_lres[pci_uart_nldevs].vector; 245 pci_uart_nldevs++; 246 } else { 247 /* TODO: print warning ? */ 248 *bar = 0; 249 *ivec= -1; 250 } 251 } 252 253 /* 254 * The IIR returns a prioritized interrupt reason: 255 * - receive data available 256 * - transmit holding register empty 257 * - modem status change 258 * 259 * Return an interrupt reason if one is available. 260 */ 261 static int 262 pci_uart_intr_reason(struct pci_uart_softc *sc) 263 { 264 265 if ((sc->lsr & LSR_OE) != 0 && (sc->ier & IER_ERLS) != 0) 266 return (IIR_RLS); 267 else if (fifo_numchars(&sc->rxfifo) > 0 && (sc->ier & IER_ERXRDY) != 0) 268 return (IIR_RXTOUT); 269 else if (sc->thre_int_pending && (sc->ier & IER_ETXRDY) != 0) 270 return (IIR_TXRDY); 271 else if ((sc->msr & MSR_DELTA_MASK) != 0 && (sc->ier & IER_EMSC) != 0) 272 return (IIR_MLSC); 273 else 274 return (IIR_NOPEND); 275 } 276 277 static void 278 pci_uart_reset(struct pci_uart_softc *sc) 279 { 280 uint16_t divisor; 281 282 divisor = DEFAULT_RCLK / DEFAULT_BAUD / 16; 283 sc->dll = divisor; 284 sc->dlh = divisor >> 16; 285 286 fifo_reset(&sc->rxfifo, 1); /* no fifo until enabled by software */ 287 } 288 289 /* 290 * Toggle the COM port's intr pin depending on whether or not we have an 291 * interrupt condition to report to the processor. 292 */ 293 static void 294 pci_uart_toggle_intr(struct pci_uart_softc *sc) 295 { 296 uint8_t intr_reason; 297 298 intr_reason = pci_uart_intr_reason(sc); 299 300 if (intr_reason == IIR_NOPEND) 301 pci_lintr_deassert(sc->pi); 302 else 303 pci_lintr_assert(sc->pi); 304 } 305 306 static void 307 pci_uart_drain(int fd, enum ev_type ev, void *arg) 308 { 309 struct pci_uart_softc *sc; 310 int ch; 311 312 sc = arg; 313 314 assert(fd == STDIN_FILENO); 315 assert(ev == EVF_READ); 316 317 /* 318 * This routine is called in the context of the mevent thread 319 * to take out the softc lock to protect against concurrent 320 * access from a vCPU i/o exit 321 */ 322 pthread_mutex_lock(&sc->mtx); 323 324 if ((sc->mcr & MCR_LOOPBACK) != 0) { 325 (void) ttyread(); 326 } else { 327 while (fifo_available(&sc->rxfifo) && 328 ((ch = ttyread()) != -1)) { 329 fifo_putchar(&sc->rxfifo, ch); 330 } 331 pci_uart_toggle_intr(sc); 332 } 333 334 pthread_mutex_unlock(&sc->mtx); 335 } 336 337 static void 338 pci_uart_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 339 int baridx, uint64_t offset, int size, uint64_t value) 340 { 341 struct pci_uart_softc *sc; 342 int fifosz; 343 uint8_t msr; 344 345 sc = pi->pi_arg; 346 347 assert(baridx == 0); 348 assert(size == 1); 349 350 /* Open terminal */ 351 if (!sc->opened && sc->stdio) { 352 pci_uart_opentty(sc); 353 sc->opened = 1; 354 } 355 356 pthread_mutex_lock(&sc->mtx); 357 358 /* 359 * Take care of the special case DLAB accesses first 360 */ 361 if ((sc->lcr & LCR_DLAB) != 0) { 362 if (offset == REG_DLL) { 363 sc->dll = value; 364 goto done; 365 } 366 367 if (offset == REG_DLH) { 368 sc->dlh = value; 369 goto done; 370 } 371 } 372 373 switch (offset) { 374 case REG_DATA: 375 if (sc->mcr & MCR_LOOPBACK) { 376 if (fifo_putchar(&sc->rxfifo, value) != 0) 377 sc->lsr |= LSR_OE; 378 } else if (sc->stdio) { 379 ttywrite(value); 380 } /* else drop on floor */ 381 sc->thre_int_pending = true; 382 break; 383 case REG_IER: 384 /* 385 * Apply mask so that bits 4-7 are 0 386 * Also enables bits 0-3 only if they're 1 387 */ 388 sc->ier = value & 0x0F; 389 break; 390 case REG_FCR: 391 /* 392 * When moving from FIFO and 16450 mode and vice versa, 393 * the FIFO contents are reset. 394 */ 395 if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) { 396 fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1; 397 fifo_reset(&sc->rxfifo, fifosz); 398 } 399 400 /* 401 * The FCR_ENABLE bit must be '1' for the programming 402 * of other FCR bits to be effective. 403 */ 404 if ((value & FCR_ENABLE) == 0) { 405 sc->fcr = 0; 406 } else { 407 if ((value & FCR_RCV_RST) != 0) 408 fifo_reset(&sc->rxfifo, FIFOSZ); 409 410 sc->fcr = value & 411 (FCR_ENABLE | FCR_DMA | FCR_RX_MASK); 412 } 413 break; 414 case REG_LCR: 415 sc->lcr = value; 416 break; 417 case REG_MCR: 418 /* Apply mask so that bits 5-7 are 0 */ 419 sc->mcr = value & 0x1F; 420 421 msr = 0; 422 if (sc->mcr & MCR_LOOPBACK) { 423 /* 424 * In the loopback mode certain bits from the 425 * MCR are reflected back into MSR 426 */ 427 if (sc->mcr & MCR_RTS) 428 msr |= MSR_CTS; 429 if (sc->mcr & MCR_DTR) 430 msr |= MSR_DSR; 431 if (sc->mcr & MCR_OUT1) 432 msr |= MSR_RI; 433 if (sc->mcr & MCR_OUT2) 434 msr |= MSR_DCD; 435 } 436 437 /* 438 * Detect if there has been any change between the 439 * previous and the new value of MSR. If there is 440 * then assert the appropriate MSR delta bit. 441 */ 442 if ((msr & MSR_CTS) ^ (sc->msr & MSR_CTS)) 443 sc->msr |= MSR_DCTS; 444 if ((msr & MSR_DSR) ^ (sc->msr & MSR_DSR)) 445 sc->msr |= MSR_DDSR; 446 if ((msr & MSR_DCD) ^ (sc->msr & MSR_DCD)) 447 sc->msr |= MSR_DDCD; 448 if ((sc->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0) 449 sc->msr |= MSR_TERI; 450 451 /* 452 * Update the value of MSR while retaining the delta 453 * bits. 454 */ 455 sc->msr &= MSR_DELTA_MASK; 456 sc->msr |= msr; 457 break; 458 case REG_LSR: 459 /* 460 * Line status register is not meant to be written to 461 * during normal operation. 462 */ 463 break; 464 case REG_MSR: 465 /* 466 * As far as I can tell MSR is a read-only register. 467 */ 468 break; 469 case REG_SCR: 470 sc->scr = value; 471 break; 472 default: 473 break; 474 } 475 476 done: 477 pci_uart_toggle_intr(sc); 478 pthread_mutex_unlock(&sc->mtx); 479 } 480 481 uint64_t 482 pci_uart_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 483 int baridx, uint64_t offset, int size) 484 { 485 struct pci_uart_softc *sc; 486 uint8_t iir, intr_reason; 487 uint64_t reg; 488 489 sc = pi->pi_arg; 490 491 assert(baridx == 0); 492 assert(size == 1); 493 494 /* Open terminal */ 495 if (!sc->opened && sc->stdio) { 496 pci_uart_opentty(sc); 497 sc->opened = 1; 498 } 499 500 pthread_mutex_lock(&sc->mtx); 501 502 /* 503 * Take care of the special case DLAB accesses first 504 */ 505 if ((sc->lcr & LCR_DLAB) != 0) { 506 if (offset == REG_DLL) { 507 reg = sc->dll; 508 goto done; 509 } 510 511 if (offset == REG_DLH) { 512 reg = sc->dlh; 513 goto done; 514 } 515 } 516 517 switch (offset) { 518 case REG_DATA: 519 reg = fifo_getchar(&sc->rxfifo); 520 break; 521 case REG_IER: 522 reg = sc->ier; 523 break; 524 case REG_IIR: 525 iir = (sc->fcr & FCR_ENABLE) ? IIR_FIFO_MASK : 0; 526 527 intr_reason = pci_uart_intr_reason(sc); 528 529 /* 530 * Deal with side effects of reading the IIR register 531 */ 532 if (intr_reason == IIR_TXRDY) 533 sc->thre_int_pending = false; 534 535 iir |= intr_reason; 536 537 reg = iir; 538 break; 539 case REG_LCR: 540 reg = sc->lcr; 541 break; 542 case REG_MCR: 543 reg = sc->mcr; 544 break; 545 case REG_LSR: 546 /* Transmitter is always ready for more data */ 547 sc->lsr |= LSR_TEMT | LSR_THRE; 548 549 /* Check for new receive data */ 550 if (fifo_numchars(&sc->rxfifo) > 0) 551 sc->lsr |= LSR_RXRDY; 552 else 553 sc->lsr &= ~LSR_RXRDY; 554 555 reg = sc->lsr; 556 557 /* The LSR_OE bit is cleared on LSR read */ 558 sc->lsr &= ~LSR_OE; 559 break; 560 case REG_MSR: 561 /* 562 * MSR delta bits are cleared on read 563 */ 564 reg = sc->msr; 565 sc->msr &= ~MSR_DELTA_MASK; 566 break; 567 case REG_SCR: 568 reg = sc->scr; 569 break; 570 default: 571 reg = 0xFF; 572 break; 573 } 574 575 done: 576 pci_uart_toggle_intr(sc); 577 pthread_mutex_unlock(&sc->mtx); 578 579 return (reg); 580 } 581 582 static int 583 pci_uart_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) 584 { 585 struct pci_uart_softc *sc; 586 uint64_t bar; 587 int ivec; 588 589 sc = malloc(sizeof(struct pci_uart_softc)); 590 memset(sc, 0, sizeof(struct pci_uart_softc)); 591 592 pi->pi_arg = sc; 593 sc->pi = pi; 594 595 pthread_mutex_init(&sc->mtx, NULL); 596 597 /* initialize config space */ 598 pci_set_cfgdata16(pi, PCIR_DEVICE, COM_DEV); 599 pci_set_cfgdata16(pi, PCIR_VENDOR, COM_VENDOR); 600 pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_SIMPLECOMM); 601 if (pci_is_legacy(pi)) { 602 pci_uart_legacy_res(&bar, &ivec); 603 pci_emul_alloc_pbar(pi, 0, bar, PCIBAR_IO, 8); 604 } else { 605 ivec = -1; 606 pci_emul_alloc_bar(pi, 0, PCIBAR_IO, 8); 607 } 608 pci_lintr_request(pi, ivec); 609 610 if (opts != NULL && !strcmp("stdio", opts) && !pci_uart_stdio) { 611 pci_uart_stdio = 1; 612 sc->stdio = 1; 613 } 614 615 pci_uart_reset(sc); 616 617 return (0); 618 } 619 620 struct pci_devemu pci_de_com = { 621 .pe_emu = "uart", 622 .pe_init = pci_uart_init, 623 .pe_barwrite = pci_uart_write, 624 .pe_barread = pci_uart_read 625 }; 626 PCI_EMUL_SET(pci_de_com); 627