1899fe063SPekka Enberg #include "kvm/8250-serial.h" 213a7760fSPekka Enberg 38eb47d29SSasha Levin #include "kvm/read-write.h" 413a7760fSPekka Enberg #include "kvm/ioport.h" 54ef0f4d6SPekka Enberg #include "kvm/mutex.h" 646aa8d69SPekka Enberg #include "kvm/util.h" 705d1a2a6SAsias He #include "kvm/term.h" 8e557eef9SPekka Enberg #include "kvm/kvm.h" 913a7760fSPekka Enberg 10*3fdf659dSSasha Levin #include <linux/types.h> 114e49b05bSCyrill Gorcunov #include <linux/serial_reg.h> 124e49b05bSCyrill Gorcunov 132932c9ebSPekka Enberg #include <pthread.h> 1413a7760fSPekka Enberg 1546aa8d69SPekka Enberg struct serial8250_device { 162932c9ebSPekka Enberg pthread_mutex_t mutex; 172932c9ebSPekka Enberg 18*3fdf659dSSasha Levin u16 iobase; 19*3fdf659dSSasha Levin u8 irq; 2076b4a122SPekka Enberg 21*3fdf659dSSasha Levin u8 rbr; /* receive buffer */ 22*3fdf659dSSasha Levin u8 dll; 23*3fdf659dSSasha Levin u8 dlm; 24*3fdf659dSSasha Levin u8 iir; 25*3fdf659dSSasha Levin u8 ier; 26*3fdf659dSSasha Levin u8 fcr; 27*3fdf659dSSasha Levin u8 lcr; 28*3fdf659dSSasha Levin u8 mcr; 29*3fdf659dSSasha Levin u8 lsr; 30*3fdf659dSSasha Levin u8 msr; 31*3fdf659dSSasha Levin u8 scr; 3246aa8d69SPekka Enberg }; 3346aa8d69SPekka Enberg 34e62c18deSPekka Enberg static struct serial8250_device devices[] = { 35c6a69c61SPekka Enberg /* ttyS0 */ 36c6a69c61SPekka Enberg [0] = { 372932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 382932c9ebSPekka Enberg 39c6a69c61SPekka Enberg .iobase = 0x3f8, 40e557eef9SPekka Enberg .irq = 4, 41e557eef9SPekka Enberg 42369c01c0SPekka Enberg .iir = UART_IIR_NO_INT, 43bc4b0ffeSPekka Enberg .lsr = UART_LSR_TEMT | UART_LSR_THRE, 44bc4b0ffeSPekka Enberg .msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, 45bc4b0ffeSPekka Enberg .mcr = UART_MCR_OUT2, 46c6a69c61SPekka Enberg }, 47e62c18deSPekka Enberg /* ttyS1 */ 48e62c18deSPekka Enberg [1] = { 492932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 502932c9ebSPekka Enberg 51e62c18deSPekka Enberg .iobase = 0x2f8, 52e62c18deSPekka Enberg .irq = 3, 53133bedc1SPekka Enberg 54133bedc1SPekka Enberg .iir = UART_IIR_NO_INT, 55e62c18deSPekka Enberg }, 56e62c18deSPekka Enberg /* ttyS2 */ 57e62c18deSPekka Enberg [2] = { 582932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 592932c9ebSPekka Enberg 60e62c18deSPekka Enberg .iobase = 0x3e8, 61e62c18deSPekka Enberg .irq = 4, 62133bedc1SPekka Enberg 63133bedc1SPekka Enberg .iir = UART_IIR_NO_INT, 64e62c18deSPekka Enberg }, 6546aa8d69SPekka Enberg }; 6646aa8d69SPekka Enberg 67a428f72eSPekka Enberg #define SYSRQ_PENDING_NONE 0 68a428f72eSPekka Enberg #define SYSRQ_PENDING_BREAK 1 69a428f72eSPekka Enberg #define SYSRQ_PENDING_CMD 2 70a428f72eSPekka Enberg 71a428f72eSPekka Enberg static int sysrq_pending; 72a428f72eSPekka Enberg 73a428f72eSPekka Enberg static void serial8250__sysrq(struct kvm *self, struct serial8250_device *dev) 74a428f72eSPekka Enberg { 75a428f72eSPekka Enberg switch (sysrq_pending) { 76a428f72eSPekka Enberg case SYSRQ_PENDING_BREAK: 77a428f72eSPekka Enberg dev->lsr |= UART_LSR_DR | UART_LSR_BI; 78a428f72eSPekka Enberg 79a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_CMD; 80a428f72eSPekka Enberg break; 81a428f72eSPekka Enberg case SYSRQ_PENDING_CMD: 82a428f72eSPekka Enberg dev->rbr = 'p'; 83a428f72eSPekka Enberg dev->lsr |= UART_LSR_DR; 84a428f72eSPekka Enberg 85a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_NONE; 86a428f72eSPekka Enberg break; 87a428f72eSPekka Enberg } 88a428f72eSPekka Enberg } 89a428f72eSPekka Enberg 90251cf9a6SPekka Enberg static void serial8250__receive(struct kvm *self, struct serial8250_device *dev) 91251cf9a6SPekka Enberg { 92251cf9a6SPekka Enberg int c; 93251cf9a6SPekka Enberg 94db34045cSPekka Enberg if (dev->lsr & UART_LSR_DR) 95db34045cSPekka Enberg return; 96db34045cSPekka Enberg 97a428f72eSPekka Enberg if (sysrq_pending) { 98a428f72eSPekka Enberg serial8250__sysrq(self, dev); 99a428f72eSPekka Enberg return; 100a428f72eSPekka Enberg } 101a428f72eSPekka Enberg 10205d1a2a6SAsias He if (!term_readable(CONSOLE_8250)) 103251cf9a6SPekka Enberg return; 104251cf9a6SPekka Enberg 10505d1a2a6SAsias He c = term_getc(CONSOLE_8250); 10605d1a2a6SAsias He 107251cf9a6SPekka Enberg if (c < 0) 108251cf9a6SPekka Enberg return; 109251cf9a6SPekka Enberg 110251cf9a6SPekka Enberg dev->rbr = c; 111251cf9a6SPekka Enberg dev->lsr |= UART_LSR_DR; 112251cf9a6SPekka Enberg } 113251cf9a6SPekka Enberg 114c6a69c61SPekka Enberg /* 115c6a69c61SPekka Enberg * Interrupts are injected for ttyS0 only. 116c6a69c61SPekka Enberg */ 11705d1a2a6SAsias He void serial8250__inject_interrupt(struct kvm *self) 1188bb34e0dSPekka Enberg { 119c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[0]; 120934c193bSPekka Enberg 1214ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 1222932c9ebSPekka Enberg 123251cf9a6SPekka Enberg serial8250__receive(self, dev); 124251cf9a6SPekka Enberg 125369c01c0SPekka Enberg if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR) 126369c01c0SPekka Enberg dev->iir = UART_IIR_RDI; 127251cf9a6SPekka Enberg else if (dev->ier & UART_IER_THRI) 128369c01c0SPekka Enberg dev->iir = UART_IIR_THRI; 129369c01c0SPekka Enberg else 130369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 13176b4a122SPekka Enberg 132369c01c0SPekka Enberg if (dev->iir != UART_IIR_NO_INT) { 133c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 0); 134c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 1); 135e557eef9SPekka Enberg } 1362932c9ebSPekka Enberg 1374ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 1388bb34e0dSPekka Enberg } 1398bb34e0dSPekka Enberg 140a428f72eSPekka Enberg void serial8250__inject_sysrq(struct kvm *self) 141a428f72eSPekka Enberg { 142a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_BREAK; 143a428f72eSPekka Enberg } 144a428f72eSPekka Enberg 145*3fdf659dSSasha Levin static struct serial8250_device *find_device(u16 port) 146c6a69c61SPekka Enberg { 147c6a69c61SPekka Enberg unsigned int i; 148c6a69c61SPekka Enberg 149c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 150c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 151c6a69c61SPekka Enberg 152c6a69c61SPekka Enberg if (dev->iobase == (port & ~0x7)) 153c6a69c61SPekka Enberg return dev; 154c6a69c61SPekka Enberg } 155c6a69c61SPekka Enberg return NULL; 156c6a69c61SPekka Enberg } 157c6a69c61SPekka Enberg 158*3fdf659dSSasha Levin static bool serial8250_out(struct kvm *self, u16 port, void *data, int size, u32 count) 15913a7760fSPekka Enberg { 160c6a69c61SPekka Enberg struct serial8250_device *dev; 161*3fdf659dSSasha Levin u16 offset; 1622932c9ebSPekka Enberg bool ret = true; 16346aa8d69SPekka Enberg 164c6a69c61SPekka Enberg dev = find_device(port); 165c6a69c61SPekka Enberg if (!dev) 166c6a69c61SPekka Enberg return false; 167c6a69c61SPekka Enberg 1684ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 1692932c9ebSPekka Enberg 170c6a69c61SPekka Enberg offset = port - dev->iobase; 171c6a69c61SPekka Enberg 172c6a69c61SPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 17346aa8d69SPekka Enberg switch (offset) { 1744e49b05bSCyrill Gorcunov case UART_DLL: 175c6a69c61SPekka Enberg dev->dll = ioport__read8(data); 17646aa8d69SPekka Enberg break; 1774e49b05bSCyrill Gorcunov case UART_DLM: 178c6a69c61SPekka Enberg dev->dlm = ioport__read8(data); 17946aa8d69SPekka Enberg break; 180369c01c0SPekka Enberg case UART_FCR: 181369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 182369c01c0SPekka Enberg break; 183369c01c0SPekka Enberg case UART_LCR: 184369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 185369c01c0SPekka Enberg break; 186369c01c0SPekka Enberg case UART_MCR: 187369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 188369c01c0SPekka Enberg break; 189369c01c0SPekka Enberg case UART_LSR: 190369c01c0SPekka Enberg /* Factory test */ 191369c01c0SPekka Enberg break; 192369c01c0SPekka Enberg case UART_MSR: 193369c01c0SPekka Enberg /* Not used */ 194369c01c0SPekka Enberg break; 195369c01c0SPekka Enberg case UART_SCR: 196369c01c0SPekka Enberg dev->scr = ioport__read8(data); 197369c01c0SPekka Enberg break; 198369c01c0SPekka Enberg default: 1992932c9ebSPekka Enberg ret = false; 2002932c9ebSPekka Enberg goto out_unlock; 20146aa8d69SPekka Enberg } 20246aa8d69SPekka Enberg } else { 20346aa8d69SPekka Enberg switch (offset) { 2044e49b05bSCyrill Gorcunov case UART_TX: { 20505d1a2a6SAsias He char *addr = data; 2060ea58e5bSPekka Enberg 2070ea58e5bSPekka Enberg if (!(dev->mcr & UART_MCR_LOOP)) 20805d1a2a6SAsias He term_putc(CONSOLE_8250, addr, size * count); 2090ea58e5bSPekka Enberg 210133bedc1SPekka Enberg dev->iir = UART_IIR_NO_INT; 21146aa8d69SPekka Enberg break; 21246aa8d69SPekka Enberg } 213369c01c0SPekka Enberg case UART_FCR: 214369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 215369c01c0SPekka Enberg break; 2164e49b05bSCyrill Gorcunov case UART_IER: 217369c01c0SPekka Enberg dev->ier = ioport__read8(data) & 0x3f; 21846aa8d69SPekka Enberg break; 219369c01c0SPekka Enberg case UART_LCR: 220369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 221369c01c0SPekka Enberg break; 222369c01c0SPekka Enberg case UART_MCR: 223369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 224369c01c0SPekka Enberg break; 225369c01c0SPekka Enberg case UART_LSR: 226369c01c0SPekka Enberg /* Factory test */ 227369c01c0SPekka Enberg break; 228369c01c0SPekka Enberg case UART_MSR: 229369c01c0SPekka Enberg /* Not used */ 230369c01c0SPekka Enberg break; 231369c01c0SPekka Enberg case UART_SCR: 232369c01c0SPekka Enberg dev->scr = ioport__read8(data); 233369c01c0SPekka Enberg break; 234369c01c0SPekka Enberg default: 2352932c9ebSPekka Enberg ret = false; 2362932c9ebSPekka Enberg goto out_unlock; 23746aa8d69SPekka Enberg } 23846aa8d69SPekka Enberg } 2392932c9ebSPekka Enberg 2402932c9ebSPekka Enberg out_unlock: 2414ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 2422932c9ebSPekka Enberg 2432932c9ebSPekka Enberg return ret; 24413a7760fSPekka Enberg } 24513a7760fSPekka Enberg 246*3fdf659dSSasha Levin static bool serial8250_in(struct kvm *self, u16 port, void *data, int size, u32 count) 24725af6674SPekka Enberg { 248c6a69c61SPekka Enberg struct serial8250_device *dev; 249*3fdf659dSSasha Levin u16 offset; 2502932c9ebSPekka Enberg bool ret = true; 25146aa8d69SPekka Enberg 252c6a69c61SPekka Enberg dev = find_device(port); 253c6a69c61SPekka Enberg if (!dev) 254c6a69c61SPekka Enberg return false; 255c6a69c61SPekka Enberg 2564ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 2572932c9ebSPekka Enberg 258c6a69c61SPekka Enberg offset = port - dev->iobase; 259c6a69c61SPekka Enberg 26019a2bb7dSPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 26119a2bb7dSPekka Enberg switch (offset) { 26219a2bb7dSPekka Enberg case UART_DLL: 26319a2bb7dSPekka Enberg ioport__write8(data, dev->dll); 2642932c9ebSPekka Enberg goto out_unlock; 2652932c9ebSPekka Enberg 26619a2bb7dSPekka Enberg case UART_DLM: 26719a2bb7dSPekka Enberg ioport__write8(data, dev->dlm); 2682932c9ebSPekka Enberg goto out_unlock; 2692932c9ebSPekka Enberg 270369c01c0SPekka Enberg default: 271369c01c0SPekka Enberg break; 27219a2bb7dSPekka Enberg } 27319a2bb7dSPekka Enberg } else { 27446aa8d69SPekka Enberg switch (offset) { 275251cf9a6SPekka Enberg case UART_RX: 276251cf9a6SPekka Enberg ioport__write8(data, dev->rbr); 277369c01c0SPekka Enberg dev->lsr &= ~UART_LSR_DR; 278369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 2792932c9ebSPekka Enberg goto out_unlock; 2802932c9ebSPekka Enberg 2814e49b05bSCyrill Gorcunov case UART_IER: 282c6a69c61SPekka Enberg ioport__write8(data, dev->ier); 2832932c9ebSPekka Enberg goto out_unlock; 2842932c9ebSPekka Enberg 285369c01c0SPekka Enberg default: 286369c01c0SPekka Enberg break; 28719a2bb7dSPekka Enberg } 28819a2bb7dSPekka Enberg } 28919a2bb7dSPekka Enberg 29019a2bb7dSPekka Enberg switch (offset) { 291369c01c0SPekka Enberg case UART_IIR: { 292*3fdf659dSSasha Levin u8 iir = dev->iir; 293369c01c0SPekka Enberg 294369c01c0SPekka Enberg if (dev->fcr & UART_FCR_ENABLE_FIFO) 295369c01c0SPekka Enberg iir |= 0xc0; 296369c01c0SPekka Enberg 297369c01c0SPekka Enberg ioport__write8(data, iir); 29846aa8d69SPekka Enberg break; 299369c01c0SPekka Enberg } 3004e49b05bSCyrill Gorcunov case UART_LCR: 301c6a69c61SPekka Enberg ioport__write8(data, dev->lcr); 30246aa8d69SPekka Enberg break; 3034e49b05bSCyrill Gorcunov case UART_MCR: 304c6a69c61SPekka Enberg ioport__write8(data, dev->mcr); 30546aa8d69SPekka Enberg break; 3064e49b05bSCyrill Gorcunov case UART_LSR: 307c6a69c61SPekka Enberg ioport__write8(data, dev->lsr); 308369c01c0SPekka Enberg dev->lsr &= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI); 30946aa8d69SPekka Enberg break; 3104e49b05bSCyrill Gorcunov case UART_MSR: 311369c01c0SPekka Enberg ioport__write8(data, dev->msr); 31246aa8d69SPekka Enberg break; 3134e49b05bSCyrill Gorcunov case UART_SCR: 314369c01c0SPekka Enberg ioport__write8(data, dev->scr); 31546aa8d69SPekka Enberg break; 316369c01c0SPekka Enberg default: 3172932c9ebSPekka Enberg ret = false; 3182932c9ebSPekka Enberg goto out_unlock; 31925af6674SPekka Enberg } 3202932c9ebSPekka Enberg out_unlock: 3214ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 3222932c9ebSPekka Enberg 3232932c9ebSPekka Enberg return ret; 32413a7760fSPekka Enberg } 32513a7760fSPekka Enberg 32646aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = { 32746aa8d69SPekka Enberg .io_in = serial8250_in, 32846aa8d69SPekka Enberg .io_out = serial8250_out, 329a93ec68bSPekka Enberg }; 330a93ec68bSPekka Enberg 331bc4b0ffeSPekka Enberg static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev) 332bc4b0ffeSPekka Enberg { 333bc4b0ffeSPekka Enberg ioport__register(dev->iobase, &serial8250_ops, 8); 334bc4b0ffeSPekka Enberg kvm__irq_line(kvm, dev->irq, 0); 335bc4b0ffeSPekka Enberg } 336bc4b0ffeSPekka Enberg 337bc4b0ffeSPekka Enberg void serial8250__init(struct kvm *kvm) 33813a7760fSPekka Enberg { 339c6a69c61SPekka Enberg unsigned int i; 340c6a69c61SPekka Enberg 341c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 342c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 343c6a69c61SPekka Enberg 344bc4b0ffeSPekka Enberg serial8250__device_init(kvm, dev); 345c6a69c61SPekka Enberg } 34613a7760fSPekka Enberg } 347