xref: /kvmtool/hw/serial.c (revision 133bedc1b844e1c883e202c511d2686a2468fb7f)
1 #include "kvm/8250-serial.h"
2 
3 #include "kvm/ioport.h"
4 #include "kvm/util.h"
5 #include "kvm/kvm.h"
6 
7 #include <linux/serial_reg.h>
8 
9 #include <stdbool.h>
10 #include <poll.h>
11 
12 struct serial8250_device {
13 	uint16_t		iobase;
14 	uint8_t			irq;
15 
16 	uint8_t			thr;
17 	uint8_t			dll;
18 	uint8_t			dlm;
19 	uint8_t			iir;
20 	uint8_t			ier;
21 	uint8_t			fcr;
22 	uint8_t			lcr;
23 	uint8_t			mcr;
24 	uint8_t			lsr;
25 	uint8_t			scr;
26 
27 	uint8_t			counter;
28 };
29 
30 static struct serial8250_device devices[] = {
31 	/* ttyS0 */
32 	[0]	= {
33 		.iobase			= 0x3f8,
34 		.irq			= 4,
35 
36 		.lsr			= UART_LSR_TEMT | UART_LSR_THRE,
37 	},
38 	/* ttyS1 */
39 	[1]	= {
40 		.iobase			= 0x2f8,
41 		.irq			= 3,
42 
43 		.iir			= UART_IIR_NO_INT,
44 	},
45 	/* ttyS2 */
46 	[2]	= {
47 		.iobase			= 0x3e8,
48 		.irq			= 4,
49 
50 		.iir			= UART_IIR_NO_INT,
51 	},
52 };
53 
54 static int read_char(int fd)
55 {
56 	int c;
57 
58 	if (read(fd, &c, 1) < 0)
59 		return -1;
60 
61 	return c;
62 }
63 
64 static bool is_readable(int fd)
65 {
66 	struct pollfd pollfd = (struct pollfd) {
67 		.fd	= fd,
68 		.events	= POLLIN,
69 	};
70 
71 	return poll(&pollfd, 1, 0) > 0;
72 }
73 
74 /*
75  * Interrupts are injected for ttyS0 only.
76  */
77 void serial8250__interrupt(struct kvm *self)
78 {
79 	struct serial8250_device *dev = &devices[0];
80 	uint8_t new_iir;
81 
82 	dev->iir	= UART_IIR_NO_INT;
83 
84 	/* No interrupts enabled. Exit... */
85 	if (!(dev->ier & (UART_IER_THRI|UART_IER_RDI)))
86 		return;
87 
88 	new_iir		= 0;
89 
90 	/* We're always good for guest sending data. */
91 	if (dev->ier & UART_IER_THRI)
92 		new_iir			|= UART_IIR_THRI;
93 
94 	/* Is there input in stdin to send to the guest? */
95 	if (!(dev->lsr & UART_LSR_DR) && is_readable(fileno(stdin))) {
96 		int c;
97 
98 		c			= read_char(fileno(stdin));
99 		if (c >= 0) {
100 			dev->thr		= c;
101 			dev->lsr		|= UART_LSR_DR;
102 			new_iir			|= UART_IIR_RDI;
103 		}
104 	}
105 
106 	/* Only send an IRQ if there's work to do. */
107 	if (new_iir) {
108 		dev->iir		= new_iir;
109 		kvm__irq_line(self, dev->irq, 0);
110 		kvm__irq_line(self, dev->irq, 1);
111 	}
112 }
113 
114 static struct serial8250_device *find_device(uint16_t port)
115 {
116 	unsigned int i;
117 
118 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
119 		struct serial8250_device *dev = &devices[i];
120 
121 		if (dev->iobase == (port & ~0x7))
122 			return dev;
123 	}
124 	return NULL;
125 }
126 
127 static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
128 {
129 	struct serial8250_device *dev;
130 	uint16_t offset;
131 
132 	dev		= find_device(port);
133 	if (!dev)
134 		return false;
135 
136 	offset		= port - dev->iobase;
137 
138 	if (dev->lcr & UART_LCR_DLAB) {
139 		switch (offset) {
140 		case UART_DLL:
141 			dev->dll		= ioport__read8(data);
142 			break;
143 		case UART_DLM:
144 			dev->dlm		= ioport__read8(data);
145 			break;
146 		case UART_FCR:
147 			dev->fcr		= ioport__read8(data);
148 			break;
149 		case UART_LCR:
150 			dev->lcr		= ioport__read8(data);
151 			break;
152 		default:
153 			return false;
154 		}
155 	} else {
156 		switch (offset) {
157 		case UART_TX: {
158 			char *p = data;
159 			int i;
160 
161 			while (count--) {
162 				for (i = 0; i < size; i++)
163 					fprintf(stdout, "%c", *p++);
164 			}
165 			fflush(stdout);
166 
167 			if (dev->counter++ > 10) {
168 				dev->iir		= UART_IIR_NO_INT;
169 				dev->counter		= 0;
170 			}
171 
172 			break;
173 		}
174 		case UART_IER:
175 			dev->ier		= ioport__read8(data);
176 			break;
177 		case UART_FCR:
178 			dev->fcr		= ioport__read8(data);
179 			break;
180 		case UART_LCR:
181 			dev->lcr		= ioport__read8(data);
182 			break;
183 		case UART_MCR:
184 			dev->mcr		= ioport__read8(data);
185 			break;
186 		case UART_SCR:
187 			dev->scr		= ioport__read8(data);
188 			break;
189 		default:
190 			return false;
191 		}
192 	}
193 
194 	return true;
195 }
196 
197 static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
198 {
199 	struct serial8250_device *dev;
200 	uint16_t offset;
201 
202 	dev		= find_device(port);
203 	if (!dev)
204 		return false;
205 
206 	offset		= port - dev->iobase;
207 
208 	if (dev->lcr & UART_LCR_DLAB)
209 		return false;
210 
211 	switch (offset) {
212 	case UART_TX:
213 		if (dev->lsr & UART_LSR_DR) {
214 			dev->iir		= UART_IIR_NO_INT;
215 
216 			dev->lsr		&= ~UART_LSR_DR;
217 			ioport__write8(data, dev->thr);
218 		}
219 		break;
220 	case UART_IER:
221 		ioport__write8(data, dev->ier);
222 		break;
223 	case UART_IIR:
224 		ioport__write8(data, dev->iir);
225 		break;
226 	case UART_LCR:
227 		ioport__write8(data, dev->lcr);
228 		break;
229 	case UART_MCR:
230 		ioport__write8(data, dev->mcr);
231 		break;
232 	case UART_LSR:
233 		ioport__write8(data, dev->lsr);
234 		break;
235 	case UART_MSR:
236 		ioport__write8(data, UART_MSR_CTS);
237 		break;
238 	case UART_SCR:
239 		ioport__write8(data, dev->scr);
240 		break;
241 	default:
242 		return false;
243 	}
244 
245 	return true;
246 }
247 
248 static struct ioport_operations serial8250_ops = {
249 	.io_in		= serial8250_in,
250 	.io_out		= serial8250_out,
251 };
252 
253 void serial8250__init(void)
254 {
255 	unsigned int i;
256 
257 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
258 		struct serial8250_device *dev = &devices[i];
259 
260 		ioport__register(dev->iobase, &serial8250_ops, 8);
261 	}
262 }
263