1899fe063SPekka Enberg #include "kvm/8250-serial.h" 213a7760fSPekka Enberg 38eb47d29SSasha Levin #include "kvm/read-write.h" 413a7760fSPekka Enberg #include "kvm/ioport.h" 546aa8d69SPekka Enberg #include "kvm/util.h" 6*05d1a2a6SAsias He #include "kvm/term.h" 7e557eef9SPekka Enberg #include "kvm/kvm.h" 813a7760fSPekka Enberg 94e49b05bSCyrill Gorcunov #include <linux/serial_reg.h> 104e49b05bSCyrill Gorcunov 1113a7760fSPekka Enberg 1246aa8d69SPekka Enberg struct serial8250_device { 1346aa8d69SPekka Enberg uint16_t iobase; 14e557eef9SPekka Enberg uint8_t irq; 1576b4a122SPekka Enberg 16251cf9a6SPekka Enberg uint8_t rbr; /* receive buffer */ 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; 25369c01c0SPekka Enberg uint8_t msr; 2646aa8d69SPekka Enberg uint8_t scr; 2746aa8d69SPekka Enberg }; 2846aa8d69SPekka Enberg 29e62c18deSPekka Enberg static struct serial8250_device devices[] = { 30c6a69c61SPekka Enberg /* ttyS0 */ 31c6a69c61SPekka Enberg [0] = { 32c6a69c61SPekka Enberg .iobase = 0x3f8, 33e557eef9SPekka Enberg .irq = 4, 34e557eef9SPekka Enberg 35369c01c0SPekka Enberg .iir = UART_IIR_NO_INT, 36bc4b0ffeSPekka Enberg .lsr = UART_LSR_TEMT | UART_LSR_THRE, 37bc4b0ffeSPekka Enberg .msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, 38bc4b0ffeSPekka Enberg .mcr = UART_MCR_OUT2, 39c6a69c61SPekka Enberg }, 40e62c18deSPekka Enberg /* ttyS1 */ 41e62c18deSPekka Enberg [1] = { 42e62c18deSPekka Enberg .iobase = 0x2f8, 43e62c18deSPekka Enberg .irq = 3, 44133bedc1SPekka Enberg 45133bedc1SPekka Enberg .iir = UART_IIR_NO_INT, 46e62c18deSPekka Enberg }, 47e62c18deSPekka Enberg /* ttyS2 */ 48e62c18deSPekka Enberg [2] = { 49e62c18deSPekka Enberg .iobase = 0x3e8, 50e62c18deSPekka Enberg .irq = 4, 51133bedc1SPekka Enberg 52133bedc1SPekka Enberg .iir = UART_IIR_NO_INT, 53e62c18deSPekka Enberg }, 5446aa8d69SPekka Enberg }; 5546aa8d69SPekka Enberg 56251cf9a6SPekka Enberg static void serial8250__receive(struct kvm *self, struct serial8250_device *dev) 57251cf9a6SPekka Enberg { 58251cf9a6SPekka Enberg int c; 59251cf9a6SPekka Enberg 60db34045cSPekka Enberg if (dev->lsr & UART_LSR_DR) 61db34045cSPekka Enberg return; 62db34045cSPekka Enberg 63*05d1a2a6SAsias He if (!term_readable(CONSOLE_8250)) 64251cf9a6SPekka Enberg return; 65251cf9a6SPekka Enberg 66*05d1a2a6SAsias He c = term_getc(CONSOLE_8250); 67*05d1a2a6SAsias He 68251cf9a6SPekka Enberg if (c < 0) 69251cf9a6SPekka Enberg return; 70251cf9a6SPekka Enberg 71251cf9a6SPekka Enberg dev->rbr = c; 72251cf9a6SPekka Enberg dev->lsr |= UART_LSR_DR; 73251cf9a6SPekka Enberg } 74251cf9a6SPekka Enberg 75c6a69c61SPekka Enberg /* 76c6a69c61SPekka Enberg * Interrupts are injected for ttyS0 only. 77c6a69c61SPekka Enberg */ 78*05d1a2a6SAsias He void serial8250__inject_interrupt(struct kvm *self) 798bb34e0dSPekka Enberg { 80c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[0]; 81934c193bSPekka Enberg 82251cf9a6SPekka Enberg serial8250__receive(self, dev); 83251cf9a6SPekka Enberg 84369c01c0SPekka Enberg if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR) 85369c01c0SPekka Enberg dev->iir = UART_IIR_RDI; 86251cf9a6SPekka Enberg else if (dev->ier & UART_IER_THRI) 87369c01c0SPekka Enberg dev->iir = UART_IIR_THRI; 88369c01c0SPekka Enberg else 89369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 9076b4a122SPekka Enberg 91369c01c0SPekka Enberg if (dev->iir != UART_IIR_NO_INT) { 92c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 0); 93c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 1); 94e557eef9SPekka Enberg } 958bb34e0dSPekka Enberg } 968bb34e0dSPekka Enberg 97c6a69c61SPekka Enberg static struct serial8250_device *find_device(uint16_t port) 98c6a69c61SPekka Enberg { 99c6a69c61SPekka Enberg unsigned int i; 100c6a69c61SPekka Enberg 101c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 102c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 103c6a69c61SPekka Enberg 104c6a69c61SPekka Enberg if (dev->iobase == (port & ~0x7)) 105c6a69c61SPekka Enberg return dev; 106c6a69c61SPekka Enberg } 107c6a69c61SPekka Enberg return NULL; 108c6a69c61SPekka Enberg } 109c6a69c61SPekka Enberg 11046aa8d69SPekka Enberg static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 11113a7760fSPekka Enberg { 112c6a69c61SPekka Enberg struct serial8250_device *dev; 113c6a69c61SPekka Enberg uint16_t offset; 11446aa8d69SPekka Enberg 115c6a69c61SPekka Enberg dev = find_device(port); 116c6a69c61SPekka Enberg if (!dev) 117c6a69c61SPekka Enberg return false; 118c6a69c61SPekka Enberg 119c6a69c61SPekka Enberg offset = port - dev->iobase; 120c6a69c61SPekka Enberg 121c6a69c61SPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 12246aa8d69SPekka Enberg switch (offset) { 1234e49b05bSCyrill Gorcunov case UART_DLL: 124c6a69c61SPekka Enberg dev->dll = ioport__read8(data); 12546aa8d69SPekka Enberg break; 1264e49b05bSCyrill Gorcunov case UART_DLM: 127c6a69c61SPekka Enberg dev->dlm = ioport__read8(data); 12846aa8d69SPekka Enberg break; 129369c01c0SPekka Enberg case UART_FCR: 130369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 131369c01c0SPekka Enberg break; 132369c01c0SPekka Enberg case UART_LCR: 133369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 134369c01c0SPekka Enberg break; 135369c01c0SPekka Enberg case UART_MCR: 136369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 137369c01c0SPekka Enberg break; 138369c01c0SPekka Enberg case UART_LSR: 139369c01c0SPekka Enberg /* Factory test */ 140369c01c0SPekka Enberg break; 141369c01c0SPekka Enberg case UART_MSR: 142369c01c0SPekka Enberg /* Not used */ 143369c01c0SPekka Enberg break; 144369c01c0SPekka Enberg case UART_SCR: 145369c01c0SPekka Enberg dev->scr = ioport__read8(data); 146369c01c0SPekka Enberg break; 147369c01c0SPekka Enberg default: 148369c01c0SPekka Enberg return false; 14946aa8d69SPekka Enberg } 15046aa8d69SPekka Enberg } else { 15146aa8d69SPekka Enberg switch (offset) { 1524e49b05bSCyrill Gorcunov case UART_TX: { 153*05d1a2a6SAsias He char *addr = data; 154369c01c0SPekka Enberg if (!(dev->mcr & UART_MCR_LOOP)) { 155*05d1a2a6SAsias He term_putc(CONSOLE_8250, addr, size * count); 156369c01c0SPekka Enberg } 157133bedc1SPekka Enberg dev->iir = UART_IIR_NO_INT; 15846aa8d69SPekka Enberg break; 15946aa8d69SPekka Enberg } 160369c01c0SPekka Enberg case UART_FCR: 161369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 162369c01c0SPekka Enberg break; 1634e49b05bSCyrill Gorcunov case UART_IER: 164369c01c0SPekka Enberg dev->ier = ioport__read8(data) & 0x3f; 16546aa8d69SPekka Enberg break; 166369c01c0SPekka Enberg case UART_LCR: 167369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 168369c01c0SPekka Enberg break; 169369c01c0SPekka Enberg case UART_MCR: 170369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 171369c01c0SPekka Enberg break; 172369c01c0SPekka Enberg case UART_LSR: 173369c01c0SPekka Enberg /* Factory test */ 174369c01c0SPekka Enberg break; 175369c01c0SPekka Enberg case UART_MSR: 176369c01c0SPekka Enberg /* Not used */ 177369c01c0SPekka Enberg break; 178369c01c0SPekka Enberg case UART_SCR: 179369c01c0SPekka Enberg dev->scr = ioport__read8(data); 180369c01c0SPekka Enberg break; 181369c01c0SPekka Enberg default: 182369c01c0SPekka Enberg return false; 18346aa8d69SPekka Enberg } 18446aa8d69SPekka Enberg } 18513a7760fSPekka Enberg return true; 18613a7760fSPekka Enberg } 18713a7760fSPekka Enberg 18846aa8d69SPekka Enberg static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 18925af6674SPekka Enberg { 190c6a69c61SPekka Enberg struct serial8250_device *dev; 191c6a69c61SPekka Enberg uint16_t offset; 19246aa8d69SPekka Enberg 193c6a69c61SPekka Enberg dev = find_device(port); 194c6a69c61SPekka Enberg if (!dev) 195c6a69c61SPekka Enberg return false; 196c6a69c61SPekka Enberg 197c6a69c61SPekka Enberg offset = port - dev->iobase; 198c6a69c61SPekka Enberg 19919a2bb7dSPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 20019a2bb7dSPekka Enberg switch (offset) { 20119a2bb7dSPekka Enberg case UART_DLL: 20219a2bb7dSPekka Enberg ioport__write8(data, dev->dll); 20319a2bb7dSPekka Enberg return true; 20419a2bb7dSPekka Enberg case UART_DLM: 20519a2bb7dSPekka Enberg ioport__write8(data, dev->dlm); 20619a2bb7dSPekka Enberg return true; 207369c01c0SPekka Enberg default: 208369c01c0SPekka Enberg break; 20919a2bb7dSPekka Enberg } 21019a2bb7dSPekka Enberg } else { 21146aa8d69SPekka Enberg switch (offset) { 212251cf9a6SPekka Enberg case UART_RX: 213251cf9a6SPekka Enberg ioport__write8(data, dev->rbr); 214369c01c0SPekka Enberg dev->lsr &= ~UART_LSR_DR; 215369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 21619a2bb7dSPekka Enberg return true; 2174e49b05bSCyrill Gorcunov case UART_IER: 218c6a69c61SPekka Enberg ioport__write8(data, dev->ier); 21919a2bb7dSPekka Enberg return true; 220369c01c0SPekka Enberg default: 221369c01c0SPekka Enberg break; 22219a2bb7dSPekka Enberg } 22319a2bb7dSPekka Enberg } 22419a2bb7dSPekka Enberg 22519a2bb7dSPekka Enberg switch (offset) { 226369c01c0SPekka Enberg case UART_IIR: { 227369c01c0SPekka Enberg uint8_t iir = dev->iir; 228369c01c0SPekka Enberg 229369c01c0SPekka Enberg if (dev->fcr & UART_FCR_ENABLE_FIFO) 230369c01c0SPekka Enberg iir |= 0xc0; 231369c01c0SPekka Enberg 232369c01c0SPekka Enberg ioport__write8(data, iir); 23346aa8d69SPekka Enberg break; 234369c01c0SPekka Enberg } 2354e49b05bSCyrill Gorcunov case UART_LCR: 236c6a69c61SPekka Enberg ioport__write8(data, dev->lcr); 23746aa8d69SPekka Enberg break; 2384e49b05bSCyrill Gorcunov case UART_MCR: 239c6a69c61SPekka Enberg ioport__write8(data, dev->mcr); 24046aa8d69SPekka Enberg break; 2414e49b05bSCyrill Gorcunov case UART_LSR: 242c6a69c61SPekka Enberg ioport__write8(data, dev->lsr); 243369c01c0SPekka Enberg dev->lsr &= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI); 24446aa8d69SPekka Enberg break; 2454e49b05bSCyrill Gorcunov case UART_MSR: 246369c01c0SPekka Enberg ioport__write8(data, dev->msr); 24746aa8d69SPekka Enberg break; 2484e49b05bSCyrill Gorcunov case UART_SCR: 249369c01c0SPekka Enberg ioport__write8(data, dev->scr); 25046aa8d69SPekka Enberg break; 251369c01c0SPekka Enberg default: 252369c01c0SPekka Enberg return false; 25325af6674SPekka Enberg } 25413a7760fSPekka Enberg return true; 25513a7760fSPekka Enberg } 25613a7760fSPekka Enberg 25746aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = { 25846aa8d69SPekka Enberg .io_in = serial8250_in, 25946aa8d69SPekka Enberg .io_out = serial8250_out, 260a93ec68bSPekka Enberg }; 261a93ec68bSPekka Enberg 262bc4b0ffeSPekka Enberg static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev) 263bc4b0ffeSPekka Enberg { 264bc4b0ffeSPekka Enberg ioport__register(dev->iobase, &serial8250_ops, 8); 265bc4b0ffeSPekka Enberg kvm__irq_line(kvm, dev->irq, 0); 266bc4b0ffeSPekka Enberg } 267bc4b0ffeSPekka Enberg 268bc4b0ffeSPekka Enberg void serial8250__init(struct kvm *kvm) 26913a7760fSPekka Enberg { 270c6a69c61SPekka Enberg unsigned int i; 271c6a69c61SPekka Enberg 272c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 273c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 274c6a69c61SPekka Enberg 275bc4b0ffeSPekka Enberg serial8250__device_init(kvm, dev); 276c6a69c61SPekka Enberg } 27713a7760fSPekka Enberg } 278