xref: /kvmtool/hw/serial.c (revision 19a2bb7d9fb82f04536805719710667a606970ef)
1899fe063SPekka Enberg #include "kvm/8250-serial.h"
213a7760fSPekka Enberg 
313a7760fSPekka Enberg #include "kvm/ioport.h"
446aa8d69SPekka Enberg #include "kvm/util.h"
5e557eef9SPekka Enberg #include "kvm/kvm.h"
613a7760fSPekka Enberg 
74e49b05bSCyrill Gorcunov #include <linux/serial_reg.h>
84e49b05bSCyrill Gorcunov 
946aa8d69SPekka Enberg #include <stdbool.h>
1076b4a122SPekka Enberg #include <poll.h>
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;
2546aa8d69SPekka Enberg 	uint8_t			scr;
26133bedc1SPekka Enberg 
27133bedc1SPekka Enberg 	uint8_t			counter;
2846aa8d69SPekka Enberg };
2946aa8d69SPekka Enberg 
30e62c18deSPekka Enberg static struct serial8250_device devices[] = {
31c6a69c61SPekka Enberg 	/* ttyS0 */
32c6a69c61SPekka Enberg 	[0]	= {
33c6a69c61SPekka Enberg 		.iobase			= 0x3f8,
34e557eef9SPekka Enberg 		.irq			= 4,
35e557eef9SPekka Enberg 
366d620acbSCyrill Gorcunov 		.lsr			= UART_LSR_TEMT | UART_LSR_THRE,
37c6a69c61SPekka Enberg 	},
38e62c18deSPekka Enberg 	/* ttyS1 */
39e62c18deSPekka Enberg 	[1]	= {
40e62c18deSPekka Enberg 		.iobase			= 0x2f8,
41e62c18deSPekka Enberg 		.irq			= 3,
42133bedc1SPekka Enberg 
43133bedc1SPekka Enberg 		.iir			= UART_IIR_NO_INT,
44e62c18deSPekka Enberg 	},
45e62c18deSPekka Enberg 	/* ttyS2 */
46e62c18deSPekka Enberg 	[2]	= {
47e62c18deSPekka Enberg 		.iobase			= 0x3e8,
48e62c18deSPekka Enberg 		.irq			= 4,
49133bedc1SPekka Enberg 
50133bedc1SPekka Enberg 		.iir			= UART_IIR_NO_INT,
51e62c18deSPekka Enberg 	},
5246aa8d69SPekka Enberg };
5346aa8d69SPekka Enberg 
5476b4a122SPekka Enberg static int read_char(int fd)
5576b4a122SPekka Enberg {
5676b4a122SPekka Enberg 	int c;
5776b4a122SPekka Enberg 
5876b4a122SPekka Enberg 	if (read(fd, &c, 1) < 0)
5976b4a122SPekka Enberg 		return -1;
6076b4a122SPekka Enberg 
6176b4a122SPekka Enberg 	return c;
6276b4a122SPekka Enberg }
6376b4a122SPekka Enberg 
6476b4a122SPekka Enberg static bool is_readable(int fd)
6576b4a122SPekka Enberg {
666d54df74SCyrill Gorcunov 	struct pollfd pollfd = (struct pollfd) {
6776b4a122SPekka Enberg 		.fd	= fd,
6876b4a122SPekka Enberg 		.events	= POLLIN,
6976b4a122SPekka Enberg 	};
7076b4a122SPekka Enberg 
716d54df74SCyrill Gorcunov 	return poll(&pollfd, 1, 0) > 0;
7276b4a122SPekka Enberg }
7376b4a122SPekka Enberg 
74251cf9a6SPekka Enberg static void serial8250__receive(struct kvm *self, struct serial8250_device *dev)
75251cf9a6SPekka Enberg {
76251cf9a6SPekka Enberg 	int c;
77251cf9a6SPekka Enberg 
78251cf9a6SPekka Enberg 	if (dev->lsr & UART_LSR_DR)
79251cf9a6SPekka Enberg 		return;
80251cf9a6SPekka Enberg 
81251cf9a6SPekka Enberg 	if (!is_readable(fileno(stdin)))
82251cf9a6SPekka Enberg 		return;
83251cf9a6SPekka Enberg 
84251cf9a6SPekka Enberg 	c		= read_char(fileno(stdin));
85251cf9a6SPekka Enberg 	if (c < 0)
86251cf9a6SPekka Enberg 		return;
87251cf9a6SPekka Enberg 
88251cf9a6SPekka Enberg 	dev->rbr	= c;
89251cf9a6SPekka Enberg 	dev->lsr	|= UART_LSR_DR;
90251cf9a6SPekka Enberg }
91251cf9a6SPekka Enberg 
92c6a69c61SPekka Enberg /*
93c6a69c61SPekka Enberg  * Interrupts are injected for ttyS0 only.
94c6a69c61SPekka Enberg  */
958bb34e0dSPekka Enberg void serial8250__interrupt(struct kvm *self)
968bb34e0dSPekka Enberg {
97c6a69c61SPekka Enberg 	struct serial8250_device *dev = &devices[0];
98934c193bSPekka Enberg 	uint8_t new_iir;
99934c193bSPekka Enberg 
100c6a69c61SPekka Enberg 	dev->iir	= UART_IIR_NO_INT;
101934c193bSPekka Enberg 
102934c193bSPekka Enberg 	/* No interrupts enabled. Exit... */
103c6a69c61SPekka Enberg 	if (!(dev->ier & (UART_IER_THRI|UART_IER_RDI)))
104934c193bSPekka Enberg 		return;
105934c193bSPekka Enberg 
106251cf9a6SPekka Enberg 	serial8250__receive(self, dev);
107251cf9a6SPekka Enberg 
108934c193bSPekka Enberg 	new_iir		= 0;
109934c193bSPekka Enberg 
110251cf9a6SPekka Enberg 	if (dev->lsr & UART_LSR_DR)
111934c193bSPekka Enberg 		new_iir			|= UART_IIR_RDI;
112251cf9a6SPekka Enberg 	else if (dev->ier & UART_IER_THRI)
113251cf9a6SPekka Enberg 		new_iir			|= UART_IIR_THRI;
11476b4a122SPekka Enberg 
115934c193bSPekka Enberg 	/* Only send an IRQ if there's work to do. */
116934c193bSPekka Enberg 	if (new_iir) {
1170bc4cf78SPekka Enberg 		dev->counter		= 0;
118c6a69c61SPekka Enberg 		dev->iir		= new_iir;
119c6a69c61SPekka Enberg 		kvm__irq_line(self, dev->irq, 0);
120c6a69c61SPekka Enberg 		kvm__irq_line(self, dev->irq, 1);
121e557eef9SPekka Enberg 	}
1228bb34e0dSPekka Enberg }
1238bb34e0dSPekka Enberg 
124c6a69c61SPekka Enberg static struct serial8250_device *find_device(uint16_t port)
125c6a69c61SPekka Enberg {
126c6a69c61SPekka Enberg 	unsigned int i;
127c6a69c61SPekka Enberg 
128c6a69c61SPekka Enberg 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
129c6a69c61SPekka Enberg 		struct serial8250_device *dev = &devices[i];
130c6a69c61SPekka Enberg 
131c6a69c61SPekka Enberg 		if (dev->iobase == (port & ~0x7))
132c6a69c61SPekka Enberg 			return dev;
133c6a69c61SPekka Enberg 	}
134c6a69c61SPekka Enberg 	return NULL;
135c6a69c61SPekka Enberg }
136c6a69c61SPekka Enberg 
13746aa8d69SPekka Enberg static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
13813a7760fSPekka Enberg {
139c6a69c61SPekka Enberg 	struct serial8250_device *dev;
140c6a69c61SPekka Enberg 	uint16_t offset;
14146aa8d69SPekka Enberg 
142c6a69c61SPekka Enberg 	dev		= find_device(port);
143c6a69c61SPekka Enberg 	if (!dev)
144c6a69c61SPekka Enberg 		return false;
145c6a69c61SPekka Enberg 
146c6a69c61SPekka Enberg 	offset		= port - dev->iobase;
147c6a69c61SPekka Enberg 
148*19a2bb7dSPekka Enberg 	/* LSR is factory test and MSR is not used for writes */
149*19a2bb7dSPekka Enberg 	if (offset == UART_LSR || offset == UART_MSR)
150*19a2bb7dSPekka Enberg 		return true;
151*19a2bb7dSPekka Enberg 
152*19a2bb7dSPekka Enberg 	/* FCR, LCR, MCR, and SCR have the same meaning regardless of DLAB */
153*19a2bb7dSPekka Enberg 	switch (offset) {
154*19a2bb7dSPekka Enberg 	case UART_FCR:
155*19a2bb7dSPekka Enberg 		dev->fcr		= ioport__read8(data);
156*19a2bb7dSPekka Enberg 		return true;
157*19a2bb7dSPekka Enberg 	case UART_LCR:
158*19a2bb7dSPekka Enberg 		dev->lcr		= ioport__read8(data);
159*19a2bb7dSPekka Enberg 		return true;
160*19a2bb7dSPekka Enberg 	case UART_MCR:
161*19a2bb7dSPekka Enberg 		dev->mcr		= ioport__read8(data);
162*19a2bb7dSPekka Enberg 		return true;
163*19a2bb7dSPekka Enberg 	case UART_SCR:
164*19a2bb7dSPekka Enberg 		dev->scr		= ioport__read8(data);
165*19a2bb7dSPekka Enberg 		return true;
166*19a2bb7dSPekka Enberg 	default:
167*19a2bb7dSPekka Enberg 		break;
168*19a2bb7dSPekka Enberg 	}
169*19a2bb7dSPekka Enberg 
170c6a69c61SPekka Enberg 	if (dev->lcr & UART_LCR_DLAB) {
17146aa8d69SPekka Enberg 		switch (offset) {
1724e49b05bSCyrill Gorcunov 		case UART_DLL:
173c6a69c61SPekka Enberg 			dev->dll		= ioport__read8(data);
17446aa8d69SPekka Enberg 			break;
1754e49b05bSCyrill Gorcunov 		case UART_DLM:
176c6a69c61SPekka Enberg 			dev->dlm		= ioport__read8(data);
17746aa8d69SPekka Enberg 			break;
17846aa8d69SPekka Enberg 		}
17946aa8d69SPekka Enberg 	} else {
18046aa8d69SPekka Enberg 		switch (offset) {
1814e49b05bSCyrill Gorcunov 		case UART_TX: {
18213a7760fSPekka Enberg 			char *p = data;
183f2d8dc88SCyrill Gorcunov 			int i;
18413a7760fSPekka Enberg 
185f2d8dc88SCyrill Gorcunov 			while (count--) {
186f2d8dc88SCyrill Gorcunov 				for (i = 0; i < size; i++)
187b7475544SPekka Enberg 					fprintf(stdout, "%c", *p++);
1885b9d0b58SAsias He 			}
189b7475544SPekka Enberg 			fflush(stdout);
190e557eef9SPekka Enberg 
1910bc4cf78SPekka Enberg 			if (dev->counter++ > 10)
192133bedc1SPekka Enberg 				dev->iir		= UART_IIR_NO_INT;
193133bedc1SPekka Enberg 
19446aa8d69SPekka Enberg 			break;
19546aa8d69SPekka Enberg 		}
1964e49b05bSCyrill Gorcunov 		case UART_IER:
197c6a69c61SPekka Enberg 			dev->ier		= ioport__read8(data);
19846aa8d69SPekka Enberg 			break;
19946aa8d69SPekka Enberg 		}
20046aa8d69SPekka Enberg 	}
20113a7760fSPekka Enberg 
20213a7760fSPekka Enberg 	return true;
20313a7760fSPekka Enberg }
20413a7760fSPekka Enberg 
20546aa8d69SPekka Enberg static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
20625af6674SPekka Enberg {
207c6a69c61SPekka Enberg 	struct serial8250_device *dev;
208c6a69c61SPekka Enberg 	uint16_t offset;
20946aa8d69SPekka Enberg 
210c6a69c61SPekka Enberg 	dev		= find_device(port);
211c6a69c61SPekka Enberg 	if (!dev)
212c6a69c61SPekka Enberg 		return false;
213c6a69c61SPekka Enberg 
214c6a69c61SPekka Enberg 	offset		= port - dev->iobase;
215c6a69c61SPekka Enberg 
216*19a2bb7dSPekka Enberg 	/* DLAB only changes the meaning of the first two registers */
217*19a2bb7dSPekka Enberg 	if (dev->lcr & UART_LCR_DLAB) {
218*19a2bb7dSPekka Enberg 		switch (offset) {
219*19a2bb7dSPekka Enberg 		case UART_DLL:
220*19a2bb7dSPekka Enberg 			ioport__write8(data, dev->dll);
221*19a2bb7dSPekka Enberg 			return true;
222*19a2bb7dSPekka Enberg 		case UART_DLM:
223*19a2bb7dSPekka Enberg 			ioport__write8(data, dev->dlm);
224*19a2bb7dSPekka Enberg 			return true;
225*19a2bb7dSPekka Enberg 		}
226*19a2bb7dSPekka Enberg 	} else {
22746aa8d69SPekka Enberg 		switch (offset) {
228251cf9a6SPekka Enberg 		case UART_RX:
229c6a69c61SPekka Enberg 			if (dev->lsr & UART_LSR_DR) {
230133bedc1SPekka Enberg 				dev->iir		= UART_IIR_NO_INT;
231133bedc1SPekka Enberg 
232c6a69c61SPekka Enberg 				dev->lsr		&= ~UART_LSR_DR;
233251cf9a6SPekka Enberg 				ioport__write8(data, dev->rbr);
23476b4a122SPekka Enberg 			}
235*19a2bb7dSPekka Enberg 			return true;
2364e49b05bSCyrill Gorcunov 		case UART_IER:
237c6a69c61SPekka Enberg 			ioport__write8(data, dev->ier);
238*19a2bb7dSPekka Enberg 			return true;
239*19a2bb7dSPekka Enberg 		}
240*19a2bb7dSPekka Enberg 	}
241*19a2bb7dSPekka Enberg 
242*19a2bb7dSPekka Enberg 	/* All other registers have the same meaning regardless of DLAB */
243*19a2bb7dSPekka Enberg 	switch (offset) {
2444e49b05bSCyrill Gorcunov 	case UART_IIR:
245855a6371SCyrill Gorcunov 		dev->iir &= 0x3f; /* no FIFO for 8250 */
246c6a69c61SPekka Enberg 		ioport__write8(data, dev->iir);
24746aa8d69SPekka Enberg 		break;
2484e49b05bSCyrill Gorcunov 	case UART_LCR:
249c6a69c61SPekka Enberg 		ioport__write8(data, dev->lcr);
25046aa8d69SPekka Enberg 		break;
2514e49b05bSCyrill Gorcunov 	case UART_MCR:
252c6a69c61SPekka Enberg 		ioport__write8(data, dev->mcr);
25346aa8d69SPekka Enberg 		break;
2544e49b05bSCyrill Gorcunov 	case UART_LSR:
255c6a69c61SPekka Enberg 		ioport__write8(data, dev->lsr);
25646aa8d69SPekka Enberg 		break;
2574e49b05bSCyrill Gorcunov 	case UART_MSR:
2589a7428ddSPekka Enberg 		ioport__write8(data, UART_MSR_CTS);
25946aa8d69SPekka Enberg 		break;
2604e49b05bSCyrill Gorcunov 	case UART_SCR:
261855a6371SCyrill Gorcunov 		/* No SCR for 8250 */
262855a6371SCyrill Gorcunov 		ioport__write8(data, 0);
26346aa8d69SPekka Enberg 		break;
26425af6674SPekka Enberg 	}
26525af6674SPekka Enberg 
26613a7760fSPekka Enberg 	return true;
26713a7760fSPekka Enberg }
26813a7760fSPekka Enberg 
26946aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = {
27046aa8d69SPekka Enberg 	.io_in		= serial8250_in,
27146aa8d69SPekka Enberg 	.io_out		= serial8250_out,
272a93ec68bSPekka Enberg };
273a93ec68bSPekka Enberg 
274899fe063SPekka Enberg void serial8250__init(void)
27513a7760fSPekka Enberg {
276c6a69c61SPekka Enberg 	unsigned int i;
277c6a69c61SPekka Enberg 
278c6a69c61SPekka Enberg 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
279c6a69c61SPekka Enberg 		struct serial8250_device *dev = &devices[i];
280c6a69c61SPekka Enberg 
281c6a69c61SPekka Enberg 		ioport__register(dev->iobase, &serial8250_ops, 8);
282c6a69c61SPekka Enberg 	}
28313a7760fSPekka Enberg }
284