xref: /kvmtool/hw/serial.c (revision 4ef0f4d620fa5df6d61ff6d4fff7f03680c7e73e)
1 #include "kvm/8250-serial.h"
2 
3 #include "kvm/read-write.h"
4 #include "kvm/ioport.h"
5 #include "kvm/mutex.h"
6 #include "kvm/util.h"
7 #include "kvm/term.h"
8 #include "kvm/kvm.h"
9 
10 #include <linux/serial_reg.h>
11 
12 #include <pthread.h>
13 
14 struct serial8250_device {
15 	pthread_mutex_t		mutex;
16 
17 	uint16_t		iobase;
18 	uint8_t			irq;
19 
20 	uint8_t			rbr;		/* receive buffer */
21 	uint8_t			dll;
22 	uint8_t			dlm;
23 	uint8_t			iir;
24 	uint8_t			ier;
25 	uint8_t			fcr;
26 	uint8_t			lcr;
27 	uint8_t			mcr;
28 	uint8_t			lsr;
29 	uint8_t			msr;
30 	uint8_t			scr;
31 };
32 
33 static struct serial8250_device devices[] = {
34 	/* ttyS0 */
35 	[0]	= {
36 		.mutex			= PTHREAD_MUTEX_INITIALIZER,
37 
38 		.iobase			= 0x3f8,
39 		.irq			= 4,
40 
41 		.iir			= UART_IIR_NO_INT,
42 		.lsr			= UART_LSR_TEMT | UART_LSR_THRE,
43 		.msr			= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS,
44 		.mcr			= UART_MCR_OUT2,
45 	},
46 	/* ttyS1 */
47 	[1]	= {
48 		.mutex			= PTHREAD_MUTEX_INITIALIZER,
49 
50 		.iobase			= 0x2f8,
51 		.irq			= 3,
52 
53 		.iir			= UART_IIR_NO_INT,
54 	},
55 	/* ttyS2 */
56 	[2]	= {
57 		.mutex			= PTHREAD_MUTEX_INITIALIZER,
58 
59 		.iobase			= 0x3e8,
60 		.irq			= 4,
61 
62 		.iir			= UART_IIR_NO_INT,
63 	},
64 };
65 
66 #define SYSRQ_PENDING_NONE		0
67 #define SYSRQ_PENDING_BREAK		1
68 #define SYSRQ_PENDING_CMD		2
69 
70 static int sysrq_pending;
71 
72 static void serial8250__sysrq(struct kvm *self, struct serial8250_device *dev)
73 {
74 	switch (sysrq_pending) {
75 	case SYSRQ_PENDING_BREAK:
76 		dev->lsr	|= UART_LSR_DR | UART_LSR_BI;
77 
78 		sysrq_pending	= SYSRQ_PENDING_CMD;
79 		break;
80 	case SYSRQ_PENDING_CMD:
81 		dev->rbr	= 'p';
82 		dev->lsr	|= UART_LSR_DR;
83 
84 		sysrq_pending	= SYSRQ_PENDING_NONE;
85 		break;
86 	}
87 }
88 
89 static void serial8250__receive(struct kvm *self, struct serial8250_device *dev)
90 {
91 	int c;
92 
93 	if (dev->lsr & UART_LSR_DR)
94 		return;
95 
96 	if (sysrq_pending) {
97 		serial8250__sysrq(self, dev);
98 		return;
99 	}
100 
101 	if (!term_readable(CONSOLE_8250))
102 		return;
103 
104 	c		= term_getc(CONSOLE_8250);
105 
106 	if (c < 0)
107 		return;
108 
109 	dev->rbr	= c;
110 	dev->lsr	|= UART_LSR_DR;
111 }
112 
113 /*
114  * Interrupts are injected for ttyS0 only.
115  */
116 void serial8250__inject_interrupt(struct kvm *self)
117 {
118 	struct serial8250_device *dev = &devices[0];
119 
120 	mutex_lock(&dev->mutex);
121 
122 	serial8250__receive(self, dev);
123 
124 	if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR)
125 		dev->iir		= UART_IIR_RDI;
126 	else if (dev->ier & UART_IER_THRI)
127 		dev->iir		= UART_IIR_THRI;
128 	else
129 		dev->iir		= UART_IIR_NO_INT;
130 
131 	if (dev->iir != UART_IIR_NO_INT) {
132 		kvm__irq_line(self, dev->irq, 0);
133 		kvm__irq_line(self, dev->irq, 1);
134 	}
135 
136 	mutex_unlock(&dev->mutex);
137 }
138 
139 void serial8250__inject_sysrq(struct kvm *self)
140 {
141 	sysrq_pending	= SYSRQ_PENDING_BREAK;
142 }
143 
144 static struct serial8250_device *find_device(uint16_t port)
145 {
146 	unsigned int i;
147 
148 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
149 		struct serial8250_device *dev = &devices[i];
150 
151 		if (dev->iobase == (port & ~0x7))
152 			return dev;
153 	}
154 	return NULL;
155 }
156 
157 static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
158 {
159 	struct serial8250_device *dev;
160 	uint16_t offset;
161 	bool ret = true;
162 
163 	dev		= find_device(port);
164 	if (!dev)
165 		return false;
166 
167 	mutex_lock(&dev->mutex);
168 
169 	offset		= port - dev->iobase;
170 
171 	if (dev->lcr & UART_LCR_DLAB) {
172 		switch (offset) {
173 		case UART_DLL:
174 			dev->dll	= ioport__read8(data);
175 			break;
176 		case UART_DLM:
177 			dev->dlm	= ioport__read8(data);
178 			break;
179 		case UART_FCR:
180 			dev->fcr	= ioport__read8(data);
181 			break;
182 		case UART_LCR:
183 			dev->lcr	= ioport__read8(data);
184 			break;
185 		case UART_MCR:
186 			dev->mcr	= ioport__read8(data);
187 			break;
188 		case UART_LSR:
189 			/* Factory test */
190 			break;
191 		case UART_MSR:
192 			/* Not used */
193 			break;
194 		case UART_SCR:
195 			dev->scr	= ioport__read8(data);
196 			break;
197 		default:
198 			ret		= false;
199 			goto out_unlock;
200 		}
201 	} else {
202 		switch (offset) {
203 		case UART_TX: {
204 			char *addr = data;
205 
206 			if (!(dev->mcr & UART_MCR_LOOP))
207 				term_putc(CONSOLE_8250, addr, size * count);
208 
209 			dev->iir		= UART_IIR_NO_INT;
210 			break;
211 		}
212 		case UART_FCR:
213 			dev->fcr	= ioport__read8(data);
214 			break;
215 		case UART_IER:
216 			dev->ier	= ioport__read8(data) & 0x3f;
217 			break;
218 		case UART_LCR:
219 			dev->lcr	= ioport__read8(data);
220 			break;
221 		case UART_MCR:
222 			dev->mcr	= ioport__read8(data);
223 			break;
224 		case UART_LSR:
225 			/* Factory test */
226 			break;
227 		case UART_MSR:
228 			/* Not used */
229 			break;
230 		case UART_SCR:
231 			dev->scr	= ioport__read8(data);
232 			break;
233 		default:
234 			ret		= false;
235 			goto out_unlock;
236 		}
237 	}
238 
239 out_unlock:
240 	mutex_unlock(&dev->mutex);
241 
242 	return ret;
243 }
244 
245 static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
246 {
247 	struct serial8250_device *dev;
248 	uint16_t offset;
249 	bool ret = true;
250 
251 	dev		= find_device(port);
252 	if (!dev)
253 		return false;
254 
255 	mutex_lock(&dev->mutex);
256 
257 	offset		= port - dev->iobase;
258 
259 	if (dev->lcr & UART_LCR_DLAB) {
260 		switch (offset) {
261 		case UART_DLL:
262 			ioport__write8(data, dev->dll);
263 			goto out_unlock;
264 
265 		case UART_DLM:
266 			ioport__write8(data, dev->dlm);
267 			goto out_unlock;
268 
269 		default:
270 			break;
271 		}
272 	} else {
273 		switch (offset) {
274 		case UART_RX:
275 			ioport__write8(data, dev->rbr);
276 			dev->lsr		&= ~UART_LSR_DR;
277 			dev->iir		= UART_IIR_NO_INT;
278 			goto out_unlock;
279 
280 		case UART_IER:
281 			ioport__write8(data, dev->ier);
282 			goto out_unlock;
283 
284 		default:
285 			break;
286 		}
287 	}
288 
289 	switch (offset) {
290 	case UART_IIR: {
291 		uint8_t iir = dev->iir;
292 
293 		if (dev->fcr & UART_FCR_ENABLE_FIFO)
294 			iir		|= 0xc0;
295 
296 		ioport__write8(data, iir);
297 		break;
298 	}
299 	case UART_LCR:
300 		ioport__write8(data, dev->lcr);
301 		break;
302 	case UART_MCR:
303 		ioport__write8(data, dev->mcr);
304 		break;
305 	case UART_LSR:
306 		ioport__write8(data, dev->lsr);
307 		dev->lsr		&= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI);
308 		break;
309 	case UART_MSR:
310 		ioport__write8(data, dev->msr);
311 		break;
312 	case UART_SCR:
313 		ioport__write8(data, dev->scr);
314 		break;
315 	default:
316 		ret		= false;
317 		goto out_unlock;
318 	}
319 out_unlock:
320 	mutex_unlock(&dev->mutex);
321 
322 	return ret;
323 }
324 
325 static struct ioport_operations serial8250_ops = {
326 	.io_in		= serial8250_in,
327 	.io_out		= serial8250_out,
328 };
329 
330 static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev)
331 {
332 	ioport__register(dev->iobase, &serial8250_ops, 8);
333 	kvm__irq_line(kvm, dev->irq, 0);
334 }
335 
336 void serial8250__init(struct kvm *kvm)
337 {
338 	unsigned int i;
339 
340 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
341 		struct serial8250_device *dev = &devices[i];
342 
343 		serial8250__device_init(kvm, dev);
344 	}
345 }
346