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 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 5676b4a122SPekka Enberg static int read_char(int fd) 5776b4a122SPekka Enberg { 5876b4a122SPekka Enberg int c; 5976b4a122SPekka Enberg 6076b4a122SPekka Enberg if (read(fd, &c, 1) < 0) 6176b4a122SPekka Enberg return -1; 6276b4a122SPekka Enberg 6376b4a122SPekka Enberg return c; 6476b4a122SPekka Enberg } 6576b4a122SPekka Enberg 6676b4a122SPekka Enberg static bool is_readable(int fd) 6776b4a122SPekka Enberg { 686d54df74SCyrill Gorcunov struct pollfd pollfd = (struct pollfd) { 6976b4a122SPekka Enberg .fd = fd, 7076b4a122SPekka Enberg .events = POLLIN, 7176b4a122SPekka Enberg }; 7276b4a122SPekka Enberg 736d54df74SCyrill Gorcunov return poll(&pollfd, 1, 0) > 0; 7476b4a122SPekka Enberg } 7576b4a122SPekka Enberg 76251cf9a6SPekka Enberg static void serial8250__receive(struct kvm *self, struct serial8250_device *dev) 77251cf9a6SPekka Enberg { 78251cf9a6SPekka Enberg int c; 79251cf9a6SPekka Enberg 80*db34045cSPekka Enberg if (dev->lsr & UART_LSR_DR) 81*db34045cSPekka Enberg return; 82*db34045cSPekka Enberg 83251cf9a6SPekka Enberg if (!is_readable(fileno(stdin))) 84251cf9a6SPekka Enberg return; 85251cf9a6SPekka Enberg 86251cf9a6SPekka Enberg c = read_char(fileno(stdin)); 87251cf9a6SPekka Enberg if (c < 0) 88251cf9a6SPekka Enberg return; 89251cf9a6SPekka Enberg 90251cf9a6SPekka Enberg dev->rbr = c; 91251cf9a6SPekka Enberg dev->lsr |= UART_LSR_DR; 92251cf9a6SPekka Enberg } 93251cf9a6SPekka Enberg 94c6a69c61SPekka Enberg /* 95c6a69c61SPekka Enberg * Interrupts are injected for ttyS0 only. 96c6a69c61SPekka Enberg */ 978bb34e0dSPekka Enberg void serial8250__interrupt(struct kvm *self) 988bb34e0dSPekka Enberg { 99c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[0]; 100934c193bSPekka Enberg 101251cf9a6SPekka Enberg serial8250__receive(self, dev); 102251cf9a6SPekka Enberg 103369c01c0SPekka Enberg if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR) 104369c01c0SPekka Enberg dev->iir = UART_IIR_RDI; 105251cf9a6SPekka Enberg else if (dev->ier & UART_IER_THRI) 106369c01c0SPekka Enberg dev->iir = UART_IIR_THRI; 107369c01c0SPekka Enberg else 108369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 10976b4a122SPekka Enberg 110369c01c0SPekka Enberg if (dev->iir != UART_IIR_NO_INT) { 111c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 0); 112c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 1); 113e557eef9SPekka Enberg } 1148bb34e0dSPekka Enberg } 1158bb34e0dSPekka Enberg 116c6a69c61SPekka Enberg static struct serial8250_device *find_device(uint16_t port) 117c6a69c61SPekka Enberg { 118c6a69c61SPekka Enberg unsigned int i; 119c6a69c61SPekka Enberg 120c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 121c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 122c6a69c61SPekka Enberg 123c6a69c61SPekka Enberg if (dev->iobase == (port & ~0x7)) 124c6a69c61SPekka Enberg return dev; 125c6a69c61SPekka Enberg } 126c6a69c61SPekka Enberg return NULL; 127c6a69c61SPekka Enberg } 128c6a69c61SPekka Enberg 12946aa8d69SPekka Enberg static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 13013a7760fSPekka Enberg { 131c6a69c61SPekka Enberg struct serial8250_device *dev; 132c6a69c61SPekka Enberg uint16_t offset; 13346aa8d69SPekka Enberg 134c6a69c61SPekka Enberg dev = find_device(port); 135c6a69c61SPekka Enberg if (!dev) 136c6a69c61SPekka Enberg return false; 137c6a69c61SPekka Enberg 138c6a69c61SPekka Enberg offset = port - dev->iobase; 139c6a69c61SPekka Enberg 140c6a69c61SPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 14146aa8d69SPekka Enberg switch (offset) { 1424e49b05bSCyrill Gorcunov case UART_DLL: 143c6a69c61SPekka Enberg dev->dll = ioport__read8(data); 14446aa8d69SPekka Enberg break; 1454e49b05bSCyrill Gorcunov case UART_DLM: 146c6a69c61SPekka Enberg dev->dlm = ioport__read8(data); 14746aa8d69SPekka Enberg break; 148369c01c0SPekka Enberg case UART_FCR: 149369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 150369c01c0SPekka Enberg break; 151369c01c0SPekka Enberg case UART_LCR: 152369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 153369c01c0SPekka Enberg break; 154369c01c0SPekka Enberg case UART_MCR: 155369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 156369c01c0SPekka Enberg break; 157369c01c0SPekka Enberg case UART_LSR: 158369c01c0SPekka Enberg /* Factory test */ 159369c01c0SPekka Enberg break; 160369c01c0SPekka Enberg case UART_MSR: 161369c01c0SPekka Enberg /* Not used */ 162369c01c0SPekka Enberg break; 163369c01c0SPekka Enberg case UART_SCR: 164369c01c0SPekka Enberg dev->scr = ioport__read8(data); 165369c01c0SPekka Enberg break; 166369c01c0SPekka Enberg default: 167369c01c0SPekka Enberg return false; 16846aa8d69SPekka Enberg } 16946aa8d69SPekka Enberg } else { 17046aa8d69SPekka Enberg switch (offset) { 1714e49b05bSCyrill Gorcunov case UART_TX: { 17213a7760fSPekka Enberg char *p = data; 173f2d8dc88SCyrill Gorcunov int i; 17413a7760fSPekka Enberg 175369c01c0SPekka Enberg if (!(dev->mcr & UART_MCR_LOOP)) { 176f2d8dc88SCyrill Gorcunov while (count--) { 177f2d8dc88SCyrill Gorcunov for (i = 0; i < size; i++) 178b7475544SPekka Enberg fprintf(stdout, "%c", *p++); 1795b9d0b58SAsias He } 180b7475544SPekka Enberg fflush(stdout); 181369c01c0SPekka Enberg } 182133bedc1SPekka Enberg dev->iir = UART_IIR_NO_INT; 18346aa8d69SPekka Enberg break; 18446aa8d69SPekka Enberg } 185369c01c0SPekka Enberg case UART_FCR: 186369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 187369c01c0SPekka Enberg break; 1884e49b05bSCyrill Gorcunov case UART_IER: 189369c01c0SPekka Enberg dev->ier = ioport__read8(data) & 0x3f; 19046aa8d69SPekka Enberg break; 191369c01c0SPekka Enberg case UART_LCR: 192369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 193369c01c0SPekka Enberg break; 194369c01c0SPekka Enberg case UART_MCR: 195369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 196369c01c0SPekka Enberg break; 197369c01c0SPekka Enberg case UART_LSR: 198369c01c0SPekka Enberg /* Factory test */ 199369c01c0SPekka Enberg break; 200369c01c0SPekka Enberg case UART_MSR: 201369c01c0SPekka Enberg /* Not used */ 202369c01c0SPekka Enberg break; 203369c01c0SPekka Enberg case UART_SCR: 204369c01c0SPekka Enberg dev->scr = ioport__read8(data); 205369c01c0SPekka Enberg break; 206369c01c0SPekka Enberg default: 207369c01c0SPekka Enberg return false; 20846aa8d69SPekka Enberg } 20946aa8d69SPekka Enberg } 21013a7760fSPekka Enberg return true; 21113a7760fSPekka Enberg } 21213a7760fSPekka Enberg 21346aa8d69SPekka Enberg static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 21425af6674SPekka Enberg { 215c6a69c61SPekka Enberg struct serial8250_device *dev; 216c6a69c61SPekka Enberg uint16_t offset; 21746aa8d69SPekka Enberg 218c6a69c61SPekka Enberg dev = find_device(port); 219c6a69c61SPekka Enberg if (!dev) 220c6a69c61SPekka Enberg return false; 221c6a69c61SPekka Enberg 222c6a69c61SPekka Enberg offset = port - dev->iobase; 223c6a69c61SPekka Enberg 22419a2bb7dSPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 22519a2bb7dSPekka Enberg switch (offset) { 22619a2bb7dSPekka Enberg case UART_DLL: 22719a2bb7dSPekka Enberg ioport__write8(data, dev->dll); 22819a2bb7dSPekka Enberg return true; 22919a2bb7dSPekka Enberg case UART_DLM: 23019a2bb7dSPekka Enberg ioport__write8(data, dev->dlm); 23119a2bb7dSPekka Enberg return true; 232369c01c0SPekka Enberg default: 233369c01c0SPekka Enberg break; 23419a2bb7dSPekka Enberg } 23519a2bb7dSPekka Enberg } else { 23646aa8d69SPekka Enberg switch (offset) { 237251cf9a6SPekka Enberg case UART_RX: 238251cf9a6SPekka Enberg ioport__write8(data, dev->rbr); 239369c01c0SPekka Enberg dev->lsr &= ~UART_LSR_DR; 240369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 24119a2bb7dSPekka Enberg return true; 2424e49b05bSCyrill Gorcunov case UART_IER: 243c6a69c61SPekka Enberg ioport__write8(data, dev->ier); 24419a2bb7dSPekka Enberg return true; 245369c01c0SPekka Enberg default: 246369c01c0SPekka Enberg break; 24719a2bb7dSPekka Enberg } 24819a2bb7dSPekka Enberg } 24919a2bb7dSPekka Enberg 25019a2bb7dSPekka Enberg switch (offset) { 251369c01c0SPekka Enberg case UART_IIR: { 252369c01c0SPekka Enberg uint8_t iir = dev->iir; 253369c01c0SPekka Enberg 254369c01c0SPekka Enberg if (dev->fcr & UART_FCR_ENABLE_FIFO) 255369c01c0SPekka Enberg iir |= 0xc0; 256369c01c0SPekka Enberg 257369c01c0SPekka Enberg ioport__write8(data, iir); 25846aa8d69SPekka Enberg break; 259369c01c0SPekka Enberg } 2604e49b05bSCyrill Gorcunov case UART_LCR: 261c6a69c61SPekka Enberg ioport__write8(data, dev->lcr); 26246aa8d69SPekka Enberg break; 2634e49b05bSCyrill Gorcunov case UART_MCR: 264c6a69c61SPekka Enberg ioport__write8(data, dev->mcr); 26546aa8d69SPekka Enberg break; 2664e49b05bSCyrill Gorcunov case UART_LSR: 267c6a69c61SPekka Enberg ioport__write8(data, dev->lsr); 268369c01c0SPekka Enberg dev->lsr &= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI); 26946aa8d69SPekka Enberg break; 2704e49b05bSCyrill Gorcunov case UART_MSR: 271369c01c0SPekka Enberg ioport__write8(data, dev->msr); 27246aa8d69SPekka Enberg break; 2734e49b05bSCyrill Gorcunov case UART_SCR: 274369c01c0SPekka Enberg ioport__write8(data, dev->scr); 27546aa8d69SPekka Enberg break; 276369c01c0SPekka Enberg default: 277369c01c0SPekka Enberg return false; 27825af6674SPekka Enberg } 27913a7760fSPekka Enberg return true; 28013a7760fSPekka Enberg } 28113a7760fSPekka Enberg 28246aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = { 28346aa8d69SPekka Enberg .io_in = serial8250_in, 28446aa8d69SPekka Enberg .io_out = serial8250_out, 285a93ec68bSPekka Enberg }; 286a93ec68bSPekka Enberg 287bc4b0ffeSPekka Enberg static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev) 288bc4b0ffeSPekka Enberg { 289bc4b0ffeSPekka Enberg ioport__register(dev->iobase, &serial8250_ops, 8); 290bc4b0ffeSPekka Enberg kvm__irq_line(kvm, dev->irq, 0); 291bc4b0ffeSPekka Enberg } 292bc4b0ffeSPekka Enberg 293bc4b0ffeSPekka Enberg void serial8250__init(struct kvm *kvm) 29413a7760fSPekka Enberg { 295c6a69c61SPekka Enberg unsigned int i; 296c6a69c61SPekka Enberg 297c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 298c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 299c6a69c61SPekka Enberg 300bc4b0ffeSPekka Enberg serial8250__device_init(kvm, dev); 301c6a69c61SPekka Enberg } 30213a7760fSPekka Enberg } 303