1899fe063SPekka Enberg #include "kvm/8250-serial.h" 213a7760fSPekka Enberg 3*8eb47d29SSasha Levin #include "kvm/read-write.h" 413a7760fSPekka Enberg #include "kvm/ioport.h" 546aa8d69SPekka Enberg #include "kvm/util.h" 6e557eef9SPekka Enberg #include "kvm/kvm.h" 713a7760fSPekka Enberg 84e49b05bSCyrill Gorcunov #include <linux/serial_reg.h> 94e49b05bSCyrill Gorcunov 1046aa8d69SPekka Enberg #include <stdbool.h> 1176b4a122SPekka Enberg #include <poll.h> 1213a7760fSPekka Enberg 1346aa8d69SPekka Enberg struct serial8250_device { 1446aa8d69SPekka Enberg uint16_t iobase; 15e557eef9SPekka Enberg uint8_t irq; 1676b4a122SPekka Enberg 17251cf9a6SPekka Enberg uint8_t rbr; /* receive buffer */ 1846aa8d69SPekka Enberg uint8_t dll; 1946aa8d69SPekka Enberg uint8_t dlm; 20e557eef9SPekka Enberg uint8_t iir; 2146aa8d69SPekka Enberg uint8_t ier; 2246aa8d69SPekka Enberg uint8_t fcr; 2346aa8d69SPekka Enberg uint8_t lcr; 2446aa8d69SPekka Enberg uint8_t mcr; 2576b4a122SPekka Enberg uint8_t lsr; 26369c01c0SPekka Enberg uint8_t msr; 2746aa8d69SPekka Enberg uint8_t scr; 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 36369c01c0SPekka Enberg .iir = UART_IIR_NO_INT, 37bc4b0ffeSPekka Enberg .lsr = UART_LSR_TEMT | UART_LSR_THRE, 38bc4b0ffeSPekka Enberg .msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, 39bc4b0ffeSPekka Enberg .mcr = UART_MCR_OUT2, 40c6a69c61SPekka Enberg }, 41e62c18deSPekka Enberg /* ttyS1 */ 42e62c18deSPekka Enberg [1] = { 43e62c18deSPekka Enberg .iobase = 0x2f8, 44e62c18deSPekka Enberg .irq = 3, 45133bedc1SPekka Enberg 46133bedc1SPekka Enberg .iir = UART_IIR_NO_INT, 47e62c18deSPekka Enberg }, 48e62c18deSPekka Enberg /* ttyS2 */ 49e62c18deSPekka Enberg [2] = { 50e62c18deSPekka Enberg .iobase = 0x3e8, 51e62c18deSPekka Enberg .irq = 4, 52133bedc1SPekka Enberg 53133bedc1SPekka Enberg .iir = UART_IIR_NO_INT, 54e62c18deSPekka Enberg }, 5546aa8d69SPekka Enberg }; 5646aa8d69SPekka Enberg 5776b4a122SPekka Enberg static int read_char(int fd) 5876b4a122SPekka Enberg { 59*8eb47d29SSasha Levin char c; 6076b4a122SPekka Enberg 61*8eb47d29SSasha Levin if (read_in_full(fd, &c, 1) == 0) 6276b4a122SPekka Enberg return -1; 6376b4a122SPekka Enberg 6476b4a122SPekka Enberg return c; 6576b4a122SPekka Enberg } 6676b4a122SPekka Enberg 6776b4a122SPekka Enberg static bool is_readable(int fd) 6876b4a122SPekka Enberg { 696d54df74SCyrill Gorcunov struct pollfd pollfd = (struct pollfd) { 7076b4a122SPekka Enberg .fd = fd, 7176b4a122SPekka Enberg .events = POLLIN, 7276b4a122SPekka Enberg }; 7376b4a122SPekka Enberg 746d54df74SCyrill Gorcunov return poll(&pollfd, 1, 0) > 0; 7576b4a122SPekka Enberg } 7676b4a122SPekka Enberg 77251cf9a6SPekka Enberg static void serial8250__receive(struct kvm *self, struct serial8250_device *dev) 78251cf9a6SPekka Enberg { 79251cf9a6SPekka Enberg int c; 80251cf9a6SPekka Enberg 81db34045cSPekka Enberg if (dev->lsr & UART_LSR_DR) 82db34045cSPekka Enberg return; 83db34045cSPekka Enberg 84b4068fdfSPekka Enberg if (!is_readable(STDIN_FILENO)) 85251cf9a6SPekka Enberg return; 86251cf9a6SPekka Enberg 87b4068fdfSPekka Enberg c = read_char(STDIN_FILENO); 88251cf9a6SPekka Enberg if (c < 0) 89251cf9a6SPekka Enberg return; 90251cf9a6SPekka Enberg 91251cf9a6SPekka Enberg dev->rbr = c; 92251cf9a6SPekka Enberg dev->lsr |= UART_LSR_DR; 93251cf9a6SPekka Enberg } 94251cf9a6SPekka Enberg 95c6a69c61SPekka Enberg /* 96c6a69c61SPekka Enberg * Interrupts are injected for ttyS0 only. 97c6a69c61SPekka Enberg */ 988bb34e0dSPekka Enberg void serial8250__interrupt(struct kvm *self) 998bb34e0dSPekka Enberg { 100c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[0]; 101934c193bSPekka Enberg 102251cf9a6SPekka Enberg serial8250__receive(self, dev); 103251cf9a6SPekka Enberg 104369c01c0SPekka Enberg if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR) 105369c01c0SPekka Enberg dev->iir = UART_IIR_RDI; 106251cf9a6SPekka Enberg else if (dev->ier & UART_IER_THRI) 107369c01c0SPekka Enberg dev->iir = UART_IIR_THRI; 108369c01c0SPekka Enberg else 109369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 11076b4a122SPekka Enberg 111369c01c0SPekka Enberg if (dev->iir != UART_IIR_NO_INT) { 112c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 0); 113c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 1); 114e557eef9SPekka Enberg } 1158bb34e0dSPekka Enberg } 1168bb34e0dSPekka Enberg 117c6a69c61SPekka Enberg static struct serial8250_device *find_device(uint16_t port) 118c6a69c61SPekka Enberg { 119c6a69c61SPekka Enberg unsigned int i; 120c6a69c61SPekka Enberg 121c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 122c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 123c6a69c61SPekka Enberg 124c6a69c61SPekka Enberg if (dev->iobase == (port & ~0x7)) 125c6a69c61SPekka Enberg return dev; 126c6a69c61SPekka Enberg } 127c6a69c61SPekka Enberg return NULL; 128c6a69c61SPekka Enberg } 129c6a69c61SPekka Enberg 13046aa8d69SPekka Enberg static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 13113a7760fSPekka Enberg { 132c6a69c61SPekka Enberg struct serial8250_device *dev; 133c6a69c61SPekka Enberg uint16_t offset; 13446aa8d69SPekka Enberg 135c6a69c61SPekka Enberg dev = find_device(port); 136c6a69c61SPekka Enberg if (!dev) 137c6a69c61SPekka Enberg return false; 138c6a69c61SPekka Enberg 139c6a69c61SPekka Enberg offset = port - dev->iobase; 140c6a69c61SPekka Enberg 141c6a69c61SPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 14246aa8d69SPekka Enberg switch (offset) { 1434e49b05bSCyrill Gorcunov case UART_DLL: 144c6a69c61SPekka Enberg dev->dll = ioport__read8(data); 14546aa8d69SPekka Enberg break; 1464e49b05bSCyrill Gorcunov case UART_DLM: 147c6a69c61SPekka Enberg dev->dlm = ioport__read8(data); 14846aa8d69SPekka Enberg break; 149369c01c0SPekka Enberg case UART_FCR: 150369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 151369c01c0SPekka Enberg break; 152369c01c0SPekka Enberg case UART_LCR: 153369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 154369c01c0SPekka Enberg break; 155369c01c0SPekka Enberg case UART_MCR: 156369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 157369c01c0SPekka Enberg break; 158369c01c0SPekka Enberg case UART_LSR: 159369c01c0SPekka Enberg /* Factory test */ 160369c01c0SPekka Enberg break; 161369c01c0SPekka Enberg case UART_MSR: 162369c01c0SPekka Enberg /* Not used */ 163369c01c0SPekka Enberg break; 164369c01c0SPekka Enberg case UART_SCR: 165369c01c0SPekka Enberg dev->scr = ioport__read8(data); 166369c01c0SPekka Enberg break; 167369c01c0SPekka Enberg default: 168369c01c0SPekka Enberg return false; 16946aa8d69SPekka Enberg } 17046aa8d69SPekka Enberg } else { 17146aa8d69SPekka Enberg switch (offset) { 1724e49b05bSCyrill Gorcunov case UART_TX: { 17313a7760fSPekka Enberg char *p = data; 174f2d8dc88SCyrill Gorcunov int i; 17513a7760fSPekka Enberg 176369c01c0SPekka Enberg if (!(dev->mcr & UART_MCR_LOOP)) { 177f2d8dc88SCyrill Gorcunov while (count--) { 178f2d8dc88SCyrill Gorcunov for (i = 0; i < size; i++) 179b7475544SPekka Enberg fprintf(stdout, "%c", *p++); 1805b9d0b58SAsias He } 181b7475544SPekka Enberg fflush(stdout); 182369c01c0SPekka Enberg } 183133bedc1SPekka Enberg dev->iir = UART_IIR_NO_INT; 18446aa8d69SPekka Enberg break; 18546aa8d69SPekka Enberg } 186369c01c0SPekka Enberg case UART_FCR: 187369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 188369c01c0SPekka Enberg break; 1894e49b05bSCyrill Gorcunov case UART_IER: 190369c01c0SPekka Enberg dev->ier = ioport__read8(data) & 0x3f; 19146aa8d69SPekka Enberg break; 192369c01c0SPekka Enberg case UART_LCR: 193369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 194369c01c0SPekka Enberg break; 195369c01c0SPekka Enberg case UART_MCR: 196369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 197369c01c0SPekka Enberg break; 198369c01c0SPekka Enberg case UART_LSR: 199369c01c0SPekka Enberg /* Factory test */ 200369c01c0SPekka Enberg break; 201369c01c0SPekka Enberg case UART_MSR: 202369c01c0SPekka Enberg /* Not used */ 203369c01c0SPekka Enberg break; 204369c01c0SPekka Enberg case UART_SCR: 205369c01c0SPekka Enberg dev->scr = ioport__read8(data); 206369c01c0SPekka Enberg break; 207369c01c0SPekka Enberg default: 208369c01c0SPekka Enberg return false; 20946aa8d69SPekka Enberg } 21046aa8d69SPekka Enberg } 21113a7760fSPekka Enberg return true; 21213a7760fSPekka Enberg } 21313a7760fSPekka Enberg 21446aa8d69SPekka Enberg static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 21525af6674SPekka Enberg { 216c6a69c61SPekka Enberg struct serial8250_device *dev; 217c6a69c61SPekka Enberg uint16_t offset; 21846aa8d69SPekka Enberg 219c6a69c61SPekka Enberg dev = find_device(port); 220c6a69c61SPekka Enberg if (!dev) 221c6a69c61SPekka Enberg return false; 222c6a69c61SPekka Enberg 223c6a69c61SPekka Enberg offset = port - dev->iobase; 224c6a69c61SPekka Enberg 22519a2bb7dSPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 22619a2bb7dSPekka Enberg switch (offset) { 22719a2bb7dSPekka Enberg case UART_DLL: 22819a2bb7dSPekka Enberg ioport__write8(data, dev->dll); 22919a2bb7dSPekka Enberg return true; 23019a2bb7dSPekka Enberg case UART_DLM: 23119a2bb7dSPekka Enberg ioport__write8(data, dev->dlm); 23219a2bb7dSPekka Enberg return true; 233369c01c0SPekka Enberg default: 234369c01c0SPekka Enberg break; 23519a2bb7dSPekka Enberg } 23619a2bb7dSPekka Enberg } else { 23746aa8d69SPekka Enberg switch (offset) { 238251cf9a6SPekka Enberg case UART_RX: 239251cf9a6SPekka Enberg ioport__write8(data, dev->rbr); 240369c01c0SPekka Enberg dev->lsr &= ~UART_LSR_DR; 241369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 24219a2bb7dSPekka Enberg return true; 2434e49b05bSCyrill Gorcunov case UART_IER: 244c6a69c61SPekka Enberg ioport__write8(data, dev->ier); 24519a2bb7dSPekka Enberg return true; 246369c01c0SPekka Enberg default: 247369c01c0SPekka Enberg break; 24819a2bb7dSPekka Enberg } 24919a2bb7dSPekka Enberg } 25019a2bb7dSPekka Enberg 25119a2bb7dSPekka Enberg switch (offset) { 252369c01c0SPekka Enberg case UART_IIR: { 253369c01c0SPekka Enberg uint8_t iir = dev->iir; 254369c01c0SPekka Enberg 255369c01c0SPekka Enberg if (dev->fcr & UART_FCR_ENABLE_FIFO) 256369c01c0SPekka Enberg iir |= 0xc0; 257369c01c0SPekka Enberg 258369c01c0SPekka Enberg ioport__write8(data, iir); 25946aa8d69SPekka Enberg break; 260369c01c0SPekka Enberg } 2614e49b05bSCyrill Gorcunov case UART_LCR: 262c6a69c61SPekka Enberg ioport__write8(data, dev->lcr); 26346aa8d69SPekka Enberg break; 2644e49b05bSCyrill Gorcunov case UART_MCR: 265c6a69c61SPekka Enberg ioport__write8(data, dev->mcr); 26646aa8d69SPekka Enberg break; 2674e49b05bSCyrill Gorcunov case UART_LSR: 268c6a69c61SPekka Enberg ioport__write8(data, dev->lsr); 269369c01c0SPekka Enberg dev->lsr &= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI); 27046aa8d69SPekka Enberg break; 2714e49b05bSCyrill Gorcunov case UART_MSR: 272369c01c0SPekka Enberg ioport__write8(data, dev->msr); 27346aa8d69SPekka Enberg break; 2744e49b05bSCyrill Gorcunov case UART_SCR: 275369c01c0SPekka Enberg ioport__write8(data, dev->scr); 27646aa8d69SPekka Enberg break; 277369c01c0SPekka Enberg default: 278369c01c0SPekka Enberg return false; 27925af6674SPekka Enberg } 28013a7760fSPekka Enberg return true; 28113a7760fSPekka Enberg } 28213a7760fSPekka Enberg 28346aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = { 28446aa8d69SPekka Enberg .io_in = serial8250_in, 28546aa8d69SPekka Enberg .io_out = serial8250_out, 286a93ec68bSPekka Enberg }; 287a93ec68bSPekka Enberg 288bc4b0ffeSPekka Enberg static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev) 289bc4b0ffeSPekka Enberg { 290bc4b0ffeSPekka Enberg ioport__register(dev->iobase, &serial8250_ops, 8); 291bc4b0ffeSPekka Enberg kvm__irq_line(kvm, dev->irq, 0); 292bc4b0ffeSPekka Enberg } 293bc4b0ffeSPekka Enberg 294bc4b0ffeSPekka Enberg void serial8250__init(struct kvm *kvm) 29513a7760fSPekka Enberg { 296c6a69c61SPekka Enberg unsigned int i; 297c6a69c61SPekka Enberg 298c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 299c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 300c6a69c61SPekka Enberg 301bc4b0ffeSPekka Enberg serial8250__device_init(kvm, dev); 302c6a69c61SPekka Enberg } 30313a7760fSPekka Enberg } 304