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 103fdf659dSSasha 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 183fdf659dSSasha Levin u16 iobase; 193fdf659dSSasha Levin u8 irq; 2076b4a122SPekka Enberg 213fdf659dSSasha Levin u8 rbr; /* receive buffer */ 223fdf659dSSasha Levin u8 dll; 233fdf659dSSasha Levin u8 dlm; 243fdf659dSSasha Levin u8 iir; 253fdf659dSSasha Levin u8 ier; 263fdf659dSSasha Levin u8 fcr; 273fdf659dSSasha Levin u8 lcr; 283fdf659dSSasha Levin u8 mcr; 293fdf659dSSasha Levin u8 lsr; 303fdf659dSSasha Levin u8 msr; 313fdf659dSSasha Levin u8 scr; 3246aa8d69SPekka Enberg }; 3346aa8d69SPekka Enberg 34*f3efa592SLiming Wang #define SERIAL_REGS_SETTING \ 35*f3efa592SLiming Wang .iir = UART_IIR_NO_INT, \ 36*f3efa592SLiming Wang .lsr = UART_LSR_TEMT | UART_LSR_THRE, \ 37*f3efa592SLiming Wang .msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, \ 38*f3efa592SLiming Wang .mcr = UART_MCR_OUT2, 39*f3efa592SLiming Wang 40e62c18deSPekka Enberg static struct serial8250_device devices[] = { 41c6a69c61SPekka Enberg /* ttyS0 */ 42c6a69c61SPekka Enberg [0] = { 432932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 442932c9ebSPekka Enberg 45c6a69c61SPekka Enberg .iobase = 0x3f8, 46e557eef9SPekka Enberg .irq = 4, 47e557eef9SPekka Enberg 48*f3efa592SLiming Wang SERIAL_REGS_SETTING 49c6a69c61SPekka Enberg }, 50e62c18deSPekka Enberg /* ttyS1 */ 51e62c18deSPekka Enberg [1] = { 522932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 532932c9ebSPekka Enberg 54e62c18deSPekka Enberg .iobase = 0x2f8, 55e62c18deSPekka Enberg .irq = 3, 56133bedc1SPekka Enberg 57*f3efa592SLiming Wang SERIAL_REGS_SETTING 58e62c18deSPekka Enberg }, 59e62c18deSPekka Enberg /* ttyS2 */ 60e62c18deSPekka Enberg [2] = { 612932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 622932c9ebSPekka Enberg 63e62c18deSPekka Enberg .iobase = 0x3e8, 64e62c18deSPekka Enberg .irq = 4, 65133bedc1SPekka Enberg 66*f3efa592SLiming Wang SERIAL_REGS_SETTING 67e62c18deSPekka Enberg }, 68bf459c83SPekka Enberg /* ttyS3 */ 69bf459c83SPekka Enberg [3] = { 70bf459c83SPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 71bf459c83SPekka Enberg 72bf459c83SPekka Enberg .iobase = 0x2e8, 73bf459c83SPekka Enberg .irq = 3, 74bf459c83SPekka Enberg 75*f3efa592SLiming Wang SERIAL_REGS_SETTING 76bf459c83SPekka Enberg }, 7746aa8d69SPekka Enberg }; 7846aa8d69SPekka Enberg 79a428f72eSPekka Enberg #define SYSRQ_PENDING_NONE 0 80a428f72eSPekka Enberg #define SYSRQ_PENDING_BREAK 1 81a428f72eSPekka Enberg #define SYSRQ_PENDING_CMD 2 82a428f72eSPekka Enberg 83a428f72eSPekka Enberg static int sysrq_pending; 84a428f72eSPekka Enberg 8543835ac9SSasha Levin static void serial8250__sysrq(struct kvm *kvm, struct serial8250_device *dev) 86a428f72eSPekka Enberg { 87a428f72eSPekka Enberg switch (sysrq_pending) { 88a428f72eSPekka Enberg case SYSRQ_PENDING_BREAK: 89a428f72eSPekka Enberg dev->lsr |= UART_LSR_DR | UART_LSR_BI; 90a428f72eSPekka Enberg 91a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_CMD; 92a428f72eSPekka Enberg break; 93a428f72eSPekka Enberg case SYSRQ_PENDING_CMD: 94a428f72eSPekka Enberg dev->rbr = 'p'; 95a428f72eSPekka Enberg dev->lsr |= UART_LSR_DR; 96a428f72eSPekka Enberg 97a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_NONE; 98a428f72eSPekka Enberg break; 99a428f72eSPekka Enberg } 100a428f72eSPekka Enberg } 101a428f72eSPekka Enberg 10243835ac9SSasha Levin static void serial8250__receive(struct kvm *kvm, struct serial8250_device *dev) 103251cf9a6SPekka Enberg { 104251cf9a6SPekka Enberg int c; 105251cf9a6SPekka Enberg 106db34045cSPekka Enberg if (dev->lsr & UART_LSR_DR) 107db34045cSPekka Enberg return; 108db34045cSPekka Enberg 109a428f72eSPekka Enberg if (sysrq_pending) { 11043835ac9SSasha Levin serial8250__sysrq(kvm, dev); 111a428f72eSPekka Enberg return; 112a428f72eSPekka Enberg } 113a428f72eSPekka Enberg 11405d1a2a6SAsias He if (!term_readable(CONSOLE_8250)) 115251cf9a6SPekka Enberg return; 116251cf9a6SPekka Enberg 11705d1a2a6SAsias He c = term_getc(CONSOLE_8250); 11805d1a2a6SAsias He 119251cf9a6SPekka Enberg if (c < 0) 120251cf9a6SPekka Enberg return; 121251cf9a6SPekka Enberg 122251cf9a6SPekka Enberg dev->rbr = c; 123251cf9a6SPekka Enberg dev->lsr |= UART_LSR_DR; 124251cf9a6SPekka Enberg } 125251cf9a6SPekka Enberg 126c6a69c61SPekka Enberg /* 127c6a69c61SPekka Enberg * Interrupts are injected for ttyS0 only. 128c6a69c61SPekka Enberg */ 12943835ac9SSasha Levin void serial8250__inject_interrupt(struct kvm *kvm) 1308bb34e0dSPekka Enberg { 131c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[0]; 132934c193bSPekka Enberg 1334ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 1342932c9ebSPekka Enberg 13543835ac9SSasha Levin serial8250__receive(kvm, dev); 136251cf9a6SPekka Enberg 137369c01c0SPekka Enberg if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR) 138369c01c0SPekka Enberg dev->iir = UART_IIR_RDI; 139251cf9a6SPekka Enberg else if (dev->ier & UART_IER_THRI) 140369c01c0SPekka Enberg dev->iir = UART_IIR_THRI; 141369c01c0SPekka Enberg else 142369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 14376b4a122SPekka Enberg 144369c01c0SPekka Enberg if (dev->iir != UART_IIR_NO_INT) { 14543835ac9SSasha Levin kvm__irq_line(kvm, dev->irq, 0); 14643835ac9SSasha Levin kvm__irq_line(kvm, dev->irq, 1); 147e557eef9SPekka Enberg } 1482932c9ebSPekka Enberg 1494ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 1508bb34e0dSPekka Enberg } 1518bb34e0dSPekka Enberg 15243835ac9SSasha Levin void serial8250__inject_sysrq(struct kvm *kvm) 153a428f72eSPekka Enberg { 154a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_BREAK; 155a428f72eSPekka Enberg } 156a428f72eSPekka Enberg 1573fdf659dSSasha Levin static struct serial8250_device *find_device(u16 port) 158c6a69c61SPekka Enberg { 159c6a69c61SPekka Enberg unsigned int i; 160c6a69c61SPekka Enberg 161c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 162c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 163c6a69c61SPekka Enberg 164c6a69c61SPekka Enberg if (dev->iobase == (port & ~0x7)) 165c6a69c61SPekka Enberg return dev; 166c6a69c61SPekka Enberg } 167c6a69c61SPekka Enberg return NULL; 168c6a69c61SPekka Enberg } 169c6a69c61SPekka Enberg 1703d62dea6SSasha Levin static bool serial8250_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) 17113a7760fSPekka Enberg { 172c6a69c61SPekka Enberg struct serial8250_device *dev; 1733fdf659dSSasha Levin u16 offset; 1742932c9ebSPekka Enberg bool ret = true; 17546aa8d69SPekka Enberg 176c6a69c61SPekka Enberg dev = find_device(port); 177c6a69c61SPekka Enberg if (!dev) 178c6a69c61SPekka Enberg return false; 179c6a69c61SPekka Enberg 1804ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 1812932c9ebSPekka Enberg 182c6a69c61SPekka Enberg offset = port - dev->iobase; 183c6a69c61SPekka Enberg 184c6a69c61SPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 18546aa8d69SPekka Enberg switch (offset) { 1864e49b05bSCyrill Gorcunov case UART_DLL: 187c6a69c61SPekka Enberg dev->dll = ioport__read8(data); 18846aa8d69SPekka Enberg break; 1894e49b05bSCyrill Gorcunov case UART_DLM: 190c6a69c61SPekka Enberg dev->dlm = ioport__read8(data); 19146aa8d69SPekka Enberg break; 192369c01c0SPekka Enberg case UART_FCR: 193369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 194369c01c0SPekka Enberg break; 195369c01c0SPekka Enberg case UART_LCR: 196369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 197369c01c0SPekka Enberg break; 198369c01c0SPekka Enberg case UART_MCR: 199369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 200369c01c0SPekka Enberg break; 201369c01c0SPekka Enberg case UART_LSR: 202369c01c0SPekka Enberg /* Factory test */ 203369c01c0SPekka Enberg break; 204369c01c0SPekka Enberg case UART_MSR: 205369c01c0SPekka Enberg /* Not used */ 206369c01c0SPekka Enberg break; 207369c01c0SPekka Enberg case UART_SCR: 208369c01c0SPekka Enberg dev->scr = ioport__read8(data); 209369c01c0SPekka Enberg break; 210369c01c0SPekka Enberg default: 2112932c9ebSPekka Enberg ret = false; 2122932c9ebSPekka Enberg goto out_unlock; 21346aa8d69SPekka Enberg } 21446aa8d69SPekka Enberg } else { 21546aa8d69SPekka Enberg switch (offset) { 2164e49b05bSCyrill Gorcunov case UART_TX: { 21705d1a2a6SAsias He char *addr = data; 2180ea58e5bSPekka Enberg 2190ea58e5bSPekka Enberg if (!(dev->mcr & UART_MCR_LOOP)) 22005d1a2a6SAsias He term_putc(CONSOLE_8250, addr, size * count); 2210ea58e5bSPekka Enberg 222133bedc1SPekka Enberg dev->iir = UART_IIR_NO_INT; 22346aa8d69SPekka Enberg break; 22446aa8d69SPekka Enberg } 225369c01c0SPekka Enberg case UART_FCR: 226369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 227369c01c0SPekka Enberg break; 2284e49b05bSCyrill Gorcunov case UART_IER: 229369c01c0SPekka Enberg dev->ier = ioport__read8(data) & 0x3f; 23046aa8d69SPekka Enberg break; 231369c01c0SPekka Enberg case UART_LCR: 232369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 233369c01c0SPekka Enberg break; 234369c01c0SPekka Enberg case UART_MCR: 235369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 236369c01c0SPekka Enberg break; 237369c01c0SPekka Enberg case UART_LSR: 238369c01c0SPekka Enberg /* Factory test */ 239369c01c0SPekka Enberg break; 240369c01c0SPekka Enberg case UART_MSR: 241369c01c0SPekka Enberg /* Not used */ 242369c01c0SPekka Enberg break; 243369c01c0SPekka Enberg case UART_SCR: 244369c01c0SPekka Enberg dev->scr = ioport__read8(data); 245369c01c0SPekka Enberg break; 246369c01c0SPekka Enberg default: 2472932c9ebSPekka Enberg ret = false; 2482932c9ebSPekka Enberg goto out_unlock; 24946aa8d69SPekka Enberg } 25046aa8d69SPekka Enberg } 2512932c9ebSPekka Enberg 2522932c9ebSPekka Enberg out_unlock: 2534ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 2542932c9ebSPekka Enberg 2552932c9ebSPekka Enberg return ret; 25613a7760fSPekka Enberg } 25713a7760fSPekka Enberg 2583d62dea6SSasha Levin static bool serial8250_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count) 25925af6674SPekka Enberg { 260c6a69c61SPekka Enberg struct serial8250_device *dev; 2613fdf659dSSasha Levin u16 offset; 2622932c9ebSPekka Enberg bool ret = true; 26346aa8d69SPekka Enberg 264c6a69c61SPekka Enberg dev = find_device(port); 265c6a69c61SPekka Enberg if (!dev) 266c6a69c61SPekka Enberg return false; 267c6a69c61SPekka Enberg 2684ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 2692932c9ebSPekka Enberg 270c6a69c61SPekka Enberg offset = port - dev->iobase; 271c6a69c61SPekka Enberg 27219a2bb7dSPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 27319a2bb7dSPekka Enberg switch (offset) { 27419a2bb7dSPekka Enberg case UART_DLL: 27519a2bb7dSPekka Enberg ioport__write8(data, dev->dll); 2762932c9ebSPekka Enberg goto out_unlock; 2772932c9ebSPekka Enberg 27819a2bb7dSPekka Enberg case UART_DLM: 27919a2bb7dSPekka Enberg ioport__write8(data, dev->dlm); 2802932c9ebSPekka Enberg goto out_unlock; 2812932c9ebSPekka Enberg 282369c01c0SPekka Enberg default: 283369c01c0SPekka Enberg break; 28419a2bb7dSPekka Enberg } 28519a2bb7dSPekka Enberg } else { 28646aa8d69SPekka Enberg switch (offset) { 287251cf9a6SPekka Enberg case UART_RX: 288251cf9a6SPekka Enberg ioport__write8(data, dev->rbr); 289369c01c0SPekka Enberg dev->lsr &= ~UART_LSR_DR; 290369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 2912932c9ebSPekka Enberg goto out_unlock; 2922932c9ebSPekka Enberg 2934e49b05bSCyrill Gorcunov case UART_IER: 294c6a69c61SPekka Enberg ioport__write8(data, dev->ier); 2952932c9ebSPekka Enberg goto out_unlock; 2962932c9ebSPekka Enberg 297369c01c0SPekka Enberg default: 298369c01c0SPekka Enberg break; 29919a2bb7dSPekka Enberg } 30019a2bb7dSPekka Enberg } 30119a2bb7dSPekka Enberg 30219a2bb7dSPekka Enberg switch (offset) { 303369c01c0SPekka Enberg case UART_IIR: { 3043fdf659dSSasha Levin u8 iir = dev->iir; 305369c01c0SPekka Enberg 306369c01c0SPekka Enberg if (dev->fcr & UART_FCR_ENABLE_FIFO) 307369c01c0SPekka Enberg iir |= 0xc0; 308369c01c0SPekka Enberg 309369c01c0SPekka Enberg ioport__write8(data, iir); 31046aa8d69SPekka Enberg break; 311369c01c0SPekka Enberg } 3124e49b05bSCyrill Gorcunov case UART_LCR: 313c6a69c61SPekka Enberg ioport__write8(data, dev->lcr); 31446aa8d69SPekka Enberg break; 3154e49b05bSCyrill Gorcunov case UART_MCR: 316c6a69c61SPekka Enberg ioport__write8(data, dev->mcr); 31746aa8d69SPekka Enberg break; 3184e49b05bSCyrill Gorcunov case UART_LSR: 319c6a69c61SPekka Enberg ioport__write8(data, dev->lsr); 320369c01c0SPekka Enberg dev->lsr &= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI); 32146aa8d69SPekka Enberg break; 3224e49b05bSCyrill Gorcunov case UART_MSR: 323369c01c0SPekka Enberg ioport__write8(data, dev->msr); 32446aa8d69SPekka Enberg break; 3254e49b05bSCyrill Gorcunov case UART_SCR: 326369c01c0SPekka Enberg ioport__write8(data, dev->scr); 32746aa8d69SPekka Enberg break; 328369c01c0SPekka Enberg default: 3292932c9ebSPekka Enberg ret = false; 3302932c9ebSPekka Enberg goto out_unlock; 33125af6674SPekka Enberg } 3322932c9ebSPekka Enberg out_unlock: 3334ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 3342932c9ebSPekka Enberg 3352932c9ebSPekka Enberg return ret; 33613a7760fSPekka Enberg } 33713a7760fSPekka Enberg 33846aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = { 33946aa8d69SPekka Enberg .io_in = serial8250_in, 34046aa8d69SPekka Enberg .io_out = serial8250_out, 341a93ec68bSPekka Enberg }; 342a93ec68bSPekka Enberg 343bc4b0ffeSPekka Enberg static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev) 344bc4b0ffeSPekka Enberg { 3453d62dea6SSasha Levin ioport__register(dev->iobase, &serial8250_ops, 8, NULL); 346bc4b0ffeSPekka Enberg kvm__irq_line(kvm, dev->irq, 0); 347bc4b0ffeSPekka Enberg } 348bc4b0ffeSPekka Enberg 349bc4b0ffeSPekka Enberg void serial8250__init(struct kvm *kvm) 35013a7760fSPekka Enberg { 351c6a69c61SPekka Enberg unsigned int i; 352c6a69c61SPekka Enberg 353c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 354c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 355c6a69c61SPekka Enberg 356bc4b0ffeSPekka Enberg serial8250__device_init(kvm, dev); 357c6a69c61SPekka Enberg } 35813a7760fSPekka Enberg } 359