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