xref: /kvmtool/hw/serial.c (revision 0ea58e5bbc3775506d99a8d9e1c78c371426a6ac)
1899fe063SPekka Enberg #include "kvm/8250-serial.h"
213a7760fSPekka Enberg 
38eb47d29SSasha Levin #include "kvm/read-write.h"
413a7760fSPekka Enberg #include "kvm/ioport.h"
546aa8d69SPekka Enberg #include "kvm/util.h"
605d1a2a6SAsias He #include "kvm/term.h"
7e557eef9SPekka Enberg #include "kvm/kvm.h"
813a7760fSPekka Enberg 
94e49b05bSCyrill Gorcunov #include <linux/serial_reg.h>
104e49b05bSCyrill Gorcunov 
1113a7760fSPekka Enberg 
1246aa8d69SPekka Enberg struct serial8250_device {
1346aa8d69SPekka Enberg 	uint16_t		iobase;
14e557eef9SPekka Enberg 	uint8_t			irq;
1576b4a122SPekka Enberg 
16251cf9a6SPekka Enberg 	uint8_t			rbr;		/* receive buffer */
1746aa8d69SPekka Enberg 	uint8_t			dll;
1846aa8d69SPekka Enberg 	uint8_t			dlm;
19e557eef9SPekka Enberg 	uint8_t			iir;
2046aa8d69SPekka Enberg 	uint8_t			ier;
2146aa8d69SPekka Enberg 	uint8_t			fcr;
2246aa8d69SPekka Enberg 	uint8_t			lcr;
2346aa8d69SPekka Enberg 	uint8_t			mcr;
2476b4a122SPekka Enberg 	uint8_t			lsr;
25369c01c0SPekka Enberg 	uint8_t			msr;
2646aa8d69SPekka Enberg 	uint8_t			scr;
2746aa8d69SPekka Enberg };
2846aa8d69SPekka Enberg 
29e62c18deSPekka Enberg static struct serial8250_device devices[] = {
30c6a69c61SPekka Enberg 	/* ttyS0 */
31c6a69c61SPekka Enberg 	[0]	= {
32c6a69c61SPekka Enberg 		.iobase			= 0x3f8,
33e557eef9SPekka Enberg 		.irq			= 4,
34e557eef9SPekka Enberg 
35369c01c0SPekka Enberg 		.iir			= UART_IIR_NO_INT,
36bc4b0ffeSPekka Enberg 		.lsr			= UART_LSR_TEMT | UART_LSR_THRE,
37bc4b0ffeSPekka Enberg 		.msr			= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS,
38bc4b0ffeSPekka Enberg 		.mcr			= UART_MCR_OUT2,
39c6a69c61SPekka Enberg 	},
40e62c18deSPekka Enberg 	/* ttyS1 */
41e62c18deSPekka Enberg 	[1]	= {
42e62c18deSPekka Enberg 		.iobase			= 0x2f8,
43e62c18deSPekka Enberg 		.irq			= 3,
44133bedc1SPekka Enberg 
45133bedc1SPekka Enberg 		.iir			= UART_IIR_NO_INT,
46e62c18deSPekka Enberg 	},
47e62c18deSPekka Enberg 	/* ttyS2 */
48e62c18deSPekka Enberg 	[2]	= {
49e62c18deSPekka Enberg 		.iobase			= 0x3e8,
50e62c18deSPekka Enberg 		.irq			= 4,
51133bedc1SPekka Enberg 
52133bedc1SPekka Enberg 		.iir			= UART_IIR_NO_INT,
53e62c18deSPekka Enberg 	},
5446aa8d69SPekka Enberg };
5546aa8d69SPekka Enberg 
56a428f72eSPekka Enberg #define SYSRQ_PENDING_NONE		0
57a428f72eSPekka Enberg #define SYSRQ_PENDING_BREAK		1
58a428f72eSPekka Enberg #define SYSRQ_PENDING_CMD		2
59a428f72eSPekka Enberg 
60a428f72eSPekka Enberg static int sysrq_pending;
61a428f72eSPekka Enberg 
62a428f72eSPekka Enberg static void serial8250__sysrq(struct kvm *self, struct serial8250_device *dev)
63a428f72eSPekka Enberg {
64a428f72eSPekka Enberg 	switch (sysrq_pending) {
65a428f72eSPekka Enberg 	case SYSRQ_PENDING_BREAK:
66a428f72eSPekka Enberg 		dev->lsr	|= UART_LSR_DR | UART_LSR_BI;
67a428f72eSPekka Enberg 
68a428f72eSPekka Enberg 		sysrq_pending	= SYSRQ_PENDING_CMD;
69a428f72eSPekka Enberg 		break;
70a428f72eSPekka Enberg 	case SYSRQ_PENDING_CMD:
71a428f72eSPekka Enberg 		dev->rbr	= 'p';
72a428f72eSPekka Enberg 		dev->lsr	|= UART_LSR_DR;
73a428f72eSPekka Enberg 
74a428f72eSPekka Enberg 		sysrq_pending	= SYSRQ_PENDING_NONE;
75a428f72eSPekka Enberg 		break;
76a428f72eSPekka Enberg 	}
77a428f72eSPekka Enberg }
78a428f72eSPekka Enberg 
79251cf9a6SPekka Enberg static void serial8250__receive(struct kvm *self, struct serial8250_device *dev)
80251cf9a6SPekka Enberg {
81251cf9a6SPekka Enberg 	int c;
82251cf9a6SPekka Enberg 
83db34045cSPekka Enberg 	if (dev->lsr & UART_LSR_DR)
84db34045cSPekka Enberg 		return;
85db34045cSPekka Enberg 
86a428f72eSPekka Enberg 	if (sysrq_pending) {
87a428f72eSPekka Enberg 		serial8250__sysrq(self, dev);
88a428f72eSPekka Enberg 		return;
89a428f72eSPekka Enberg 	}
90a428f72eSPekka Enberg 
9105d1a2a6SAsias He 	if (!term_readable(CONSOLE_8250))
92251cf9a6SPekka Enberg 		return;
93251cf9a6SPekka Enberg 
9405d1a2a6SAsias He 	c		= term_getc(CONSOLE_8250);
9505d1a2a6SAsias He 
96251cf9a6SPekka Enberg 	if (c < 0)
97251cf9a6SPekka Enberg 		return;
98251cf9a6SPekka Enberg 
99251cf9a6SPekka Enberg 	dev->rbr	= c;
100251cf9a6SPekka Enberg 	dev->lsr	|= UART_LSR_DR;
101251cf9a6SPekka Enberg }
102251cf9a6SPekka Enberg 
103c6a69c61SPekka Enberg /*
104c6a69c61SPekka Enberg  * Interrupts are injected for ttyS0 only.
105c6a69c61SPekka Enberg  */
10605d1a2a6SAsias He void serial8250__inject_interrupt(struct kvm *self)
1078bb34e0dSPekka Enberg {
108c6a69c61SPekka Enberg 	struct serial8250_device *dev = &devices[0];
109934c193bSPekka Enberg 
110251cf9a6SPekka Enberg 	serial8250__receive(self, dev);
111251cf9a6SPekka Enberg 
112369c01c0SPekka Enberg 	if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR)
113369c01c0SPekka Enberg 		dev->iir		= UART_IIR_RDI;
114251cf9a6SPekka Enberg 	else if (dev->ier & UART_IER_THRI)
115369c01c0SPekka Enberg 		dev->iir		= UART_IIR_THRI;
116369c01c0SPekka Enberg 	else
117369c01c0SPekka Enberg 		dev->iir		= UART_IIR_NO_INT;
11876b4a122SPekka Enberg 
119369c01c0SPekka Enberg 	if (dev->iir != UART_IIR_NO_INT) {
120c6a69c61SPekka Enberg 		kvm__irq_line(self, dev->irq, 0);
121c6a69c61SPekka Enberg 		kvm__irq_line(self, dev->irq, 1);
122e557eef9SPekka Enberg 	}
1238bb34e0dSPekka Enberg }
1248bb34e0dSPekka Enberg 
125a428f72eSPekka Enberg void serial8250__inject_sysrq(struct kvm *self)
126a428f72eSPekka Enberg {
127a428f72eSPekka Enberg 	sysrq_pending	= SYSRQ_PENDING_BREAK;
128a428f72eSPekka Enberg }
129a428f72eSPekka Enberg 
130c6a69c61SPekka Enberg static struct serial8250_device *find_device(uint16_t port)
131c6a69c61SPekka Enberg {
132c6a69c61SPekka Enberg 	unsigned int i;
133c6a69c61SPekka Enberg 
134c6a69c61SPekka Enberg 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
135c6a69c61SPekka Enberg 		struct serial8250_device *dev = &devices[i];
136c6a69c61SPekka Enberg 
137c6a69c61SPekka Enberg 		if (dev->iobase == (port & ~0x7))
138c6a69c61SPekka Enberg 			return dev;
139c6a69c61SPekka Enberg 	}
140c6a69c61SPekka Enberg 	return NULL;
141c6a69c61SPekka Enberg }
142c6a69c61SPekka Enberg 
14346aa8d69SPekka Enberg static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
14413a7760fSPekka Enberg {
145c6a69c61SPekka Enberg 	struct serial8250_device *dev;
146c6a69c61SPekka Enberg 	uint16_t offset;
14746aa8d69SPekka Enberg 
148c6a69c61SPekka Enberg 	dev		= find_device(port);
149c6a69c61SPekka Enberg 	if (!dev)
150c6a69c61SPekka Enberg 		return false;
151c6a69c61SPekka Enberg 
152c6a69c61SPekka Enberg 	offset		= port - dev->iobase;
153c6a69c61SPekka Enberg 
154c6a69c61SPekka Enberg 	if (dev->lcr & UART_LCR_DLAB) {
15546aa8d69SPekka Enberg 		switch (offset) {
1564e49b05bSCyrill Gorcunov 		case UART_DLL:
157c6a69c61SPekka Enberg 			dev->dll	= ioport__read8(data);
15846aa8d69SPekka Enberg 			break;
1594e49b05bSCyrill Gorcunov 		case UART_DLM:
160c6a69c61SPekka Enberg 			dev->dlm	= ioport__read8(data);
16146aa8d69SPekka Enberg 			break;
162369c01c0SPekka Enberg 		case UART_FCR:
163369c01c0SPekka Enberg 			dev->fcr	= ioport__read8(data);
164369c01c0SPekka Enberg 			break;
165369c01c0SPekka Enberg 		case UART_LCR:
166369c01c0SPekka Enberg 			dev->lcr	= ioport__read8(data);
167369c01c0SPekka Enberg 			break;
168369c01c0SPekka Enberg 		case UART_MCR:
169369c01c0SPekka Enberg 			dev->mcr	= ioport__read8(data);
170369c01c0SPekka Enberg 			break;
171369c01c0SPekka Enberg 		case UART_LSR:
172369c01c0SPekka Enberg 			/* Factory test */
173369c01c0SPekka Enberg 			break;
174369c01c0SPekka Enberg 		case UART_MSR:
175369c01c0SPekka Enberg 			/* Not used */
176369c01c0SPekka Enberg 			break;
177369c01c0SPekka Enberg 		case UART_SCR:
178369c01c0SPekka Enberg 			dev->scr	= ioport__read8(data);
179369c01c0SPekka Enberg 			break;
180369c01c0SPekka Enberg 		default:
181369c01c0SPekka Enberg 			return false;
18246aa8d69SPekka Enberg 		}
18346aa8d69SPekka Enberg 	} else {
18446aa8d69SPekka Enberg 		switch (offset) {
1854e49b05bSCyrill Gorcunov 		case UART_TX: {
18605d1a2a6SAsias He 			char *addr = data;
187*0ea58e5bSPekka Enberg 
188*0ea58e5bSPekka Enberg 			if (!(dev->mcr & UART_MCR_LOOP))
18905d1a2a6SAsias He 				term_putc(CONSOLE_8250, addr, size * count);
190*0ea58e5bSPekka Enberg 
191133bedc1SPekka Enberg 			dev->iir		= UART_IIR_NO_INT;
19246aa8d69SPekka Enberg 			break;
19346aa8d69SPekka Enberg 		}
194369c01c0SPekka Enberg 		case UART_FCR:
195369c01c0SPekka Enberg 			dev->fcr	= ioport__read8(data);
196369c01c0SPekka Enberg 			break;
1974e49b05bSCyrill Gorcunov 		case UART_IER:
198369c01c0SPekka Enberg 			dev->ier	= ioport__read8(data) & 0x3f;
19946aa8d69SPekka Enberg 			break;
200369c01c0SPekka Enberg 		case UART_LCR:
201369c01c0SPekka Enberg 			dev->lcr	= ioport__read8(data);
202369c01c0SPekka Enberg 			break;
203369c01c0SPekka Enberg 		case UART_MCR:
204369c01c0SPekka Enberg 			dev->mcr	= ioport__read8(data);
205369c01c0SPekka Enberg 			break;
206369c01c0SPekka Enberg 		case UART_LSR:
207369c01c0SPekka Enberg 			/* Factory test */
208369c01c0SPekka Enberg 			break;
209369c01c0SPekka Enberg 		case UART_MSR:
210369c01c0SPekka Enberg 			/* Not used */
211369c01c0SPekka Enberg 			break;
212369c01c0SPekka Enberg 		case UART_SCR:
213369c01c0SPekka Enberg 			dev->scr	= ioport__read8(data);
214369c01c0SPekka Enberg 			break;
215369c01c0SPekka Enberg 		default:
216369c01c0SPekka Enberg 			return false;
21746aa8d69SPekka Enberg 		}
21846aa8d69SPekka Enberg 	}
21913a7760fSPekka Enberg 	return true;
22013a7760fSPekka Enberg }
22113a7760fSPekka Enberg 
22246aa8d69SPekka Enberg static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
22325af6674SPekka Enberg {
224c6a69c61SPekka Enberg 	struct serial8250_device *dev;
225c6a69c61SPekka Enberg 	uint16_t offset;
22646aa8d69SPekka Enberg 
227c6a69c61SPekka Enberg 	dev		= find_device(port);
228c6a69c61SPekka Enberg 	if (!dev)
229c6a69c61SPekka Enberg 		return false;
230c6a69c61SPekka Enberg 
231c6a69c61SPekka Enberg 	offset		= port - dev->iobase;
232c6a69c61SPekka Enberg 
23319a2bb7dSPekka Enberg 	if (dev->lcr & UART_LCR_DLAB) {
23419a2bb7dSPekka Enberg 		switch (offset) {
23519a2bb7dSPekka Enberg 		case UART_DLL:
23619a2bb7dSPekka Enberg 			ioport__write8(data, dev->dll);
23719a2bb7dSPekka Enberg 			return true;
23819a2bb7dSPekka Enberg 		case UART_DLM:
23919a2bb7dSPekka Enberg 			ioport__write8(data, dev->dlm);
24019a2bb7dSPekka Enberg 			return true;
241369c01c0SPekka Enberg 		default:
242369c01c0SPekka Enberg 			break;
24319a2bb7dSPekka Enberg 		}
24419a2bb7dSPekka Enberg 	} else {
24546aa8d69SPekka Enberg 		switch (offset) {
246251cf9a6SPekka Enberg 		case UART_RX:
247251cf9a6SPekka Enberg 			ioport__write8(data, dev->rbr);
248369c01c0SPekka Enberg 			dev->lsr		&= ~UART_LSR_DR;
249369c01c0SPekka Enberg 			dev->iir		= UART_IIR_NO_INT;
25019a2bb7dSPekka Enberg 			return true;
2514e49b05bSCyrill Gorcunov 		case UART_IER:
252c6a69c61SPekka Enberg 			ioport__write8(data, dev->ier);
25319a2bb7dSPekka Enberg 			return true;
254369c01c0SPekka Enberg 		default:
255369c01c0SPekka Enberg 			break;
25619a2bb7dSPekka Enberg 		}
25719a2bb7dSPekka Enberg 	}
25819a2bb7dSPekka Enberg 
25919a2bb7dSPekka Enberg 	switch (offset) {
260369c01c0SPekka Enberg 	case UART_IIR: {
261369c01c0SPekka Enberg 		uint8_t iir = dev->iir;
262369c01c0SPekka Enberg 
263369c01c0SPekka Enberg 		if (dev->fcr & UART_FCR_ENABLE_FIFO)
264369c01c0SPekka Enberg 			iir		|= 0xc0;
265369c01c0SPekka Enberg 
266369c01c0SPekka Enberg 		ioport__write8(data, iir);
26746aa8d69SPekka Enberg 		break;
268369c01c0SPekka Enberg 	}
2694e49b05bSCyrill Gorcunov 	case UART_LCR:
270c6a69c61SPekka Enberg 		ioport__write8(data, dev->lcr);
27146aa8d69SPekka Enberg 		break;
2724e49b05bSCyrill Gorcunov 	case UART_MCR:
273c6a69c61SPekka Enberg 		ioport__write8(data, dev->mcr);
27446aa8d69SPekka Enberg 		break;
2754e49b05bSCyrill Gorcunov 	case UART_LSR:
276c6a69c61SPekka Enberg 		ioport__write8(data, dev->lsr);
277369c01c0SPekka Enberg 		dev->lsr		&= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI);
27846aa8d69SPekka Enberg 		break;
2794e49b05bSCyrill Gorcunov 	case UART_MSR:
280369c01c0SPekka Enberg 		ioport__write8(data, dev->msr);
28146aa8d69SPekka Enberg 		break;
2824e49b05bSCyrill Gorcunov 	case UART_SCR:
283369c01c0SPekka Enberg 		ioport__write8(data, dev->scr);
28446aa8d69SPekka Enberg 		break;
285369c01c0SPekka Enberg 	default:
286369c01c0SPekka Enberg 		return false;
28725af6674SPekka Enberg 	}
28813a7760fSPekka Enberg 	return true;
28913a7760fSPekka Enberg }
29013a7760fSPekka Enberg 
29146aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = {
29246aa8d69SPekka Enberg 	.io_in		= serial8250_in,
29346aa8d69SPekka Enberg 	.io_out		= serial8250_out,
294a93ec68bSPekka Enberg };
295a93ec68bSPekka Enberg 
296bc4b0ffeSPekka Enberg static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev)
297bc4b0ffeSPekka Enberg {
298bc4b0ffeSPekka Enberg 	ioport__register(dev->iobase, &serial8250_ops, 8);
299bc4b0ffeSPekka Enberg 	kvm__irq_line(kvm, dev->irq, 0);
300bc4b0ffeSPekka Enberg }
301bc4b0ffeSPekka Enberg 
302bc4b0ffeSPekka Enberg void serial8250__init(struct kvm *kvm)
30313a7760fSPekka Enberg {
304c6a69c61SPekka Enberg 	unsigned int i;
305c6a69c61SPekka Enberg 
306c6a69c61SPekka Enberg 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
307c6a69c61SPekka Enberg 		struct serial8250_device *dev = &devices[i];
308c6a69c61SPekka Enberg 
309bc4b0ffeSPekka Enberg 		serial8250__device_init(kvm, dev);
310c6a69c61SPekka Enberg 	}
31113a7760fSPekka Enberg }
312