1 #include "kvm/8250-serial.h" 2 3 #include "kvm/ioport.h" 4 #include "kvm/util.h" 5 #include "kvm/kvm.h" 6 7 #include <linux/serial_reg.h> 8 9 #include <stdbool.h> 10 #include <poll.h> 11 12 struct serial8250_device { 13 uint16_t iobase; 14 uint8_t irq; 15 16 uint8_t thr; 17 uint8_t dll; 18 uint8_t dlm; 19 uint8_t iir; 20 uint8_t ier; 21 uint8_t fcr; 22 uint8_t lcr; 23 uint8_t mcr; 24 uint8_t lsr; 25 uint8_t scr; 26 }; 27 28 static struct serial8250_device devices[1] = { 29 /* ttyS0 */ 30 [0] = { 31 .iobase = 0x3f8, 32 .irq = 4, 33 34 .lsr = UART_LSR_TEMT | UART_LSR_THRE, 35 }, 36 }; 37 38 static int read_char(int fd) 39 { 40 int c; 41 42 if (read(fd, &c, 1) < 0) 43 return -1; 44 45 return c; 46 } 47 48 static bool is_readable(int fd) 49 { 50 struct pollfd pollfd = (struct pollfd) { 51 .fd = fd, 52 .events = POLLIN, 53 }; 54 55 return poll(&pollfd, 1, 0) > 0; 56 } 57 58 /* 59 * Interrupts are injected for ttyS0 only. 60 */ 61 void serial8250__interrupt(struct kvm *self) 62 { 63 struct serial8250_device *dev = &devices[0]; 64 uint8_t new_iir; 65 66 dev->iir = UART_IIR_NO_INT; 67 68 /* No interrupts enabled. Exit... */ 69 if (!(dev->ier & (UART_IER_THRI|UART_IER_RDI))) 70 return; 71 72 new_iir = 0; 73 74 /* We're always good for guest sending data. */ 75 if (dev->ier & UART_IER_THRI) 76 new_iir |= UART_IIR_THRI; 77 78 /* Is there input in stdin to send to the guest? */ 79 if (!(dev->lsr & UART_LSR_DR) && is_readable(fileno(stdin))) { 80 int c; 81 82 c = read_char(fileno(stdin)); 83 if (c >= 0) { 84 dev->thr = c; 85 dev->lsr |= UART_LSR_DR; 86 new_iir |= UART_IIR_RDI; 87 } 88 } 89 90 /* Only send an IRQ if there's work to do. */ 91 if (new_iir) { 92 dev->iir = new_iir; 93 kvm__irq_line(self, dev->irq, 0); 94 kvm__irq_line(self, dev->irq, 1); 95 } 96 } 97 98 static struct serial8250_device *find_device(uint16_t port) 99 { 100 unsigned int i; 101 102 for (i = 0; i < ARRAY_SIZE(devices); i++) { 103 struct serial8250_device *dev = &devices[i]; 104 105 if (dev->iobase == (port & ~0x7)) 106 return dev; 107 } 108 return NULL; 109 } 110 111 static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 112 { 113 struct serial8250_device *dev; 114 uint16_t offset; 115 116 dev = find_device(port); 117 if (!dev) 118 return false; 119 120 offset = port - dev->iobase; 121 122 if (dev->lcr & UART_LCR_DLAB) { 123 switch (offset) { 124 case UART_DLL: 125 dev->dll = ioport__read8(data); 126 break; 127 case UART_DLM: 128 dev->dlm = ioport__read8(data); 129 break; 130 case UART_FCR: 131 dev->fcr = ioport__read8(data); 132 break; 133 case UART_LCR: 134 dev->lcr = ioport__read8(data); 135 break; 136 default: 137 return false; 138 } 139 } else { 140 switch (offset) { 141 case UART_TX: { 142 char *p = data; 143 int i; 144 145 while (count--) { 146 for (i = 0; i < size; i++) 147 fprintf(stdout, "%c", *p++); 148 } 149 fflush(stdout); 150 151 break; 152 } 153 case UART_IER: 154 dev->ier = ioport__read8(data); 155 break; 156 case UART_FCR: 157 dev->fcr = ioport__read8(data); 158 break; 159 case UART_LCR: 160 dev->lcr = ioport__read8(data); 161 break; 162 case UART_MCR: 163 dev->mcr = ioport__read8(data); 164 break; 165 case UART_SCR: 166 dev->scr = ioport__read8(data); 167 break; 168 default: 169 return false; 170 } 171 } 172 173 return true; 174 } 175 176 static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 177 { 178 struct serial8250_device *dev; 179 uint16_t offset; 180 181 dev = find_device(port); 182 if (!dev) 183 return false; 184 185 offset = port - dev->iobase; 186 187 if (dev->lcr & UART_LCR_DLAB) 188 return false; 189 190 switch (offset) { 191 case UART_TX: 192 if (dev->lsr & UART_LSR_DR) { 193 dev->lsr &= ~UART_LSR_DR; 194 ioport__write8(data, dev->thr); 195 } 196 break; 197 case UART_IER: 198 ioport__write8(data, dev->ier); 199 break; 200 case UART_IIR: 201 ioport__write8(data, dev->iir); 202 break; 203 case UART_LCR: 204 ioport__write8(data, dev->lcr); 205 break; 206 case UART_MCR: 207 ioport__write8(data, dev->mcr); 208 break; 209 case UART_LSR: 210 ioport__write8(data, dev->lsr); 211 break; 212 case UART_MSR: 213 ioport__write8(data, UART_MSR_CTS); 214 break; 215 case UART_SCR: 216 ioport__write8(data, dev->scr); 217 break; 218 default: 219 return false; 220 } 221 222 return true; 223 } 224 225 static struct ioport_operations serial8250_ops = { 226 .io_in = serial8250_in, 227 .io_out = serial8250_out, 228 }; 229 230 void serial8250__init(void) 231 { 232 unsigned int i; 233 234 for (i = 0; i < ARRAY_SIZE(devices); i++) { 235 struct serial8250_device *dev = &devices[i]; 236 237 ioport__register(dev->iobase, &serial8250_ops, 8); 238 } 239 } 240