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; 2646aa8d69SPekka Enberg }; 2746aa8d69SPekka Enberg 28*e62c18deSPekka Enberg static struct serial8250_device devices[] = { 29c6a69c61SPekka Enberg /* ttyS0 */ 30c6a69c61SPekka Enberg [0] = { 31c6a69c61SPekka Enberg .iobase = 0x3f8, 32e557eef9SPekka Enberg .irq = 4, 33e557eef9SPekka Enberg 346d620acbSCyrill Gorcunov .lsr = UART_LSR_TEMT | UART_LSR_THRE, 35c6a69c61SPekka Enberg }, 36*e62c18deSPekka Enberg /* ttyS1 */ 37*e62c18deSPekka Enberg [1] = { 38*e62c18deSPekka Enberg .iobase = 0x2f8, 39*e62c18deSPekka Enberg .irq = 3, 40*e62c18deSPekka Enberg }, 41*e62c18deSPekka Enberg /* ttyS2 */ 42*e62c18deSPekka Enberg [2] = { 43*e62c18deSPekka Enberg .iobase = 0x3e8, 44*e62c18deSPekka Enberg .irq = 4, 45*e62c18deSPekka Enberg }, 4646aa8d69SPekka Enberg }; 4746aa8d69SPekka Enberg 4876b4a122SPekka Enberg static int read_char(int fd) 4976b4a122SPekka Enberg { 5076b4a122SPekka Enberg int c; 5176b4a122SPekka Enberg 5276b4a122SPekka Enberg if (read(fd, &c, 1) < 0) 5376b4a122SPekka Enberg return -1; 5476b4a122SPekka Enberg 5576b4a122SPekka Enberg return c; 5676b4a122SPekka Enberg } 5776b4a122SPekka Enberg 5876b4a122SPekka Enberg static bool is_readable(int fd) 5976b4a122SPekka Enberg { 606d54df74SCyrill Gorcunov struct pollfd pollfd = (struct pollfd) { 6176b4a122SPekka Enberg .fd = fd, 6276b4a122SPekka Enberg .events = POLLIN, 6376b4a122SPekka Enberg }; 6476b4a122SPekka Enberg 656d54df74SCyrill Gorcunov return poll(&pollfd, 1, 0) > 0; 6676b4a122SPekka Enberg } 6776b4a122SPekka Enberg 68c6a69c61SPekka Enberg /* 69c6a69c61SPekka Enberg * Interrupts are injected for ttyS0 only. 70c6a69c61SPekka Enberg */ 718bb34e0dSPekka Enberg void serial8250__interrupt(struct kvm *self) 728bb34e0dSPekka Enberg { 73c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[0]; 74934c193bSPekka Enberg uint8_t new_iir; 75934c193bSPekka Enberg 76c6a69c61SPekka Enberg dev->iir = UART_IIR_NO_INT; 77934c193bSPekka Enberg 78934c193bSPekka Enberg /* No interrupts enabled. Exit... */ 79c6a69c61SPekka Enberg if (!(dev->ier & (UART_IER_THRI|UART_IER_RDI))) 80934c193bSPekka Enberg return; 81934c193bSPekka Enberg 82934c193bSPekka Enberg new_iir = 0; 83934c193bSPekka Enberg 84934c193bSPekka Enberg /* We're always good for guest sending data. */ 85c6a69c61SPekka Enberg if (dev->ier & UART_IER_THRI) 86934c193bSPekka Enberg new_iir |= UART_IIR_THRI; 87934c193bSPekka Enberg 88934c193bSPekka Enberg /* Is there input in stdin to send to the guest? */ 89c6a69c61SPekka Enberg if (!(dev->lsr & UART_LSR_DR) && is_readable(fileno(stdin))) { 9076b4a122SPekka Enberg int c; 9176b4a122SPekka Enberg 9276b4a122SPekka Enberg c = read_char(fileno(stdin)); 9376b4a122SPekka Enberg if (c >= 0) { 94c6a69c61SPekka Enberg dev->thr = c; 95c6a69c61SPekka Enberg dev->lsr |= UART_LSR_DR; 96934c193bSPekka Enberg new_iir |= UART_IIR_RDI; 9776b4a122SPekka Enberg } 9876b4a122SPekka Enberg } 9976b4a122SPekka Enberg 100934c193bSPekka Enberg /* Only send an IRQ if there's work to do. */ 101934c193bSPekka Enberg if (new_iir) { 102c6a69c61SPekka Enberg dev->iir = new_iir; 103c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 0); 104c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 1); 105e557eef9SPekka Enberg } 1068bb34e0dSPekka Enberg } 1078bb34e0dSPekka Enberg 108c6a69c61SPekka Enberg static struct serial8250_device *find_device(uint16_t port) 109c6a69c61SPekka Enberg { 110c6a69c61SPekka Enberg unsigned int i; 111c6a69c61SPekka Enberg 112c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 113c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 114c6a69c61SPekka Enberg 115c6a69c61SPekka Enberg if (dev->iobase == (port & ~0x7)) 116c6a69c61SPekka Enberg return dev; 117c6a69c61SPekka Enberg } 118c6a69c61SPekka Enberg return NULL; 119c6a69c61SPekka Enberg } 120c6a69c61SPekka Enberg 12146aa8d69SPekka Enberg static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 12213a7760fSPekka Enberg { 123c6a69c61SPekka Enberg struct serial8250_device *dev; 124c6a69c61SPekka Enberg uint16_t offset; 12546aa8d69SPekka Enberg 126c6a69c61SPekka Enberg dev = find_device(port); 127c6a69c61SPekka Enberg if (!dev) 128c6a69c61SPekka Enberg return false; 129c6a69c61SPekka Enberg 130c6a69c61SPekka Enberg offset = port - dev->iobase; 131c6a69c61SPekka Enberg 132c6a69c61SPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 13346aa8d69SPekka Enberg switch (offset) { 1344e49b05bSCyrill Gorcunov case UART_DLL: 135c6a69c61SPekka Enberg dev->dll = ioport__read8(data); 13646aa8d69SPekka Enberg break; 1374e49b05bSCyrill Gorcunov case UART_DLM: 138c6a69c61SPekka Enberg dev->dlm = ioport__read8(data); 13946aa8d69SPekka Enberg break; 1404e49b05bSCyrill Gorcunov case UART_FCR: 141c6a69c61SPekka Enberg dev->fcr = ioport__read8(data); 14246aa8d69SPekka Enberg break; 1434e49b05bSCyrill Gorcunov case UART_LCR: 144c6a69c61SPekka Enberg dev->lcr = ioport__read8(data); 14546aa8d69SPekka Enberg break; 14646aa8d69SPekka Enberg default: 14746aa8d69SPekka Enberg return false; 14846aa8d69SPekka Enberg } 14946aa8d69SPekka Enberg } else { 15046aa8d69SPekka Enberg switch (offset) { 1514e49b05bSCyrill Gorcunov case UART_TX: { 15213a7760fSPekka Enberg char *p = data; 153f2d8dc88SCyrill Gorcunov int i; 15413a7760fSPekka Enberg 155f2d8dc88SCyrill Gorcunov while (count--) { 156f2d8dc88SCyrill Gorcunov for (i = 0; i < size; i++) 157b7475544SPekka Enberg fprintf(stdout, "%c", *p++); 1585b9d0b58SAsias He } 159b7475544SPekka Enberg fflush(stdout); 160e557eef9SPekka Enberg 16146aa8d69SPekka Enberg break; 16246aa8d69SPekka Enberg } 1634e49b05bSCyrill Gorcunov case UART_IER: 164c6a69c61SPekka Enberg dev->ier = ioport__read8(data); 16546aa8d69SPekka Enberg break; 1664e49b05bSCyrill Gorcunov case UART_FCR: 167c6a69c61SPekka Enberg dev->fcr = ioport__read8(data); 16846aa8d69SPekka Enberg break; 1694e49b05bSCyrill Gorcunov case UART_LCR: 170c6a69c61SPekka Enberg dev->lcr = ioport__read8(data); 17146aa8d69SPekka Enberg break; 1724e49b05bSCyrill Gorcunov case UART_MCR: 173c6a69c61SPekka Enberg dev->mcr = ioport__read8(data); 17446aa8d69SPekka Enberg break; 1754e49b05bSCyrill Gorcunov case UART_SCR: 176c6a69c61SPekka Enberg dev->scr = ioport__read8(data); 17746aa8d69SPekka Enberg break; 17846aa8d69SPekka Enberg default: 17946aa8d69SPekka Enberg return false; 18046aa8d69SPekka Enberg } 18146aa8d69SPekka Enberg } 18213a7760fSPekka Enberg 18313a7760fSPekka Enberg return true; 18413a7760fSPekka Enberg } 18513a7760fSPekka Enberg 18646aa8d69SPekka Enberg static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 18725af6674SPekka Enberg { 188c6a69c61SPekka Enberg struct serial8250_device *dev; 189c6a69c61SPekka Enberg uint16_t offset; 19046aa8d69SPekka Enberg 191c6a69c61SPekka Enberg dev = find_device(port); 192c6a69c61SPekka Enberg if (!dev) 193c6a69c61SPekka Enberg return false; 194c6a69c61SPekka Enberg 195c6a69c61SPekka Enberg offset = port - dev->iobase; 196c6a69c61SPekka Enberg 197c6a69c61SPekka Enberg if (dev->lcr & UART_LCR_DLAB) 19846aa8d69SPekka Enberg return false; 19946aa8d69SPekka Enberg 20046aa8d69SPekka Enberg switch (offset) { 2014e49b05bSCyrill Gorcunov case UART_TX: 202c6a69c61SPekka Enberg if (dev->lsr & UART_LSR_DR) { 203c6a69c61SPekka Enberg dev->lsr &= ~UART_LSR_DR; 204c6a69c61SPekka Enberg ioport__write8(data, dev->thr); 20576b4a122SPekka Enberg } 20646aa8d69SPekka Enberg break; 2074e49b05bSCyrill Gorcunov case UART_IER: 208c6a69c61SPekka Enberg ioport__write8(data, dev->ier); 20946aa8d69SPekka Enberg break; 2104e49b05bSCyrill Gorcunov case UART_IIR: 211c6a69c61SPekka Enberg ioport__write8(data, dev->iir); 21246aa8d69SPekka Enberg break; 2134e49b05bSCyrill Gorcunov case UART_LCR: 214c6a69c61SPekka Enberg ioport__write8(data, dev->lcr); 21546aa8d69SPekka Enberg break; 2164e49b05bSCyrill Gorcunov case UART_MCR: 217c6a69c61SPekka Enberg ioport__write8(data, dev->mcr); 21846aa8d69SPekka Enberg break; 2194e49b05bSCyrill Gorcunov case UART_LSR: 220c6a69c61SPekka Enberg ioport__write8(data, dev->lsr); 22146aa8d69SPekka Enberg break; 2224e49b05bSCyrill Gorcunov case UART_MSR: 2239a7428ddSPekka Enberg ioport__write8(data, UART_MSR_CTS); 22446aa8d69SPekka Enberg break; 2254e49b05bSCyrill Gorcunov case UART_SCR: 226c6a69c61SPekka Enberg ioport__write8(data, dev->scr); 22746aa8d69SPekka Enberg break; 22846aa8d69SPekka Enberg default: 22946aa8d69SPekka Enberg return false; 23025af6674SPekka Enberg } 23125af6674SPekka Enberg 23213a7760fSPekka Enberg return true; 23313a7760fSPekka Enberg } 23413a7760fSPekka Enberg 23546aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = { 23646aa8d69SPekka Enberg .io_in = serial8250_in, 23746aa8d69SPekka Enberg .io_out = serial8250_out, 238a93ec68bSPekka Enberg }; 239a93ec68bSPekka Enberg 240899fe063SPekka Enberg void serial8250__init(void) 24113a7760fSPekka Enberg { 242c6a69c61SPekka Enberg unsigned int i; 243c6a69c61SPekka Enberg 244c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 245c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 246c6a69c61SPekka Enberg 247c6a69c61SPekka Enberg ioport__register(dev->iobase, &serial8250_ops, 8); 248c6a69c61SPekka Enberg } 24913a7760fSPekka Enberg } 250