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 rbr; /* receive buffer */ 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 msr; 26 uint8_t scr; 27 }; 28 29 static struct serial8250_device devices[] = { 30 /* ttyS0 */ 31 [0] = { 32 .iobase = 0x3f8, 33 .irq = 4, 34 35 .lsr = UART_LSR_TEMT | UART_LSR_THRE, 36 .iir = UART_IIR_NO_INT, 37 }, 38 /* ttyS1 */ 39 [1] = { 40 .iobase = 0x2f8, 41 .irq = 3, 42 43 .iir = UART_IIR_NO_INT, 44 }, 45 /* ttyS2 */ 46 [2] = { 47 .iobase = 0x3e8, 48 .irq = 4, 49 50 .iir = UART_IIR_NO_INT, 51 }, 52 }; 53 54 static int read_char(int fd) 55 { 56 int c; 57 58 if (read(fd, &c, 1) < 0) 59 return -1; 60 61 return c; 62 } 63 64 static bool is_readable(int fd) 65 { 66 struct pollfd pollfd = (struct pollfd) { 67 .fd = fd, 68 .events = POLLIN, 69 }; 70 71 return poll(&pollfd, 1, 0) > 0; 72 } 73 74 static void serial8250__receive(struct kvm *self, struct serial8250_device *dev) 75 { 76 int c; 77 78 if (!is_readable(fileno(stdin))) 79 return; 80 81 c = read_char(fileno(stdin)); 82 if (c < 0) 83 return; 84 85 if (dev->lsr & UART_LSR_DR) 86 dev->lsr |= UART_LSR_OE; 87 88 dev->rbr = c; 89 dev->lsr |= UART_LSR_DR; 90 } 91 92 /* 93 * Interrupts are injected for ttyS0 only. 94 */ 95 void serial8250__interrupt(struct kvm *self) 96 { 97 struct serial8250_device *dev = &devices[0]; 98 99 serial8250__receive(self, dev); 100 101 if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR) 102 dev->iir = UART_IIR_RDI; 103 else if (dev->ier & UART_IER_THRI) 104 dev->iir = UART_IIR_THRI; 105 else 106 dev->iir = UART_IIR_NO_INT; 107 108 if (dev->iir != UART_IIR_NO_INT) { 109 kvm__irq_line(self, dev->irq, 0); 110 kvm__irq_line(self, dev->irq, 1); 111 } 112 } 113 114 static struct serial8250_device *find_device(uint16_t port) 115 { 116 unsigned int i; 117 118 for (i = 0; i < ARRAY_SIZE(devices); i++) { 119 struct serial8250_device *dev = &devices[i]; 120 121 if (dev->iobase == (port & ~0x7)) 122 return dev; 123 } 124 return NULL; 125 } 126 127 static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 128 { 129 struct serial8250_device *dev; 130 uint16_t offset; 131 132 dev = find_device(port); 133 if (!dev) 134 return false; 135 136 offset = port - dev->iobase; 137 138 if (dev->lcr & UART_LCR_DLAB) { 139 switch (offset) { 140 case UART_DLL: 141 dev->dll = ioport__read8(data); 142 break; 143 case UART_DLM: 144 dev->dlm = ioport__read8(data); 145 break; 146 case UART_FCR: 147 dev->fcr = ioport__read8(data); 148 break; 149 case UART_LCR: 150 dev->lcr = ioport__read8(data); 151 break; 152 case UART_MCR: 153 dev->mcr = ioport__read8(data); 154 break; 155 case UART_LSR: 156 /* Factory test */ 157 break; 158 case UART_MSR: 159 /* Not used */ 160 break; 161 case UART_SCR: 162 dev->scr = ioport__read8(data); 163 break; 164 default: 165 return false; 166 } 167 } else { 168 switch (offset) { 169 case UART_TX: { 170 char *p = data; 171 int i; 172 173 if (!(dev->mcr & UART_MCR_LOOP)) { 174 while (count--) { 175 for (i = 0; i < size; i++) 176 fprintf(stdout, "%c", *p++); 177 } 178 fflush(stdout); 179 } 180 dev->iir = UART_IIR_NO_INT; 181 break; 182 } 183 case UART_FCR: 184 dev->fcr = ioport__read8(data); 185 break; 186 case UART_IER: 187 dev->ier = ioport__read8(data) & 0x3f; 188 break; 189 case UART_LCR: 190 dev->lcr = ioport__read8(data); 191 break; 192 case UART_MCR: 193 dev->mcr = ioport__read8(data); 194 break; 195 case UART_LSR: 196 /* Factory test */ 197 break; 198 case UART_MSR: 199 /* Not used */ 200 break; 201 case UART_SCR: 202 dev->scr = ioport__read8(data); 203 break; 204 default: 205 return false; 206 } 207 } 208 return true; 209 } 210 211 static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 212 { 213 struct serial8250_device *dev; 214 uint16_t offset; 215 216 dev = find_device(port); 217 if (!dev) 218 return false; 219 220 offset = port - dev->iobase; 221 222 if (dev->lcr & UART_LCR_DLAB) { 223 switch (offset) { 224 case UART_DLL: 225 ioport__write8(data, dev->dll); 226 return true; 227 case UART_DLM: 228 ioport__write8(data, dev->dlm); 229 return true; 230 default: 231 break; 232 } 233 } else { 234 switch (offset) { 235 case UART_RX: 236 ioport__write8(data, dev->rbr); 237 dev->lsr &= ~UART_LSR_DR; 238 dev->iir = UART_IIR_NO_INT; 239 return true; 240 case UART_IER: 241 ioport__write8(data, dev->ier); 242 return true; 243 default: 244 break; 245 } 246 } 247 248 switch (offset) { 249 case UART_IIR: { 250 uint8_t iir = dev->iir; 251 252 if (dev->fcr & UART_FCR_ENABLE_FIFO) 253 iir |= 0xc0; 254 255 ioport__write8(data, iir); 256 break; 257 } 258 case UART_LCR: 259 ioport__write8(data, dev->lcr); 260 break; 261 case UART_MCR: 262 ioport__write8(data, dev->mcr); 263 break; 264 case UART_LSR: 265 ioport__write8(data, dev->lsr); 266 dev->lsr &= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI); 267 break; 268 case UART_MSR: 269 ioport__write8(data, dev->msr); 270 break; 271 case UART_SCR: 272 ioport__write8(data, dev->scr); 273 break; 274 default: 275 return false; 276 } 277 return true; 278 } 279 280 static struct ioport_operations serial8250_ops = { 281 .io_in = serial8250_in, 282 .io_out = serial8250_out, 283 }; 284 285 void serial8250__init(void) 286 { 287 unsigned int i; 288 289 for (i = 0; i < ARRAY_SIZE(devices); i++) { 290 struct serial8250_device *dev = &devices[i]; 291 292 ioport__register(dev->iobase, &serial8250_ops, 8); 293 } 294 } 295