xref: /kvmtool/hw/serial.c (revision db34045c543bc4fa5b801f8aa4339e2c1e1ba1a6)
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;
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 
5676b4a122SPekka Enberg static int read_char(int fd)
5776b4a122SPekka Enberg {
5876b4a122SPekka Enberg 	int c;
5976b4a122SPekka Enberg 
6076b4a122SPekka Enberg 	if (read(fd, &c, 1) < 0)
6176b4a122SPekka Enberg 		return -1;
6276b4a122SPekka Enberg 
6376b4a122SPekka Enberg 	return c;
6476b4a122SPekka Enberg }
6576b4a122SPekka Enberg 
6676b4a122SPekka Enberg static bool is_readable(int fd)
6776b4a122SPekka Enberg {
686d54df74SCyrill Gorcunov 	struct pollfd pollfd = (struct pollfd) {
6976b4a122SPekka Enberg 		.fd	= fd,
7076b4a122SPekka Enberg 		.events	= POLLIN,
7176b4a122SPekka Enberg 	};
7276b4a122SPekka Enberg 
736d54df74SCyrill Gorcunov 	return poll(&pollfd, 1, 0) > 0;
7476b4a122SPekka Enberg }
7576b4a122SPekka Enberg 
76251cf9a6SPekka Enberg static void serial8250__receive(struct kvm *self, struct serial8250_device *dev)
77251cf9a6SPekka Enberg {
78251cf9a6SPekka Enberg 	int c;
79251cf9a6SPekka Enberg 
80*db34045cSPekka Enberg 	if (dev->lsr & UART_LSR_DR)
81*db34045cSPekka Enberg 		return;
82*db34045cSPekka Enberg 
83251cf9a6SPekka Enberg 	if (!is_readable(fileno(stdin)))
84251cf9a6SPekka Enberg 		return;
85251cf9a6SPekka Enberg 
86251cf9a6SPekka Enberg 	c		= read_char(fileno(stdin));
87251cf9a6SPekka Enberg 	if (c < 0)
88251cf9a6SPekka Enberg 		return;
89251cf9a6SPekka Enberg 
90251cf9a6SPekka Enberg 	dev->rbr	= c;
91251cf9a6SPekka Enberg 	dev->lsr	|= UART_LSR_DR;
92251cf9a6SPekka Enberg }
93251cf9a6SPekka Enberg 
94c6a69c61SPekka Enberg /*
95c6a69c61SPekka Enberg  * Interrupts are injected for ttyS0 only.
96c6a69c61SPekka Enberg  */
978bb34e0dSPekka Enberg void serial8250__interrupt(struct kvm *self)
988bb34e0dSPekka Enberg {
99c6a69c61SPekka Enberg 	struct serial8250_device *dev = &devices[0];
100934c193bSPekka Enberg 
101251cf9a6SPekka Enberg 	serial8250__receive(self, dev);
102251cf9a6SPekka Enberg 
103369c01c0SPekka Enberg 	if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR)
104369c01c0SPekka Enberg 		dev->iir		= UART_IIR_RDI;
105251cf9a6SPekka Enberg 	else if (dev->ier & UART_IER_THRI)
106369c01c0SPekka Enberg 		dev->iir		= UART_IIR_THRI;
107369c01c0SPekka Enberg 	else
108369c01c0SPekka Enberg 		dev->iir		= UART_IIR_NO_INT;
10976b4a122SPekka Enberg 
110369c01c0SPekka Enberg 	if (dev->iir != UART_IIR_NO_INT) {
111c6a69c61SPekka Enberg 		kvm__irq_line(self, dev->irq, 0);
112c6a69c61SPekka Enberg 		kvm__irq_line(self, dev->irq, 1);
113e557eef9SPekka Enberg 	}
1148bb34e0dSPekka Enberg }
1158bb34e0dSPekka Enberg 
116c6a69c61SPekka Enberg static struct serial8250_device *find_device(uint16_t port)
117c6a69c61SPekka Enberg {
118c6a69c61SPekka Enberg 	unsigned int i;
119c6a69c61SPekka Enberg 
120c6a69c61SPekka Enberg 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
121c6a69c61SPekka Enberg 		struct serial8250_device *dev = &devices[i];
122c6a69c61SPekka Enberg 
123c6a69c61SPekka Enberg 		if (dev->iobase == (port & ~0x7))
124c6a69c61SPekka Enberg 			return dev;
125c6a69c61SPekka Enberg 	}
126c6a69c61SPekka Enberg 	return NULL;
127c6a69c61SPekka Enberg }
128c6a69c61SPekka Enberg 
12946aa8d69SPekka Enberg static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
13013a7760fSPekka Enberg {
131c6a69c61SPekka Enberg 	struct serial8250_device *dev;
132c6a69c61SPekka Enberg 	uint16_t offset;
13346aa8d69SPekka Enberg 
134c6a69c61SPekka Enberg 	dev		= find_device(port);
135c6a69c61SPekka Enberg 	if (!dev)
136c6a69c61SPekka Enberg 		return false;
137c6a69c61SPekka Enberg 
138c6a69c61SPekka Enberg 	offset		= port - dev->iobase;
139c6a69c61SPekka Enberg 
140c6a69c61SPekka Enberg 	if (dev->lcr & UART_LCR_DLAB) {
14146aa8d69SPekka Enberg 		switch (offset) {
1424e49b05bSCyrill Gorcunov 		case UART_DLL:
143c6a69c61SPekka Enberg 			dev->dll	= ioport__read8(data);
14446aa8d69SPekka Enberg 			break;
1454e49b05bSCyrill Gorcunov 		case UART_DLM:
146c6a69c61SPekka Enberg 			dev->dlm	= ioport__read8(data);
14746aa8d69SPekka Enberg 			break;
148369c01c0SPekka Enberg 		case UART_FCR:
149369c01c0SPekka Enberg 			dev->fcr	= ioport__read8(data);
150369c01c0SPekka Enberg 			break;
151369c01c0SPekka Enberg 		case UART_LCR:
152369c01c0SPekka Enberg 			dev->lcr	= ioport__read8(data);
153369c01c0SPekka Enberg 			break;
154369c01c0SPekka Enberg 		case UART_MCR:
155369c01c0SPekka Enberg 			dev->mcr	= ioport__read8(data);
156369c01c0SPekka Enberg 			break;
157369c01c0SPekka Enberg 		case UART_LSR:
158369c01c0SPekka Enberg 			/* Factory test */
159369c01c0SPekka Enberg 			break;
160369c01c0SPekka Enberg 		case UART_MSR:
161369c01c0SPekka Enberg 			/* Not used */
162369c01c0SPekka Enberg 			break;
163369c01c0SPekka Enberg 		case UART_SCR:
164369c01c0SPekka Enberg 			dev->scr	= ioport__read8(data);
165369c01c0SPekka Enberg 			break;
166369c01c0SPekka Enberg 		default:
167369c01c0SPekka Enberg 			return false;
16846aa8d69SPekka Enberg 		}
16946aa8d69SPekka Enberg 	} else {
17046aa8d69SPekka Enberg 		switch (offset) {
1714e49b05bSCyrill Gorcunov 		case UART_TX: {
17213a7760fSPekka Enberg 			char *p = data;
173f2d8dc88SCyrill Gorcunov 			int i;
17413a7760fSPekka Enberg 
175369c01c0SPekka Enberg 			if (!(dev->mcr & UART_MCR_LOOP)) {
176f2d8dc88SCyrill Gorcunov 				while (count--) {
177f2d8dc88SCyrill Gorcunov 					for (i = 0; i < size; i++)
178b7475544SPekka Enberg 						fprintf(stdout, "%c", *p++);
1795b9d0b58SAsias He 				}
180b7475544SPekka Enberg 				fflush(stdout);
181369c01c0SPekka Enberg 			}
182133bedc1SPekka Enberg 			dev->iir		= UART_IIR_NO_INT;
18346aa8d69SPekka Enberg 			break;
18446aa8d69SPekka Enberg 		}
185369c01c0SPekka Enberg 		case UART_FCR:
186369c01c0SPekka Enberg 			dev->fcr	= ioport__read8(data);
187369c01c0SPekka Enberg 			break;
1884e49b05bSCyrill Gorcunov 		case UART_IER:
189369c01c0SPekka Enberg 			dev->ier	= ioport__read8(data) & 0x3f;
19046aa8d69SPekka Enberg 			break;
191369c01c0SPekka Enberg 		case UART_LCR:
192369c01c0SPekka Enberg 			dev->lcr	= ioport__read8(data);
193369c01c0SPekka Enberg 			break;
194369c01c0SPekka Enberg 		case UART_MCR:
195369c01c0SPekka Enberg 			dev->mcr	= ioport__read8(data);
196369c01c0SPekka Enberg 			break;
197369c01c0SPekka Enberg 		case UART_LSR:
198369c01c0SPekka Enberg 			/* Factory test */
199369c01c0SPekka Enberg 			break;
200369c01c0SPekka Enberg 		case UART_MSR:
201369c01c0SPekka Enberg 			/* Not used */
202369c01c0SPekka Enberg 			break;
203369c01c0SPekka Enberg 		case UART_SCR:
204369c01c0SPekka Enberg 			dev->scr	= ioport__read8(data);
205369c01c0SPekka Enberg 			break;
206369c01c0SPekka Enberg 		default:
207369c01c0SPekka Enberg 			return false;
20846aa8d69SPekka Enberg 		}
20946aa8d69SPekka Enberg 	}
21013a7760fSPekka Enberg 	return true;
21113a7760fSPekka Enberg }
21213a7760fSPekka Enberg 
21346aa8d69SPekka Enberg static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
21425af6674SPekka Enberg {
215c6a69c61SPekka Enberg 	struct serial8250_device *dev;
216c6a69c61SPekka Enberg 	uint16_t offset;
21746aa8d69SPekka Enberg 
218c6a69c61SPekka Enberg 	dev		= find_device(port);
219c6a69c61SPekka Enberg 	if (!dev)
220c6a69c61SPekka Enberg 		return false;
221c6a69c61SPekka Enberg 
222c6a69c61SPekka Enberg 	offset		= port - dev->iobase;
223c6a69c61SPekka Enberg 
22419a2bb7dSPekka Enberg 	if (dev->lcr & UART_LCR_DLAB) {
22519a2bb7dSPekka Enberg 		switch (offset) {
22619a2bb7dSPekka Enberg 		case UART_DLL:
22719a2bb7dSPekka Enberg 			ioport__write8(data, dev->dll);
22819a2bb7dSPekka Enberg 			return true;
22919a2bb7dSPekka Enberg 		case UART_DLM:
23019a2bb7dSPekka Enberg 			ioport__write8(data, dev->dlm);
23119a2bb7dSPekka Enberg 			return true;
232369c01c0SPekka Enberg 		default:
233369c01c0SPekka Enberg 			break;
23419a2bb7dSPekka Enberg 		}
23519a2bb7dSPekka Enberg 	} else {
23646aa8d69SPekka Enberg 		switch (offset) {
237251cf9a6SPekka Enberg 		case UART_RX:
238251cf9a6SPekka Enberg 			ioport__write8(data, dev->rbr);
239369c01c0SPekka Enberg 			dev->lsr		&= ~UART_LSR_DR;
240369c01c0SPekka Enberg 			dev->iir		= UART_IIR_NO_INT;
24119a2bb7dSPekka Enberg 			return true;
2424e49b05bSCyrill Gorcunov 		case UART_IER:
243c6a69c61SPekka Enberg 			ioport__write8(data, dev->ier);
24419a2bb7dSPekka Enberg 			return true;
245369c01c0SPekka Enberg 		default:
246369c01c0SPekka Enberg 			break;
24719a2bb7dSPekka Enberg 		}
24819a2bb7dSPekka Enberg 	}
24919a2bb7dSPekka Enberg 
25019a2bb7dSPekka Enberg 	switch (offset) {
251369c01c0SPekka Enberg 	case UART_IIR: {
252369c01c0SPekka Enberg 		uint8_t iir = dev->iir;
253369c01c0SPekka Enberg 
254369c01c0SPekka Enberg 		if (dev->fcr & UART_FCR_ENABLE_FIFO)
255369c01c0SPekka Enberg 			iir		|= 0xc0;
256369c01c0SPekka Enberg 
257369c01c0SPekka Enberg 		ioport__write8(data, iir);
25846aa8d69SPekka Enberg 		break;
259369c01c0SPekka Enberg 	}
2604e49b05bSCyrill Gorcunov 	case UART_LCR:
261c6a69c61SPekka Enberg 		ioport__write8(data, dev->lcr);
26246aa8d69SPekka Enberg 		break;
2634e49b05bSCyrill Gorcunov 	case UART_MCR:
264c6a69c61SPekka Enberg 		ioport__write8(data, dev->mcr);
26546aa8d69SPekka Enberg 		break;
2664e49b05bSCyrill Gorcunov 	case UART_LSR:
267c6a69c61SPekka Enberg 		ioport__write8(data, dev->lsr);
268369c01c0SPekka Enberg 		dev->lsr		&= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI);
26946aa8d69SPekka Enberg 		break;
2704e49b05bSCyrill Gorcunov 	case UART_MSR:
271369c01c0SPekka Enberg 		ioport__write8(data, dev->msr);
27246aa8d69SPekka Enberg 		break;
2734e49b05bSCyrill Gorcunov 	case UART_SCR:
274369c01c0SPekka Enberg 		ioport__write8(data, dev->scr);
27546aa8d69SPekka Enberg 		break;
276369c01c0SPekka Enberg 	default:
277369c01c0SPekka Enberg 		return false;
27825af6674SPekka Enberg 	}
27913a7760fSPekka Enberg 	return true;
28013a7760fSPekka Enberg }
28113a7760fSPekka Enberg 
28246aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = {
28346aa8d69SPekka Enberg 	.io_in		= serial8250_in,
28446aa8d69SPekka Enberg 	.io_out		= serial8250_out,
285a93ec68bSPekka Enberg };
286a93ec68bSPekka Enberg 
287bc4b0ffeSPekka Enberg static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev)
288bc4b0ffeSPekka Enberg {
289bc4b0ffeSPekka Enberg 	ioport__register(dev->iobase, &serial8250_ops, 8);
290bc4b0ffeSPekka Enberg 	kvm__irq_line(kvm, dev->irq, 0);
291bc4b0ffeSPekka Enberg }
292bc4b0ffeSPekka Enberg 
293bc4b0ffeSPekka Enberg void serial8250__init(struct kvm *kvm)
29413a7760fSPekka Enberg {
295c6a69c61SPekka Enberg 	unsigned int i;
296c6a69c61SPekka Enberg 
297c6a69c61SPekka Enberg 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
298c6a69c61SPekka Enberg 		struct serial8250_device *dev = &devices[i];
299c6a69c61SPekka Enberg 
300bc4b0ffeSPekka Enberg 		serial8250__device_init(kvm, dev);
301c6a69c61SPekka Enberg 	}
30213a7760fSPekka Enberg }
303