xref: /kvmtool/hw/serial.c (revision 369c01c0e76cc5b78578ec8bd5c923fa0a800238)
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