1899fe063SPekka Enberg #include "kvm/8250-serial.h" 213a7760fSPekka Enberg 313a7760fSPekka Enberg #include "kvm/ioport.h" 446aa8d69SPekka Enberg #include "kvm/util.h" 5e557eef9SPekka Enberg #include "kvm/kvm.h" 613a7760fSPekka Enberg 74e49b05bSCyrill Gorcunov #include <linux/serial_reg.h> 84e49b05bSCyrill Gorcunov 946aa8d69SPekka Enberg #include <stdbool.h> 1076b4a122SPekka Enberg #include <poll.h> 1113a7760fSPekka Enberg 1246aa8d69SPekka Enberg struct serial8250_device { 1346aa8d69SPekka Enberg uint16_t iobase; 14e557eef9SPekka Enberg uint8_t irq; 1576b4a122SPekka Enberg 1676b4a122SPekka Enberg uint8_t thr; 1746aa8d69SPekka Enberg uint8_t dll; 1846aa8d69SPekka Enberg uint8_t dlm; 19e557eef9SPekka Enberg uint8_t iir; 2046aa8d69SPekka Enberg uint8_t ier; 2146aa8d69SPekka Enberg uint8_t fcr; 2246aa8d69SPekka Enberg uint8_t lcr; 2346aa8d69SPekka Enberg uint8_t mcr; 2476b4a122SPekka Enberg uint8_t lsr; 2546aa8d69SPekka Enberg uint8_t scr; 26*133bedc1SPekka Enberg 27*133bedc1SPekka Enberg uint8_t counter; 2846aa8d69SPekka Enberg }; 2946aa8d69SPekka Enberg 30e62c18deSPekka Enberg static struct serial8250_device devices[] = { 31c6a69c61SPekka Enberg /* ttyS0 */ 32c6a69c61SPekka Enberg [0] = { 33c6a69c61SPekka Enberg .iobase = 0x3f8, 34e557eef9SPekka Enberg .irq = 4, 35e557eef9SPekka Enberg 366d620acbSCyrill Gorcunov .lsr = UART_LSR_TEMT | UART_LSR_THRE, 37c6a69c61SPekka Enberg }, 38e62c18deSPekka Enberg /* ttyS1 */ 39e62c18deSPekka Enberg [1] = { 40e62c18deSPekka Enberg .iobase = 0x2f8, 41e62c18deSPekka Enberg .irq = 3, 42*133bedc1SPekka Enberg 43*133bedc1SPekka Enberg .iir = UART_IIR_NO_INT, 44e62c18deSPekka Enberg }, 45e62c18deSPekka Enberg /* ttyS2 */ 46e62c18deSPekka Enberg [2] = { 47e62c18deSPekka Enberg .iobase = 0x3e8, 48e62c18deSPekka Enberg .irq = 4, 49*133bedc1SPekka Enberg 50*133bedc1SPekka Enberg .iir = UART_IIR_NO_INT, 51e62c18deSPekka Enberg }, 5246aa8d69SPekka Enberg }; 5346aa8d69SPekka Enberg 5476b4a122SPekka Enberg static int read_char(int fd) 5576b4a122SPekka Enberg { 5676b4a122SPekka Enberg int c; 5776b4a122SPekka Enberg 5876b4a122SPekka Enberg if (read(fd, &c, 1) < 0) 5976b4a122SPekka Enberg return -1; 6076b4a122SPekka Enberg 6176b4a122SPekka Enberg return c; 6276b4a122SPekka Enberg } 6376b4a122SPekka Enberg 6476b4a122SPekka Enberg static bool is_readable(int fd) 6576b4a122SPekka Enberg { 666d54df74SCyrill Gorcunov struct pollfd pollfd = (struct pollfd) { 6776b4a122SPekka Enberg .fd = fd, 6876b4a122SPekka Enberg .events = POLLIN, 6976b4a122SPekka Enberg }; 7076b4a122SPekka Enberg 716d54df74SCyrill Gorcunov return poll(&pollfd, 1, 0) > 0; 7276b4a122SPekka Enberg } 7376b4a122SPekka Enberg 74c6a69c61SPekka Enberg /* 75c6a69c61SPekka Enberg * Interrupts are injected for ttyS0 only. 76c6a69c61SPekka Enberg */ 778bb34e0dSPekka Enberg void serial8250__interrupt(struct kvm *self) 788bb34e0dSPekka Enberg { 79c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[0]; 80934c193bSPekka Enberg uint8_t new_iir; 81934c193bSPekka Enberg 82c6a69c61SPekka Enberg dev->iir = UART_IIR_NO_INT; 83934c193bSPekka Enberg 84934c193bSPekka Enberg /* No interrupts enabled. Exit... */ 85c6a69c61SPekka Enberg if (!(dev->ier & (UART_IER_THRI|UART_IER_RDI))) 86934c193bSPekka Enberg return; 87934c193bSPekka Enberg 88934c193bSPekka Enberg new_iir = 0; 89934c193bSPekka Enberg 90934c193bSPekka Enberg /* We're always good for guest sending data. */ 91c6a69c61SPekka Enberg if (dev->ier & UART_IER_THRI) 92934c193bSPekka Enberg new_iir |= UART_IIR_THRI; 93934c193bSPekka Enberg 94934c193bSPekka Enberg /* Is there input in stdin to send to the guest? */ 95c6a69c61SPekka Enberg if (!(dev->lsr & UART_LSR_DR) && is_readable(fileno(stdin))) { 9676b4a122SPekka Enberg int c; 9776b4a122SPekka Enberg 9876b4a122SPekka Enberg c = read_char(fileno(stdin)); 9976b4a122SPekka Enberg if (c >= 0) { 100c6a69c61SPekka Enberg dev->thr = c; 101c6a69c61SPekka Enberg dev->lsr |= UART_LSR_DR; 102934c193bSPekka Enberg new_iir |= UART_IIR_RDI; 10376b4a122SPekka Enberg } 10476b4a122SPekka Enberg } 10576b4a122SPekka Enberg 106934c193bSPekka Enberg /* Only send an IRQ if there's work to do. */ 107934c193bSPekka Enberg if (new_iir) { 108c6a69c61SPekka Enberg dev->iir = new_iir; 109c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 0); 110c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 1); 111e557eef9SPekka Enberg } 1128bb34e0dSPekka Enberg } 1138bb34e0dSPekka Enberg 114c6a69c61SPekka Enberg static struct serial8250_device *find_device(uint16_t port) 115c6a69c61SPekka Enberg { 116c6a69c61SPekka Enberg unsigned int i; 117c6a69c61SPekka Enberg 118c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 119c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 120c6a69c61SPekka Enberg 121c6a69c61SPekka Enberg if (dev->iobase == (port & ~0x7)) 122c6a69c61SPekka Enberg return dev; 123c6a69c61SPekka Enberg } 124c6a69c61SPekka Enberg return NULL; 125c6a69c61SPekka Enberg } 126c6a69c61SPekka Enberg 12746aa8d69SPekka Enberg static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 12813a7760fSPekka Enberg { 129c6a69c61SPekka Enberg struct serial8250_device *dev; 130c6a69c61SPekka Enberg uint16_t offset; 13146aa8d69SPekka Enberg 132c6a69c61SPekka Enberg dev = find_device(port); 133c6a69c61SPekka Enberg if (!dev) 134c6a69c61SPekka Enberg return false; 135c6a69c61SPekka Enberg 136c6a69c61SPekka Enberg offset = port - dev->iobase; 137c6a69c61SPekka Enberg 138c6a69c61SPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 13946aa8d69SPekka Enberg switch (offset) { 1404e49b05bSCyrill Gorcunov case UART_DLL: 141c6a69c61SPekka Enberg dev->dll = ioport__read8(data); 14246aa8d69SPekka Enberg break; 1434e49b05bSCyrill Gorcunov case UART_DLM: 144c6a69c61SPekka Enberg dev->dlm = ioport__read8(data); 14546aa8d69SPekka Enberg break; 1464e49b05bSCyrill Gorcunov case UART_FCR: 147c6a69c61SPekka Enberg dev->fcr = ioport__read8(data); 14846aa8d69SPekka Enberg break; 1494e49b05bSCyrill Gorcunov case UART_LCR: 150c6a69c61SPekka Enberg dev->lcr = ioport__read8(data); 15146aa8d69SPekka Enberg break; 15246aa8d69SPekka Enberg default: 15346aa8d69SPekka Enberg return false; 15446aa8d69SPekka Enberg } 15546aa8d69SPekka Enberg } else { 15646aa8d69SPekka Enberg switch (offset) { 1574e49b05bSCyrill Gorcunov case UART_TX: { 15813a7760fSPekka Enberg char *p = data; 159f2d8dc88SCyrill Gorcunov int i; 16013a7760fSPekka Enberg 161f2d8dc88SCyrill Gorcunov while (count--) { 162f2d8dc88SCyrill Gorcunov for (i = 0; i < size; i++) 163b7475544SPekka Enberg fprintf(stdout, "%c", *p++); 1645b9d0b58SAsias He } 165b7475544SPekka Enberg fflush(stdout); 166e557eef9SPekka Enberg 167*133bedc1SPekka Enberg if (dev->counter++ > 10) { 168*133bedc1SPekka Enberg dev->iir = UART_IIR_NO_INT; 169*133bedc1SPekka Enberg dev->counter = 0; 170*133bedc1SPekka Enberg } 171*133bedc1SPekka Enberg 17246aa8d69SPekka Enberg break; 17346aa8d69SPekka Enberg } 1744e49b05bSCyrill Gorcunov case UART_IER: 175c6a69c61SPekka Enberg dev->ier = ioport__read8(data); 17646aa8d69SPekka Enberg break; 1774e49b05bSCyrill Gorcunov case UART_FCR: 178c6a69c61SPekka Enberg dev->fcr = ioport__read8(data); 17946aa8d69SPekka Enberg break; 1804e49b05bSCyrill Gorcunov case UART_LCR: 181c6a69c61SPekka Enberg dev->lcr = ioport__read8(data); 18246aa8d69SPekka Enberg break; 1834e49b05bSCyrill Gorcunov case UART_MCR: 184c6a69c61SPekka Enberg dev->mcr = ioport__read8(data); 18546aa8d69SPekka Enberg break; 1864e49b05bSCyrill Gorcunov case UART_SCR: 187c6a69c61SPekka Enberg dev->scr = ioport__read8(data); 18846aa8d69SPekka Enberg break; 18946aa8d69SPekka Enberg default: 19046aa8d69SPekka Enberg return false; 19146aa8d69SPekka Enberg } 19246aa8d69SPekka Enberg } 19313a7760fSPekka Enberg 19413a7760fSPekka Enberg return true; 19513a7760fSPekka Enberg } 19613a7760fSPekka Enberg 19746aa8d69SPekka Enberg static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 19825af6674SPekka Enberg { 199c6a69c61SPekka Enberg struct serial8250_device *dev; 200c6a69c61SPekka Enberg uint16_t offset; 20146aa8d69SPekka Enberg 202c6a69c61SPekka Enberg dev = find_device(port); 203c6a69c61SPekka Enberg if (!dev) 204c6a69c61SPekka Enberg return false; 205c6a69c61SPekka Enberg 206c6a69c61SPekka Enberg offset = port - dev->iobase; 207c6a69c61SPekka Enberg 208c6a69c61SPekka Enberg if (dev->lcr & UART_LCR_DLAB) 20946aa8d69SPekka Enberg return false; 21046aa8d69SPekka Enberg 21146aa8d69SPekka Enberg switch (offset) { 2124e49b05bSCyrill Gorcunov case UART_TX: 213c6a69c61SPekka Enberg if (dev->lsr & UART_LSR_DR) { 214*133bedc1SPekka Enberg dev->iir = UART_IIR_NO_INT; 215*133bedc1SPekka Enberg 216c6a69c61SPekka Enberg dev->lsr &= ~UART_LSR_DR; 217c6a69c61SPekka Enberg ioport__write8(data, dev->thr); 21876b4a122SPekka Enberg } 21946aa8d69SPekka Enberg break; 2204e49b05bSCyrill Gorcunov case UART_IER: 221c6a69c61SPekka Enberg ioport__write8(data, dev->ier); 22246aa8d69SPekka Enberg break; 2234e49b05bSCyrill Gorcunov case UART_IIR: 224c6a69c61SPekka Enberg ioport__write8(data, dev->iir); 22546aa8d69SPekka Enberg break; 2264e49b05bSCyrill Gorcunov case UART_LCR: 227c6a69c61SPekka Enberg ioport__write8(data, dev->lcr); 22846aa8d69SPekka Enberg break; 2294e49b05bSCyrill Gorcunov case UART_MCR: 230c6a69c61SPekka Enberg ioport__write8(data, dev->mcr); 23146aa8d69SPekka Enberg break; 2324e49b05bSCyrill Gorcunov case UART_LSR: 233c6a69c61SPekka Enberg ioport__write8(data, dev->lsr); 23446aa8d69SPekka Enberg break; 2354e49b05bSCyrill Gorcunov case UART_MSR: 2369a7428ddSPekka Enberg ioport__write8(data, UART_MSR_CTS); 23746aa8d69SPekka Enberg break; 2384e49b05bSCyrill Gorcunov case UART_SCR: 239c6a69c61SPekka Enberg ioport__write8(data, dev->scr); 24046aa8d69SPekka Enberg break; 24146aa8d69SPekka Enberg default: 24246aa8d69SPekka Enberg return false; 24325af6674SPekka Enberg } 24425af6674SPekka Enberg 24513a7760fSPekka Enberg return true; 24613a7760fSPekka Enberg } 24713a7760fSPekka Enberg 24846aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = { 24946aa8d69SPekka Enberg .io_in = serial8250_in, 25046aa8d69SPekka Enberg .io_out = serial8250_out, 251a93ec68bSPekka Enberg }; 252a93ec68bSPekka Enberg 253899fe063SPekka Enberg void serial8250__init(void) 25413a7760fSPekka Enberg { 255c6a69c61SPekka Enberg unsigned int i; 256c6a69c61SPekka Enberg 257c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 258c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 259c6a69c61SPekka Enberg 260c6a69c61SPekka Enberg ioport__register(dev->iobase, &serial8250_ops, 8); 261c6a69c61SPekka Enberg } 26213a7760fSPekka Enberg } 263