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